polyphony 0.43.11 → 0.45.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -1
  3. data/CHANGELOG.md +40 -0
  4. data/Gemfile.lock +18 -8
  5. data/Rakefile +1 -1
  6. data/TODO.md +22 -9
  7. data/docs/_posts/2020-07-26-polyphony-0.44.md +77 -0
  8. data/docs/api-reference/thread.md +1 -1
  9. data/docs/getting-started/overview.md +14 -14
  10. data/docs/getting-started/tutorial.md +1 -1
  11. data/examples/adapters/redis_client.rb +3 -1
  12. data/examples/adapters/redis_pubsub_perf.rb +11 -8
  13. data/examples/adapters/sequel_mysql.rb +23 -0
  14. data/examples/adapters/sequel_mysql_pool.rb +33 -0
  15. data/examples/adapters/sequel_pg.rb +24 -0
  16. data/examples/core/{02-awaiting-fibers.rb → await.rb} +0 -0
  17. data/examples/core/{xx-channels.rb → channels.rb} +0 -0
  18. data/examples/core/deferring-an-operation.rb +16 -0
  19. data/examples/core/{xx-erlang-style-genserver.rb → erlang-style-genserver.rb} +16 -9
  20. data/examples/core/{xx-forking.rb → forking.rb} +1 -1
  21. data/examples/core/handling-signals.rb +11 -0
  22. data/examples/core/{03-interrupting.rb → interrupt.rb} +0 -0
  23. data/examples/core/{xx-pingpong.rb → pingpong.rb} +7 -5
  24. data/examples/core/{xx-recurrent-timer.rb → recurrent-timer.rb} +1 -1
  25. data/examples/core/{xx-resource_delegate.rb → resource_delegate.rb} +3 -4
  26. data/examples/core/{01-spinning-up-fibers.rb → spin.rb} +1 -1
  27. data/examples/core/{xx-spin_error_backtrace.rb → spin_error_backtrace.rb} +1 -1
  28. data/examples/core/{xx-supervise-process.rb → supervise-process.rb} +8 -5
  29. data/examples/core/supervisor.rb +20 -0
  30. data/examples/core/{xx-thread-sleep.rb → thread-sleep.rb} +0 -0
  31. data/examples/core/{xx-thread_pool.rb → thread_pool.rb} +0 -0
  32. data/examples/core/{xx-throttling.rb → throttling.rb} +0 -0
  33. data/examples/core/{xx-timeout.rb → timeout.rb} +0 -0
  34. data/examples/core/{xx-using-a-mutex.rb → using-a-mutex.rb} +0 -0
  35. data/examples/core/{xx-worker-thread.rb → worker-thread.rb} +2 -2
  36. data/examples/io/{xx-backticks.rb → backticks.rb} +0 -0
  37. data/examples/io/{xx-echo_client.rb → echo_client.rb} +1 -1
  38. data/examples/io/{xx-echo_client_from_stdin.rb → echo_client_from_stdin.rb} +2 -2
  39. data/examples/io/{xx-echo_pipe.rb → echo_pipe.rb} +1 -1
  40. data/examples/io/{xx-echo_server.rb → echo_server.rb} +0 -0
  41. data/examples/io/{xx-echo_server_with_timeout.rb → echo_server_with_timeout.rb} +1 -1
  42. data/examples/io/{xx-echo_stdin.rb → echo_stdin.rb} +0 -0
  43. data/examples/io/{xx-happy-eyeballs.rb → happy-eyeballs.rb} +0 -0
  44. data/examples/io/{xx-httparty.rb → httparty.rb} +4 -13
  45. data/examples/io/{xx-irb.rb → irb.rb} +0 -0
  46. data/examples/io/{xx-net-http.rb → net-http.rb} +0 -0
  47. data/examples/io/{xx-open.rb → open.rb} +0 -0
  48. data/examples/io/pry.rb +18 -0
  49. data/examples/io/rack_server.rb +71 -0
  50. data/examples/io/raw.rb +14 -0
  51. data/examples/io/reline.rb +18 -0
  52. data/examples/io/{xx-system.rb → system.rb} +1 -1
  53. data/examples/io/{xx-tcpserver.rb → tcpserver.rb} +0 -0
  54. data/examples/io/{xx-tcpsocket.rb → tcpsocket.rb} +0 -0
  55. data/examples/io/tunnel.rb +6 -1
  56. data/examples/io/{xx-zip.rb → zip.rb} +0 -0
  57. data/examples/performance/fiber_transfer.rb +2 -1
  58. data/examples/performance/fs_read.rb +5 -6
  59. data/examples/{io/xx-switch.rb → performance/switch.rb} +2 -1
  60. data/examples/performance/thread-vs-fiber/{xx-httparty_multi.rb → httparty_multi.rb} +3 -4
  61. data/examples/performance/thread-vs-fiber/{xx-httparty_threaded.rb → httparty_threaded.rb} +0 -0
  62. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +1 -1
  63. data/examples/performance/thread-vs-fiber/polyphony_server.rb +1 -1
  64. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +1 -1
  65. data/examples/performance/thread-vs-fiber/threaded_server.rb +1 -5
  66. data/examples/performance/thread_pool_perf.rb +6 -7
  67. data/ext/polyphony/backend.h +40 -0
  68. data/ext/polyphony/event.c +3 -3
  69. data/ext/polyphony/extconf.rb +1 -1
  70. data/ext/polyphony/fiber.c +66 -6
  71. data/ext/polyphony/{libev_agent.c → libev_backend.c} +237 -238
  72. data/ext/polyphony/polyphony.c +3 -3
  73. data/ext/polyphony/polyphony.h +15 -20
  74. data/ext/polyphony/polyphony_ext.c +3 -4
  75. data/ext/polyphony/queue.c +5 -6
  76. data/ext/polyphony/ring_buffer.c +0 -1
  77. data/ext/polyphony/thread.c +36 -33
  78. data/lib/polyphony.rb +26 -39
  79. data/lib/polyphony/adapters/fs.rb +1 -1
  80. data/lib/polyphony/adapters/irb.rb +2 -17
  81. data/lib/polyphony/adapters/mysql2.rb +19 -0
  82. data/lib/polyphony/adapters/postgres.rb +5 -5
  83. data/lib/polyphony/adapters/process.rb +2 -5
  84. data/lib/polyphony/adapters/readline.rb +17 -0
  85. data/lib/polyphony/adapters/redis.rb +1 -1
  86. data/lib/polyphony/adapters/sequel.rb +45 -0
  87. data/lib/polyphony/core/exceptions.rb +11 -0
  88. data/lib/polyphony/core/global_api.rb +17 -12
  89. data/lib/polyphony/core/resource_pool.rb +20 -7
  90. data/lib/polyphony/core/sync.rb +46 -8
  91. data/lib/polyphony/core/throttler.rb +1 -1
  92. data/lib/polyphony/extensions/core.rb +30 -30
  93. data/lib/polyphony/extensions/fiber.rb +30 -49
  94. data/lib/polyphony/extensions/io.rb +60 -16
  95. data/lib/polyphony/extensions/openssl.rb +6 -6
  96. data/lib/polyphony/extensions/socket.rb +14 -15
  97. data/lib/polyphony/extensions/thread.rb +6 -5
  98. data/lib/polyphony/version.rb +1 -1
  99. data/polyphony.gemspec +7 -3
  100. data/test/helper.rb +1 -1
  101. data/test/{test_agent.rb → test_backend.rb} +22 -22
  102. data/test/test_fiber.rb +29 -12
  103. data/test/test_io.rb +59 -1
  104. data/test/test_kernel.rb +5 -0
  105. data/test/test_resource_pool.rb +29 -4
  106. data/test/test_signal.rb +16 -37
  107. data/test/test_socket.rb +17 -0
  108. data/test/test_sync.rb +52 -0
  109. metadata +127 -97
  110. data/.gitbook.yaml +0 -4
  111. data/examples/adapters/concurrent-ruby.rb +0 -9
  112. data/examples/core/04-handling-signals.rb +0 -19
  113. data/examples/core/xx-agent.rb +0 -102
  114. data/examples/core/xx-at_exit.rb +0 -29
  115. data/examples/core/xx-caller.rb +0 -12
  116. data/examples/core/xx-daemon.rb +0 -14
  117. data/examples/core/xx-deadlock.rb +0 -8
  118. data/examples/core/xx-deferring-an-operation.rb +0 -14
  119. data/examples/core/xx-exception-backtrace.rb +0 -40
  120. data/examples/core/xx-fork-cleanup.rb +0 -22
  121. data/examples/core/xx-fork-spin.rb +0 -42
  122. data/examples/core/xx-fork-terminate.rb +0 -27
  123. data/examples/core/xx-move_on.rb +0 -23
  124. data/examples/core/xx-queue-async.rb +0 -120
  125. data/examples/core/xx-readpartial.rb +0 -18
  126. data/examples/core/xx-signals.rb +0 -16
  127. data/examples/core/xx-sleep-forever.rb +0 -9
  128. data/examples/core/xx-sleeping.rb +0 -25
  129. data/examples/core/xx-snooze-starve.rb +0 -16
  130. data/examples/core/xx-spin-fork.rb +0 -49
  131. data/examples/core/xx-state-machine.rb +0 -51
  132. data/examples/core/xx-stop.rb +0 -20
  133. data/examples/core/xx-supervisors.rb +0 -21
  134. data/examples/core/xx-thread-selector-sleep.rb +0 -51
  135. data/examples/core/xx-thread-selector-snooze.rb +0 -46
  136. data/examples/core/xx-thread-snooze.rb +0 -34
  137. data/examples/core/xx-timer-gc.rb +0 -17
  138. data/examples/core/xx-trace.rb +0 -79
  139. data/examples/performance/xx-array.rb +0 -11
  140. data/examples/performance/xx-fiber-switch.rb +0 -9
  141. data/examples/performance/xx-snooze.rb +0 -15
  142. data/examples/xx-spin.rb +0 -32
  143. data/ext/polyphony/agent.h +0 -41
