polyphony 0.99.4 → 0.99.5

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +10 -0
  3. data/examples/pipes/gzip_http_server.rb +2 -2
  4. data/examples/pipes/http_server.rb +1 -1
  5. data/examples/pipes/tcp_proxy.rb +1 -1
  6. data/ext/polyphony/backend_common.c +4 -4
  7. data/ext/polyphony/backend_io_uring.c +8 -8
  8. data/ext/polyphony/backend_libev.c +5 -5
  9. data/ext/polyphony/fiber.c +32 -41
  10. data/ext/polyphony/io_extensions.c +50 -37
  11. data/ext/polyphony/pipe.c +6 -18
  12. data/ext/polyphony/polyphony.c +63 -133
  13. data/ext/polyphony/queue.c +25 -63
  14. data/ext/polyphony/thread.c +3 -12
  15. data/lib/polyphony/adapters/process.rb +1 -2
  16. data/lib/polyphony/adapters/sequel.rb +2 -2
  17. data/lib/polyphony/core/debug.rb +1 -1
  18. data/lib/polyphony/core/exceptions.rb +1 -1
  19. data/lib/polyphony/core/global_api.rb +24 -38
  20. data/lib/polyphony/core/resource_pool.rb +7 -8
  21. data/lib/polyphony/core/sync.rb +1 -2
  22. data/lib/polyphony/core/thread_pool.rb +2 -5
  23. data/lib/polyphony/core/throttler.rb +1 -5
  24. data/lib/polyphony/core/timer.rb +24 -25
  25. data/lib/polyphony/extensions/fiber.rb +507 -540
  26. data/lib/polyphony/extensions/io.rb +3 -12
  27. data/lib/polyphony/extensions/openssl.rb +2 -23
  28. data/lib/polyphony/extensions/pipe.rb +4 -15
  29. data/lib/polyphony/extensions/socket.rb +15 -109
  30. data/lib/polyphony/extensions/thread.rb +0 -13
  31. data/lib/polyphony/extensions/timeout.rb +0 -1
  32. data/lib/polyphony/net.rb +5 -8
  33. data/lib/polyphony/version.rb +1 -1
  34. data/lib/polyphony.rb +2 -6
  35. data/test/test_io.rb +221 -221
  36. data/test/test_socket.rb +3 -3
  37. data/test/test_trace.rb +2 -2
  38. metadata +1 -1
@@ -8,12 +8,11 @@ module Polyphony
8
8
  # Watches a forked or spawned process, waiting for it to terminate. If
9
9
  # `cmd` is given it is spawned, otherwise the process is forked with the
10
10
  # given block.
11
- #
11
+ #
12
12
  # If the operation is interrupted for any reason, the spawned or forked
13
13
  # process is killed.
14
14
  #
15
15
  # @param cmd [String, nil] command to spawn
16
- # @yield [] block to fork
17
16
  # @return [void]
18
17
  def watch(cmd = nil, &block)
19
18
  terminated = nil
@@ -4,10 +4,10 @@ require_relative '../../polyphony'
4
4
  require 'sequel'
5
5
 
6
6
  module Polyphony
7
-
7
+
8
8
  # Sequel ConnectionPool that delegates to Polyphony::ResourcePool.
9
9
  class FiberConnectionPool < Sequel::ConnectionPool
10
-
10
+
11
11
  # Initializes the connection pool.
12
12
  #
13
13
  # @param db [any] db to connect to
@@ -32,7 +32,7 @@ module Polyphony
32
32
  # If an IO instance is given, events are dumped to it instead.
33
33
  #
34
34
  # @param io [IO, nil] IO instance
35
- # @yield [Hash] event handler block
35
+ # @yield [Hash] event information
36
36
  # @return [void]
37
37
  def start_event_firehose(io = nil, &block)
38
38
  Thread.backend.trace_proc = firehose_proc(io, block)
@@ -40,7 +40,7 @@ module Polyphony
40
40
 
41
41
  # Interjection is used to run arbitrary code on arbitrary fibers at any point
42
42
  class Interjection < BaseException
43
-
43
+
44
44
  # Initializes an Interjection with the given proc.
45
45
  #
46
46
  # @param proc [Proc] interjection proc
