polyphony 0.40 → 0.41

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +11 -2
  3. data/.gitignore +2 -2
  4. data/.rubocop.yml +30 -0
  5. data/CHANGELOG.md +6 -2
  6. data/Gemfile.lock +9 -6
  7. data/Rakefile +2 -2
  8. data/TODO.md +18 -97
  9. data/docs/_includes/head.html +40 -0
  10. data/docs/_includes/nav.html +5 -5
  11. data/docs/api-reference/fiber.md +2 -2
  12. data/docs/main-concepts/design-principles.md +67 -9
  13. data/docs/main-concepts/extending.md +1 -1
  14. data/examples/core/xx-agent.rb +102 -0
  15. data/examples/core/xx-sleeping.rb +14 -6
  16. data/examples/io/xx-irb.rb +1 -1
  17. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +7 -6
  18. data/examples/performance/thread-vs-fiber/polyphony_server.rb +14 -25
  19. data/ext/{gyro → polyphony}/extconf.rb +2 -2
  20. data/ext/{gyro → polyphony}/fiber.c +15 -19
  21. data/ext/{gyro → polyphony}/libev.c +0 -0
  22. data/ext/{gyro → polyphony}/libev.h +0 -0
  23. data/ext/polyphony/libev_agent.c +503 -0
  24. data/ext/polyphony/libev_queue.c +214 -0
  25. data/ext/{gyro/gyro.c → polyphony/polyphony.c} +16 -25
  26. data/ext/polyphony/polyphony.h +90 -0
  27. data/ext/polyphony/polyphony_ext.c +23 -0
  28. data/ext/{gyro → polyphony}/socket.c +14 -14
  29. data/ext/{gyro → polyphony}/thread.c +32 -115
  30. data/ext/{gyro → polyphony}/tracing.c +1 -1
  31. data/lib/polyphony.rb +16 -12
  32. data/lib/polyphony/adapters/irb.rb +1 -1
  33. data/lib/polyphony/adapters/postgres.rb +6 -5
  34. data/lib/polyphony/adapters/process.rb +5 -5
  35. data/lib/polyphony/adapters/trace.rb +28 -28
  36. data/lib/polyphony/core/channel.rb +3 -3
  37. data/lib/polyphony/core/exceptions.rb +1 -1
  38. data/lib/polyphony/core/global_api.rb +11 -9
  39. data/lib/polyphony/core/resource_pool.rb +3 -3
  40. data/lib/polyphony/core/sync.rb +2 -2
  41. data/lib/polyphony/core/thread_pool.rb +6 -6
  42. data/lib/polyphony/core/throttler.rb +13 -6
  43. data/lib/polyphony/event.rb +27 -0
  44. data/lib/polyphony/extensions/core.rb +20 -11
  45. data/lib/polyphony/extensions/fiber.rb +4 -4
  46. data/lib/polyphony/extensions/io.rb +56 -26
  47. data/lib/polyphony/extensions/openssl.rb +4 -8
  48. data/lib/polyphony/extensions/socket.rb +27 -9
  49. data/lib/polyphony/extensions/thread.rb +16 -9
  50. data/lib/polyphony/net.rb +9 -9
  51. data/lib/polyphony/version.rb +1 -1
  52. data/polyphony.gemspec +2 -2
  53. data/test/helper.rb +12 -1
  54. data/test/test_agent.rb +77 -0
  55. data/test/{test_async.rb → test_event.rb} +13 -7
  56. data/test/test_ext.rb +25 -4
  57. data/test/test_fiber.rb +19 -10
  58. data/test/test_global_api.rb +4 -4
  59. data/test/test_io.rb +46 -24
  60. data/test/test_queue.rb +74 -0
  61. data/test/test_signal.rb +3 -40
  62. data/test/test_socket.rb +33 -0
  63. data/test/test_thread.rb +37 -16
  64. data/test/test_trace.rb +6 -5
  65. metadata +24 -24
  66. data/ext/gyro/async.c +0 -132
  67. data/ext/gyro/child.c +0 -108
  68. data/ext/gyro/gyro.h +0 -158
  69. data/ext/gyro/gyro_ext.c +0 -33
  70. data/ext/gyro/io.c +0 -457
  71. data/ext/gyro/queue.c +0 -146
  72. data/ext/gyro/selector.c +0 -205
  73. data/ext/gyro/signal.c +0 -99
  74. data/ext/gyro/timer.c +0 -115
  75. data/test/test_timer.rb +0 -56
