polyphony 0.40 → 0.43.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +11 -2
- data/.gitignore +2 -2
- data/.rubocop.yml +30 -0
- data/CHANGELOG.md +29 -2
- data/Gemfile.lock +13 -10
- data/README.md +0 -1
- data/Rakefile +3 -3
- data/TODO.md +27 -97
- data/docs/_config.yml +56 -7
- data/docs/_sass/custom/custom.scss +6 -26
- data/docs/_sass/overrides.scss +0 -46
- data/docs/{user-guide → _user-guide}/all-about-timers.md +0 -0
- data/docs/_user-guide/index.md +9 -0
- data/docs/{user-guide → _user-guide}/web-server.md +0 -0
- data/docs/api-reference/fiber.md +2 -2
- data/docs/api-reference/index.md +9 -0
- data/docs/api-reference/polyphony-process.md +1 -1
- data/docs/api-reference/thread.md +1 -1
- data/docs/faq.md +21 -11
- data/docs/favicon.ico +0 -0
- data/docs/getting-started/index.md +10 -0
- data/docs/getting-started/installing.md +2 -6
- data/docs/getting-started/overview.md +486 -0
- data/docs/getting-started/tutorial.md +27 -19
- data/docs/index.md +6 -2
- data/docs/main-concepts/concurrency.md +0 -5
- data/docs/main-concepts/design-principles.md +69 -21
- data/docs/main-concepts/extending.md +1 -1
- data/docs/main-concepts/index.md +9 -0
- data/docs/polyphony-logo.png +0 -0
- data/examples/adapters/redis_blpop.rb +12 -0
- data/examples/core/01-spinning-up-fibers.rb +1 -0
- data/examples/core/03-interrupting.rb +4 -1
- data/examples/core/04-handling-signals.rb +19 -0
- data/examples/core/xx-agent.rb +102 -0
- data/examples/core/xx-sleeping.rb +14 -6
- data/examples/io/xx-irb.rb +1 -1
- data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +7 -6
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +13 -36
- data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +58 -0
- data/examples/performance/xx-array.rb +11 -0
- data/examples/performance/xx-fiber-switch.rb +9 -0
- data/examples/performance/xx-snooze.rb +15 -0
- data/ext/{gyro → polyphony}/extconf.rb +2 -2
- data/ext/{gyro → polyphony}/fiber.c +15 -22
- data/ext/{gyro → polyphony}/libev.c +0 -0
- data/ext/{gyro → polyphony}/libev.h +0 -0
- data/ext/polyphony/libev_agent.c +725 -0
- data/ext/polyphony/libev_queue.c +217 -0
- data/ext/{gyro/gyro.c → polyphony/polyphony.c} +12 -37
- data/ext/polyphony/polyphony.h +90 -0
- data/ext/polyphony/polyphony_ext.c +21 -0
- data/ext/{gyro → polyphony}/thread.c +34 -151
- data/ext/{gyro → polyphony}/tracing.c +1 -1
- data/lib/polyphony.rb +19 -12
- data/lib/polyphony/adapters/irb.rb +1 -1
- data/lib/polyphony/adapters/postgres.rb +6 -5
- data/lib/polyphony/adapters/process.rb +5 -5
- data/lib/polyphony/adapters/redis.rb +3 -2
- data/lib/polyphony/adapters/trace.rb +28 -28
- data/lib/polyphony/core/channel.rb +3 -3
- data/lib/polyphony/core/exceptions.rb +1 -1
- data/lib/polyphony/core/global_api.rb +13 -11
- data/lib/polyphony/core/resource_pool.rb +3 -3
- data/lib/polyphony/core/sync.rb +2 -2
- data/lib/polyphony/core/thread_pool.rb +6 -6
- data/lib/polyphony/core/throttler.rb +13 -6
- data/lib/polyphony/event.rb +27 -0
- data/lib/polyphony/extensions/core.rb +22 -14
- data/lib/polyphony/extensions/fiber.rb +4 -4
- data/lib/polyphony/extensions/io.rb +59 -25
- data/lib/polyphony/extensions/openssl.rb +36 -16
- data/lib/polyphony/extensions/socket.rb +28 -10
- data/lib/polyphony/extensions/thread.rb +16 -9
- data/lib/polyphony/net.rb +9 -9
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +3 -3
- data/test/helper.rb +12 -1
- data/test/test_agent.rb +130 -0
- data/test/{test_async.rb → test_event.rb} +13 -7
- data/test/test_ext.rb +25 -4
- data/test/test_fiber.rb +19 -10
- data/test/test_global_api.rb +6 -6
- data/test/test_io.rb +46 -24
- data/test/test_queue.rb +74 -0
- data/test/test_signal.rb +3 -40
- data/test/test_socket.rb +34 -0
- data/test/test_thread.rb +37 -16
- data/test/test_trace.rb +6 -5
- metadata +39 -41
- data/docs/_includes/nav.html +0 -51
- data/docs/_includes/prevnext.html +0 -17
- data/docs/_layouts/default.html +0 -106
- data/docs/api-reference.md +0 -11
- data/docs/api-reference/gyro-async.md +0 -57
- data/docs/api-reference/gyro-child.md +0 -29
- data/docs/api-reference/gyro-queue.md +0 -44
- data/docs/api-reference/gyro-timer.md +0 -51
- data/docs/api-reference/gyro.md +0 -25
- data/docs/getting-started.md +0 -10
- data/docs/main-concepts.md +0 -10
- data/docs/user-guide.md +0 -10
- data/examples/core/forever_sleep.rb +0 -19
- data/ext/gyro/async.c +0 -132
- data/ext/gyro/child.c +0 -108
- data/ext/gyro/gyro.h +0 -158
- data/ext/gyro/gyro_ext.c +0 -33
- data/ext/gyro/io.c +0 -457
- data/ext/gyro/queue.c +0 -146
- data/ext/gyro/selector.c +0 -205
- data/ext/gyro/signal.c +0 -99
- data/ext/gyro/socket.c +0 -213
- data/ext/gyro/timer.c +0 -115
- data/test/test_timer.rb +0 -56
@@ -1,29 +0,0 @@
|
|
1
|
-
---
|
2
|
-
layout: page
|
3
|
-
title: Gyro::Child
|
4
|
-
parent: API Reference
|
5
|
-
permalink: /api-reference/gyro-child/
|
6
|
-
---
|
7
|
-
# Gyro::Child
|
8
|
-
|
9
|
-
`Gyro::Child` encapsulates a libev [child
|
10
|
-
watcher](http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_ev_child_code_watch_out_for_pro),
|
11
|
-
used for waiting for a child process to terminate. A `Gyro::Child` watcher
|
12
|
-
instance can be used for low-level control of child processes, instead of using
|
13
|
-
more high-level APIs such `Process.wait` etc.
|
14
|
-
|
15
|
-
## Instance methods
|
16
|
-
|
17
|
-
### #await → [pid, exitcode]
|
18
|
-
|
19
|
-
Blocks the current thread until the watcher is signalled. The return value is an
|
20
|
-
array containing the child's pid and the exit code.
|
21
|
-
|
22
|
-
```ruby
|
23
|
-
pid = Polyphony.fork { sleep 1 }
|
24
|
-
Gyro::Child.new(pid).await #=> [pid, 0]
|
25
|
-
```
|
26
|
-
|
27
|
-
### #initialize(pid)
|
28
|
-
|
29
|
-
Initializes the watcher instance with the given pid
|
@@ -1,44 +0,0 @@
|
|
1
|
-
---
|
2
|
-
layout: page
|
3
|
-
title: Gyro::Queue
|
4
|
-
parent: API Reference
|
5
|
-
permalink: /api-reference/gyro-queue/
|
6
|
-
---
|
7
|
-
# Gyro::Queue
|
8
|
-
|
9
|
-
`Gyro::Queue` implements a polyphonic (fiber-aware) queue that can store 0 or
|
10
|
-
more items of any data types. Adding an item to the queue never blocks.
|
11
|
-
Retrieving an item from the queue will block if the queue is empty.
|
12
|
-
`Gyro::Queue` is both fiber-safe and thread-safe. This means multiple fibers
|
13
|
-
from multiple threads can concurrently interact with the same queue.
|
14
|
-
`Gyro::Queue` is used pervasively across the Polyphony code base for
|
15
|
-
synchronisation and fiber control.
|
16
|
-
|
17
|
-
## Instance methods
|
18
|
-
|
19
|
-
### #<<(object) → queue<br>#push(object) → queue
|
20
|
-
|
21
|
-
Adds an item to the queue.
|
22
|
-
|
23
|
-
### #clear → queue
|
24
|
-
|
25
|
-
Removes all items currently in the queue.
|
26
|
-
|
27
|
-
### #empty? → true or false
|
28
|
-
|
29
|
-
Returns true if the queue is empty. Otherwise returns false.
|
30
|
-
|
31
|
-
### #initialize
|
32
|
-
|
33
|
-
Initializes an empty queue.
|
34
|
-
|
35
|
-
### #shift → object<br>#pop → object
|
36
|
-
|
37
|
-
Retrieves an item from the queue. If the queue is empty, `#shift` blocks until
|
38
|
-
an item is added to the queue or until interrupted. Multiple fibers calling
|
39
|
-
`#shift` are served in a first-ordered first-served manner.
|
40
|
-
|
41
|
-
### #shift_each → [*object]<br>#shift_each({ block }) → queue
|
42
|
-
|
43
|
-
Removes and returns all items currently in the queue. If a block is given, it
|
44
|
-
will be invoked for each item.
|
@@ -1,51 +0,0 @@
|
|
1
|
-
---
|
2
|
-
layout: page
|
3
|
-
title: Gyro::Timer
|
4
|
-
parent: API Reference
|
5
|
-
permalink: /api-reference/gyro-timer/
|
6
|
-
---
|
7
|
-
# Gyro::Timer
|
8
|
-
|
9
|
-
`Gyro::Timer` encapsulates a libev [timer
|
10
|
-
watcher](http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_ev_timer_code_relative_and_opti),
|
11
|
-
allowing waiting a certain amount of time before proceeding with an operation.
|
12
|
-
Watchers can be either one-time timers or recurring timers. The Polyphony API
|
13
|
-
provides various APIs that use timer watchers for timeouts, throttled
|
14
|
-
operations, and sleeping.
|
15
|
-
|
16
|
-
## Instance methods
|
17
|
-
|
18
|
-
### #await → object
|
19
|
-
|
20
|
-
Blocks the current thread until the timer has elapsed. For recurrent timers,
|
21
|
-
`#await` will block until the next timer period has elapsed, as specified by the
|
22
|
-
`repeat` argument given to `#initialize`.
|
23
|
-
|
24
|
-
### #initialize(after, repeat)
|
25
|
-
|
26
|
-
Initializes the watcher instance. The `after` argument gives the time duration
|
27
|
-
in seconds before the timer has elapsed. The `repeat` argument gives the time
|
28
|
-
period for recurring timers, or `0` for non-recurring timers.
|
29
|
-
|
30
|
-
### #stop
|
31
|
-
|
32
|
-
Stops an active recurring timer. Recurring timers stay active (from the point of
|
33
|
-
view of the event loop) even after the timer period has elapsed. Calling `#stop`
|
34
|
-
marks the timer as inactive and cleans up associated resources. This should
|
35
|
-
normally be done inside an `ensure` block:
|
36
|
-
|
37
|
-
```ruby
|
38
|
-
def repeat(period)
|
39
|
-
timer = Gyro::Timer.new(period, period)
|
40
|
-
loop do
|
41
|
-
timer.await
|
42
|
-
yield
|
43
|
-
end
|
44
|
-
ensure
|
45
|
-
timer.stop
|
46
|
-
end
|
47
|
-
|
48
|
-
repeat(10) { puts Time.now }
|
49
|
-
```
|
50
|
-
|
51
|
-
There's no need to call `#stop` for non-recurring timers.
|
data/docs/api-reference/gyro.md
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
---
|
2
|
-
layout: page
|
3
|
-
title: Gyro
|
4
|
-
parent: API Reference
|
5
|
-
permalink: /api-reference/gyro/
|
6
|
-
---
|
7
|
-
# Gyro
|
8
|
-
|
9
|
-
`Gyro` is the subsystem in charge of the low-level functionality in Polyphony.
|
10
|
-
It contains all of the different event watcher classes, as well as other
|
11
|
-
low-level constructs such as `Gyro::Queue`, a fiber-aware queue implementation,
|
12
|
-
used pervasively across the Polyphony code base.
|
13
|
-
|
14
|
-
While most Polyphony-based applications do not normally need to interact
|
15
|
-
directly with the `Gyro` classes, more advanced applications and libraries may
|
16
|
-
use those classes to enhance Polyphony and create custom concurrency patterns.
|
17
|
-
|
18
|
-
## Classes
|
19
|
-
|
20
|
-
- [`Gyro::Async`](../gyro-async/) - async event watcher
|
21
|
-
- [`Gyro::Child`](../gyro-child/) - child process event watcher
|
22
|
-
- [`Gyro::IO`](../gyro-io/) - IO event watcher
|
23
|
-
- [`Gyro::Queue`](../gyro-queue/) - fiber-aware queue
|
24
|
-
- [`Gyro::Signal`](../gyro-signal/) - signal event watcher
|
25
|
-
- [`Gyro::Timer`](../gyro-timer/) - timer event watcher
|
data/docs/getting-started.md
DELETED
data/docs/main-concepts.md
DELETED
data/docs/user-guide.md
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bundler/setup'
|
4
|
-
require 'polyphony'
|
5
|
-
|
6
|
-
trap('TERM') do
|
7
|
-
# do nothing
|
8
|
-
end
|
9
|
-
|
10
|
-
trap('INT') do
|
11
|
-
# do nothing
|
12
|
-
end
|
13
|
-
|
14
|
-
puts "go to sleep"
|
15
|
-
begin
|
16
|
-
sleep
|
17
|
-
ensure
|
18
|
-
puts "done sleeping"
|
19
|
-
end
|
data/ext/gyro/async.c
DELETED
@@ -1,132 +0,0 @@
|
|
1
|
-
#include "gyro.h"
|
2
|
-
|
3
|
-
struct Gyro_Async {
|
4
|
-
GYRO_WATCHER_DECL(ev_async);
|
5
|
-
VALUE value;
|
6
|
-
};
|
7
|
-
|
8
|
-
VALUE cGyro_Async = Qnil;
|
9
|
-
|
10
|
-
static void Gyro_Async_mark(void *ptr) {
|
11
|
-
struct Gyro_Async *async = ptr;
|
12
|
-
|
13
|
-
GYRO_WATCHER_MARK(async);
|
14
|
-
if (async->value != Qnil) rb_gc_mark(async->value);
|
15
|
-
}
|
16
|
-
|
17
|
-
static void Gyro_Async_free(void *ptr) {
|
18
|
-
struct Gyro_Async *async = ptr;
|
19
|
-
|
20
|
-
GYRO_WATCHER_FREE(async);
|
21
|
-
}
|
22
|
-
|
23
|
-
static size_t Gyro_Async_size(const void *ptr) {
|
24
|
-
return sizeof(struct Gyro_Async);
|
25
|
-
}
|
26
|
-
|
27
|
-
static const rb_data_type_t Gyro_Async_type = {
|
28
|
-
"Gyro_Async",
|
29
|
-
{Gyro_Async_mark, Gyro_Async_free, Gyro_Async_size,},
|
30
|
-
0, 0, 0
|
31
|
-
};
|
32
|
-
|
33
|
-
static VALUE Gyro_Async_allocate(VALUE klass) {
|
34
|
-
struct Gyro_Async *async = ALLOC(struct Gyro_Async);
|
35
|
-
|
36
|
-
return TypedData_Wrap_Struct(klass, &Gyro_Async_type, async);
|
37
|
-
}
|
38
|
-
|
39
|
-
inline void async_activate(struct Gyro_Async *async) {
|
40
|
-
if (async->active) return;
|
41
|
-
|
42
|
-
async->active = 1;
|
43
|
-
async->fiber = rb_fiber_current();
|
44
|
-
async->selector = Thread_current_event_selector();
|
45
|
-
async->ev_loop = Gyro_Selector_ev_loop(async->selector);
|
46
|
-
Gyro_Selector_add_active_watcher(async->selector, async->self);
|
47
|
-
ev_async_start(async->ev_loop, &async->ev_async);
|
48
|
-
}
|
49
|
-
|
50
|
-
inline void async_deactivate(struct Gyro_Async *async) {
|
51
|
-
if (!async->active) return;
|
52
|
-
|
53
|
-
ev_async_stop(async->ev_loop, &async->ev_async);
|
54
|
-
Gyro_Selector_remove_active_watcher(async->selector, async->self);
|
55
|
-
async->active = 0;
|
56
|
-
async->ev_loop = 0;
|
57
|
-
async->selector = Qnil;
|
58
|
-
async->fiber = Qnil;
|
59
|
-
async->value = Qnil;
|
60
|
-
}
|
61
|
-
|
62
|
-
void Gyro_Async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, int revents) {
|
63
|
-
struct Gyro_Async *async = (struct Gyro_Async*)ev_async;
|
64
|
-
|
65
|
-
Fiber_make_runnable(async->fiber, async->value);
|
66
|
-
async_deactivate(async);
|
67
|
-
}
|
68
|
-
|
69
|
-
#define GetGyro_Async(obj, async) \
|
70
|
-
TypedData_Get_Struct((obj), struct Gyro_Async, &Gyro_Async_type, (async))
|
71
|
-
|
72
|
-
static VALUE Gyro_Async_initialize(VALUE self) {
|
73
|
-
struct Gyro_Async *async;
|
74
|
-
GetGyro_Async(self, async);
|
75
|
-
|
76
|
-
GYRO_WATCHER_INITIALIZE(async, self);
|
77
|
-
async->value = Qnil;
|
78
|
-
ev_async_init(&async->ev_async, Gyro_Async_callback);
|
79
|
-
|
80
|
-
return Qnil;
|
81
|
-
}
|
82
|
-
|
83
|
-
static VALUE Gyro_Async_signal(int argc, VALUE *argv, VALUE self) {
|
84
|
-
struct Gyro_Async *async;
|
85
|
-
GetGyro_Async(self, async);
|
86
|
-
|
87
|
-
if (!async->active) {
|
88
|
-
// printf("signal called before await\n");
|
89
|
-
return Qnil;
|
90
|
-
}
|
91
|
-
|
92
|
-
async->value = (argc == 1) ? argv[0] : Qnil;
|
93
|
-
ev_async_send(async->ev_loop, &async->ev_async);
|
94
|
-
|
95
|
-
return Qnil;
|
96
|
-
}
|
97
|
-
|
98
|
-
VALUE Gyro_Async_await(VALUE self) {
|
99
|
-
struct Gyro_Async *async;
|
100
|
-
VALUE ret;
|
101
|
-
GetGyro_Async(self, async);
|
102
|
-
|
103
|
-
async_activate(async);
|
104
|
-
ret = Gyro_switchpoint();
|
105
|
-
async_deactivate(async);
|
106
|
-
|
107
|
-
TEST_RESUME_EXCEPTION(ret);
|
108
|
-
RB_GC_GUARD(ret);
|
109
|
-
return ret;
|
110
|
-
}
|
111
|
-
|
112
|
-
VALUE Gyro_Async_await_no_raise(VALUE self) {
|
113
|
-
struct Gyro_Async *async;
|
114
|
-
VALUE ret;
|
115
|
-
GetGyro_Async(self, async);
|
116
|
-
|
117
|
-
async_activate(async);
|
118
|
-
ret = Gyro_switchpoint();
|
119
|
-
async_deactivate(async);
|
120
|
-
|
121
|
-
RB_GC_GUARD(ret);
|
122
|
-
return ret;
|
123
|
-
}
|
124
|
-
|
125
|
-
void Init_Gyro_Async() {
|
126
|
-
cGyro_Async = rb_define_class_under(mGyro, "Async", rb_cData);
|
127
|
-
rb_define_alloc_func(cGyro_Async, Gyro_Async_allocate);
|
128
|
-
|
129
|
-
rb_define_method(cGyro_Async, "initialize", Gyro_Async_initialize, 0);
|
130
|
-
rb_define_method(cGyro_Async, "await", Gyro_Async_await, 0);
|
131
|
-
rb_define_method(cGyro_Async, "signal", Gyro_Async_signal, -1);
|
132
|
-
}
|
data/ext/gyro/child.c
DELETED
@@ -1,108 +0,0 @@
|
|
1
|
-
#include "gyro.h"
|
2
|
-
|
3
|
-
struct Gyro_Child {
|
4
|
-
GYRO_WATCHER_DECL(ev_child);
|
5
|
-
int pid;
|
6
|
-
};
|
7
|
-
|
8
|
-
static VALUE cGyro_Child = Qnil;
|
9
|
-
|
10
|
-
static void Gyro_Child_mark(void *ptr) {
|
11
|
-
struct Gyro_Child *child = ptr;
|
12
|
-
GYRO_WATCHER_MARK(child);
|
13
|
-
}
|
14
|
-
|
15
|
-
static void Gyro_Child_free(void *ptr) {
|
16
|
-
struct Gyro_Child *child = ptr;
|
17
|
-
GYRO_WATCHER_FREE(child);
|
18
|
-
}
|
19
|
-
|
20
|
-
static size_t Gyro_Child_size(const void *ptr) {
|
21
|
-
return sizeof(struct Gyro_Child);
|
22
|
-
}
|
23
|
-
|
24
|
-
static const rb_data_type_t Gyro_Child_type = {
|
25
|
-
"Gyro_Child",
|
26
|
-
{Gyro_Child_mark, Gyro_Child_free, Gyro_Child_size,},
|
27
|
-
0, 0, 0
|
28
|
-
};
|
29
|
-
|
30
|
-
static VALUE Gyro_Child_allocate(VALUE klass) {
|
31
|
-
struct Gyro_Child *child = ALLOC(struct Gyro_Child);
|
32
|
-
return TypedData_Wrap_Struct(klass, &Gyro_Child_type, child);
|
33
|
-
}
|
34
|
-
|
35
|
-
inline void child_activate(struct Gyro_Child *child) {
|
36
|
-
if (child->active) return;
|
37
|
-
|
38
|
-
child->active = 1;
|
39
|
-
child->fiber = rb_fiber_current();
|
40
|
-
child->selector = Thread_current_event_selector();
|
41
|
-
child->ev_loop = Gyro_Selector_ev_loop(child->selector);
|
42
|
-
Gyro_Selector_add_active_watcher(child->selector, child->self);
|
43
|
-
ev_child_start(child->ev_loop, &child->ev_child);
|
44
|
-
}
|
45
|
-
|
46
|
-
inline void child_deactivate(struct Gyro_Child *child) {
|
47
|
-
if (!child->active) return;
|
48
|
-
|
49
|
-
ev_child_stop(child->ev_loop, &child->ev_child);
|
50
|
-
Gyro_Selector_remove_active_watcher(child->selector, child->self);
|
51
|
-
child->active = 0;
|
52
|
-
child->ev_loop = 0;
|
53
|
-
child->selector = Qnil;
|
54
|
-
child->fiber = Qnil;
|
55
|
-
}
|
56
|
-
|
57
|
-
VALUE Gyro_Child_resume_value(struct ev_child *ev_child) {
|
58
|
-
int exit_status = ev_child->rstatus >> 8; // weird, why should we do this?
|
59
|
-
|
60
|
-
return rb_ary_new_from_args(
|
61
|
-
2, INT2NUM(ev_child->rpid), INT2NUM(exit_status)
|
62
|
-
);
|
63
|
-
}
|
64
|
-
|
65
|
-
void Gyro_Child_callback(struct ev_loop *ev_loop, struct ev_child *ev_child, int revents) {
|
66
|
-
struct Gyro_Child *child = (struct Gyro_Child*)ev_child;
|
67
|
-
|
68
|
-
VALUE resume_value = Gyro_Child_resume_value(ev_child);
|
69
|
-
Fiber_make_runnable(child->fiber, resume_value);
|
70
|
-
|
71
|
-
child_deactivate(child);
|
72
|
-
}
|
73
|
-
|
74
|
-
#define GetGyro_Child(obj, child) \
|
75
|
-
TypedData_Get_Struct((obj), struct Gyro_Child, &Gyro_Child_type, (child))
|
76
|
-
|
77
|
-
static VALUE Gyro_Child_initialize(VALUE self, VALUE pid) {
|
78
|
-
struct Gyro_Child *child;
|
79
|
-
|
80
|
-
GetGyro_Child(self, child);
|
81
|
-
GYRO_WATCHER_INITIALIZE(child, self);
|
82
|
-
child->pid = NUM2INT(pid);
|
83
|
-
ev_child_init(&child->ev_child, Gyro_Child_callback, child->pid, 0);
|
84
|
-
|
85
|
-
return Qnil;
|
86
|
-
}
|
87
|
-
|
88
|
-
static VALUE Gyro_Child_await(VALUE self) {
|
89
|
-
struct Gyro_Child *child;
|
90
|
-
VALUE ret;
|
91
|
-
GetGyro_Child(self, child);
|
92
|
-
|
93
|
-
child_activate(child);
|
94
|
-
ret = Gyro_switchpoint();
|
95
|
-
child_deactivate(child);
|
96
|
-
|
97
|
-
TEST_RESUME_EXCEPTION(ret);
|
98
|
-
RB_GC_GUARD(ret);
|
99
|
-
return ret;
|
100
|
-
}
|
101
|
-
|
102
|
-
void Init_Gyro_Child() {
|
103
|
-
cGyro_Child = rb_define_class_under(mGyro, "Child", rb_cData);
|
104
|
-
rb_define_alloc_func(cGyro_Child, Gyro_Child_allocate);
|
105
|
-
|
106
|
-
rb_define_method(cGyro_Child, "initialize", Gyro_Child_initialize, 1);
|
107
|
-
rb_define_method(cGyro_Child, "await", Gyro_Child_await, 0);
|
108
|
-
}
|