polyphony 0.99.5 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,8 +1,289 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../core/global_api'
3
+ require_relative '../core/throttler'
4
4
 
5
5
  # Object extensions (methods available to all objects / call sites)
6
6
  class ::Object
7
- include Polyphony::GlobalAPI
7
+ # Spins up a fiber that will run the given block after sleeping for the
8
+ # given delay.
9
+ #
10
+ # @param interval [Number] delay in seconds before running the given block
11
+ # @return [Fiber] spun fiber
12
+ def after(interval, &block)
13
+ spin do
14
+ sleep interval
15
+ block.()
16
+ end
17
+ end
18
+
19
+ # Runs the given block after setting up a cancellation timer for
20
+ # cancellation. If the cancellation timer elapses, the execution will be
21
+ # interrupted with an exception defaulting to `Polyphony::Cancel`.
22
+ #
23
+ # This method should be used when a timeout should cause an exception to be
24
+ # propagated down the call stack or up the fiber tree.
25
+ #
26
+ # Example of normal use:
27
+ #
28
+ # def read_from_io_with_timeout(io)
29
+ # cancel_after(10) { io.read }
30
+ # rescue Polyphony::Cancel
31
+ # nil
32
+ # end
33
+ #
34
+ # The timeout period can be reset by passing a block that takes a single
35
+ # argument. The block will be provided with the canceller fiber. To reset
36
+ # the timeout, use `Fiber#reset`, as shown in the following example:
37
+ #
38
+ # cancel_after(10) do |timeout|
39
+ # loop do
40
+ # msg = socket.gets
41
+ # timeout.reset
42
+ # handle_msg(msg)
43
+ # end
44
+ # end
45
+ #
46
+ # @overload cancel_after(interval)
47
+ # @param interval [Number] timout in seconds
48
+ # @yield [Fiber] timeout fiber
49
+ # @return [any] block's return value
50
+ # @overload cancel_after(interval, with_exception: exception)
51
+ # @param interval [Number] timout in seconds
52
+ # @param with_exception [Class, Exception] exception or exception class
53
+ # @yield [Fiber] timeout fiber
54
+ # @return [any] block's return value
55
+ # @overload cancel_after(interval, with_exception: [klass, message])
56
+ # @param interval [Number] timout in seconds
57
+ # @param with_exception [Array] array containing class and message to use as exception
58
+ # @yield [Fiber] timeout fiber
59
+ # @return [any] block's return value
60
+ def cancel_after(interval, with_exception: Polyphony::Cancel, &block)
61
+ if block.arity > 0
62
+ cancel_after_with_optional_reset(interval, with_exception, &block)
63
+ else
64
+ Polyphony.backend_timeout(interval, with_exception, &block)
65
+ end
66
+ end
67
+
68
+ # Spins up a new fiber.
69
+ #
70
+ # @param tag [any] optional tag for the new fiber
71
+ # @return [Fiber] new fiber
72
+ def spin(tag = nil, &block)
73
+ Fiber.current.spin(tag, caller, &block)
74
+ end
75
+
76
+ # Spins up a new fiber, running the given block inside an infinite loop. If
77
+ # `rate:` or `interval:` parameters are given, the loop is throttled
78
+ # accordingly.
79
+ #
80
+ # @param tag [any] optional tag for the new fiber
81
+ # @param rate [Number, nil] loop rate (times per second)
82
+ # @param interval [Number, nil] interval between consecutive iterations in seconds
83
+ # @return [Fiber] new fiber
84
+ def spin_loop(tag = nil, rate: nil, interval: nil, &block)
85
+ if rate || interval
86
+ Fiber.current.spin(tag, caller) do
87
+ throttled_loop(rate: rate, interval: interval, &block)
88
+ end
89
+ else
90
+ spin_loop_without_throttling(tag, caller, block)
91
+ end
92
+ end
93
+
94
+ # Runs the given code, then waits for any child fibers of the current fibers
95
+ # to terminate.
96
+ #
97
+ # @return [any] given block's return value
98
+ def spin_scope(&block)
99
+ raise unless block
100
+
101
+ spin do
102
+ result = yield
103
+ Fiber.current.await_all_children
104
+ result
105
+ end.await
106
+ end
107
+
108
+ # Runs the given block in an infinite loop with a regular interval between
109
+ # consecutive iterations.
110
+ #
111
+ # @param interval [Number] interval between consecutive iterations in seconds
112
+ def every(interval, &block)
113
+ Polyphony.backend_timer_loop(interval, &block)
114
+ end
115
+
116
+ # Runs the given block after setting up a cancellation timer for
117
+ # cancellation. If the cancellation timer elapses, the execution will be
118
+ # interrupted with a `Polyphony::MoveOn` exception, which will be rescued,
119
+ # and with cause the operation to return the given value.
120
+ #
121
+ # This method should be used when a timeout is to be handled locally,
122
+ # without generating an exception that is to propagated down the call stack
123
+ # or up the fiber tree.
124
+ #
125
+ # Example of normal use:
126
+ #
127
+ # move_on_after(10) {
128
+ # sleep 60
129
+ # 42
130
+ # } #=> nil
131
+ #
132
+ # move_on_after(10, with_value: :oops) {
133
+ # sleep 60
134
+ # 42
135
+ # } #=> :oops
136
+ #
137
+ # The timeout period can be reset by passing a block that takes a single
138
+ # argument. The block will be provided with the canceller fiber. To reset
139
+ # the timeout, use `Fiber#reset`, as shown in the following example:
140
+ #
141
+ # move_on_after(10) do |timeout|
142
+ # loop do
143
+ # msg = socket.gets
144
+ # timeout.reset
145
+ # handle_msg(msg)
146
+ # end
147
+ # end
148
+ #
149
+ # @overload move_on_after(interval) { ... }
150
+ # @param interval [Number] timout in seconds
151
+ # @yield [Fiber] timeout fiber
152
+ # @return [any] block's return value
153
+ # @overload move_on_after(interval, with_value: value) { ... }
154
+ # @param interval [Number] timout in seconds
155
+ # @param with_value [any] return value in case of timeout
156
+ # @yield [Fiber] timeout fiber
157
+ # @return [any] block's return value
158
+ def move_on_after(interval, with_value: nil, &block)
159
+ if block.arity > 0
160
+ move_on_after_with_optional_reset(interval, with_value, &block)
161
+ else
162
+ Polyphony.backend_timeout(interval, nil, with_value, &block)
163
+ end
164
+ end
165
+
166
+ # Returns the first message from the current fiber's mailbox. If the mailbox
167
+ # is empty, blocks until a message is available.
168
+ #
169
+ # @return [any] received message
170
+ def receive
171
+ Fiber.current.receive
172
+ end
173
+
174
+ # Returns all messages currently pending on the current fiber's mailbox.
175
+ #
176
+ # @return [Array] array of received messages
177
+ def receive_all_pending
178
+ Fiber.current.receive_all_pending
179
+ end
180
+
181
+ # Supervises the current fiber's children. See `Fiber#supervise` for
182
+ # options.
183
+ #
184
+ # @param args [Array] positional parameters
185
+ # @param opts [Hash] named parameters
186
+ # @return [any]
187
+ def supervise(*args, **opts, &block)
188
+ Fiber.current.supervise(*args, **opts, &block)
189
+ end
190
+
191
+ # Sleeps for the given duration. If the duration is `nil`, sleeps
192
+ # indefinitely.
193
+ #
194
+ # @param duration [Number, nil] duration
195
+ # @return [any]
196
+ def sleep(duration = nil)
197
+ duration ?
198
+ Polyphony.backend_sleep(duration) : Polyphony.backend_wait_event(true)
199
+ end
200
+
201
+ # Starts a throttled loop with the given rate. If `count:` is given, the
202
+ # loop is run for the given number of times. Otherwise, the loop is
203
+ # infinite. The loop rate (times per second) can be given as the rate
204
+ # parameter. The throttling can also be controlled by providing an
205
+ # `interval:` or `rate:` named parameter.
206
+ #
207
+ # @param rate [Number, nil] loop rate (times per second)
208
+ # @option opts [Number] :rate loop rate (times per second)
209
+ # @option opts [Number] :interval loop interval in seconds
210
+ # @option opts [Number] :count number of iterations (nil for infinite)
211
+ # @return [any]
212
+ def throttled_loop(rate = nil, **opts, &block)
213
+ throttler = Polyphony::Throttler.new(rate || opts)
214
+ if opts[:count]
215
+ opts[:count].times { |_i| throttler.(&block) }
216
+ else
217
+ while true
218
+ throttler.(&block)
219
+ end
220
+ end
221
+ rescue LocalJumpError, StopIteration
222
+ # break called or StopIteration raised
223
+ end
224
+
225
+ private
226
+
227
+ # Helper method for performing a `cancel_after` with optional reset.
228
+ #
229
+ # @param interval [Number] timeout interval in seconds
230
+ # @param exception [Exception, Class, Array<class, message>] exception spec
231
+ # @return [any] block's return value
232
+ def cancel_after_with_optional_reset(interval, exception, &block)
233
+ fiber = Fiber.current
234
+ canceller = spin do
235
+ Polyphony.backend_sleep(interval)
236
+ exception = cancel_exception(exception)
237
+ exception.raising_fiber = Fiber.current
238
+ fiber.cancel(exception)
239
+ end
240
+ block.call(canceller)
241
+ ensure
242
+ canceller.stop
243
+ end
244
+
245
+ # Converts the given exception spec to an exception instance.
246
+ #
247
+ # @param exception [Exception, Class, Array<class, message>] exception spec
248
+ # @return [Exception] exception instance
249
+ def cancel_exception(exception)
250
+ case exception
251
+ when Class then exception.new
252
+ when Array then exception[0].new(exception[1])
253
+ else RuntimeError.new(exception)
254
+ end
255
+ end
256
+
257
+ # Helper method for performing `#spin_loop` without throttling. Spins up a
258
+ # new fiber in which to run the loop.
259
+ #
260
+ # @param tag [any] new fiber's tag
261
+ # @param caller [Array<String>] caller info
262
+ # @param block [Proc] code to run
263
+ # @return [any]
264
+ def spin_loop_without_throttling(tag, caller, block)
265
+ Fiber.current.spin(tag, caller) do
266
+ block.call while true
267
+ rescue LocalJumpError, StopIteration
268
+ # break called or StopIteration raised
269
+ end
270
+ end
271
+
272
+ # Helper method for performing `#move_on_after` with optional reset.
273
+ #
274
+ # @param interval [Number] timeout interval in seconds
275
+ # @param value [any] return value in case of timeout
276
+ # @return [any] return value of given block or timeout value
277
+ def move_on_after_with_optional_reset(interval, value, &block)
278
+ fiber = Fiber.current
279
+ canceller = spin do
280
+ sleep interval
281
+ fiber.move_on(value)
282
+ end
283
+ block.call(canceller)
284
+ rescue Polyphony::MoveOn => e
285
+ e.value
286
+ ensure
287
+ canceller.stop
288
+ end
8
289
  end
