polyphony 0.49.2 → 0.50.0
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +1 -1
- data/TODO.md +3 -0
- data/examples/core/nested.rb +21 -0
- data/examples/core/suspend.rb +13 -0
- data/examples/core/terminate_main_fiber.rb +12 -0
- data/ext/polyphony/backend_common.h +1 -1
- data/ext/polyphony/fiber.c +2 -1
- data/ext/polyphony/polyphony.h +1 -0
- data/ext/polyphony/runqueue.c +6 -0
- data/ext/polyphony/runqueue_ring_buffer.c +9 -0
- data/ext/polyphony/runqueue_ring_buffer.h +1 -0
- data/ext/polyphony/thread.c +14 -0
- data/lib/polyphony/core/exceptions.rb +1 -0
- data/lib/polyphony/core/global_api.rb +1 -1
- data/lib/polyphony/core/timer.rb +63 -20
- data/lib/polyphony/extensions/core.rb +4 -4
- data/lib/polyphony/extensions/fiber.rb +2 -0
- data/lib/polyphony/version.rb +1 -1
- data/test/test_fiber.rb +16 -0
- data/test/test_timer.rb +41 -8
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2aac80a08ca16498c3ee0044b0ba6de039b179425051cbcee67af4c9b948c349
|
|
4
|
+
data.tar.gz: bbe016d6b2ad3c5c89129089f9ebb8457a37159e03be2ff84f2572454880b0c2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f91d0b40bceb4600e4bbd22f39cdbd6bfd4ac5b5fc038f77deb7d26a464ce3cad177884f9aadde60c78bc48df170ab6909c44d133283af3abf77a090ac58332
|
|
7
|
+
data.tar.gz: 37dfa412a25f41dd704a203a865817bf273a23db0ccbe1bbec1a3f6017b9cd953301d67077e3b58601485f4dd96db94bef77da3d46cabd57fb563d3652173175
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## 0.50.0
|
|
2
|
+
|
|
3
|
+
- Use `Process::CLOCK_MONOTONIC` in Timer
|
|
4
|
+
- Add `Timer#sleep`, `Timer#after`, `Timer#every`
|
|
5
|
+
- Prevent fiber from being resumed after terminating
|
|
6
|
+
- Add `Thread#fiber_index_of` method
|
|
7
|
+
- Use `Backend#wait_event` in `Fiber#await`
|
|
8
|
+
|
|
1
9
|
## 0.49.2
|
|
2
10
|
|
|
3
11
|
- Fix hang with 100s or more child fibers when terminating
|
data/Gemfile.lock
CHANGED
data/TODO.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
- Check segfault when resetting a `cancel_after` timeout lots of times at very high rate
|
|
2
2
|
- Check why `throttled_loop` inside of `move_on_after` fails to stop
|
|
3
3
|
|
|
4
|
+
- Commented out `io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);` in `io_uring_backend_defer_submit_and_await`:
|
|
5
|
+
- This flag should be set for I/O ops, not for other stuff
|
|
6
|
+
|
|
4
7
|
- Override stock `::SizedQueue` impl with Queue with capacity
|
|
5
8
|
|
|
6
9
|
- Add support for `break` and `StopIteration` in all loops (with tests)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'polyphony'
|
|
5
|
+
|
|
6
|
+
def process
|
|
7
|
+
p :b_start
|
|
8
|
+
sleep 1
|
|
9
|
+
p :b_stop
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
spin do
|
|
13
|
+
p :a_start
|
|
14
|
+
spin { process }
|
|
15
|
+
sleep 60
|
|
16
|
+
p :a_stop
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
p :main_start
|
|
20
|
+
sleep 120
|
|
21
|
+
p :main_stop
|
data/ext/polyphony/fiber.c
CHANGED
|
@@ -101,7 +101,8 @@ VALUE Fiber_await(VALUE self) {
|
|
|
101
101
|
}
|
|
102
102
|
rb_hash_aset(waiting_fibers, fiber, Qtrue);
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
VALUE backend = rb_ivar_get(rb_thread_current(), ID_ivar_backend);
|
|
105
|
+
result = Backend_wait_event(backend, Qnil);
|
|
105
106
|
|
|
106
107
|
rb_hash_delete(waiting_fibers, fiber);
|
|
107
108
|
RAISE_IF_EXCEPTION(result);
|
data/ext/polyphony/polyphony.h
CHANGED
|
@@ -84,6 +84,7 @@ void Runqueue_push(VALUE self, VALUE fiber, VALUE value, int reschedule);
|
|
|
84
84
|
void Runqueue_unshift(VALUE self, VALUE fiber, VALUE value, int reschedule);
|
|
85
85
|
runqueue_entry Runqueue_shift(VALUE self);
|
|
86
86
|
void Runqueue_delete(VALUE self, VALUE fiber);
|
|
87
|
+
int Runqueue_index_of(VALUE self, VALUE fiber);
|
|
87
88
|
void Runqueue_clear(VALUE self);
|
|
88
89
|
long Runqueue_len(VALUE self);
|
|
89
90
|
int Runqueue_empty_p(VALUE self);
|
data/ext/polyphony/runqueue.c
CHANGED
|
@@ -74,6 +74,12 @@ void Runqueue_delete(VALUE self, VALUE fiber) {
|
|
|
74
74
|
runqueue_ring_buffer_delete(&runqueue->entries, fiber);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
int Runqueue_index_of(VALUE self, VALUE fiber) {
|
|
78
|
+
Runqueue_t *runqueue;
|
|
79
|
+
GetRunqueue(self, runqueue);
|
|
80
|
+
return runqueue_ring_buffer_index_of(&runqueue->entries, fiber);
|
|
81
|
+
}
|
|
82
|
+
|
|
77
83
|
void Runqueue_clear(VALUE self) {
|
|
78
84
|
Runqueue_t *runqueue;
|
|
79
85
|
GetRunqueue(self, runqueue);
|
|
@@ -80,6 +80,15 @@ void runqueue_ring_buffer_delete(runqueue_ring_buffer *buffer, VALUE fiber) {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
int runqueue_ring_buffer_index_of(runqueue_ring_buffer *buffer, VALUE fiber) {
|
|
84
|
+
for (unsigned int i = 0; i < buffer->count; i++) {
|
|
85
|
+
unsigned int idx = (buffer->head + i) % buffer->size;
|
|
86
|
+
if (buffer->entries[idx].fiber == fiber)
|
|
87
|
+
return i;
|
|
88
|
+
}
|
|
89
|
+
return -1;
|
|
90
|
+
}
|
|
91
|
+
|
|
83
92
|
void runqueue_ring_buffer_clear(runqueue_ring_buffer *buffer) {
|
|
84
93
|
buffer->count = buffer->head = buffer->tail = 0;
|
|
85
94
|
}
|
|
@@ -27,5 +27,6 @@ void runqueue_ring_buffer_unshift(runqueue_ring_buffer *buffer, VALUE fiber, VAL
|
|
|
27
27
|
void runqueue_ring_buffer_push(runqueue_ring_buffer *buffer, VALUE fiber, VALUE value);
|
|
28
28
|
|
|
29
29
|
void runqueue_ring_buffer_delete(runqueue_ring_buffer *buffer, VALUE fiber);
|
|
30
|
+
int runqueue_ring_buffer_index_of(runqueue_ring_buffer *buffer, VALUE fiber);
|
|
30
31
|
|
|
31
32
|
#endif /* RUNQUEUE_RING_BUFFER_H */
|
data/ext/polyphony/thread.c
CHANGED
|
@@ -59,6 +59,18 @@ void schedule_fiber(VALUE self, VALUE fiber, VALUE value, int prioritize) {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
VALUE Thread_fiber_scheduling_index(VALUE self, VALUE fiber) {
|
|
63
|
+
VALUE runqueue = rb_ivar_get(self, ID_ivar_runqueue);
|
|
64
|
+
|
|
65
|
+
return INT2NUM(Runqueue_index_of(runqueue, fiber));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
VALUE Thread_fiber_unschedule(VALUE self, VALUE fiber) {
|
|
69
|
+
VALUE runqueue = rb_ivar_get(self, ID_ivar_runqueue);
|
|
70
|
+
Runqueue_delete(runqueue, fiber);
|
|
71
|
+
return self;
|
|
72
|
+
}
|
|
73
|
+
|
|
62
74
|
VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
|
|
63
75
|
schedule_fiber(self, fiber, value, 0);
|
|
64
76
|
return self;
|
|
@@ -135,6 +147,8 @@ void Init_Thread() {
|
|
|
135
147
|
rb_define_method(rb_cThread, "schedule_fiber_with_priority",
|
|
136
148
|
Thread_schedule_fiber_with_priority, 2);
|
|
137
149
|
rb_define_method(rb_cThread, "switch_fiber", Thread_switch_fiber, 0);
|
|
150
|
+
rb_define_method(rb_cThread, "fiber_scheduling_index", Thread_fiber_scheduling_index, 1);
|
|
151
|
+
rb_define_method(rb_cThread, "fiber_unschedule", Thread_fiber_unschedule, 1);
|
|
138
152
|
|
|
139
153
|
rb_define_method(rb_cThread, "debug!", Thread_debug, 0);
|
|
140
154
|
|
data/lib/polyphony/core/timer.rb
CHANGED
|
@@ -11,12 +11,45 @@ module Polyphony
|
|
|
11
11
|
def stop
|
|
12
12
|
@fiber.stop
|
|
13
13
|
end
|
|
14
|
+
|
|
15
|
+
def sleep(duration)
|
|
16
|
+
fiber = Fiber.current
|
|
17
|
+
@timeouts[fiber] = {
|
|
18
|
+
interval: duration,
|
|
19
|
+
target_stamp: now + duration
|
|
20
|
+
}
|
|
21
|
+
Thread.current.backend.wait_event(true)
|
|
22
|
+
ensure
|
|
23
|
+
@timeouts.delete(fiber)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def after(interval, &block)
|
|
27
|
+
spin do
|
|
28
|
+
self.sleep interval
|
|
29
|
+
block.()
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def every(interval)
|
|
34
|
+
fiber = Fiber.current
|
|
35
|
+
@timeouts[fiber] = {
|
|
36
|
+
interval: interval,
|
|
37
|
+
target_stamp: now + interval,
|
|
38
|
+
recurring: true
|
|
39
|
+
}
|
|
40
|
+
while true
|
|
41
|
+
Thread.current.backend.wait_event(true)
|
|
42
|
+
yield
|
|
43
|
+
end
|
|
44
|
+
ensure
|
|
45
|
+
@timeouts.delete(fiber)
|
|
46
|
+
end
|
|
14
47
|
|
|
15
|
-
def cancel_after(
|
|
48
|
+
def cancel_after(interval, with_exception: Polyphony::Cancel)
|
|
16
49
|
fiber = Fiber.current
|
|
17
50
|
@timeouts[fiber] = {
|
|
18
|
-
|
|
19
|
-
target_stamp:
|
|
51
|
+
interval: interval,
|
|
52
|
+
target_stamp: now + interval,
|
|
20
53
|
exception: with_exception
|
|
21
54
|
}
|
|
22
55
|
yield
|
|
@@ -24,12 +57,12 @@ module Polyphony
|
|
|
24
57
|
@timeouts.delete(fiber)
|
|
25
58
|
end
|
|
26
59
|
|
|
27
|
-
def move_on_after(
|
|
60
|
+
def move_on_after(interval, with_value: nil)
|
|
28
61
|
fiber = Fiber.current
|
|
29
62
|
@timeouts[fiber] = {
|
|
30
|
-
|
|
31
|
-
target_stamp:
|
|
32
|
-
|
|
63
|
+
interval: interval,
|
|
64
|
+
target_stamp: now + interval,
|
|
65
|
+
exception: [Polyphony::MoveOn, with_value]
|
|
33
66
|
}
|
|
34
67
|
yield
|
|
35
68
|
rescue Polyphony::MoveOn => e
|
|
@@ -37,36 +70,46 @@ module Polyphony
|
|
|
37
70
|
ensure
|
|
38
71
|
@timeouts.delete(fiber)
|
|
39
72
|
end
|
|
40
|
-
|
|
73
|
+
|
|
41
74
|
def reset
|
|
42
75
|
record = @timeouts[Fiber.current]
|
|
43
76
|
return unless record
|
|
44
77
|
|
|
45
|
-
record[:target_stamp] =
|
|
78
|
+
record[:target_stamp] = now + record[:interval]
|
|
46
79
|
end
|
|
47
|
-
|
|
80
|
+
|
|
48
81
|
private
|
|
49
82
|
|
|
83
|
+
def now
|
|
84
|
+
::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
|
85
|
+
end
|
|
86
|
+
|
|
50
87
|
def timeout_exception(record)
|
|
51
88
|
case (exception = record[:exception])
|
|
52
|
-
when
|
|
53
|
-
|
|
54
|
-
when
|
|
55
|
-
|
|
89
|
+
when Array
|
|
90
|
+
exception[0].new(exception[1])
|
|
91
|
+
when Class
|
|
92
|
+
exception.new
|
|
93
|
+
else
|
|
94
|
+
RuntimeError.new(exception)
|
|
56
95
|
end
|
|
57
96
|
end
|
|
58
97
|
|
|
59
98
|
def update
|
|
60
|
-
|
|
61
|
-
|
|
99
|
+
return if @timeouts.empty?
|
|
100
|
+
|
|
62
101
|
@timeouts.each do |fiber, record|
|
|
63
102
|
next if record[:target_stamp] > now
|
|
64
103
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
104
|
+
value = record[:exception] ? timeout_exception(record) : record[:value]
|
|
105
|
+
fiber.schedule value
|
|
106
|
+
|
|
107
|
+
next unless record[:recurring]
|
|
108
|
+
|
|
109
|
+
while record[:target_stamp] <= now
|
|
110
|
+
record[:target_stamp] += record[:interval]
|
|
111
|
+
end
|
|
68
112
|
end
|
|
69
|
-
# elapsed&.each { |f| @timeouts.delete(f) }
|
|
70
113
|
end
|
|
71
114
|
end
|
|
72
115
|
end
|
|
@@ -12,11 +12,11 @@ class ::Exception
|
|
|
12
12
|
attr_accessor :__disable_sanitized_backtrace__
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
attr_accessor :source_fiber, :
|
|
15
|
+
attr_accessor :source_fiber, :raising_fiber
|
|
16
16
|
|
|
17
17
|
alias_method :orig_initialize, :initialize
|
|
18
18
|
def initialize(*args)
|
|
19
|
-
@
|
|
19
|
+
@raising_fiber = Fiber.current
|
|
20
20
|
orig_initialize(*args)
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -31,10 +31,10 @@ class ::Exception
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def sanitized_backtrace
|
|
34
|
-
return sanitize(orig_backtrace) unless @
|
|
34
|
+
return sanitize(orig_backtrace) unless @raising_fiber
|
|
35
35
|
|
|
36
36
|
backtrace = orig_backtrace || []
|
|
37
|
-
sanitize(backtrace + @
|
|
37
|
+
sanitize(backtrace + @raising_fiber.caller)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
POLYPHONY_DIR = File.expand_path(File.join(__dir__, '..'))
|
data/lib/polyphony/version.rb
CHANGED
data/test/test_fiber.rb
CHANGED
|
@@ -349,6 +349,22 @@ class FiberTest < MiniTest::Test
|
|
|
349
349
|
assert_equal [:foo, :terminate], buffer
|
|
350
350
|
end
|
|
351
351
|
|
|
352
|
+
CMD_TERMINATE_MAIN_FIBER = <<~BASH
|
|
353
|
+
ruby -rbundler/setup -rpolyphony -e"spin { sleep 0.1; Thread.current.main_fiber.terminate }; begin; sleep; rescue Polyphony::Terminate; STDOUT << 'terminated'; end" 2>&1
|
|
354
|
+
BASH
|
|
355
|
+
|
|
356
|
+
CMD_TERMINATE_CHILD_FIBER = <<~BASH
|
|
357
|
+
ruby -rbundler/setup -rpolyphony -e"f = spin { sleep }; spin { sleep 0.1; f.terminate }; f.await" 2>&1
|
|
358
|
+
BASH
|
|
359
|
+
|
|
360
|
+
def test_terminate_main_fiber
|
|
361
|
+
output = `#{CMD_TERMINATE_CHILD_FIBER}`
|
|
362
|
+
assert_equal '', output
|
|
363
|
+
|
|
364
|
+
output = `#{CMD_TERMINATE_MAIN_FIBER}`
|
|
365
|
+
assert_equal 'terminated', output
|
|
366
|
+
end
|
|
367
|
+
|
|
352
368
|
def test_interrupt_timer
|
|
353
369
|
result = []
|
|
354
370
|
f = Fiber.current.spin do
|
data/test/test_timer.rb
CHANGED
|
@@ -11,7 +11,7 @@ class TimerMoveOnAfterTest < MiniTest::Test
|
|
|
11
11
|
@timer.stop
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def
|
|
14
|
+
def test_timer_move_on_after
|
|
15
15
|
t0 = Time.now
|
|
16
16
|
v = @timer.move_on_after(0.1) do
|
|
17
17
|
sleep 1
|
|
@@ -23,7 +23,7 @@ class TimerMoveOnAfterTest < MiniTest::Test
|
|
|
23
23
|
assert_nil v
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def
|
|
26
|
+
def test_timer_move_on_after_with_value
|
|
27
27
|
t0 = Time.now
|
|
28
28
|
v = @timer.move_on_after(0.01, with_value: :bar) do
|
|
29
29
|
sleep 1
|
|
@@ -35,7 +35,7 @@ class TimerMoveOnAfterTest < MiniTest::Test
|
|
|
35
35
|
assert_equal :bar, v
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
def
|
|
38
|
+
def test_timer_move_on_after_with_reset
|
|
39
39
|
t0 = Time.now
|
|
40
40
|
v = @timer.move_on_after(0.01, with_value: :moved_on) do
|
|
41
41
|
sleep 0.007
|
|
@@ -48,7 +48,7 @@ class TimerMoveOnAfterTest < MiniTest::Test
|
|
|
48
48
|
t1 = Time.now
|
|
49
49
|
|
|
50
50
|
assert_nil v
|
|
51
|
-
assert_in_range 0.
|
|
51
|
+
assert_in_range 0.015..0.03, t1 - t0
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
@@ -61,7 +61,7 @@ class TimerCancelAfterTest < MiniTest::Test
|
|
|
61
61
|
@timer.stop
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
def
|
|
64
|
+
def test_timer_cancel_after
|
|
65
65
|
t0 = Time.now
|
|
66
66
|
|
|
67
67
|
assert_raises Polyphony::Cancel do
|
|
@@ -74,7 +74,7 @@ class TimerCancelAfterTest < MiniTest::Test
|
|
|
74
74
|
assert_in_range 0.01..0.03, t1 - t0
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
def
|
|
77
|
+
def test_timer_cancel_after_with_reset
|
|
78
78
|
t0 = Time.now
|
|
79
79
|
@timer.cancel_after(0.01) do
|
|
80
80
|
sleep 0.007
|
|
@@ -82,13 +82,13 @@ class TimerCancelAfterTest < MiniTest::Test
|
|
|
82
82
|
sleep 0.007
|
|
83
83
|
end
|
|
84
84
|
t1 = Time.now
|
|
85
|
-
assert_in_range 0.
|
|
85
|
+
assert_in_range 0.013..0.024, t1 - t0
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
class CustomException < Exception
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
-
def
|
|
91
|
+
def test_timer_cancel_after_with_custom_exception
|
|
92
92
|
assert_raises CustomException do
|
|
93
93
|
@timer.cancel_after(0.01, with_exception: CustomException) do
|
|
94
94
|
sleep 1
|
|
@@ -122,3 +122,36 @@ class TimerCancelAfterTest < MiniTest::Test
|
|
|
122
122
|
end
|
|
123
123
|
end
|
|
124
124
|
end
|
|
125
|
+
|
|
126
|
+
class TimerMiscTest < MiniTest::Test
|
|
127
|
+
def setup
|
|
128
|
+
@timer = Polyphony::Timer.new(resolution: 0.001)
|
|
129
|
+
sleep 0
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def teardown
|
|
133
|
+
@timer.stop
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def test_timer_after
|
|
137
|
+
buffer = []
|
|
138
|
+
f = @timer.after(0.01) { buffer << 2 }
|
|
139
|
+
assert_kind_of Fiber, f
|
|
140
|
+
snooze
|
|
141
|
+
assert_equal [], buffer
|
|
142
|
+
sleep 0.1
|
|
143
|
+
p :post_sleep
|
|
144
|
+
assert_equal [2], buffer
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def test_timer_every
|
|
148
|
+
buffer = []
|
|
149
|
+
t0 = Time.now
|
|
150
|
+
f = spin do
|
|
151
|
+
@timer.every(0.01) { buffer << 1 }
|
|
152
|
+
end
|
|
153
|
+
sleep 0.05
|
|
154
|
+
f.stop
|
|
155
|
+
assert_in_range 4..6, buffer.size
|
|
156
|
+
end
|
|
157
|
+
end
|
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.
|
|
4
|
+
version: 0.50.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sharon Rosner
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-01-
|
|
11
|
+
date: 2021-01-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake-compiler
|
|
@@ -353,6 +353,7 @@ files:
|
|
|
353
353
|
- examples/core/forking.rb
|
|
354
354
|
- examples/core/handling-signals.rb
|
|
355
355
|
- examples/core/interrupt.rb
|
|
356
|
+
- examples/core/nested.rb
|
|
356
357
|
- examples/core/pingpong.rb
|
|
357
358
|
- examples/core/recurrent-timer.rb
|
|
358
359
|
- examples/core/resource_delegate.rb
|
|
@@ -360,6 +361,8 @@ files:
|
|
|
360
361
|
- examples/core/spin_error_backtrace.rb
|
|
361
362
|
- examples/core/supervise-process.rb
|
|
362
363
|
- examples/core/supervisor.rb
|
|
364
|
+
- examples/core/suspend.rb
|
|
365
|
+
- examples/core/terminate_main_fiber.rb
|
|
363
366
|
- examples/core/thread-sleep.rb
|
|
364
367
|
- examples/core/thread_pool.rb
|
|
365
368
|
- examples/core/throttling.rb
|