@@ -7,8 +7,8 @@ ID ID_caller;
7
7
  ID ID_clear;
8
8
  ID ID_each;
9
9
  ID ID_inspect;
10
+ ID ID_invoke;
10
11
  ID ID_new;
11
- ID ID_raise;
12
12
  ID ID_ivar_running;
13
13
  ID ID_ivar_thread;
14
14
  ID ID_runnable;
@@ -21,7 +21,7 @@ ID ID_R;
21
21
  ID ID_W;
22
22
  ID ID_RW;
23
23
 
24
- agent_interface_t agent_interface;
24
+ backend_interface_t backend_interface;
25
25
 
26
26
  VALUE Polyphony_snooze(VALUE self) {
27
27
  VALUE ret;
@@ -60,10 +60,10 @@ void Init_Polyphony() {
60
60
  ID_clear = rb_intern("clear");
61
61
  ID_each = rb_intern("each");
62
62
  ID_inspect = rb_intern("inspect");
63
+ ID_invoke = rb_intern("invoke");
63
64
  ID_ivar_running = rb_intern("@running");
64
65
  ID_ivar_thread = rb_intern("@thread");
65
66
  ID_new = rb_intern("new");
66
- ID_raise = rb_intern("raise");
67
67
  ID_runnable = rb_intern("runnable");
68
68
  ID_runnable_value = rb_intern("runnable_value");
69
69
  ID_signal = rb_intern("signal");
@@ -4,23 +4,28 @@
4
4
  #include "ruby.h"
5
5
  #include "ruby/io.h"
6
6
  #include "libev.h"
7
- #include "agent.h"
7
+ #include "backend.h"
8
8
 
9
9
  // debugging
10
10
  #define OBJ_ID(obj) (NUM2LONG(rb_funcall(obj, rb_intern("object_id"), 0)))
11
- #define INSPECT(str, obj) { printf(str); VALUE s = rb_funcall(obj, rb_intern("inspect"), 0); printf("%s\n", StringValueCStr(s));}
12
- #define FIBER_TRACE(...) if (__tracing_enabled__) { \
13
- rb_funcall(rb_cObject, ID_fiber_trace, __VA_ARGS__); \
11
+ #define INSPECT(str, obj) { printf(str); VALUE s = rb_funcall(obj, rb_intern("inspect"), 0); printf("%s\n", StringValueCStr(s)); }
12
+ #define TRACE_CALLER() { VALUE c = rb_funcall(rb_mKernel, rb_intern("caller"), 0); INSPECT("caller: ", c); }
13
+
14
+ // tracing
15
+ #define TRACE(...) rb_funcall(rb_cObject, ID_fiber_trace, __VA_ARGS__)
16
+ #define COND_TRACE(...) if (__tracing_enabled__) { \
17
+ TRACE(__VA_ARGS__); \
14
18
  }
15
19
 
16
20
  #define TEST_EXCEPTION(ret) (RTEST(rb_obj_is_kind_of(ret, rb_eException)))
17
21
 
22
+ #define RAISE_EXCEPTION(e) rb_funcall(e, ID_invoke, 0);
18
23
  #define TEST_RESUME_EXCEPTION(ret) if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) { \
19
- return rb_funcall(rb_mKernel, ID_raise, 1, ret); \
24
+ return RAISE_EXCEPTION(ret); \
20
25
  }