@@ -17,7 +17,6 @@ class ::OpenSSL::SSL::SSLSocket
17
17
  #
18
18
  # @param socket [TCPSocket] socket to wrap
19
19
  # @param context [OpenSSL::SSL::SSLContext] optional SSL context
20
- # @return [void]
21
20
  def initialize(socket, context = nil)
22
21
  socket = socket.respond_to?(:io) ? socket.io || socket : socket
23
22
  context ? orig_initialize(socket, context) : orig_initialize(socket)
@@ -155,7 +154,7 @@ class ::OpenSSL::SSL::SSLSocket
155
154
  #
156
155
  # @param maxlen [Integer] maximum bytes to receive
157
156
  # @yield [String] read data
158
- # @return [void]
157
+ # @return [OpenSSL::SSL::SSLSocket] self
159
158
  def read_loop(maxlen = 8192)
160
159
  while (data = sysread(maxlen))
161
160
  yield data
@@ -263,8 +262,9 @@ class ::OpenSSL::SSL::SSLServer
263
262
 
264
263
  # Accepts incoming connections in an infinite loop.
265
264
  #
265
+ # @param ignore_errors [boolean] whether to ignore IO and SSL errors
266
266
  # @yield [OpenSSL::SSL::SSLSocket] accepted socket
267
- # @return [void]
267
+ # @return [OpenSSL::SSL::SSLServer] self
268
268
  def accept_loop(ignore_errors = true)
