polyphony 0.40 → 0.41
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 +6 -2
- data/Gemfile.lock +9 -6
- data/Rakefile +2 -2
- data/TODO.md +18 -97
- data/docs/_includes/head.html +40 -0
- data/docs/_includes/nav.html +5 -5
- data/docs/api-reference/fiber.md +2 -2
- data/docs/main-concepts/design-principles.md +67 -9
- data/docs/main-concepts/extending.md +1 -1
- 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 +14 -25
- data/ext/{gyro → polyphony}/extconf.rb +2 -2
- data/ext/{gyro → polyphony}/fiber.c +15 -19
- data/ext/{gyro → polyphony}/libev.c +0 -0
- data/ext/{gyro → polyphony}/libev.h +0 -0
- data/ext/polyphony/libev_agent.c +503 -0
- data/ext/polyphony/libev_queue.c +214 -0
- data/ext/{gyro/gyro.c → polyphony/polyphony.c} +16 -25
- data/ext/polyphony/polyphony.h +90 -0
- data/ext/polyphony/polyphony_ext.c +23 -0
- data/ext/{gyro → polyphony}/socket.c +14 -14
- data/ext/{gyro → polyphony}/thread.c +32 -115
- data/ext/{gyro → polyphony}/tracing.c +1 -1
- data/lib/polyphony.rb +16 -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/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 +11 -9
- 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 +20 -11
- data/lib/polyphony/extensions/fiber.rb +4 -4
- data/lib/polyphony/extensions/io.rb +56 -26
- data/lib/polyphony/extensions/openssl.rb +4 -8
- data/lib/polyphony/extensions/socket.rb +27 -9
- 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 +2 -2
- data/test/helper.rb +12 -1
- data/test/test_agent.rb +77 -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 +4 -4
- 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 +33 -0
- data/test/test_thread.rb +37 -16
- data/test/test_trace.rb +6 -5
- metadata +24 -24
- 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/timer.c +0 -115
- data/test/test_timer.rb +0 -56
@@ -0,0 +1,214 @@
|
|
1
|
+
#include "polyphony.h"
|
2
|
+
|
3
|
+
struct async_watcher {
|
4
|
+
ev_async async;
|
5
|
+
struct ev_loop *ev_loop;
|
6
|
+
VALUE fiber;
|
7
|
+
};
|
8
|
+
|
9
|
+
struct async_queue {
|
10
|
+
struct async_watcher **queue;
|
11
|
+
unsigned int len;
|
12
|
+
unsigned int count;
|
13
|
+
unsigned int push_idx;
|
14
|
+
unsigned int pop_idx;
|
15
|
+
};
|
16
|
+
|
17
|
+
void async_queue_init(struct async_queue *queue) {
|
18
|
+
queue->len = 4;
|
19
|
+
queue->count = 0;
|
20
|
+
queue->queue = malloc(sizeof(struct async_watcher *) * queue->len);
|
21
|
+
queue->push_idx = 0;
|
22
|
+
queue->pop_idx = 0;
|
23
|
+
}
|
24
|
+
|
25
|
+
void async_queue_free(struct async_queue *queue) {
|
26
|
+
free(queue->queue);
|
27
|
+
}
|
28
|
+
|
29
|
+
void async_queue_push(struct async_queue *queue, struct async_watcher *watcher) {
|
30
|
+
if (queue->push_idx == queue->len) {
|
31
|
+
queue->len = queue->len * 2;
|
32
|
+
queue->queue = realloc(queue->queue, sizeof(struct async_watcher *) * queue->len);
|
33
|
+
}
|
34
|
+
if (queue->count == 0) {
|
35
|
+
queue->push_idx = 0;
|
36
|
+
queue->pop_idx = 0;
|
37
|
+
}
|
38
|
+
queue->count++;
|
39
|
+
queue->queue[queue->push_idx++] = watcher;
|
40
|
+
}
|
41
|
+
|
42
|
+
struct async_watcher *async_queue_pop(struct async_queue *queue) {
|
43
|
+
if (queue->count == 0) return 0;
|
44
|
+
|
45
|
+
queue->count--;
|
46
|
+
|
47
|
+
return queue->queue[queue->pop_idx++];
|
48
|
+
}
|
49
|
+
|
50
|
+
void async_queue_remove_at_idx(struct async_queue *queue, unsigned int remove_idx) {
|
51
|
+
queue->count--;
|
52
|
+
queue->push_idx--;
|
53
|
+
if (remove_idx < queue->push_idx)
|
54
|
+
memmove(
|
55
|
+
queue->queue + remove_idx,
|
56
|
+
queue->queue + remove_idx + 1,
|
57
|
+
(queue->push_idx - remove_idx) * sizeof(struct async_watcher *)
|
58
|
+
);
|
59
|
+
}
|
60
|
+
|
61
|
+
void async_queue_remove_by_fiber(struct async_queue *queue, VALUE fiber) {
|
62
|
+
if (queue->count == 0) return;
|
63
|
+
|
64
|
+
for (unsigned idx = queue->pop_idx; idx < queue->push_idx; idx++) {
|
65
|
+
if (queue->queue[idx]->fiber == fiber) {
|
66
|
+
async_queue_remove_at_idx(queue, idx);
|
67
|
+
return;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
typedef struct queue {
|
73
|
+
VALUE items;
|
74
|
+
struct async_queue shift_queue;
|
75
|
+
} LibevQueue_t;
|
76
|
+
|
77
|
+
|
78
|
+
VALUE cLibevQueue = Qnil;
|
79
|
+
|
80
|
+
static void LibevQueue_mark(void *ptr) {
|
81
|
+
LibevQueue_t *queue = ptr;
|
82
|
+
rb_gc_mark(queue->items);
|
83
|
+
}
|
84
|
+
|
85
|
+
static void LibevQueue_free(void *ptr) {
|
86
|
+
LibevQueue_t *queue = ptr;
|
87
|
+
async_queue_free(&queue->shift_queue);
|
88
|
+
xfree(ptr);
|
89
|
+
}
|
90
|
+
|
91
|
+
static size_t LibevQueue_size(const void *ptr) {
|
92
|
+
return sizeof(LibevQueue_t);
|
93
|
+
}
|
94
|
+
|
95
|
+
static const rb_data_type_t LibevQueue_type = {
|
96
|
+
"Queue",
|
97
|
+
{LibevQueue_mark, LibevQueue_free, LibevQueue_size,},
|
98
|
+
0, 0, 0
|
99
|
+
};
|
100
|
+
|
101
|
+
static VALUE LibevQueue_allocate(VALUE klass) {
|
102
|
+
LibevQueue_t *queue;
|
103
|
+
|
104
|
+
queue = ALLOC(LibevQueue_t);
|
105
|
+
return TypedData_Wrap_Struct(klass, &LibevQueue_type, queue);
|
106
|
+
}
|
107
|
+
|
108
|
+
#define GetQueue(obj, queue) \
|
109
|
+
TypedData_Get_Struct((obj), LibevQueue_t, &LibevQueue_type, (queue))
|
110
|
+
|
111
|
+
static VALUE LibevQueue_initialize(VALUE self) {
|
112
|
+
LibevQueue_t *queue;
|
113
|
+
GetQueue(self, queue);
|
114
|
+
|
115
|
+
queue->items = rb_ary_new();
|
116
|
+
async_queue_init(&queue->shift_queue);
|
117
|
+
|
118
|
+
return self;
|
119
|
+
}
|
120
|
+
|
121
|
+
VALUE LibevQueue_push(VALUE self, VALUE value) {
|
122
|
+
LibevQueue_t *queue;
|
123
|
+
struct async_watcher *watcher;
|
124
|
+
GetQueue(self, queue);
|
125
|
+
watcher = async_queue_pop(&queue->shift_queue);
|
126
|
+
if (watcher) {
|
127
|
+
ev_async_send(watcher->ev_loop, &watcher->async);
|
128
|
+
}
|
129
|
+
rb_ary_push(queue->items, value);
|
130
|
+
return self;
|
131
|
+
}
|
132
|
+
|
133
|
+
struct ev_loop *LibevAgent_ev_loop(VALUE self);
|
134
|
+
|
135
|
+
void async_queue_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, int revents) {
|
136
|
+
struct async_watcher *watcher = (struct async_watcher *)ev_async;
|
137
|
+
Fiber_make_runnable(watcher->fiber, Qnil);
|
138
|
+
}
|
139
|
+
|
140
|
+
VALUE LibevQueue_shift(VALUE self) {
|
141
|
+
LibevQueue_t *queue;
|
142
|
+
GetQueue(self, queue);
|
143
|
+
|
144
|
+
if (RARRAY_LEN(queue->items) == 0) {
|
145
|
+
struct async_watcher watcher;
|
146
|
+
VALUE agent = rb_ivar_get(rb_thread_current(), ID_ivar_agent);
|
147
|
+
VALUE switchpoint_result = Qnil;
|
148
|
+
|
149
|
+
watcher.ev_loop = LibevAgent_ev_loop(agent);
|
150
|
+
watcher.fiber = rb_fiber_current();
|
151
|
+
async_queue_push(&queue->shift_queue, &watcher);
|
152
|
+
ev_async_init(&watcher.async, async_queue_callback);
|
153
|
+
ev_async_start(watcher.ev_loop, &watcher.async);
|
154
|
+
|
155
|
+
switchpoint_result = Polyphony_switchpoint();
|
156
|
+
ev_async_stop(watcher.ev_loop, &watcher.async);
|
157
|
+
|
158
|
+
if (RTEST(rb_obj_is_kind_of(switchpoint_result, rb_eException))) {
|
159
|
+
async_queue_remove_by_fiber(&queue->shift_queue, watcher.fiber);
|
160
|
+
return rb_funcall(rb_mKernel, ID_raise, 1, switchpoint_result);
|
161
|
+
}
|
162
|
+
RB_GC_GUARD(watcher.fiber);
|
163
|
+
RB_GC_GUARD(agent);
|
164
|
+
RB_GC_GUARD(switchpoint_result);
|
165
|
+
}
|
166
|
+
|
167
|
+
return rb_ary_shift(queue->items);
|
168
|
+
}
|
169
|
+
|
170
|
+
VALUE LibevQueue_shift_each(VALUE self) {
|
171
|
+
LibevQueue_t *queue;
|
172
|
+
VALUE old_queue;
|
173
|
+
GetQueue(self, queue);
|
174
|
+
old_queue = queue->items;
|
175
|
+
queue->items = rb_ary_new();
|
176
|
+
|
177
|
+
if (rb_block_given_p()) {
|
178
|
+
long len = RARRAY_LEN(old_queue);
|
179
|
+
long i;
|
180
|
+
for (i = 0; i < len; i++) {
|
181
|
+
rb_yield(RARRAY_AREF(old_queue, i));
|
182
|
+
}
|
183
|
+
RB_GC_GUARD(old_queue);
|
184
|
+
return self;
|
185
|
+
}
|
186
|
+
else {
|
187
|
+
RB_GC_GUARD(old_queue);
|
188
|
+
return old_queue;
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
192
|
+
VALUE LibevQueue_empty_p(VALUE self) {
|
193
|
+
LibevQueue_t *queue;
|
194
|
+
GetQueue(self, queue);
|
195
|
+
|
196
|
+
return (RARRAY_LEN(queue->items) == 0) ? Qtrue : Qfalse;
|
197
|
+
}
|
198
|
+
|
199
|
+
void Init_LibevQueue() {
|
200
|
+
cLibevQueue = rb_define_class_under(mPolyphony, "LibevQueue", rb_cData);
|
201
|
+
rb_define_alloc_func(cLibevQueue, LibevQueue_allocate);
|
202
|
+
|
203
|
+
rb_define_method(cLibevQueue, "initialize", LibevQueue_initialize, 0);
|
204
|
+
rb_define_method(cLibevQueue, "push", LibevQueue_push, 1);
|
205
|
+
rb_define_method(cLibevQueue, "<<", LibevQueue_push, 1);
|
206
|
+
|
207
|
+
rb_define_method(cLibevQueue, "pop", LibevQueue_shift, 0);
|
208
|
+
rb_define_method(cLibevQueue, "shift", LibevQueue_shift, 0);
|
209
|
+
|
210
|
+
rb_define_method(cLibevQueue, "shift_each", LibevQueue_shift_each, 0);
|
211
|
+
rb_define_method(cLibevQueue, "empty?", LibevQueue_empty_p, 0);
|
212
|
+
}
|
213
|
+
|
214
|
+
|
@@ -1,8 +1,8 @@
|
|
1
|
-
#include "
|
1
|
+
#include "polyphony.h"
|
2
2
|
|
3
|
-
VALUE
|
4
|
-
int __gyro_current_generation__ = 0;
|
3
|
+
VALUE mPolyphony;
|
5
4
|
|
5
|
+
ID ID_await_no_raise;
|
6
6
|
ID ID_call;
|
7
7
|
ID ID_caller;
|
8
8
|
ID ID_clear;
|
@@ -25,7 +25,7 @@ ID ID_R;
|
|
25
25
|
ID ID_W;
|
26
26
|
ID ID_RW;
|
27
27
|
|
28
|
-
VALUE
|
28
|
+
VALUE Polyphony_snooze(VALUE self) {
|
29
29
|
VALUE ret;
|
30
30
|
VALUE fiber = rb_fiber_current();
|
31
31
|
|
@@ -36,15 +36,15 @@ VALUE Gyro_snooze(VALUE self) {
|
|
36
36
|
return ret;
|
37
37
|
}
|
38
38
|
|
39
|
-
static VALUE
|
39
|
+
static VALUE Polyphony_ref(VALUE self) {
|
40
40
|
return Thread_ref(rb_thread_current());
|
41
41
|
}
|
42
42
|
|
43
|
-
static VALUE
|
43
|
+
static VALUE Polyphony_unref(VALUE self) {
|
44
44
|
return Thread_unref(rb_thread_current());
|
45
45
|
}
|
46
46
|
|
47
|
-
static VALUE
|
47
|
+
static VALUE Polyphony_suspend(VALUE self) {
|
48
48
|
VALUE ret = Thread_switch_fiber(rb_thread_current());
|
49
49
|
|
50
50
|
TEST_RESUME_EXCEPTION(ret);
|
@@ -52,27 +52,22 @@ static VALUE Gyro_suspend(VALUE self) {
|
|
52
52
|
return ret;
|
53
53
|
}
|
54
54
|
|
55
|
-
VALUE
|
55
|
+
VALUE Polyphony_trace(VALUE self, VALUE enabled) {
|
56
56
|
__tracing_enabled__ = RTEST(enabled) ? 1 : 0;
|
57
57
|
return Qnil;
|
58
58
|
}
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
return Qnil;
|
63
|
-
}
|
60
|
+
void Init_Polyphony() {
|
61
|
+
mPolyphony = rb_define_module("Polyphony");
|
64
62
|
|
65
|
-
|
66
|
-
|
63
|
+
rb_define_singleton_method(mPolyphony, "ref", Polyphony_ref, 0);
|
64
|
+
rb_define_singleton_method(mPolyphony, "trace", Polyphony_trace, 1);
|
65
|
+
rb_define_singleton_method(mPolyphony, "unref", Polyphony_unref, 0);
|
67
66
|
|
68
|
-
|
69
|
-
|
70
|
-
rb_define_singleton_method(mGyro, "trace", Gyro_trace, 1);
|
71
|
-
rb_define_singleton_method(mGyro, "unref", Gyro_unref, 0);
|
72
|
-
|
73
|
-
rb_define_global_function("snooze", Gyro_snooze, 0);
|
74
|
-
rb_define_global_function("suspend", Gyro_suspend, 0);
|
67
|
+
rb_define_global_function("snooze", Polyphony_snooze, 0);
|
68
|
+
rb_define_global_function("suspend", Polyphony_suspend, 0);
|
75
69
|
|
70
|
+
ID_await_no_raise = rb_intern("await_no_raise");
|
76
71
|
ID_call = rb_intern("call");
|
77
72
|
ID_caller = rb_intern("caller");
|
78
73
|
ID_clear = rb_intern("clear");
|
@@ -91,8 +86,4 @@ void Init_Gyro() {
|
|
91
86
|
ID_size = rb_intern("size");
|
92
87
|
ID_switch_fiber = rb_intern("switch_fiber");
|
93
88
|
ID_transfer = rb_intern("transfer");
|
94
|
-
|
95
|
-
ID_R = rb_intern("r");
|
96
|
-
ID_RW = rb_intern("rw");
|
97
|
-
ID_W = rb_intern("w");
|
98
89
|
}
|
@@ -0,0 +1,90 @@
|
|
1
|
+
#ifndef RUBY_EV_H
|
2
|
+
#define RUBY_EV_H
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
#include "ruby/io.h"
|
6
|
+
#include "libev.h"
|
7
|
+
|
8
|
+
// debugging
|
9
|
+
#define OBJ_ID(obj) (NUM2LONG(rb_funcall(obj, rb_intern("object_id"), 0)))
|
10
|
+
#define INSPECT(...) (rb_funcall(rb_cObject, rb_intern("p"), __VA_ARGS__))
|
11
|
+
#define FIBER_TRACE(...) if (__tracing_enabled__) { \
|
12
|
+
rb_funcall(rb_cObject, ID_fiber_trace, __VA_ARGS__); \
|
13
|
+
}
|
14
|
+
|
15
|
+
#define TEST_EXCEPTION(ret) (RTEST(rb_obj_is_kind_of(ret, rb_eException)))
|
16
|
+
|
17
|
+
#define TEST_RESUME_EXCEPTION(ret) if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) { \
|
18
|
+
return rb_funcall(rb_mKernel, ID_raise, 1, ret); \
|
19
|
+
}
|
20
|
+
|
21
|
+
extern VALUE mPolyphony;
|
22
|
+
extern VALUE cLibevQueue;
|
23
|
+
extern VALUE cEvent;
|
24
|
+
|
25
|
+
extern ID ID_await_no_raise;
|
26
|
+
extern ID ID_call;
|
27
|
+
extern ID ID_caller;
|
28
|
+
extern ID ID_clear;
|
29
|
+
extern ID ID_each;
|
30
|
+
extern ID ID_fiber_trace;
|
31
|
+
extern ID ID_inspect;
|
32
|
+
extern ID ID_ivar_agent;
|
33
|
+
extern ID ID_ivar_running;
|
34
|
+
extern ID ID_ivar_thread;
|
35
|
+
extern ID ID_new;
|
36
|
+
extern ID ID_raise;
|
37
|
+
extern ID ID_runnable;
|
38
|
+
extern ID ID_runnable_value;
|
39
|
+
extern ID ID_signal;
|
40
|
+
extern ID ID_size;
|
41
|
+
extern ID ID_switch_fiber;
|
42
|
+
extern ID ID_transfer;
|
43
|
+
|
44
|
+
extern VALUE SYM_fiber_create;
|
45
|
+
extern VALUE SYM_fiber_ev_loop_enter;
|
46
|
+
extern VALUE SYM_fiber_ev_loop_leave;
|
47
|
+
extern VALUE SYM_fiber_run;
|
48
|
+
extern VALUE SYM_fiber_schedule;
|
49
|
+
extern VALUE SYM_fiber_switchpoint;
|
50
|
+
extern VALUE SYM_fiber_terminate;
|
51
|
+
|
52
|
+
extern int __tracing_enabled__;
|
53
|
+
|
54
|
+
enum {
|
55
|
+
FIBER_STATE_NOT_SCHEDULED = 0,
|
56
|
+
FIBER_STATE_WAITING = 1,
|
57
|
+
FIBER_STATE_SCHEDULED = 2
|
58
|
+
};
|
59
|
+
|
60
|
+
// watcher flags
|
61
|
+
enum {
|
62
|
+
// a watcher's active field will be set to this after fork
|
63
|
+
GYRO_WATCHER_POST_FORK = 0xFF
|
64
|
+
};
|
65
|
+
|
66
|
+
VALUE Fiber_auto_watcher(VALUE self);
|
67
|
+
void Fiber_make_runnable(VALUE fiber, VALUE value);
|
68
|
+
|
69
|
+
VALUE Polyphony_switchpoint();
|
70
|
+
|
71
|
+
VALUE LibevAgent_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE queue);
|
72
|
+
VALUE LibevAgent_break(VALUE self);
|
73
|
+
VALUE LibevAgent_pending_count(VALUE self);
|
74
|
+
VALUE LibevAgent_wait_io(VALUE self, VALUE io, VALUE write);
|
75
|
+
|
76
|
+
VALUE Polyphony_snooze(VALUE self);
|
77
|
+
|
78
|
+
VALUE Polyphony_Queue_push(VALUE self, VALUE value);
|
79
|
+
|
80
|
+
VALUE Thread_post_fork(VALUE thread);
|
81
|
+
VALUE Thread_ref(VALUE thread);
|
82
|
+
VALUE Thread_schedule_fiber(VALUE thread, VALUE fiber, VALUE value);
|
83
|
+
VALUE Thread_switch_fiber(VALUE thread);
|
84
|
+
VALUE Thread_unref(VALUE thread);
|
85
|
+
|
86
|
+
int io_setstrbuf(VALUE *str, long len);
|
87
|
+
void io_set_read_length(VALUE str, long n, int shrinkable);
|
88
|
+
VALUE io_enc_str(VALUE str, rb_io_t *fptr);
|
89
|
+
|
90
|
+
#endif /* RUBY_EV_H */
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#include "polyphony.h"
|
2
|
+
|
3
|
+
void Init_Fiber();
|
4
|
+
void Init_Polyphony();
|
5
|
+
void Init_LibevAgent();
|
6
|
+
void Init_LibevQueue();
|
7
|
+
void Init_Socket();
|
8
|
+
void Init_Thread();
|
9
|
+
void Init_Tracing();
|
10
|
+
|
11
|
+
void Init_polyphony_ext() {
|
12
|
+
ev_set_allocator(xrealloc);
|
13
|
+
|
14
|
+
Init_Polyphony();
|
15
|
+
Init_LibevAgent();
|
16
|
+
Init_LibevQueue();
|
17
|
+
|
18
|
+
Init_Fiber();
|
19
|
+
Init_Socket();
|
20
|
+
Init_Thread();
|
21
|
+
|
22
|
+
Init_Tracing();
|
23
|
+
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#include "
|
1
|
+
#include "polyphony.h"
|
2
2
|
#include <sys/socket.h>
|
3
3
|
|
4
4
|
static VALUE cTCPSocket;
|
@@ -71,7 +71,7 @@ static VALUE BasicSocket_send(int argc, VALUE *argv, VALUE sock) {
|
|
71
71
|
ssize_t n;
|
72
72
|
rb_blocking_function_t *func;
|
73
73
|
const char *funcname;
|
74
|
-
VALUE
|
74
|
+
VALUE agent = Qnil;
|
75
75
|
|
76
76
|
rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
|
77
77
|
|
@@ -94,9 +94,9 @@ static VALUE BasicSocket_send(int argc, VALUE *argv, VALUE sock) {
|
|
94
94
|
arg.fd = fptr->fd;
|
95
95
|
arg.flags = NUM2INT(flags);
|
96
96
|
while ((n = (ssize_t)func(&arg)) < 0) {
|
97
|
-
if (NIL_P(
|
98
|
-
|
99
|
-
|
97
|
+
if (NIL_P(agent))
|
98
|
+
agent = rb_ivar_get(rb_thread_current(), ID_ivar_agent);
|
99
|
+
LibevAgent_wait_io(agent, sock, Qtrue);
|
100
100
|
}
|
101
101
|
return SSIZET2NUM(n);
|
102
102
|
}
|
@@ -112,7 +112,7 @@ static VALUE BasicSocket_recv(int argc, VALUE *argv, VALUE sock) {
|
|
112
112
|
rb_io_t *fptr;
|
113
113
|
long n;
|
114
114
|
int shrinkable;
|
115
|
-
VALUE
|
115
|
+
VALUE agent = Qnil;
|
116
116
|
|
117
117
|
|
118
118
|
VALUE str = argc >= 3 ? argv[2] : Qnil;
|
@@ -131,9 +131,9 @@ static VALUE BasicSocket_recv(int argc, VALUE *argv, VALUE sock) {
|
|
131
131
|
if (n < 0) {
|
132
132
|
int e = errno;
|
133
133
|
if (e == EWOULDBLOCK || e == EAGAIN) {
|
134
|
-
if (NIL_P(
|
135
|
-
|
136
|
-
|
134
|
+
if (NIL_P(agent))
|
135
|
+
agent = rb_ivar_get(rb_thread_current(), ID_ivar_agent);
|
136
|
+
LibevAgent_wait_io(agent, sock, Qnil);
|
137
137
|
}
|
138
138
|
else
|
139
139
|
rb_syserr_fail(e, strerror(e));
|
@@ -157,7 +157,7 @@ static VALUE Socket_accept(VALUE sock) {
|
|
157
157
|
int fd;
|
158
158
|
struct sockaddr addr;
|
159
159
|
socklen_t len = (socklen_t)sizeof addr;
|
160
|
-
VALUE
|
160
|
+
VALUE agent = Qnil;
|
161
161
|
|
162
162
|
GetOpenFile(sock, fptr);
|
163
163
|
rb_io_set_nonblock(fptr);
|
@@ -168,9 +168,9 @@ static VALUE Socket_accept(VALUE sock) {
|
|
168
168
|
if (fd < 0) {
|
169
169
|
int e = errno;
|
170
170
|
if (e == EWOULDBLOCK || e == EAGAIN) {
|
171
|
-
if (NIL_P(
|
172
|
-
|
173
|
-
|
171
|
+
if (NIL_P(agent))
|
172
|
+
agent = rb_ivar_get(rb_thread_current(), ID_ivar_agent);
|
173
|
+
LibevAgent_wait_io(agent, sock, Qnil);
|
174
174
|
}
|
175
175
|
else
|
176
176
|
rb_syserr_fail(e, strerror(e));
|
@@ -207,7 +207,7 @@ void Init_Socket() {
|
|
207
207
|
|
208
208
|
cSocket = rb_const_get(rb_cObject, rb_intern("Socket"));
|
209
209
|
|
210
|
-
rb_define_method(cSocket, "accept", Socket_accept, 0);
|
210
|
+
// rb_define_method(cSocket, "accept", Socket_accept, 0);
|
211
211
|
|
212
212
|
cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
213
213
|
}
|