@@ -3,7 +3,7 @@
3
3
  require_relative './throttler'
4
4
 
5
5
  module Polyphony
6
-
6
+
7
7
  # Global API methods to be included in `::Object`
8
8
  module GlobalAPI
9
9
 
@@ -11,7 +11,6 @@ module Polyphony
11
11
  # given delay.
12
12
  #
13
13
  # @param interval [Number] delay in seconds before running the given block
14
- # @yield [] block to run
15
14
  # @return [Fiber] spun fiber
16
15
  def after(interval, &block)
17
16
  spin do
@@ -20,14 +19,6 @@ module Polyphony
20
19
  end
21
20
  end
22
21
 
23
- # call-seq:
24
- # cancel_after(interval) { ... }
25
- # cancel_after(interval, with_exception: exception) { ... }
26
- # cancel_after(interval, with_exception: [klass, message]) { ... }
27
- # cancel_after(interval) { |timeout| ... }
28
- # cancel_after(interval, with_exception: exception) { |timeout| ... }
29
- # cancel_after(interval, with_exception: [klass, message]) { |timeout| ... }
30
- #
31
22
  # Runs the given block after setting up a cancellation timer for
32
23
  # cancellation. If the cancellation timer elapses, the execution will be
33
24
  # interrupted with an exception defaulting to `Polyphony::Cancel`.
@@ -55,10 +46,20 @@ module Polyphony
55
46
  # end
56
47
  # end
57
48
  #
58
- # @param interval [Number] timout in seconds
59
- # @param with_exception [Class, Exception] exception or exception class
60
- # @yield [Fiber] block to execute
61
- # @return [any] block's return value
49
+ # @overload cancel_after(interval)
50
+ # @param interval [Number] timout in seconds
51
+ # @yield [Fiber] timeout fiber
52
+ # @return [any] block's return value
53
+ # @overload cancel_after(interval, with_exception: exception)
54
+ # @param interval [Number] timout in seconds
55
+ # @param with_exception [Class, Exception] exception or exception class
56
+ # @yield [Fiber] timeout fiber
57
+ # @return [any] block's return value
58
+ # @overload cancel_after(interval, with_exception: [klass, message])
59
+ # @param interval [Number] timout in seconds
60
+ # @param with_exception [Array] array containing class and message to use as exception
61
+ # @yield [Fiber] timeout fiber
62
+ # @return [any] block's return value
62
63
  def cancel_after(interval, with_exception: Polyphony::Cancel, &block)
63
64
  if block.arity > 0
64
65
  cancel_after_with_optional_reset(interval, with_exception, &block)
@@ -70,7 +71,6 @@ module Polyphony
70
71
  # Spins up a new fiber.
71
72
  #
72
73
  # @param tag [any] optional tag for the new fiber
73
- # @yield [any] fiber block
74
74
  # @return [Fiber] new fiber
75
75
  def spin(tag = nil, &block)
76
76
  Fiber.current.spin(tag, caller, &block)
@@ -83,7 +83,6 @@ module Polyphony
83
83
  # @param tag [any] optional tag for the new fiber
84
84
  # @param rate [Number, nil] loop rate (times per second)
85
85
  # @param interval [Number, nil] interval between consecutive iterations in seconds
86
- # @yield [any] code to run
87
86
  # @return [Fiber] new fiber
88
87
  def spin_loop(tag = nil, rate: nil, interval: nil, &block)
89
88
  if rate || interval
@@ -98,7 +97,6 @@ module Polyphony
98
97
  # Runs the given code, then waits for any child fibers of the current fibers
99
98
  # to terminate.
100
99
  #
101
- # @yield [any] code to run
102
100
  # @return [any] given block's return value
103
101
  def spin_scope(&block)
104
102
  raise unless block
@@ -114,18 +112,11 @@ module Polyphony
114
112
  # consecutive iterations.
115
113
  #
116
114
  # @param interval [Number] interval between consecutive iterations in seconds
117
- # @yield [any] block to run
118
115
  # @return [void]
119
116
  def every(interval, &block)
120
117
  Polyphony.backend_timer_loop(interval, &block)
121
118
  end
122
119
 