269
269
  loop do
270
270
  yield accept
@@ -178,7 +178,7 @@ class Polyphony::Pipe
178
178
  #
179
179
  # @param maxlen [Integer] maximum bytes to read
180
180
  # @yield [String] read data
181
- # @return [void]
181
+ # @return [Polyphony::Pipe] self
182
182
  def read_loop(maxlen = 8192, &block)
183
183
  Polyphony.backend_read_loop(self, maxlen, &block)
184
184
  end
@@ -199,7 +199,7 @@ class Polyphony::Pipe
199
199
  #
200
200
  # @param receiver [any] receiver object
201
201
  # @param method [Symbol] method to call
202
- # @return [void]
202
+ # @return [Polyphony::Pipe] self
203
203
  def feed_loop(receiver, method = :call, &block)
204
204
  Polyphony.backend_feed_loop(self, receiver, method, &block)
205
205
  end
@@ -37,7 +37,7 @@ class ::Socket < ::BasicSocket
37
37
  # Accepts incoming connections in an infinite loop.
38
38
  #
39
39
  # @yield [Socket] accepted socket
40
- # @return [void]
40
+ # @return [nil]
41
41
  def accept_loop(&block)
42
42
  Polyphony.backend_accept_loop(self, TCPSocket, &block)
43
43
  end