21
26
 
22
- extern agent_interface_t agent_interface;
23
- #define __AGENT__ (agent_interface)
27
+ extern backend_interface_t backend_interface;
28
+ #define __BACKEND__ (backend_interface)
24
29
 
25
30
  extern VALUE mPolyphony;
26
31
  extern VALUE cQueue;
@@ -32,7 +37,8 @@ extern ID ID_clear;
32
37
  extern ID ID_each;
33
38
  extern ID ID_fiber_trace;
34
39
  extern ID ID_inspect;
35
- extern ID ID_ivar_agent;
40
+ extern ID ID_invoke;
41
+ extern ID ID_ivar_backend;
36
42
  extern ID ID_ivar_running;
37
43
  extern ID ID_ivar_thread;
38
44
  extern ID ID_new;
@@ -60,31 +66,20 @@ enum {
60
66
  FIBER_STATE_SCHEDULED = 2
61
67
  };
62
68
 
63
- // watcher flags
64
- enum {
65
- // a watcher's active field will be set to this after fork
66
- GYRO_WATCHER_POST_FORK = 0xFF
67
- };
68
-
69
69
  VALUE Fiber_auto_watcher(VALUE self);
70
70
  void Fiber_make_runnable(VALUE fiber, VALUE value);
71
71
 