@@ -1,33 +0,0 @@
1
- #include "gyro.h"
2
-
3
- void Init_Fiber();
4
- void Init_Gyro();
5
- void Init_Gyro_Async();
6
- void Init_Gyro_Child();
7
- void Init_Gyro_IO();
8
- void Init_Gyro_Queue();
9
- void Init_Gyro_Selector();
10
- void Init_Gyro_Signal();
11
- void Init_Gyro_Timer();
12
- void Init_Socket();
13
- void Init_Thread();
14
- void Init_Tracing();
15
-
16
- void Init_gyro_ext() {
17
- ev_set_allocator(xrealloc);
18
-
19
- Init_Gyro();
20
- Init_Gyro_Async();
21
- Init_Gyro_Child();
22
- Init_Gyro_IO();
23
- Init_Gyro_Queue();
24
- Init_Gyro_Selector();
25
- Init_Gyro_Signal();
26
- Init_Gyro_Timer();
27
-
28
- Init_Fiber();
29
- Init_Socket();
30
- Init_Thread();
31
-
32
- Init_Tracing();
33
- }
@@ -1,457 +0,0 @@
1
- #include "gyro.h"
2
-
3
- #ifdef GetReadFile
4
- # define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
5
- #else
6
- # define FPTR_TO_FD(fptr) fptr->fd
7
- #endif /* GetReadFile */
8
-
9
- struct Gyro_IO {
10
- GYRO_WATCHER_DECL(ev_io);
11
- };
12
-
13
- VALUE cGyro_IO = Qnil;
14
-
15
- ID ID_ivar_read_watcher;
16
- ID ID_ivar_write_watcher;
17
- VALUE SYM_r;
18
- VALUE SYM_w;
19
-
20
- static void Gyro_IO_mark(void *ptr) {
21
- struct Gyro_IO *io = ptr;
22
- GYRO_WATCHER_MARK(io);
23
- }
24
-
25
- static void Gyro_IO_free(void *ptr) {
26
- struct Gyro_IO *io = ptr;
27
- GYRO_WATCHER_FREE(io);
28
- }
29
-
30
- static size_t Gyro_IO_size(const void *ptr) {
31
- return sizeof(struct Gyro_IO);
32
- }
33
-
34
- static const rb_data_type_t Gyro_IO_type = {
35
- "Gyro_IO",
36
- {Gyro_IO_mark, Gyro_IO_free, Gyro_IO_size,},
37
- 0, 0, 0
38
- };
39
-
40
- static VALUE Gyro_IO_allocate(VALUE klass) {
41
- struct Gyro_IO *io = ALLOC(struct Gyro_IO);
42
-
43
- return TypedData_Wrap_Struct(klass, &Gyro_IO_type, io);
44
- }
45
-
46
- inline void io_activate(struct Gyro_IO *io) {
47
- if (io->active) return;
48
-
49
- io->active = 1;
50
- io->fiber = rb_fiber_current();
51
- io->selector = Thread_current_event_selector();
52
- io->ev_loop = Gyro_Selector_ev_loop(io->selector);
53
- Gyro_Selector_add_active_watcher(io->selector, io->self);
54
- ev_io_start(io->ev_loop, &io->ev_io);
55
- }
56
-
57
- inline void io_deactivate(struct Gyro_IO *io) {
58
- if (!io->active) return;
59
-
60
- ev_io_stop(io->ev_loop, &io->ev_io);
61
- Gyro_Selector_remove_active_watcher(io->selector, io->self);
62
- io->active = 0;
63
- io->ev_loop = 0;
64
- io->selector = Qnil;
65
- io->fiber = Qnil;
66
- }
67
-
68
- void Gyro_IO_callback(struct ev_loop *ev_loop, struct ev_io *ev_io, int revents) {
69
- struct Gyro_IO *io = (struct Gyro_IO*)ev_io;
70
-
71
- Fiber_make_runnable(io->fiber, Qnil);
72
- io_deactivate(io);
73
- }
74
-
75
- static int Gyro_IO_symbol2event_mask(VALUE sym) {
76
- ID sym_id;
77
-
78
- if (NIL_P(sym)) {
79
- return 0;
80
- }
81
-
82
- sym_id = SYM2ID(sym);
83
-
84
- if(sym_id == ID_R) {
85
- return EV_READ;
86
- } else if(sym_id == ID_W) {
87
- return EV_WRITE;
88
- } else if(sym_id == ID_RW) {
89
- return EV_READ | EV_WRITE;
90
- } else {
91
- rb_raise(rb_eArgError, "invalid interest type %s (must be :r, :w, or :rw)",
92
- RSTRING_PTR(rb_funcall(sym, ID_inspect, 0)));
93
- }
94
- }
95
-
96
- #define GetGyro_IO(obj, io) TypedData_Get_Struct((obj), struct Gyro_IO, &Gyro_IO_type, (io))
97
-
98
- static const char * S_IO = "IO";
99
- static const char * S_to_io = "to_io";
100
-
101
- static VALUE Gyro_IO_initialize(VALUE self, VALUE io_obj, VALUE event_mask) {
102
- struct Gyro_IO *io;
103
- rb_io_t *fptr;
104
- int fd;
105
- int events;
106
-
107
- GetGyro_IO(self, io);
108
- GYRO_WATCHER_INITIALIZE(io, self);
109
- if (NIL_P(io_obj)) {
110
- fd = 0;
111
- }
112
- else {
113
- GetOpenFile(rb_convert_type(io_obj, T_FILE, S_IO, S_to_io), fptr);
114
- fd = FPTR_TO_FD(fptr);
115
- }
116
- events = Gyro_IO_symbol2event_mask(event_mask);
117
- ev_io_init(&io->ev_io, Gyro_IO_callback, fd, events);
118
-
119
- return Qnil;
120
- }
121
-
122
- VALUE Gyro_IO_await(VALUE self) {
123
- struct Gyro_IO *io;
124
- VALUE ret;
125
- GetGyro_IO(self, io);
126
-
127
- io_activate(io);
128
- ret = Gyro_switchpoint();
129
- io_deactivate(io);
130
-
131
- TEST_RESUME_EXCEPTION(ret);
132
- RB_GC_GUARD(ret);
133
- return ret;
134
- }
135
-
136
- VALUE Gyro_IO_auto_io(int fd, int events) {
137
- VALUE watcher = Fiber_auto_io(rb_fiber_current());
138
- struct Gyro_IO *io;
139
- GetGyro_IO(watcher, io);
140
-
141
- ev_io_set(&io->ev_io, fd, events);
142
-
143
- RB_GC_GUARD(watcher);
144
- return watcher;
145
- }
146
-
147
-
148
- //////////////////////////////////////////////////////////////////////
149
- //////////////////////////////////////////////////////////////////////
150
- // the following is copied verbatim from the Ruby source code (io.c)
151
- struct io_internal_read_struct {
152
- int fd;
153
- int nonblock;
154
- void *buf;
155
- size_t capa;
156
- };
157
-
158
- int io_setstrbuf(VALUE *str, long len) {
159
- #ifdef _WIN32
160
- len = (len + 1) & ~1L; /* round up for wide char */
161
- #endif
162
- if (NIL_P(*str)) {
163
- *str = rb_str_new(0, len);
164
- return 1;
165
- }
166
- else {
167
- VALUE s = StringValue(*str);
168
- long clen = RSTRING_LEN(s);
169
- if (clen >= len) {
170
- rb_str_modify(s);
171
- return 0;
172
- }
173
- len -= clen;
174
- }
175
- rb_str_modify_expand(*str, len);
176
- return 0;
177
- }
178
-
179
- #define MAX_REALLOC_GAP 4096
180
- static void io_shrink_read_string(VALUE str, long n) {
181
- if (rb_str_capacity(str) - n > MAX_REALLOC_GAP) {
182
- rb_str_resize(str, n);
183
- }
184
- }
185
-
186
- void io_set_read_length(VALUE str, long n, int shrinkable) {
187
- if (RSTRING_LEN(str) != n) {
188
- rb_str_modify(str);
189
- rb_str_set_len(str, n);
190
- if (shrinkable) io_shrink_read_string(str, n);
191
- }
192
- }
193
-
194
- static rb_encoding* io_read_encoding(rb_io_t *fptr) {
195
- if (fptr->encs.enc) {
196
- return fptr->encs.enc;
197
- }
198
- return rb_default_external_encoding();
199
- }
200
-
201
- VALUE io_enc_str(VALUE str, rb_io_t *fptr) {
202
- OBJ_TAINT(str);
203
- rb_enc_associate(str, io_read_encoding(fptr));
204
- return str;
205
- }
206
-
207
- //////////////////////////////////////////////////////////////////////
208
- //////////////////////////////////////////////////////////////////////
209
-
210
- static VALUE IO_read(int argc, VALUE *argv, VALUE io) {
211
- VALUE underlying_io = rb_iv_get(io, "@io");
212
- if (!NIL_P(underlying_io)) io = underlying_io;
213
-
214
- long len = argc == 1 ? NUM2LONG(argv[0]) : (1 << 30);
215
-
216
- rb_io_t *fptr;
217
- long n;
218
- int shrinkable;
219
- VALUE read_watcher = Qnil;
220
-
221
- if (len < 0) {
222
- rb_raise(rb_eArgError, "negative length %ld given", len);
223
- }
224
-
225
- VALUE str = argc >= 2 ? argv[1] : Qnil;
226
-
227
- shrinkable = io_setstrbuf(&str, len);
228
- OBJ_TAINT(str);
229
- GetOpenFile(io, fptr);
230
- rb_io_check_byte_readable(fptr);
231
- rb_io_set_nonblock(fptr);
232
-
233
- if (len == 0)
234
- return str;
235
-
236
- char *buf = RSTRING_PTR(str);
237
- long total = 0;
238
-
239
- while (1) {
240
- n = read(fptr->fd, buf, len);
241
- if (n < 0) {
242
- int e = errno;
243
- if ((e == EWOULDBLOCK || e == EAGAIN)) {
244
- if (NIL_P(read_watcher))
245
- read_watcher = Gyro_IO_auto_io(fptr->fd, EV_READ);
246
- Gyro_IO_await(read_watcher);
247
- }
248
- else
249
- rb_syserr_fail(e, strerror(e));
250
- // rb_syserr_fail_path(e, fptr->pathv);
251
- }
252
- else if (n == 0)
253
- break;
254
- else {
255
- total = total + n;
256
- buf += n;
257
- len -= n;
258
- if (len == 0)
259
- break;
260
- }
261
- }
262
-
263
- if (total == 0)
264
- return Qnil;
265
-
266
- io_set_read_length(str, total, shrinkable);
267
- io_enc_str(str, fptr);
268
-
269
- return str;
270
- }
271
-
272
- #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
273
- #define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(size_t)(n))
274
-
275
- static long
276
- read_buffered_data(char *ptr, long len, rb_io_t *fptr)
277
- {
278
- int n;
279
-
280
- n = READ_DATA_PENDING_COUNT(fptr);
281
- if (n <= 0) return 0;
282
- if (n > len) n = (int)len;
283
- MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
284
- fptr->rbuf.off += n;
285
- fptr->rbuf.len -= n;
286
- return n;
287
- }
288
-
289
- static VALUE IO_readpartial(int argc, VALUE *argv, VALUE io) {
290
- VALUE underlying_io = rb_iv_get(io, "@io");
291
- if (!NIL_P(underlying_io)) io = underlying_io;
292
-
293
- long len = argc >= 1 ? NUM2LONG(argv[0]) : 8192;
294
-
295
- rb_io_t *fptr;
296
- long n;
297
- int shrinkable;
298
- VALUE read_watcher = Qnil;
299
-
300
- if (len < 0) {
301
- rb_raise(rb_eArgError, "negative length %ld given", len);
302
- }
303
-
304
- VALUE str = argc >= 2 ? argv[1] : Qnil;
305
-
306
- shrinkable = io_setstrbuf(&str, len);
307
- OBJ_TAINT(str);
308
- GetOpenFile(io, fptr);
309
- rb_io_set_nonblock(fptr);
310
- rb_io_check_byte_readable(fptr);
311
-
312
- if (len == 0)
313
- return str;
314
-
315
- n = read_buffered_data(RSTRING_PTR(str), len, fptr);
316
- if (n <= 0) {
317
- while (1) {
318
- n = read(fptr->fd, RSTRING_PTR(str), len);
319
- if (n < 0) {
320
- int e = errno;
321
- if (e == EWOULDBLOCK || e == EAGAIN) {
322
- if (NIL_P(read_watcher))
323
- read_watcher = Gyro_IO_auto_io(fptr->fd, EV_READ);
324
- Gyro_IO_await(read_watcher);
325
- }
326
- else
327
- rb_syserr_fail(e, strerror(e));
328
- // rb_syserr_fail_path(e, fptr->pathv);
329
- }
330
- else
331
- break;
332
- }
333
- }
334
-
335
- io_set_read_length(str, n, shrinkable);
336
- io_enc_str(str, fptr);
337
-
338
- // ensure yielding to reactor if haven't yielded while reading
339
- // if (read_watcher == Qnil) {
340
- // Gyro_snooze(Qnil);
341
- // }
342
-
343
- if (n == 0)
344
- return Qnil;
345
-
346
- return str;
347
- }
348
-
349
- static VALUE IO_write(int argc, VALUE *argv, VALUE io) {
350
- VALUE underlying_io = rb_iv_get(io, "@io");
351
- if (!NIL_P(underlying_io)) io = underlying_io;
352
-
353
- long i;
354
- long n;
355
- long total = 0;
356
- rb_io_t *fptr;
357
-
358
- io = rb_io_get_write_io(io);
359
- VALUE write_watcher = Qnil;
360
-
361
- GetOpenFile(io, fptr);
362
- rb_io_check_writable(fptr);
363
- rb_io_set_nonblock(fptr);
364
-
365
- for (i = 0; i < argc; i++) {
366
- VALUE str = argv[i];
367
- if (!RB_TYPE_P(str, T_STRING))
368
- str = rb_obj_as_string(str);
369
- char *buf = RSTRING_PTR(str);
370
- long len = RSTRING_LEN(str);
371
- RB_GC_GUARD(str);
372
- while (1) {
373
- n = write(fptr->fd, buf, len);
374
-
375
- if (n < 0) {
376
- int e = errno;
377
- if (e == EWOULDBLOCK || e == EAGAIN) {
378
- if (NIL_P(write_watcher))
379
- write_watcher = Gyro_IO_auto_io(fptr->fd, EV_WRITE);
380
- Gyro_IO_await(write_watcher);
381
- }
382
- else {
383
- rb_syserr_fail(e, strerror(e));
384
- // rb_syserr_fail_path(e, fptr->pathv);
385
- }
386
- }
387
- else {
388
- total += n;
389
- if (n < len) {
390
- buf += n;
391
- len -= n;
392
- }
393
- else break;
394
- }
395
- }
396
- }
397
-
398
- // ensure yielding to reactor if haven't yielded while writing
399
- // if (write_watcher == Qnil) {
400
- // Gyro_snooze(Qnil);
401
- // }
402
-
403
- return LONG2FIX(total);
404
- }
405
-
406
- static VALUE IO_write_chevron(VALUE io, VALUE str) {
407
- IO_write(1, &str, io);
408
- return io;
409
- }
410
-
411
- VALUE IO_read_watcher(VALUE self) {
412
- VALUE watcher = rb_ivar_get(self, ID_ivar_read_watcher);
413
- if (watcher == Qnil) {
414
- VALUE args[] = {self, SYM_r};
415
- watcher = rb_class_new_instance(2, args, cGyro_IO);
416
- rb_ivar_set(self, ID_ivar_read_watcher, watcher);
417
- }
418
- return watcher;
419
- }
420
-
421
- VALUE IO_write_watcher(VALUE self) {
422
- VALUE watcher = rb_ivar_get(self, ID_ivar_write_watcher);
423
- if (watcher == Qnil) {
424
- VALUE args[] = {self, SYM_w};
425
- watcher = rb_class_new_instance(2, args, cGyro_IO);
426
- rb_ivar_set(self, ID_ivar_write_watcher, watcher);
427
- }
428
- return watcher;
429
- }
430
-
431
- void Init_Gyro_IO() {
432
- VALUE cIO;
433
-
434
- cGyro_IO = rb_define_class_under(mGyro, "IO", rb_cData);
435
- rb_define_alloc_func(cGyro_IO, Gyro_IO_allocate);
436
-
437
- rb_define_method(cGyro_IO, "initialize", Gyro_IO_initialize, 2);
438
- rb_define_method(cGyro_IO, "await", Gyro_IO_await, 0);
439
-
440
- cIO = rb_const_get(rb_cObject, rb_intern("IO"));
441
- // rb_define_method(cIO, "gets", IO_gets, -1);
442
- rb_define_method(cIO, "read", IO_read, -1);
443
- rb_define_method(cIO, "readpartial", IO_readpartial, -1);
444
- rb_define_method(cIO, "write", IO_write, -1);
445
- rb_define_method(cIO, "write_nonblock", IO_write, -1);
446
- rb_define_method(cIO, "<<", IO_write_chevron, 1);
447
- rb_define_method(cIO, "read_watcher", IO_read_watcher, 0);
448
- rb_define_method(cIO, "write_watcher", IO_write_watcher, 0);
449
-
450
- ID_ivar_read_watcher = rb_intern("@read_watcher");
451
- ID_ivar_write_watcher = rb_intern("@write_watcher");
452
- SYM_r = ID2SYM(rb_intern("r"));
453
- SYM_w = ID2SYM(rb_intern("w"));
454
-
455
- rb_global_variable(&SYM_r);
456
- rb_global_variable(&SYM_w);
457
- }