@@ -109,7 +109,7 @@ class ::Socket < ::BasicSocket
109
109
  #
110
110
  # @param maxlen [Integer] maximum bytes to receive
111
111
  # @yield [String] received data
112
- # @return [void]
112
+ # @return [Socket] self
113
113
  def recv_loop(maxlen = 8192, &block)
114
114
  Polyphony.backend_recv_loop(self, maxlen, &block)
115
115
  end
@@ -131,7 +131,7 @@ class ::Socket < ::BasicSocket
131
131
  #
132
132
  # @param receiver [any] receiver object
133
133
  # @param method [Symbol] method to call
134
- # @return [void]
134
+ # @return [Socket] self
135
135
  def feed_loop(receiver, method = :call, &block)
136
136
  Polyphony.backend_recv_feed_loop(self, receiver, method, &block)
137
137
  end
@@ -376,7 +376,7 @@ class ::TCPSocket < ::IPSocket
376
376
  #
377
377
  # @param maxlen [Integer] maximum bytes to receive
378
378
  # @yield [String] received data
379
- # @return [void]
379
+ # @return [Socket] self
380
380
  def recv_loop(maxlen = 8192, &block)
381
381
  Polyphony.backend_recv_loop(self, maxlen, &block)
382
382
  end
@@ -398,7 +398,7 @@ class ::TCPSocket < ::IPSocket
398
398
  #
399
399
  # @param receiver [any] receiver object
400
400
  # @param method [Symbol] method to call
401
- # @return [void]
401
+ # @return [Socket] self
402
402
  def feed_loop(receiver, method = :call, &block)
403
403
  Polyphony.backend_recv_feed_loop(self, receiver, method, &block)
404
404
  end
@@ -494,7 +494,7 @@ class ::TCPServer < ::TCPSocket
494
494
  # Accepts incoming connections in an infinite loop.
495
495
  #
496
496
  # @yield [TCPSocket] accepted socket
497
- # @return [void]
497
+ # @return [nil]
498
498
  def accept_loop(&block)
499
499
  Polyphony.backend_accept_loop(@io, TCPSocket, &block)
500
500
  end
@@ -526,7 +526,7 @@ class ::UNIXServer < ::UNIXSocket
526
526
  # Accepts incoming connections in an infinite loop.
527
527
  #
528
528
  # @yield [UNIXSocket] accepted socket
529
- # @return [void]
529
+ # @return [nil]
530
530
  def accept_loop(&block)
531
531
  Polyphony.backend_accept_loop(self, UNIXSocket, &block)
532
532
  end
@@ -588,7 +588,7 @@ class ::UNIXSocket < ::BasicSocket
588
588
  #
589
589
  # @param maxlen [Integer] maximum bytes to receive
590
590
  # @yield [String] received data
591
- # @return [void]
591
+ # @return [Socket] self
592
592
  def recv_loop(maxlen = 8192, &block)
593
593
  Polyphony.backend_recv_loop(self, maxlen, &block)
594
594
  end
@@ -610,7 +610,7 @@ class ::UNIXSocket < ::BasicSocket
610
610
  #
611
611
  # @param receiver [any] receiver object
612
612
  # @param method [Symbol] method to call
613
- # @return [void]
613
+ # @return [Socket] self
614
614
  def feed_loop(receiver, method = :call, &block)
615
615
  Polyphony.backend_recv_feed_loop(self, receiver, method, &block)
616
616
  end
@@ -12,7 +12,6 @@ class ::Thread
12
12
 
13
13
  # Initializes the thread.
14
14
  # @param args [Array] arguments to pass to thread block
15
- # @return [void]
16
15
  def initialize(*args, &block)
17
16
  @join_wait_queue = []
18
17
  @finalization_mutex = Mutex.new
@@ -23,11 +22,12 @@ class ::Thread
23
22
 
24
23
  # Sets up the thread and its main fiber.
25
24
  #
26
- # @return [void]
25
+ # @return [Thread] self
27
26
  def setup
28
27
  @main_fiber = Fiber.current
29
28
  @main_fiber.setup_main_fiber
30
29
  setup_fiber_scheduling
30
+ self
31
31
  end
32
32
 
33
33
  # @!visibility private
@@ -133,7 +133,7 @@ class ::Thread
133
133
 
134
134
  # Runs the thread's block, handling any uncaught exceptions.
135
135
  #
136
- # @return [void]
136
+ # @return [any] thread result value
137
137
  def execute
138
138
  # backend must be created in the context of the new thread, therefore it
139
139
  # cannot be created in Thread#initialize
@@ -159,7 +159,6 @@ class ::Thread
159
159
  # Finalizes the thread.
160
160
  #
161
161
  # @param result [any] thread's return value
162
- # @return [void]
163
162
  def finalize(result)
164
163
  unless Fiber.current.children.empty?
165
164
  Fiber.current.shutdown_all_children
@@ -175,7 +174,6 @@ class ::Thread
175
174
  # Signals all fibers waiting for the thread to terminate.
176
175
  #
177
176
  # @param result [any] thread's return value
178
- # @return [void]
179
177
  def signal_waiters(result)
180
178
  @join_wait_queue.each { |w| w.signal(result) }
181
179
  end
data/lib/polyphony/net.rb CHANGED
@@ -57,7 +57,6 @@ module Polyphony
57
57
  #
58
58
  # @param context [SSLContext] SSL context
