polyphony 0.45.1 → 0.45.2

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