72
72
  VALUE Queue_push(VALUE self, VALUE value);
73
73
  VALUE Queue_unshift(VALUE self, VALUE value);
74
74
  VALUE Queue_shift(VALUE self);
75
+ VALUE Queue_shift_all(VALUE self);
75
76
  VALUE Queue_shift_no_wait(VALUE self);
76
77
  VALUE Queue_clear(VALUE self);
77
78
  VALUE Queue_delete(VALUE self, VALUE value);
78
79
  long Queue_len(VALUE self);
79
80
  void Queue_trace(VALUE self);
80
81
 
81
- VALUE Polyphony_snooze(VALUE self);
82
-
83
82
  VALUE Thread_schedule_fiber(VALUE thread, VALUE fiber, VALUE value);
84
83
  VALUE Thread_switch_fiber(VALUE thread);
85
84
 
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
85
  #endif /* POLYPHONY_H */
@@ -2,7 +2,7 @@
2
2
 
3
3
  void Init_Fiber();
4
4
  void Init_Polyphony();
5
- void Init_LibevAgent();
5
+ void Init_LibevBackend();
6
6
  void Init_Queue();
7
7
  void Init_Event();
8
8
  void Init_Thread();
@@ -12,12 +12,11 @@ void Init_polyphony_ext() {
12
12
  ev_set_allocator(xrealloc);
13
13
 
14
14
  Init_Polyphony();
15
- Init_LibevAgent();
15
+
16
+ Init_LibevBackend();
16
17
  Init_Queue();
17
18
  Init_Event();
18
-
19
19
  Init_Fiber();
20
20
  Init_Thread();
21
-
22
21
  Init_Tracing();
23
22
  }