59
59
  # @param protocols [Array] array of supported protocols
60
- # @return [void]
61
60
  def setup_alpn(context, protocols)
62
61
  context.alpn_protocols = protocols
63
62
  context.alpn_select_cb = lambda do |peer_protocols|
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Polyphony
4
4
  # @!visibility private
5
- VERSION = '0.99.5'
5
+ VERSION = '1.0'
6
6
  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.99.5
4
+ version: '1.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: 2023-05-10 00:00:00.000000000 Z
11
+ date: 2023-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -144,9 +144,6 @@ files:
144
144
  - README.md
145
145
  - Rakefile
146
146
  - TODO.md
147
- - assets/echo-fibers.svg
148
- - assets/polyphony-logo.png
149
- - assets/sleeping-fiber.svg
150
147
  - bin/pdbg
151
148
  - bin/polyphony-debug
152
149
  - bin/stress.rb
@@ -154,15 +151,15 @@ files:
154
151
  - docs/_user-guide/all-about-timers.md
155
152
  - docs/_user-guide/index.md
156
153
  - docs/_user-guide/web-server.md
154
+ - docs/assets/echo-fibers.svg
155
+ - docs/assets/polyphony-logo.png
156
+ - docs/assets/sleeping-fiber.svg
157
157
  - docs/concurrency.md
158
158
  - docs/design-principles.md
159
159
  - docs/exception-handling.md
160
160
  - docs/extending.md
161
161
  - docs/faq.md
162
162
  - docs/fiber-scheduling.md
163
- - docs/index.md
164
- - docs/link_rewriter.rb
165
- - docs/main-concepts/index.md
166
163
  - docs/overview.md
167
164
  - docs/readme.md
168
165
  - docs/tutorial.md
@@ -335,7 +332,6 @@ files:
335
332
  - lib/polyphony/core/channel.rb
336
333
  - lib/polyphony/core/debug.rb
337
334
  - lib/polyphony/core/exceptions.rb
338
- - lib/polyphony/core/global_api.rb
339
335
  - lib/polyphony/core/resource_pool.rb
340
336
  - lib/polyphony/core/sync.rb
341
337
  - lib/polyphony/core/thread_pool.rb
