fiber-scheduler 0.10.0 → 0.12.0

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: f7fa0c2f81a443cd6c852a51ad9c8d89d30ee080013980c94c2d16335aa074f1
4
- data.tar.gz: 83b4f910992b1f5d44976095d51c822acac07b98eb795ed1208cfd41e935e320
3
+ metadata.gz: d6a375b6e9a2d17be96e9c118ac624bbcbea154f961a205a9e1b0fc560b96f5e
4
+ data.tar.gz: 54e447b2977cfeb14bb06db5286eb3b291e2645dd9f0cc92f5aca2f5a8081372
5
5
  SHA512:
6
- metadata.gz: 41c1fed81c488cb5e4044688bc80b2b95136b5e8401260a35d3abdb8d05e8603ea40087d96f9f730417543783729cc713dbaafe46eaa3f7b5a8936cfd617857b
7
- data.tar.gz: 7f712132eedc368609578b6f07073aa4be1d4db11305e6b70b9627807f8acee48fd41f1a6876f214062d7da5c1bdd881c2a65830a2fe84b5ea202dc2079ae969
6
+ metadata.gz: c5f13b97d884ae06d98cdd2cea421ea8df2294e04a4ba4bc5a508df36a35f089eafd83741b7d57a105169ba93efdb512f65590c0624b225f527a046fefd23042
7
+ data.tar.gz: e055549f62f5ffabf6470a6d2ec3069f3d4df7bfd02bcf43f4f6a82e094927fa09ff6604186182e5d4123a6893f04b7fe6fb2ebd3b14e8da2d06468f53d6c3ee
@@ -1,22 +1,26 @@
1
1
  class FiberScheduler
2
2
  module Compatibility
3
+ Close = Class.new(RuntimeError)
4
+
3
5
  def fiber(*args, **opts, &block)
4
6
  return super unless Compatibility.internal?
5
7
 
6
8
  # This is `Fiber.schedule` call inside `FiberScheduler { ... }` block.
7
- if opts[:blocking]
9
+ type = args.first
10
+ case type
11
+ when :blocking
8
12
  Fiber.new(blocking: true) {
9
13
  Compatibility.set_internal!
10
14
  yield
11
15
  }.tap(&:resume)
12
16
 
13
- elsif opts[:waiting]
17
+ when :waiting
14
18
  parent = Fiber.current
15
19
  finished = false # prevents races
16
20
  blocking = false # prevents #unblock-ing a fiber that never blocked
17
21
 
18
22
  # Don't pass *args and **opts to an unknown fiber scheduler class.
19
- super() do
23
+ fiber = super() do
20
24
  Compatibility.set_internal!
21
25
  yield
22
26
  ensure
@@ -29,15 +33,58 @@ class FiberScheduler
29
33
  block(nil, nil)
30
34
  end
31
35
 
32
- else
36
+ fiber
37
+
38
+ when :fleeting
39
+ # Transfer to current fiber some time after a fleeting fiber yields.
40
+ unblock(nil, Fiber.current)
41
+ # Alternative to #unblock: Fiber.scheduler.push(Fiber.current)
42
+
43
+ fiber = Fiber.new(blocking: false) do
44
+ Compatibility.set_internal!
45
+ yield
46
+ rescue Close
47
+ # Fiber scheduler is closing.
48
+ ensure
49
+ _fleeting.delete(Fiber.current)
50
+ end
51
+ _fleeting[fiber] = nil
52
+ fiber.tap(&:transfer)
53
+
54
+ when nil
33
55
  # Don't pass *args and **opts to an unknown fiber scheduler class.
34
56
  super() do
35
57
  Compatibility.set_internal!
36
58
  yield
37
59
  end
60
+
61
+ else
62
+ raise "Unknown type"
63
+ end
64
+ end
65
+
66
+ # #close and #_fleeting handle a complexity in Async::Scheduler#close, more
67
+ # specifically this line:
68
+ # https://github.com/socketry/async/blob/456df488d801572821eaf5ec2fda10e3b9744a5f/lib/async/scheduler.rb#L55
69
+ def close
70
+ super
71
+ rescue
72
+ if _fleeting.empty?
73
+ Kernel.raise
74
+ else
75
+ # #dup is used because #_fleeting is modified during iteration.
76
+ _fleeting.dup.each do |fiber, _|
77
+ fiber.raise(Close)
78
+ end
79
+
80
+ super # retry
38
81
  end
39
82
  end
40
83
 
84
+ def _fleeting
85
+ @_fleeting ||= {}
86
+ end
87
+
41
88
  def self.set_internal!
42
89
  Thread.current[:_fiber_scheduler] = true # Sets a FIBER local var!
43
90
  end
@@ -1,3 +1,3 @@
1
1
  class FiberScheduler
2
- VERSION = "0.10.0".freeze
2
+ VERSION = "0.12.0".freeze
3
3
  end
@@ -10,14 +10,12 @@ rescue LoadError
10
10
  end
11
11
 
12
12
  module Kernel
13
- def FiberScheduler(blocking: false, waiting: true, &block)
13
+ def FiberScheduler(type = nil, &block)
14
14
  if Fiber.scheduler.nil?
15
- scheduler = FiberScheduler.new
16
- Fiber.set_scheduler(scheduler)
15
+ Fiber.set_scheduler(FiberScheduler.new)
17
16
 
18
17
  begin
19
18
  yield
20
- scheduler.close
21
19
  ensure
22
20
  Fiber.set_scheduler(nil)
23
21
  end
@@ -28,26 +26,27 @@ module Kernel
28
26
  if scheduler.is_a?(FiberScheduler)
29
27
  # The default waiting is 'true' as that is the most intuitive behavior
30
28
  # for a nested FiberScheduler call.
31
- Fiber.schedule(blocking: blocking, waiting: waiting, &block)
29
+ Fiber.schedule(type, &block)
32
30
 
33
31
  # Unknown fiber scheduler class; can't just pass options to
34
32
  # Fiber.schedule, handle each option separately.
35
33
  else
36
34
  scheduler.singleton_class.prepend(FiberScheduler::Compatibility)
37
35
 
38
- if blocking
36
+ case type
37
+ when :blocking
39
38
  fiber = Fiber.new(blocking: true) do
40
39
  FiberScheduler::Compatibility.set_internal!
41
40
  yield
42
41
  end
43
42
  fiber.tap(&:resume)
44
43
 
45
- elsif waiting
44
+ when :waiting
46
45
  parent = Fiber.current
47
46
  finished = false # prevents races
48
47
  blocking = false # prevents #unblock-ing a fiber that never blocked
49
48
 
50
- Fiber.schedule do
49
+ fiber = Fiber.schedule do
51
50
  FiberScheduler::Compatibility.set_internal!
52
51
  yield
53
52
  ensure
@@ -67,11 +66,30 @@ module Kernel
67
66
  scheduler.block(nil, nil)
68
67
  end
69
68
 
70
- else
69
+ fiber
70
+
71
+ when :fleeting
72
+ scheduler.unblock(nil, Fiber.current)
73
+
74
+ fiber = Fiber.new(blocking: false) do
75
+ FiberScheduler::Compatibility.set_internal!
76
+ yield
77
+ rescue FiberScheduler::Compatibility::Close
78
+ # Fiber scheduler is closing.
79
+ ensure
80
+ scheduler._fleeting.delete(Fiber.current)
81
+ end
82
+ scheduler._fleeting[fiber] = nil
83
+ fiber.tap(&:transfer)
84
+
85
+ when nil
71
86
  Fiber.schedule do
72
87
  FiberScheduler::Compatibility.set_internal!
73
88
  yield
74
89
  end
90
+
91
+ else
92
+ raise "Unknown type"
75
93
  end
76
94
  end
77
95
  end
@@ -170,13 +188,14 @@ class FiberScheduler
170
188
  @timeouts.timeout(duration, exception, message, &block)
171
189
  end
172
190
 
173
- def fiber(blocking: false, waiting: false, &block)
191
+ def fiber(type = nil, &block)
174
192
  current = Fiber.current
175
193
 
176
- if blocking
177
- # All fibers wait on a blocking fiber, so 'waiting' option is ignored.
194
+ case type
195
+ when :blocking
178
196
  Fiber.new(blocking: true, &block).tap(&:resume)
179
- elsif waiting
197
+
198
+ when :waiting
180
199
  finished = false # prevents races
181
200
  fiber = Fiber.new(blocking: false) do
182
201
  @count += 1
@@ -201,7 +220,16 @@ class FiberScheduler
201
220
  end
202
221
 
203
222
  fiber
204
- else
223
+
224
+ when :fleeting
225
+ if current != @fiber
226
+ # nested Fiber.schedule
227
+ @nested << current
228
+ end
229
+
230
+ Fiber.new(blocking: false, &block).tap(&:transfer)
231
+
232
+ when nil
205
233
  if current != @fiber
206
234
  # nested Fiber.schedule
207
235
  @nested << current
@@ -214,6 +242,9 @@ class FiberScheduler
214
242
  @count -= 1
215
243
  end
216
244
  fiber.tap(&:transfer)
245
+
246
+ else
247
+ raise "Unknown type"
217
248
  end
218
249
  end
219
250
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fiber-scheduler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bruno Sutic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-15 00:00:00.000000000 Z
11
+ date: 2022-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.0'
33
+ version: '0.10'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.0'
40
+ version: '0.10'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement