polyphony 0.99.4 → 0.99.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +11 -0
  3. data/.yardopts +0 -2
  4. data/README.md +1 -1
  5. data/docs/readme.md +1 -1
  6. data/docs/tutorial.md +2 -2
  7. data/examples/pipes/gzip_http_server.rb +2 -2
  8. data/examples/pipes/http_server.rb +1 -1
  9. data/examples/pipes/tcp_proxy.rb +1 -1
  10. data/ext/polyphony/backend_common.c +4 -4
  11. data/ext/polyphony/backend_io_uring.c +8 -8
  12. data/ext/polyphony/backend_libev.c +5 -5
  13. data/ext/polyphony/fiber.c +33 -42
  14. data/ext/polyphony/io_extensions.c +50 -37
  15. data/ext/polyphony/pipe.c +6 -20
  16. data/ext/polyphony/polyphony.c +72 -144
  17. data/ext/polyphony/queue.c +23 -63
  18. data/ext/polyphony/thread.c +4 -13
  19. data/lib/polyphony/adapters/process.rb +2 -5
  20. data/lib/polyphony/adapters/sequel.rb +2 -2
  21. data/lib/polyphony/core/debug.rb +1 -4
  22. data/lib/polyphony/core/exceptions.rb +1 -5
  23. data/lib/polyphony/core/resource_pool.rb +7 -8
  24. data/lib/polyphony/core/sync.rb +5 -8
  25. data/lib/polyphony/core/thread_pool.rb +3 -10
  26. data/lib/polyphony/core/throttler.rb +1 -5
  27. data/lib/polyphony/core/timer.rb +23 -30
  28. data/lib/polyphony/extensions/fiber.rb +513 -543
  29. data/lib/polyphony/extensions/io.rb +5 -14
  30. data/lib/polyphony/extensions/object.rb +283 -2
  31. data/lib/polyphony/extensions/openssl.rb +5 -26
  32. data/lib/polyphony/extensions/pipe.rb +6 -17
  33. data/lib/polyphony/extensions/socket.rb +24 -118
  34. data/lib/polyphony/extensions/thread.rb +3 -18
  35. data/lib/polyphony/extensions/timeout.rb +0 -1
  36. data/lib/polyphony/net.rb +5 -9
  37. data/lib/polyphony/version.rb +1 -1
  38. data/lib/polyphony.rb +2 -6
  39. data/test/test_io.rb +221 -221
  40. data/test/test_socket.rb +3 -3
  41. data/test/test_trace.rb +2 -2
  42. metadata +5 -9
  43. data/docs/index.md +0 -94
  44. data/docs/link_rewriter.rb +0 -17
  45. data/docs/main-concepts/index.md +0 -9
  46. data/lib/polyphony/core/global_api.rb +0 -309
  47. /data/{assets → docs/assets}/echo-fibers.svg +0 -0
  48. /data/{assets → docs/assets}/polyphony-logo.png +0 -0
  49. /data/{assets → docs/assets}/sleeping-fiber.svg +0 -0
@@ -19,11 +19,8 @@ inline void schedule_fiber(VALUE self, VALUE fiber, VALUE value, int prioritize)
19
19
  Backend_schedule_fiber(self, rb_ivar_get(self, ID_ivar_backend), fiber, value, prioritize);
20
20
  }
21
21
 
22
- /* call-seq:
23
- * thread.unschedule_fiber(fiber)
22
+ /* Removes the given fiber from the thread's runqueue.
24
23
  *
25
- * Removes the given fiber from the thread's runqueue.
26
- *
27
24
  * @param fiber [Fiber] fiber to unschedule
28
25
  * @return [Thread] self
29
26
  */
@@ -45,12 +42,9 @@ inline void Thread_schedule_fiber_with_priority(VALUE self, VALUE fiber, VALUE v
45
42
  // schedule_fiber(self, fiber, value, 1);
46
43
  }
47
44
 
48
- /* call-seq:
49
- * thread.switch_fiber()
45
+ /* Switches to the next fiber in the thread's runqueue.
50
46
  *
51
- * Switches to the next fiber in the thread's runqueue.
52
- *
53
- * @return [void]
47
+ * @return [any] resume value
54
48
  */
55
49
 
56
50
  VALUE Thread_switch_fiber(VALUE self) {
@@ -80,11 +74,8 @@ VALUE Thread_debug(VALUE self) {
80
74
  return self;
81
75
  }
82
76
 
83
- /* call-seq:
84
- * Thread.backend
77
+ /* Returns the backend for the current thread.
85
78
  *
86
- * Returns the backend for the current thread.
87
- *
88
79
  * @return [Polyphony::Backend] backend for the current thread
89
80
  */
90
81
 
@@ -8,13 +8,12 @@ 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
- # @return [void]
16
+ # @return [true]
18
17
  def watch(cmd = nil, &block)
19
18
  terminated = nil
20
19
  pid = cmd ? Kernel.spawn(cmd) : Polyphony.fork(&block)
@@ -28,7 +27,6 @@ module Polyphony
28
27
  # seconds.
29
28
  #
30
29
  # @param pid [Integer] pid
31
- # @return [void]
32
30
  def kill_process(pid)
33
31
  cancel_after(5) do
34
32
  kill_and_await('TERM', pid)
@@ -43,7 +41,6 @@ module Polyphony
43
41
  #
44
42
  # @param sig [String, Symbol, Integer] signal to use
45
43
  # @param pid [Integer] pid
46
- # @return [void]
47
44
  def kill_and_await(sig, pid)
48
45
  ::Process.kill(sig, pid)
49
46
  Polyphony.backend_waitpid(pid)
@@ -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
@@ -1,8 +1,6 @@
1
1
  # Kernel extensions
2
2
  module ::Kernel
3
3
  # Prints a trace message to `STDOUT`, bypassing the Polyphony backend.
4
- #
5
- # @return [void]
6
4
  def trace(*args)
7
5
  STDOUT.orig_write(format_trace(args))
8
6
  end
@@ -32,8 +30,7 @@ module Polyphony
32
30
  # If an IO instance is given, events are dumped to it instead.
33
31
  #
34
32
  # @param io [IO, nil] IO instance
35
- # @yield [Hash] event handler block
36
- # @return [void]
33
+ # @yield [Hash] event information
37
34
  def start_event_firehose(io = nil, &block)
38
35
  Thread.backend.trace_proc = firehose_proc(io, block)
39
36
  end
@@ -16,7 +16,6 @@ module Polyphony
16
16
  # Initializes the exception, setting the caller and the value.
17
17
  #
18
18
  # @param value [any] Exception value
19
- # @return [void]
20
19
  def initialize(value = nil)
21
20
  @caller_backtrace = caller
22
21
  @value = value
@@ -40,18 +39,15 @@ module Polyphony
40
39
 
41
40
  # Interjection is used to run arbitrary code on arbitrary fibers at any point
42
41
  class Interjection < BaseException
43
-
42
+
44
43
  # Initializes an Interjection with the given proc.
45
44
  #
46
45
  # @param proc [Proc] interjection proc
47
- # @return [void]
48
46
  def initialize(proc)
49
47
  @proc = proc
50
48
  end
51
49
 
52
50
  # Invokes the exception by calling the associated proc.
53
- #
54
- # @return [void]
55
51
  def invoke
56
52
  @proc.call
57
53
  end
@@ -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
@@ -28,7 +27,7 @@ module Polyphony
28
27
  # Conditionally releases the mutex. This method is used by condition
29
28
  # variables.
30
29
  #
31
- # @return [void]
30
+ # @return [nil]
32
31
  def conditional_release
33
32
  @store << @token
34
33
  @token = nil
@@ -38,7 +37,7 @@ module Polyphony
38
37
  # Conditionally reacquires the mutex. This method is used by condition
39
38
  # variables.
40
39
  #
41
- # @return [void]
40
+ # @return [Fiber] current fiber
42
41
  def conditional_reacquire
43
42
  @token = @store.shift
44
43
  @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
@@ -141,7 +140,7 @@ module Polyphony
141
140
  #
142
141
  # @param mutex [Polyphony::Mutex] mutex to release while waiting for signal
143
142
  # @param _timeout [Number, nil] timeout in seconds (currently not implemented)
144
- # @return [void]
143
+ # @return [any]
145
144
  def wait(mutex, _timeout = nil)
146
145
  mutex.conditional_release
147
146
  @queue << Fiber.current
@@ -152,7 +151,7 @@ module Polyphony
152
151
  # Signals the condition variable, causing the first fiber in the waiting
153
152
  # queue to be resumed.
154
153
  #
155
- # @return [void]
154
+ # @return [Fiber] resumed fiber
156
155
  def signal
157
156
  return if @queue.empty?
158
157
 
@@ -161,8 +160,6 @@ module Polyphony
161
160
  end
162
161
 
163
162
  # Resumes all waiting fibers.
164
- #
165
- # @return [void]
166
163
  def broadcast
167
164
  return if @queue.empty?
168
165
 
@@ -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
@@ -21,7 +20,7 @@ module Polyphony
21
20
 
22
21
  # Resets the default thread pool.
23
22
  #
24
- # @return [void]
23
+ # @return [nil]
25
24
  def self.reset
26
25
  return unless @default_pool
27
26
 
@@ -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
@@ -81,8 +78,6 @@ module Polyphony
81
78
  private
82
79
 
83
80
  # Runs a processing loop on a worker thread.
84
- #
85
- # @return [void]
86
81
  def thread_loop
87
82
  while true
88
83
  run_queued_task
@@ -90,8 +85,6 @@ module Polyphony
90
85
  end
91
86
 
92
87
  # Runs the first queued task in the task queue.
93
- #
94
- # @return [void]
95
88
  def run_queued_task
96
89
  (block, watcher) = @task_queue.shift
97
90
  result = block.()
@@ -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
@@ -28,7 +28,6 @@ module Polyphony
28
28
  # Sleeps for the given duration.
29
29
  #
30
30
  # @param duration [Number] sleep duration in seconds
31
- # @return [void]
32
31
  def sleep(duration)
33
32
  fiber = Fiber.current
34
33
  @timeouts[fiber] = {
@@ -44,7 +43,6 @@ module Polyphony
44
43
  # given delay.
45
44
  #
46
45
  # @param interval [Number] delay in seconds before running the given block
47
- # @yield [] block to run
48
46
  # @return [Fiber] spun fiber
49
47
  def after(interval, &block)
50
48
  spin do
@@ -57,8 +55,6 @@ module Polyphony
57
55
  # consecutive iterations.
58
56
  #
59
57
  # @param interval [Number] interval between consecutive iterations in seconds
60
- # @yield [] block to run
61
- # @return [void]
62
58
  def every(interval)
63
59
  fiber = Fiber.current
64
60
  @timeouts[fiber] = {
@@ -74,14 +70,6 @@ module Polyphony
74
70
  @timeouts.delete(fiber)
75
71
  end
76
72
 
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
73
  # Runs the given block after setting up a cancellation timer for
86
74
  # cancellation. If the cancellation timer elapses, the execution will be
87
75
  # interrupted with an exception defaulting to `Polyphony::Cancel`.
@@ -108,10 +96,20 @@ module Polyphony
108
96
  # end
109
97
  # end
110
98
  #
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
99
+ # @overload cancel_after(interval)
100
+ # @param interval [Number] timout in seconds
101
+ # @yield [Fiber] timeout fiber
102
+ # @return [any] block's return value
103
+ # @overload cancel_after(interval, with_exception: exception)
104
+ # @param interval [Number] timout in seconds
105
+ # @param with_exception [Class, Exception] exception or exception class
106
+ # @yield [Fiber] timeout fiber
107
+ # @return [any] block's return value
108
+ # @overload cancel_after(interval, with_exception: [klass, message])
109
+ # @param interval [Number] timout in seconds
110
+ # @param with_exception [Array] array containing class and message to use as exception
111
+ # @yield [Fiber] timeout fiber
112
+ # @return [any] block's return value
115
113
  def cancel_after(interval, with_exception: Polyphony::Cancel)
116
114
  fiber = Fiber.current
117
115
  @timeouts[fiber] = {
@@ -124,12 +122,6 @@ module Polyphony
124
122
  @timeouts.delete(fiber)
125
123
  end
126
124
 
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
125
  # Runs the given block after setting up a cancellation timer for
134
126
  # cancellation. If the cancellation timer elapses, the execution will be
135
127
  # interrupted with a `Polyphony::MoveOn` exception, which will be rescued,
@@ -162,10 +154,15 @@ module Polyphony
162
154
  # end
163
155
  # end
164
156
  #
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
157
+ # @overload move_on_after(interval) { ... }
158
+ # @param interval [Number] timout in seconds
159
+ # @yield [Fiber] timeout fiber
160
+ # @return [any] block's return value
161
+ # @overload move_on_after(interval, with_value: value) { ... }
162
+ # @param interval [Number] timout in seconds
163
+ # @param with_value [any] return value in case of timeout
164
+ # @yield [Fiber] timeout fiber
165
+ # @return [any] block's return value
169
166
  def move_on_after(interval, with_value: nil)
170
167
  fiber = Fiber.current
171
168
  @timeouts[fiber] = {
@@ -181,8 +178,6 @@ module Polyphony
181
178
  end
182
179
 
183
180
  # Resets the timeout for the current fiber.
184
- #
185
- # @return [void]
186
181
  def reset
187
182
  record = @timeouts[Fiber.current]
188
183
  return unless record
@@ -217,8 +212,6 @@ module Polyphony
217
212
  end
218
213
 
219
214
  # Runs a timer iteration, invoking any timeouts that are due.
220
- #
221
- # @return [void]
222
215
  def update
223
216
  return if @timeouts.empty?
224
217