123
- # call-seq:
124
- # move_on_after(interval) { ... }
125
- # move_on_after(interval, with_value: value) { ... }
126
- # move_on_after(interval) { |canceller| ... }
127
- # move_on_after(interval, with_value: value) { |canceller| ... }
128
- #
129
120
  # Runs the given block after setting up a cancellation timer for
130
121
  # cancellation. If the cancellation timer elapses, the execution will be
131
122
  # interrupted with a `Polyphony::MoveOn` exception, which will be rescued,
@@ -159,10 +150,15 @@ module Polyphony
159
150
  # end
160
151
  # end
161
152
  #
162
- # @param interval [Number] timout in seconds
163
- # @param with_value [any] return value in case of timeout
164
- # @yield [Fiber] block to execute
165
- # @return [any] block's return value
153
+ # @overload move_on_after(interval) { ... }
154
+ # @param interval [Number] timout in seconds
155
+ # @yield [Fiber] timeout fiber
156
+ # @return [any] block's return value
157
+ # @overload move_on_after(interval, with_value: value) { ... }
158
+ # @param interval [Number] timout in seconds
159
+ # @param with_value [any] return value in case of timeout
160
+ # @yield [Fiber] timeout fiber
161
+ # @return [any] block's return value
166
162
  def move_on_after(interval, with_value: nil, &block)
167
163
  if block.arity > 0
168
164
  move_on_after_with_optional_reset(interval, with_value, &block)
@@ -191,7 +187,6 @@ module Polyphony
191
187
  #
192
188
  # @param args [Array] positional parameters
193
189
  # @param opts [Hash] named parameters
194
- # @yield [any] given block
195
190
  # @return [void]
196
191
  def supervise(*args, **opts, &block)
197
192
  Fiber.current.supervise(*args, **opts, &block)
@@ -207,12 +202,6 @@ module Polyphony
207
202
  Polyphony.backend_sleep(duration) : Polyphony.backend_wait_event(true)
208
203
  end
209
204
 
210
- # call-seq:
211
- # throttled_loop(rate) { ... }
212
- # throttled_loop(interval: value) { ... }
213
- # throttled_loop(rate: value) { ... }
214
- # throttled_loop(rate, count: value) { ... }
215
- #
216
205
  # Starts a throttled loop with the given rate. If `count:` is given, the
217
206
  # loop is run for the given number of times. Otherwise, the loop is
218
207
  # infinite. The loop rate (times per second) can be given as the rate
@@ -223,7 +212,6 @@ module Polyphony
223
212
  # @option opts [Number] :rate loop rate (times per second)
224
213
  # @option opts [Number] :interval loop interval in seconds
225
214
  # @option opts [Number] :count number of iterations (nil for infinite)
226
- # @yield [] code to run
227
215
  # @return [void]
228
216
  def throttled_loop(rate = nil, **opts, &block)
229
217
  throttler = Polyphony::Throttler.new(rate || opts)
@@ -244,7 +232,6 @@ module Polyphony
244
232
  #
245
233
  # @param interval [Number] timeout interval in seconds
246
234
  # @param exception [Exception, Class, Array<class, message>] exception spec
247
- # @yield [Fiber] block to run
248
235
  # @return [any] block's return value
249
236
  def cancel_after_with_optional_reset(interval, exception, &block)
250
237
  fiber = Fiber.current
@@ -290,7 +277,6 @@ module Polyphony
290
277
  #
291
278
  # @param interval [Number] timeout interval in seconds
292
279
  # @param value [any] return value in case of timeout
293
- # @yield [Fiber] code to run
294
280
  # @return [any] return value of given block or timeout value
295
281
  def move_on_after_with_optional_reset(interval, value, &block)
296
282
  fiber = Fiber.current
@@ -5,13 +5,15 @@ module Polyphony
5
5
  class ResourcePool
6
6
  attr_reader :limit, :size
7
7
 
8
- # Initializes a new resource pool.
8
+ # Initializes a new resource pool. The given block is used for creating a
9
+ # resource:
9
10
  #
10
- # @param opts [Hash] options
11
- # @yield [] allocator block
12
- def initialize(opts, &block)
11
+ # ResourcePool.new { Sequel.connect(DB_URL) }
12
+ #
13
+ # @param limit [Integer] maximum open resources
14
+ def initialize(limit: 4, &block)
13
15
  @allocator = block
