polyphony 0.45.1 → 0.45.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f54b88851ca73f121975839812e0a1ad5686d017199b83a6365deda2b656d3a
4
- data.tar.gz: 92671a26215f19e36c0b0f49edb990a6818e2c64d7a8ed8bc9c4f2621a5de170
3
+ metadata.gz: a2fa4fa731ff52272d3aed456f7a26751e76c63b4335366919bffaf089bf96dd
4
+ data.tar.gz: 1afe67258c5c73d9cc1082ca238eb358dac0f5b7a975f90a77b4f6de6a23b2a4
5
5
  SHA512:
6
- metadata.gz: fd3caf340b523eccb1f86b10e06996ec26704ed1906bd82188363fb5142901b585992df8d88d0ca20adc188e51a010144fba8f10843ba79503d2984f63a08a05
7
- data.tar.gz: 2b44d80a6ac0bf3f0f42ece1b7d2008c3d0b933c1df11be7f698bbc9dae80341bd1d302a1e0ccaa56b223468b607b7f024bbaa949a88ff1c343028d6cd256ba5
6
+ metadata.gz: 175edf315d759f85d2c0d934be36b9fcacd68342206d984ad64f800120a8b65668e9ea81595f47cbbb439402c256b47fde78f0cdad4b42e0c3b1d6ee321135b9
7
+ data.tar.gz: 01cfe1d8b51d60a736adb80062eb22e7983a1879a5491cb7a2e47ec4ad5734e0c8bd8664653870a4393276b42fa912953721658ecff634521a672419c8d3cab6
@@ -1,3 +1,7 @@
1
+ ## 0.45.2
2
+
3
+ * Rewrite `Fiber#<<`, `Fiber#await`, `Fiber#receive` in C
4
+
1
5
  ## 0.45.1
2
6
 
3
7
  * Fix Net::HTTP compatibility
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.45.1)
4
+ polyphony (0.45.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/TODO.md CHANGED
@@ -1,4 +1,4 @@
1
- 0.45.1
1
+ 0.45.2
2
2
 
3
3
  - Adapter for Pry and IRB (Which fixes #5 and #6)
4
4
  - Redesign signal handling - the current mechanism is problematic in that it
@@ -2,12 +2,9 @@
2
2
 
3
3
  ID ID_fiber_trace;
4
4
  ID ID_ivar_auto_watcher;
5
- ID ID_trace_ev_loop_enter;
6
- ID ID_trace_ev_loop_leave;
7
- ID ID_trace_run;
8
- ID ID_trace_runnable;
9
- ID ID_trace_terminate;
10
- ID ID_trace_wait;
5
+ ID ID_ivar_mailbox;
6
+ ID ID_ivar_result;
7
+ ID ID_ivar_waiting_fibers;
11
8
 
12
9
  VALUE SYM_dead;
13
10
  VALUE SYM_running;
@@ -67,6 +64,57 @@ void Fiber_make_runnable(VALUE fiber, VALUE value) {
67
64
  }
68
65
  }
69
66
 
67
+ VALUE Fiber_await(VALUE self) {
68
+ VALUE result;
69
+
70
+ // we compare with false, since a fiber that has not yet started will have
71
+ // @running set to nil
72
+ if (rb_ivar_get(self, ID_ivar_running) == Qfalse) {
73
+ result = rb_ivar_get(self, ID_ivar_result);
74
+ TEST_RESUME_EXCEPTION(result);
75
+ return result;
76
+ }
77
+
78
+ VALUE fiber = rb_fiber_current();
79
+ VALUE waiting_fibers = rb_ivar_get(self, ID_ivar_waiting_fibers);
80
+ if (waiting_fibers == Qnil) {
81
+ waiting_fibers = rb_hash_new();
82
+ rb_ivar_set(self, ID_ivar_waiting_fibers, waiting_fibers);
83
+ }
84
+ rb_hash_aset(waiting_fibers, fiber, Qtrue);
85
+
86
+ result = Thread_switch_fiber(rb_thread_current());
87
+
88
+ rb_hash_delete(waiting_fibers, fiber);
89
+ TEST_RESUME_EXCEPTION(result);
90
+ RB_GC_GUARD(result);
91
+ return result;
92
+ }
93
+
94
+ VALUE Fiber_send(VALUE self, VALUE value) {
95
+ VALUE mailbox = rb_ivar_get(self, ID_ivar_mailbox);
96
+ if (mailbox == Qnil) {
97
+ mailbox = rb_funcall(cQueue, ID_new, 0);
98
+ rb_ivar_set(self, ID_ivar_mailbox, mailbox);
99
+ }
100
+ Queue_push(mailbox, value);
101
+ return self;
102
+ }
103
+
104
+ VALUE Fiber_receive(VALUE self) {
105
+ VALUE mailbox = rb_ivar_get(self, ID_ivar_mailbox);
106
+ if (mailbox == Qnil) {
107
+ mailbox = rb_funcall(cQueue, ID_new, 0);
108
+ rb_ivar_set(self, ID_ivar_mailbox, mailbox);
109
+ }
110
+ return Queue_shift(mailbox);
111
+ }
112
+
113
+ VALUE Fiber_receive_all_pending(VALUE self) {
114
+ VALUE mailbox = rb_ivar_get(self, ID_ivar_mailbox);
115
+ return (mailbox == Qnil) ? rb_ary_new() : Queue_shift_all(mailbox);
116
+ }
117
+
70
118
  void Init_Fiber() {
71
119
  VALUE cFiber = rb_const_get(rb_cObject, rb_intern("Fiber"));
72
120
  rb_define_method(cFiber, "safe_transfer", Fiber_safe_transfer, -1);
@@ -74,6 +122,15 @@ void Init_Fiber() {
74
122
  rb_define_method(cFiber, "state", Fiber_state, 0);
75
123
  rb_define_method(cFiber, "auto_watcher", Fiber_auto_watcher, 0);
76
124
 
125
+ rb_define_method(cFiber, "await", Fiber_await, 0);
126
+ rb_define_method(cFiber, "join", Fiber_await, 0);
127
+
128
+ rb_define_method(cFiber, "<<", Fiber_send, 1);
129
+ rb_define_method(cFiber, "send", Fiber_send, 1);
130
+
131
+ rb_define_method(cFiber, "receive", Fiber_receive, 0);
132
+ rb_define_method(cFiber, "receive_all_pending", Fiber_receive_all_pending, 0);
133
+
77
134
  SYM_dead = ID2SYM(rb_intern("dead"));
78
135
  SYM_running = ID2SYM(rb_intern("running"));
79
136
  SYM_runnable = ID2SYM(rb_intern("runnable"));
@@ -85,6 +142,9 @@ void Init_Fiber() {
85
142
 
86
143
  ID_fiber_trace = rb_intern("__fiber_trace__");
87
144
  ID_ivar_auto_watcher = rb_intern("@auto_watcher");
145
+ ID_ivar_mailbox = rb_intern("@mailbox");
146
+ ID_ivar_result = rb_intern("@result");
147
+ ID_ivar_waiting_fibers = rb_intern("@waiting_fibers");
88
148
 
89
149
  SYM_fiber_create = ID2SYM(rb_intern("fiber_create"));
90
150
  SYM_fiber_ev_loop_enter = ID2SYM(rb_intern("fiber_ev_loop_enter"));
@@ -72,6 +72,7 @@ void Fiber_make_runnable(VALUE fiber, VALUE value);
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);
@@ -92,8 +92,8 @@ module Polyphony
92
92
  Fiber.current.receive
93
93
  end
94
94
 
95
- def receive_pending
96
- Fiber.current.receive_pending
95
+ def receive_all_pending
96
+ Fiber.current.receive_all_pending
97
97
  end
98
98
 
99
99
  def supervise(*args, &block)
@@ -7,20 +7,6 @@ require_relative '../core/exceptions'
7
7
  module Polyphony
8
8
  # Fiber control API
9
9
  module FiberControl
10
- def await
11
- if @running == false
12
- return @result.is_a?(Exception) ? (Kernel.raise @result) : @result
13
- end
14
-
15
- fiber = Fiber.current
16
- @waiting_fibers ||= {}
17
- @waiting_fibers[fiber] = true
18
- suspend
19
- ensure
20
- @waiting_fibers&.delete(fiber)
21
- end
22
- alias_method :join, :await
23
-
24
10
  def interrupt(value = nil)
25
11
  return if @running == false
26
12
 
@@ -181,22 +167,6 @@ module Polyphony
181
167
  end
182
168
  end
183
169
 
184
- # Messaging functionality
185
- module FiberMessaging
186
- def <<(value)
187
- @mailbox << value
188
- end
189
- alias_method :send, :<<
190
-
191
- def receive
192
- @mailbox.shift
193
- end
194
-
195
- def receive_pending
196
- @mailbox.shift_all
197
- end
198
- end
199
-
200
170
  # Methods for controlling child fibers
201
171
  module ChildFiberControl
202
172
  def children
@@ -225,14 +195,14 @@ module Polyphony
225
195
  def await_all_children
226
196
  return unless @children && !@children.empty?
227
197
 
228
- @results = @children.dup
198
+ results = @children.dup
229
199
  @on_child_done = proc do |c, r|
230
- @results[c] = r
200
+ results[c] = r
231
201
  schedule if @children.empty?
232
202
  end
233
203
  suspend
234
204
  @on_child_done = nil
235
- @results.values
205
+ results.values
236
206
  end
237
207
 
238
208
  def shutdown_all_children
@@ -249,7 +219,6 @@ module Polyphony
249
219
  @parent = parent
250
220
  @caller = caller
251
221
  @block = block
252
- @mailbox = Polyphony::Queue.new
253
222
  __fiber_trace__(:fiber_create, self)
254
223
  schedule
255
224
  end
@@ -279,7 +248,6 @@ module Polyphony
279
248
  # allows the fiber to be scheduled and to receive messages.
280
249
  def setup_raw
281
250
  @thread = Thread.current
282
- @mailbox = Polyphony::Queue.new
283
251
  end
284
252
 
285
253
  def setup_main_fiber
@@ -288,11 +256,10 @@ module Polyphony
288
256
  @thread = Thread.current
289
257
  @running = true
290
258
  @children&.clear
291
- @mailbox = Polyphony::Queue.new
292
259
  end
293
260
 
294
261
  def restart_self(first_value)
295
- @mailbox = Polyphony::Queue.new
262
+ @mailbox = nil
296
263
  @when_done_procs = nil
297
264
  @waiting_fibers = nil
298
265
  run(first_value)
@@ -324,13 +291,10 @@ module Polyphony
324
291
  def inform_dependants(result, uncaught_exception)
325
292
  @parent&.child_done(self, result)
326
293
  @when_done_procs&.each { |p| p.(result) }
327
- @waiting_fibers&.each_key do |f|
328
- f.schedule(result)
329
- end
330
- return unless uncaught_exception && !@waiting_fibers
331
-
294
+ @waiting_fibers&.each_key { |f| f.schedule(result) }
295
+
332
296
  # propagate unaught exception to parent
333
- @parent&.schedule(result)
297
+ @parent&.schedule(result) if uncaught_exception && !@waiting_fibers
334
298
  end
335
299
 
336
300
  def when_done(&block)
@@ -344,7 +308,6 @@ end
344
308
  class ::Fiber
345
309
  prepend Polyphony::FiberControl
346
310
  include Polyphony::FiberSupervision
347
- include Polyphony::FiberMessaging
348
311
  include Polyphony::ChildFiberControl
349
312
  include Polyphony::FiberLifeCycle
350
313
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.45.1'
4
+ VERSION = '0.45.2'
5
5
  end
@@ -700,15 +700,16 @@ class FiberTest < MiniTest::Test
700
700
  buffer = []
701
701
  f = Fiber.new { buffer << receive }
702
702
 
703
- assert_raises(NoMethodError) { f << 'foo' }
703
+ assert_nil f.thread
704
704
  snooze
705
705
  f.setup_raw
706
706
  assert_equal Thread.current, f.thread
707
707
  assert_nil f.parent
708
708
 
709
709
  f.schedule
710
+ snooze
710
711
  f << 'bar'
711
- 2.times { snooze }
712
+ snooze
712
713
  assert_equal ['bar'], buffer
713
714
  end
714
715
  end
@@ -811,20 +812,20 @@ class MailboxTest < MiniTest::Test
811
812
  assert_equal ['foo'] * 100, messages
812
813
  end
813
814
 
814
- def test_receive_pending
815
- assert_equal [], receive_pending
815
+ def test_receive_all_pending
816
+ assert_equal [], receive_all_pending
816
817
 
817
818
  (1..5).each { |i| Fiber.current << i }
818
- assert_equal (1..5).to_a, receive_pending
819
- assert_equal [], receive_pending
819
+ assert_equal (1..5).to_a, receive_all_pending
820
+ assert_equal [], receive_all_pending
820
821
  end
821
822
 
822
- def test_receive_pending_on_termination
823
+ def test_receive_all_pending_on_termination
823
824
  buffer = []
824
825
  worker = spin do
825
826
  loop { buffer << receive }
826
827
  rescue Polyphony::Terminate
827
- receive_pending.each { |r| buffer << r }
828
+ receive_all_pending.each { |r| buffer << r }
828
829
  end
829
830
 
830
831
  worker << 1
@@ -12,7 +12,6 @@ class ThrottlerTest < MiniTest::Test
12
12
  f.stop
13
13
  elapsed = Time.now - t0
14
14
  expected = (elapsed * 10).to_i
15
- STDOUT.orig_write "xxxxxxxx #{[elapsed, expected].inspect}\n"
16
15
  assert buffer.size >= expected - 1 && buffer.size <= expected + 1
17
16
  ensure
18
17
  t.stop
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: polyphony
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.45.1
4
+ version: 0.45.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-01 00:00:00.000000000 Z
11
+ date: 2020-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler