polyphony 0.40 → 0.41
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|