data/docs/index.md DELETED
@@ -1,94 +0,0 @@
1
- ---
2
- layout: page
3
- title: Home
4
- nav_order: 1
5
- permalink: /
6
- next_title: Installing Polyphony
7
- ---
8
-
9
- <p align="center"><img src="{{ 'polyphony-logo.png' | absolute_url }}" /></p>
10
-
11
- # Polyphony
12
- {:.text-center .logo-title}
13
-
14
- ## Fine-grained concurrency for Ruby
15
- {:.text-center .logo-title}
16
-
17
- Polyphony is a library for building concurrent applications in Ruby. Polyphony
18
- implements a comprehensive
19
- [fiber](https://ruby-doc.org/core-2.5.1/Fiber.html)-based concurrency model,
20
- using [libev](https://github.com/enki/libev) as a high-performance event reactor
21
- for I/O, timers, and other asynchronous events.
22
-
23
- [Overview](getting-started/overview){: .btn .btn-green .text-gamma }
24
- [Take the tutorial](getting-started/tutorial){: .btn .btn-blue .text-gamma }
25
- [Source code](https://github.com/digital-fabric/polyphony){: .btn .btn-purple .text-gamma target="_blank" }
26
- {:.text-center .mt-6 .h-align-center }
27
-
28
- ## Focused on Developer Happiness
29
-
30
- Polyphony is designed to make concurrent Ruby programming feel natural and
31
- fluent. The Polyphony API is easy to use, easy to understand, and above all
32
- idiomatic.
33
-
34
- ## Optimized for High Performance
35
-
36
- Polyphony offers high performance for I/O bound Ruby apps. Distributing
37
- concurrent operations over fibers, instead of threads or processes, minimizes
38
- memory consumption and reduces the cost of context-switching.
39
-
40
- ## Designed for Interoperability
41
-
42
- With Polyphony you can use any of the stock Ruby classes and modules like `IO`,
43
- `Process`, `Socket` and `OpenSSL` in a concurrent multi-fiber environment. In
44
- addition, Polyphony provides a structured model for exception handling that
45
- builds on and enhances Ruby's exception handling system.
46
-
47
- ## A Growing Ecosystem
48
-
49
- Polyphony includes a full-blown HTTP server implementation with integrated
50
- support for HTTP 2, WebSockets, TLS/SSL termination and more. Polyphony also
51
- provides fiber-aware adapters for connecting to PostgreSQL and Redis. More
52
- adapters are being developed.
53
-
54
- ## Features
55
-
56
- * Co-operative scheduling of concurrent tasks using Ruby fibers.
57
- * High-performance event reactor for handling I/O events and timers.
58
- * Natural, sequential programming style that makes it easy to reason about
59
- concurrent code.
60
- * Abstractions and constructs for controlling the execution of concurrent code:
61
- supervisors, throttling, resource pools etc.
62
- * Code can use native networking classes and libraries, growing support for
63
- third-party gems such as `pg` and `redis`.
64
- * Use stdlib classes such as `TCPServer` and `TCPSocket` and `Net::HTTP`.
65
- * Competitive performance and scalability characteristics, in terms of both
66
- throughput and memory consumption.
67
-
68
- ## Prior Art
69
-
70
- Polyphony draws inspiration from the following, in no particular order:
71
-
72
- * [nio4r](https://github.com/socketry/nio4r/) and
73
- [async](https://github.com/socketry/async) (Polyphony's C-extension code
74
- started as a spinoff of
75
- [nio4r's](https://github.com/socketry/nio4r/tree/master/ext))
76
- * The [go scheduler](https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part2.html)
77
- * [EventMachine](https://github.com/eventmachine/eventmachine)
78
- * [Trio](https://trio.readthedocs.io/)
79
- * [Erlang supervisors](http://erlang.org/doc/man/supervisor.html) (and actually,
80
- Erlang in general)
81
-
82
- ## Developer Resources
83
-
84
- * [Tutorial](getting-started/tutorial)
85
- * [Main Concepts](main-concepts/concurrency/)
86
- * [User Guide](user-guide/all-about-timers/)
87
- * [API Reference](api-reference/exception/)
88
- * [Examples](https://github.com/digital-fabric/polyphony/tree/9e0f3b09213156bdf376ef33684ef267517f06e8/examples/README.md)
89
-
90
- ## Contributing to Polyphony
91
-
92
- Issues and pull requests will be gladly accepted. Please use the [Polyphony git
93
- repository](https://github.com/digital-fabric/polyphony) as your primary point
94
- of departure for contributing.
@@ -1,17 +0,0 @@
1
- require 'yard'
2
-
3
- # shamelessly copied from https://github.com/troessner/reek/blob/master/docs/yard_plugin.rb
4
-
5
- # Template helper to modify processing of links in HTML generated from our
6
- # markdown files.
7
- module LocalLinkHelper
8
- # Rewrites links to (assumed local) markdown files so they're processed as
9
- # {file: } directives.
10
- def resolve_links(text)
11
- text = text.gsub(%r{<a href="(docs/[^"]*.md)">([^<]*)</a>}, '{file:/\1 \2}')
12
- .gsub(%r{<img src="(assets/[^"]*)">}, '{rdoc-image:/\1}')
13
- super text
14
- end
15
- end
16
-
17
- YARD::Templates::Template.extra_includes << LocalLinkHelper
@@ -1,9 +0,0 @@
1
- ---
2
- layout: page
3
- title: Main Concepts
4
- has_children: true
5
- nav_order: 3
6
- ---
7
-
8
- # Main Concepts
9
- {: .no_toc }