@@ -80,17 +80,16 @@ VALUE Queue_shift(VALUE self) {
80
80
 
81
81
  VALUE fiber = rb_fiber_current();
82
82
  VALUE thread = rb_thread_current();
83
- VALUE agent = rb_ivar_get(thread, ID_ivar_agent);
83
+ VALUE backend = rb_ivar_get(thread, ID_ivar_backend);
84
84
 
85
85
  while (1) {
86
86
  ring_buffer_push(&queue->shift_queue, fiber);
87
87
  if (queue->values.count > 0) Fiber_make_runnable(fiber, Qnil);
88
-
89
- VALUE switchpoint_result = __AGENT__.wait_event(agent, Qnil);
88
+
89
+ VALUE switchpoint_result = __BACKEND__.wait_event(backend, Qnil);
90
90
  ring_buffer_delete(&queue->shift_queue, fiber);
91
91
 
92
- if (RTEST(rb_obj_is_kind_of(switchpoint_result, rb_eException)))
93
- return rb_funcall(rb_mKernel, ID_raise, 1, switchpoint_result);
92
+ TEST_RESUME_EXCEPTION(switchpoint_result);
94
93
  RB_GC_GUARD(switchpoint_result);
95
94
 
96
95
  if (queue->values.count > 0)
@@ -152,7 +151,7 @@ VALUE Queue_flush_waiters(VALUE self, VALUE value) {
152
151
  while(1) {
153
152
  VALUE fiber = ring_buffer_shift(&queue->shift_queue);
154
153
  if (fiber == Qnil) return self;
155
-
154
+
156
155
  Fiber_make_runnable(fiber, value);
157
156
  }
158
157
  }
@@ -24,7 +24,6 @@ VALUE ring_buffer_shift(ring_buffer *buffer) {
24
24
  value = buffer->entries[buffer->head];
25
25
  buffer->head = (buffer->head + 1) % buffer->size;
26
26
  buffer->count--;
27
- // INSPECT(value);
28
27
  return value;
29
28
  }
30
29
 
@@ -1,7 +1,7 @@
1
1
  #include "polyphony.h"
2
2
 
3
3
  ID ID_deactivate_all_watchers_post_fork;
4
- ID ID_ivar_agent;
4
+ ID ID_ivar_backend;
5
5
  ID ID_ivar_join_wait_queue;
6
6
  ID ID_ivar_main_fiber;
7
7
  ID ID_ivar_result;
@@ -12,7 +12,7 @@ ID ID_stop;
12
12
 
13
13
  static VALUE Thread_setup_fiber_scheduling(VALUE self) {
14
14
  VALUE queue = rb_funcall(cQueue, ID_new, 0);
15
-
15
+
16
16
  rb_ivar_set(self, ID_ivar_main_fiber, rb_fiber_current());
17
17
  rb_ivar_set(self, ID_run_queue, queue);
18
18
 
@@ -20,20 +20,20 @@ static VALUE Thread_setup_fiber_scheduling(VALUE self) {
20
20
  }
21
21
 
22
22
  int Thread_fiber_ref_count(VALUE self) {
23
- VALUE agent = rb_ivar_get(self, ID_ivar_agent);
24
- return NUM2INT(__AGENT__.ref_count(agent));
23
+ VALUE backend = rb_ivar_get(self, ID_ivar_backend);
24
+ return NUM2INT(__BACKEND__.ref_count(backend));
25
25
  }
26
26
 
27
27
  inline void Thread_fiber_reset_ref_count(VALUE self) {
28
- VALUE agent = rb_ivar_get(self, ID_ivar_agent);
29
- __AGENT__.reset_ref_count(agent);
28
+ VALUE backend = rb_ivar_get(self, ID_ivar_backend);
29
+ __BACKEND__.reset_ref_count(backend);
30
30
  }
31
31
 
32
32
  static VALUE SYM_scheduled_fibers;
33
33
  static VALUE SYM_pending_watchers;
34
34
 
35
35
  static VALUE Thread_fiber_scheduling_stats(VALUE self) {
36
- VALUE agent = rb_ivar_get(self,ID_ivar_agent);
36
+ VALUE backend = rb_ivar_get(self,ID_ivar_backend);
37
37
  VALUE stats = rb_hash_new();
38
38
  VALUE queue = rb_ivar_get(self, ID_run_queue);
39
39
  long pending_count;
@@ -41,7 +41,7 @@ static VALUE Thread_fiber_scheduling_stats(VALUE self) {
41
41
  long scheduled_count = RARRAY_LEN(queue);
42
42
  rb_hash_aset(stats, SYM_scheduled_fibers, INT2NUM(scheduled_count));
43
43
 
44
- pending_count = __AGENT__.pending_count(agent);
44
+ pending_count = __BACKEND__.pending_count(backend);
45
45
  rb_hash_aset(stats, SYM_pending_watchers, INT2NUM(pending_count));
46
46
 
47
47
  return stats;
@@ -64,7 +64,7 @@ VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
64
64
  }
65
65
 
66
66
  rb_ivar_set(fiber, ID_runnable_value, value);
67
- FIBER_TRACE(3, SYM_fiber_schedule, fiber, value);
67
+ COND_TRACE(3, SYM_fiber_schedule, fiber, value);
68
68
 
69
69
  if (!already_runnable) {
70
70
  queue = rb_ivar_get(self, ID_run_queue);
@@ -77,8 +77,8 @@ VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
77
77
  // event selector. Otherwise it's gonna be stuck waiting for an event to
78
78
  // happen, not knowing that it there's already a fiber ready to run in its
79
79
  // run queue.
80
- VALUE agent = rb_ivar_get(self,ID_ivar_agent);
81
- __AGENT__.wakeup(agent);
80
+ VALUE backend = rb_ivar_get(self,ID_ivar_backend);
81
+ __BACKEND__.wakeup(backend);
82
82
  }
83
83
  }
84
84
  return self;
@@ -89,7 +89,7 @@ VALUE Thread_schedule_fiber_with_priority(VALUE self, VALUE fiber, VALUE value)
89
89
 
90
90
  if (rb_fiber_alive_p(fiber) != Qtrue) return self;
91
91
 
92
- FIBER_TRACE(3, SYM_fiber_schedule, fiber, value);
92
+ COND_TRACE(3, SYM_fiber_schedule, fiber, value);
93
93
  rb_ivar_set(fiber, ID_runnable_value, value);
94
94
 
95
95
  queue = rb_ivar_get(self, ID_run_queue);
@@ -110,8 +110,8 @@ VALUE Thread_schedule_fiber_with_priority(VALUE self, VALUE fiber, VALUE value)
110
110
  // event loop. Otherwise it's gonna be stuck waiting for an event to
111
111
  // happen, not knowing that it there's already a fiber ready to run in its
112
112
  // run queue.
113
- VALUE agent = rb_ivar_get(self, ID_ivar_agent);
114
- __AGENT__.wakeup(agent);
113
+ VALUE backend = rb_ivar_get(self, ID_ivar_backend);
114
+ __BACKEND__.wakeup(backend);
115
115
  }
116
116
  return self;
117
117
  }
@@ -121,43 +121,39 @@ VALUE Thread_switch_fiber(VALUE self) {
121
121
  VALUE queue = rb_ivar_get(self, ID_run_queue);
122
122
  VALUE next_fiber;
123
123
  VALUE value;
124
- VALUE agent = rb_ivar_get(self, ID_ivar_agent);
124
+ VALUE backend = rb_ivar_get(self, ID_ivar_backend);
125
125
  int ref_count;
126
- int agent_was_polled = 0;1;
126
+ int backend_was_polled = 0;
127
127
 
128
- if (__tracing_enabled__) {
129
- if (rb_ivar_get(current_fiber, ID_ivar_running) != Qfalse) {
130
- rb_funcall(rb_cObject, ID_fiber_trace, 2, SYM_fiber_switchpoint, current_fiber);
131
- }
132
- }
128
+ if (__tracing_enabled__ && (rb_ivar_get(current_fiber, ID_ivar_running) != Qfalse))
129
+ TRACE(2, SYM_fiber_switchpoint, current_fiber);
133
130
 
134
- ref_count = __AGENT__.ref_count(agent);
131
+ ref_count = __BACKEND__.ref_count(backend);
135
132
  while (1) {
136
133
  next_fiber = Queue_shift_no_wait(queue);
137
134
  if (next_fiber != Qnil) {
138
- if (agent_was_polled == 0 && ref_count > 0) {
139
- // this mechanism prevents event starvation in case the run queue never
140
- // empties
141
- __AGENT__.poll(agent, Qtrue, current_fiber, queue);
135
+ if (backend_was_polled == 0 && ref_count > 0) {
136
+ // this prevents event starvation in case the run queue never empties
137
+ __BACKEND__.poll(backend, Qtrue, current_fiber, queue);
142
138
  }
143
139
  break;
144
140
  }
145
141
  if (ref_count == 0) break;
146
142
 
147
- __AGENT__.poll(agent, Qnil, current_fiber, queue);
148
- agent_was_polled = 1;
143
+ __BACKEND__.poll(backend, Qnil, current_fiber, queue);
144
+ backend_was_polled = 1;
149
145
  }
150
146
 
151
147
  if (next_fiber == Qnil) return Qnil;
152
148
 
153
149
  // run next fiber
154
150
  value = rb_ivar_get(next_fiber, ID_runnable_value);
155
- FIBER_TRACE(3, SYM_fiber_run, next_fiber, value);
151
+ COND_TRACE(3, SYM_fiber_run, next_fiber, value);
156
152
 
157
153
  rb_ivar_set(next_fiber, ID_runnable, Qnil);
158
154
  RB_GC_GUARD(next_fiber);
159
155
  RB_GC_GUARD(value);
160
- return (next_fiber == current_fiber) ?
156
+ return (next_fiber == current_fiber) ?
161
157
  value : rb_funcall(next_fiber, ID_transfer, 1, value);
162
158
  }
163
159
 
@@ -175,12 +171,12 @@ VALUE Thread_reset_fiber_scheduling(VALUE self) {
175
171
  }
176
172
 
177
173
  VALUE Thread_fiber_break_out_of_ev_loop(VALUE self, VALUE fiber, VALUE resume_obj) {
178
- VALUE agent = rb_ivar_get(self, ID_ivar_agent);
174
+ VALUE backend = rb_ivar_get(self, ID_ivar_backend);
179
175
  if (fiber != Qnil) {
180
176
  Thread_schedule_fiber_with_priority(self, fiber, resume_obj);
181
177
  }
182
178
 
183
- if (__AGENT__.wakeup(agent) == Qnil) {
179
+ if (__BACKEND__.wakeup(backend) == Qnil) {
184
180
  // we're not inside the ev_loop, so we just do a switchpoint
185
181
  Thread_switch_fiber(self);
186
182
  }
@@ -188,6 +184,11 @@ VALUE Thread_fiber_break_out_of_ev_loop(VALUE self, VALUE fiber, VALUE resume_ob
188
184
  return self;
189
185
  }
190
186
 
187
+ VALUE Thread_debug(VALUE self) {
188
+ rb_ivar_set(self, rb_intern("@__debug__"), Qtrue);
189
+ return self;
190
+ }
191
+
191
192
  void Init_Thread() {
192
193
  rb_define_method(rb_cThread, "setup_fiber_scheduling", Thread_setup_fiber_scheduling, 0);
193
194
  rb_define_method(rb_cThread, "reset_fiber_scheduling", Thread_reset_fiber_scheduling, 0);
@@ -200,8 +201,10 @@ void Init_Thread() {
200
201
  rb_define_method(rb_cThread, "switch_fiber", Thread_switch_fiber, 0);
201
202
  rb_define_method(rb_cThread, "run_queue_trace", Thread_run_queue_trace, 0);
202
203
 
204
+ rb_define_method(rb_cThread, "debug!", Thread_debug, 0);
205
+
203
206
  ID_deactivate_all_watchers_post_fork = rb_intern("deactivate_all_watchers_post_fork");
204
- ID_ivar_agent = rb_intern("@agent");
207
+ ID_ivar_backend = rb_intern("@backend");
205
208
  ID_ivar_join_wait_queue = rb_intern("@join_wait_queue");
206
209
  ID_ivar_main_fiber = rb_intern("@main_fiber");
207
210
  ID_ivar_result = rb_intern("@result");
@@ -3,50 +3,36 @@
3
3
  require 'fiber'
4
4
  require_relative './polyphony_ext'
5
5
 
6
- module Polyphony
7
- # replace core Queue class with our own
8
- verbose = $VERBOSE
9
- $VERBOSE = nil
10
- Object.const_set(:Queue, Polyphony::Queue)
11
- $VERBOSE = verbose
12
- end
13
-
14
6
  require_relative './polyphony/extensions/core'
15
7
  require_relative './polyphony/extensions/thread'
16
8
  require_relative './polyphony/extensions/fiber'
17
9
  require_relative './polyphony/extensions/io'
18
10
 
19
11
  Thread.current.setup_fiber_scheduling
20
- Thread.current.agent = Polyphony::Agent.new
12
+ Thread.current.backend = Polyphony::Backend.new
21
13
 
22
14
  require_relative './polyphony/core/global_api'
23
15
  require_relative './polyphony/core/resource_pool'
16
+ require_relative './polyphony/core/sync'
24
17
  require_relative './polyphony/net'
25
18
  require_relative './polyphony/adapters/process'
26
19
 
27
- # Main Polyphony API
20
+ # Polyphony API
28
21
  module Polyphony
29
22
  class << self
30
- def wait_for_signal(sig)
31
- raise "should be reimplemented"
32
-
33
- fiber = Fiber.current
34
- # Polyphony.ref
35
- old_trap = trap(sig) do
36
- # Polyphony.unref
37
- fiber.schedule(sig)
38
- trap(sig, old_trap)
39
- end
40
- suspend
41
-
42
- end
43
-
44
23
  def fork(&block)
45
24
  Kernel.fork do
46
- # # Since the fiber doing the fork will become the main fiber of the
47
- # # forked process, we leave it behind by transferring to a new fiber
48
- # # created in the context of the forked process, which rescues *all*
49
- # # exceptions, including Interrupt and SystemExit.
25
+ # A race condition can arise if a TERM or INT signal is received before
26
+ # the forked process has finished initializing. To prevent this we restore
27
+ # the default signal handlers, and then reinstall the custom Polyphony
28
+ # handlers just before running the given block.
29
+ trap('SIGTERM', 'DEFAULT')
30
+ trap('SIGINT', 'DEFAULT')
31
+
32
+ # Since the fiber doing the fork will become the main fiber of the
33
+ # forked process, we leave it behind by transferring to a new fiber
34
+ # created in the context of the forked process, which rescues *all*
35
+ # exceptions, including Interrupt and SystemExit.
50
36
  spin_forked_block(&block).transfer
51
37
  end
52
38
  end
@@ -65,16 +51,9 @@ module Polyphony
65
51
  end
66
52
 
67
53
  def run_forked_block(&block)
68
- # A race condition can arise if a TERM or INT signal is received before
69
- # the forked process has finished initializing. To prevent this we restore
70
- # the default signal handlers, and then reinstall the custom Polyphony
71
- # handlers just before running the given block.
72
- trap('SIGTERM', 'DEFAULT')
73
- trap('SIGINT', 'DEFAULT')
74
-
75
54
  Thread.current.setup
76
55
  Fiber.current.setup_main_fiber
77
- Thread.current.agent.post_fork
56
+ Thread.current.backend.post_fork
78
57
 
79
58
  install_terminating_signal_handlers
80
59
 
@@ -97,10 +76,10 @@ module Polyphony
97
76
  end
98
77
 
99
78
  def install_terminating_signal_handlers
100
- trap('SIGTERM', SystemExit)
79
+ trap('SIGTERM') { raise SystemExit }
101
80
  orig_trap('SIGINT') do
102
81
  orig_trap('SIGINT') { exit! }
103
- Thread.current.break_out_of_ev_loop(Thread.main.main_fiber, Interrupt.new)
82
+ Fiber.schedule_priority_oob_fiber { raise Interrupt }
104
83
  end
105
84
  end
106
85
 
@@ -123,12 +102,20 @@ module Polyphony
123
102
  # processes (see Polyphony.fork).
124
103
  at_exit do
125
104
  next unless @original_pid == ::Process.pid
126
-
105
+
127
106
  Polyphony.terminate_threads
128
107
  Fiber.current.shutdown_all_children
129
108
  end
130
109
  end
131
110
  end
111
+
112
+ # replace core Queue class with our own
113
+ verbose = $VERBOSE
114
+ $VERBOSE = nil
115
+ Object.const_set(:Queue, Polyphony::Queue)
116
+ Object.const_set(:Mutex, Polyphony::Mutex)
117
+ Object.const_set(:ConditionVariable, Polyphony::ConditionVariable)
118
+ $VERBOSE = verbose
132
119
  end
133
120
 
134
121
  Polyphony.install_terminating_signal_handlers