14
- @limit = opts[:limit] || 4
16
+ @limit = limit
15
17
  @size = 0
16
18
  @stock = Polyphony::Queue.new
17
19
  @acquired_resources = {}
@@ -36,7 +38,6 @@ module Polyphony
36
38
  # db.query(sql).to_a
37
39
  # end
38
40
  #
39
- # @yield [any] code to run
40
41
  # @return [any] return value of block
41
42
  def acquire(&block)
42
43
  fiber = Fiber.current
@@ -55,7 +56,6 @@ module Polyphony
55
56
  #
56
57
  # @param sym [Symbol] method name
57
58
  # @param args [Array<any>] method arguments
58
- # @yield [any] block passed to method
59
59
  # @return [any] result of method call
60
60
  def method_missing(sym, *args, &block)
61
61
  acquire { |r| r.send(sym, *args, &block) }
@@ -88,7 +88,6 @@ module Polyphony
88
88
  # Acquires a resource from stock, yielding it to the given block.
89
89
  #
90
90
  # @param fiber [Fiber] the fiber the resource will be associated with
91
- # @yield [any] given block
92
91
  # @return [any] return value of block
93
92
  def acquire_from_stock(fiber)
94
93
  add_to_stock if (@stock.empty? || @stock.pending?) && @size < @limit
@@ -17,7 +17,6 @@ module Polyphony
17
17
  # This method is re-entrant. Recursive calls from the given block will not
18
18
  # block.
19
19
  #
20
- # @yield [] code to run
21
20
  # @return [any] return value of block
22
21
  def synchronize(&block)
23
22
  return yield if @holding_fiber == Fiber.current
@@ -64,7 +63,7 @@ module Polyphony
64
63
  # @return [Mutex] self
65
64
  def lock
66
65
  raise ThreadError if owned?
67
-
66
+
68
67
  @token = @store.shift
69
68
  @holding_fiber = Fiber.current
70
69
  self
@@ -3,16 +3,15 @@
3
3
  require 'etc'
4
4
 
5
5
  module Polyphony
6
-
6
+
7
7
  # Implements a pool of threads
8
8
  class ThreadPool
9
-
9
+
10
10
  # The pool size.
11
11
  attr_reader :size
12
12
 
13
13
  # Runs the given block on an available thread from the default thread pool.
14
14
  #
15
- # @yield [] given block
16
15
  # @return [any] return value of given block
17
16
  def self.process(&block)
18
17
  @default_pool ||= new
@@ -41,7 +40,6 @@ module Polyphony
41
40
 
42
41
  # Runs the given block on an available thread from the pool.
43
42
  #
44
- # @yield [] given block
45
43
  # @return [any] return value of block
46
44
  def process(&block)
47
45
  setup unless @task_queue
@@ -55,7 +53,6 @@ module Polyphony
55
53
  # method does not block. The task will be performed once a thread becomes
56
54
  # available.
57
55
  #
58
- # @yield [] given block
59
56
  # @return [Polyphony::ThreadPool] self
60
57
  def cast(&block)
61
58
  setup unless @task_queue
@@ -13,10 +13,6 @@ module Polyphony
13
13
  @next_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
14
14
  end
15
15
 
16
- # call-seq:
17
- # throttler.call { ... }
18
- # throttler.process { ... }
19
- #
20
16
  # Invokes the throttler with the given block. The throttler will
21
17
  # automatically introduce a delay to keep to the maximum specified rate.
22
18
  # The throttler instance is passed to the given block.
@@ -32,7 +28,7 @@ module Polyphony
32
28
  @next_time += @min_dt
33
29
  break if @next_time > now
34
30
  end
35
-
31
+
36
32
  result
37
33
  end
38
34
  alias_method :process, :call
@@ -44,7 +44,6 @@ module Polyphony
44
44
  # given delay.
45
45
  #
46
46
  # @param interval [Number] delay in seconds before running the given block
47
- # @yield [] block to run
48
47
  # @return [Fiber] spun fiber
49
48
  def after(interval, &block)
50
49
  spin do
@@ -57,7 +56,6 @@ module Polyphony
57
56
  # consecutive iterations.
58
57
  #
59
58
  # @param interval [Number] interval between consecutive iterations in seconds
60
- # @yield [] block to run
61
59
  # @return [void]
62
60
  def every(interval)
63
61
  fiber = Fiber.current
@@ -74,14 +72,6 @@ module Polyphony
74
72
  @timeouts.delete(fiber)
75
73
  end
76
74
 
77
- # call-seq:
78
- # timer.cancel_after(interval) { ... }
79
- # timer.cancel_after(interval, with_exception: exception) { ... }
80
- # timer.cancel_after(interval, with_exception: [klass, message]) { ... }
81
- # timer.cancel_after(interval) { |timeout| ... }
82
- # timer.cancel_after(interval, with_exception: exception) { |timeout| ... }
83
- # timer.cancel_after(interval, with_exception: [klass, message]) { |timeout| ... }
84
- #
85
75
  # Runs the given block after setting up a cancellation timer for
86
76
  # cancellation. If the cancellation timer elapses, the execution will be
87
77
  # interrupted with an exception defaulting to `Polyphony::Cancel`.
@@ -108,10 +98,20 @@ module Polyphony
108
98
  # end
109
99
  # end
110
100
  #
111
- # @param interval [Number] timout in seconds
112
- # @param with_exception [Class, Exception] exception or exception class
113
- # @yield [Canceller] block to execute
114
- # @return [any] block's return value
101
+ # @overload cancel_after(interval)
102
+ # @param interval [Number] timout in seconds
103
+ # @yield [Fiber] timeout fiber
104
+ # @return [any] block's return value
105
+ # @overload cancel_after(interval, with_exception: exception)
106
+ # @param interval [Number] timout in seconds
107
+ # @param with_exception [Class, Exception] exception or exception class
108
+ # @yield [Fiber] timeout fiber
109
+ # @return [any] block's return value
110
+ # @overload cancel_after(interval, with_exception: [klass, message])
111
+ # @param interval [Number] timout in seconds
112
+ # @param with_exception [Array] array containing class and message to use as exception
113
+ # @yield [Fiber] timeout fiber
114
+ # @return [any] block's return value
115
115
  def cancel_after(interval, with_exception: Polyphony::Cancel)
116
116
  fiber = Fiber.current
117
117
  @timeouts[fiber] = {
@@ -124,12 +124,6 @@ module Polyphony
124
124
  @timeouts.delete(fiber)
125
125
  end
126
126
 
127
- # call-seq:
128
- # timer.move_on_after(interval) { ... }
129
- # timer.move_on_after(interval, with_value: value) { ... }
130
- # timer.move_on_after(interval) { |canceller| ... }
131
- # timer.move_on_after(interval, with_value: value) { |canceller| ... }
132
- #
133
127
  # Runs the given block after setting up a cancellation timer for
134
128
  # cancellation. If the cancellation timer elapses, the execution will be
135
129
  # interrupted with a `Polyphony::MoveOn` exception, which will be rescued,
@@ -162,10 +156,15 @@ module Polyphony
162
156
  # end
163
157
  # end
164
158
  #
165
- # @param interval [Number] timout in seconds
166
- # @param with_value [any] return value in case of timeout
167
- # @yield [Fiber] block to execute
168
- # @return [any] block's return value
159
+ # @overload move_on_after(interval) { ... }
160
+ # @param interval [Number] timout in seconds
161
+ # @yield [Fiber] timeout fiber
162
+ # @return [any] block's return value
163
+ # @overload move_on_after(interval, with_value: value) { ... }
164
+ # @param interval [Number] timout in seconds
165
+ # @param with_value [any] return value in case of timeout
166
+ # @yield [Fiber] timeout fiber
167
+ # @return [any] block's return value
169
168
  def move_on_after(interval, with_value: nil)
170
169
  fiber = Fiber.current
171
170
  @timeouts[fiber] = {
@@ -218,7 +217,7 @@ module Polyphony
218
217
 
219
218
  # Runs a timer iteration, invoking any timeouts that are due.
220
219
  #
221
- # @return [void]
220
+ # @return [void]
222
221
  def update
223
222
  return if @timeouts.empty?
224
223