polyphony 0.71 → 0.72
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/.github/FUNDING.yml +1 -0
- data/CHANGELOG.md +18 -4
- data/Gemfile.lock +1 -1
- data/TODO.md +1 -1
- data/bin/pdbg +1 -1
- data/bin/polyphony-debug +0 -0
- data/bin/stress.rb +0 -0
- data/bin/test +0 -0
- data/docs/_user-guide/all-about-timers.md +1 -1
- data/docs/api-reference/fiber.md +2 -2
- data/docs/faq.md +1 -1
- data/docs/getting-started/overview.md +8 -8
- data/docs/getting-started/tutorial.md +3 -3
- data/docs/main-concepts/concurrency.md +1 -1
- data/docs/main-concepts/extending.md +3 -3
- data/docs/main-concepts/fiber-scheduling.md +1 -1
- data/examples/core/calc.rb +37 -0
- data/examples/core/calc_with_restart.rb +40 -0
- data/examples/core/calc_with_supervise.rb +37 -0
- data/examples/core/message_based_supervision.rb +1 -1
- data/examples/io/rack_server.rb +1 -1
- data/examples/io/tunnel.rb +1 -1
- data/examples/performance/fiber_transfer.rb +1 -1
- data/examples/performance/line_splitting.rb +1 -1
- data/examples/performance/thread-vs-fiber/compare.rb +1 -1
- data/ext/polyphony/backend_common.c +8 -8
- data/ext/polyphony/backend_io_uring.c +26 -33
- data/ext/polyphony/backend_io_uring_context.c +1 -1
- data/ext/polyphony/backend_io_uring_context.h +1 -1
- data/ext/polyphony/backend_libev.c +11 -11
- data/ext/polyphony/extconf.rb +24 -13
- data/ext/polyphony/queue.c +2 -2
- data/ext/polyphony/runqueue_ring_buffer.c +3 -2
- data/lib/polyphony/adapters/irb.rb +11 -1
- data/lib/polyphony/core/global_api.rb +3 -3
- data/lib/polyphony/core/timer.rb +2 -2
- data/lib/polyphony/debugger.rb +3 -3
- data/lib/polyphony/extensions/fiber.rb +19 -8
- data/lib/polyphony/extensions/io.rb +2 -2
- data/lib/polyphony/extensions/openssl.rb +20 -5
- data/lib/polyphony/extensions/socket.rb +3 -4
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -1
- data/test/coverage.rb +2 -2
- data/test/test_backend.rb +12 -12
- data/test/test_event.rb +1 -1
- data/test/test_ext.rb +1 -1
- data/test/test_fiber.rb +31 -7
- data/test/test_global_api.rb +2 -2
- data/test/test_io.rb +3 -3
- data/test/test_queue.rb +6 -6
- data/test/test_socket.rb +12 -10
- data/test/test_supervise.rb +85 -0
- data/test/test_sync.rb +2 -2
- data/test/test_thread.rb +22 -2
- data/test/test_thread_pool.rb +1 -1
- data/test/test_throttler.rb +1 -1
- data/test/test_timer.rb +2 -2
- data/test/test_trace.rb +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2af189faeecbe2eecb367a7400005306ab74370e56c61de1d703edd40d851d92
|
4
|
+
data.tar.gz: c0888b10d03b9bf29f1d10a41b0050231db655c587d06035039b4c09e1c68baa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b86fd5682ce52e635658a8d620031f8ae841ef5f7876d6239f74772d8f700054eb3bb7732488e246433a91e5ab4279479c6f18bb0d1a154172d90f351ab8149e
|
7
|
+
data.tar.gz: 713ba61a64ef73c5c16971bd0d678d6575b7bd37062a29348f02ec8e0578821d7ec41f826f1868cd017bede9c70d47192e19a0217469b331f17ff66afac21054
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
github: ciconia
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 0.72 2021-11-22
|
2
|
+
|
3
|
+
- Add support for supervising added child fibers
|
4
|
+
- Do not use io_uring under LinuxKit (#66)
|
5
|
+
- Fix error message in `Fiber#restart`
|
6
|
+
- refactor `runqueue_ring_buffer_mark`
|
7
|
+
- Fix setting up test server on random port
|
8
|
+
- Enhance `Fiber#supervise`
|
9
|
+
- Add support for specifying `restart: true` (same as `restart: :always`)
|
10
|
+
- Add support for supervising child fibers (when fibers are not specified)
|
11
|
+
- Add `Fiber#attach_all_children_to`
|
12
|
+
- Improve `SSLServer#accept` when `servername_cb` is set
|
13
|
+
- Fix `#supervise` in Ruby 3.0
|
14
|
+
|
1
15
|
## 0.71 2021-08-20
|
2
16
|
|
3
17
|
- Fix compilation on Ruby 3.0
|
@@ -27,7 +41,7 @@
|
|
27
41
|
## 0.66 2021-08-01
|
28
42
|
|
29
43
|
- Fix all splicing APIs on non-linux OSes (#63)
|
30
|
-
- Add GC marking of buffers when cancelling read/write ops in io_uring backend
|
44
|
+
- Add GC marking of buffers when cancelling read/write ops in io_uring backend
|
31
45
|
|
32
46
|
## 0.65 2021-07-29
|
33
47
|
|
@@ -91,7 +105,7 @@
|
|
91
105
|
## 0.55.0 2021-06-17
|
92
106
|
|
93
107
|
- Finish io_uring implementation of Backend#chain
|
94
|
-
- Reimplement io_uring op_context acquire/release algorithm (using ref count)
|
108
|
+
- Reimplement io_uring op_context acquire/release algorithm (using ref count)
|
95
109
|
- Fix #gets on sockets
|
96
110
|
- Redesign event anti-starvation mechanism
|
97
111
|
|
@@ -186,7 +200,7 @@
|
|
186
200
|
|
187
201
|
## 0.47.0 2020-11-10
|
188
202
|
|
189
|
-
- Implement `#spin_scope` used for creating blocking fiber scopes
|
203
|
+
- Implement `#spin_scope` used for creating blocking fiber scopes
|
190
204
|
- Reimplement `move_on_after`, `cancel_after`, `Timeout.timeout` using
|
191
205
|
`Backend#timeout` (avoids creating canceller fiber for most common use case)
|
192
206
|
- Implement `Backend#timeout` API
|
@@ -281,7 +295,7 @@
|
|
281
295
|
- Reimplement Event using `Agent#wait_event`
|
282
296
|
- Improve Queue shift queue performance
|
283
297
|
- Introduce `Agent#wait_event` API for waiting on asynchronous events
|
284
|
-
- Minimize `fcntl` syscalls in IO operations
|
298
|
+
- Minimize `fcntl` syscalls in IO operations
|
285
299
|
|
286
300
|
## 0.43.7 2020-07-20
|
287
301
|
|
data/Gemfile.lock
CHANGED
data/TODO.md
CHANGED
@@ -107,7 +107,7 @@
|
|
107
107
|
|
108
108
|
Hitting the breakpoint will show the current location in the source code
|
109
109
|
(with few lines before and after), and present a prompt for commands.
|
110
|
-
|
110
|
+
|
111
111
|
- commands:
|
112
112
|
- `step` / `up` / `skip` / `continue` etc. - step into, step out, step over, run
|
113
113
|
- `switch` - switch fiber
|
data/bin/pdbg
CHANGED
data/bin/polyphony-debug
CHANGED
File without changes
|
data/bin/stress.rb
CHANGED
File without changes
|
data/bin/test
CHANGED
File without changes
|
@@ -44,7 +44,7 @@ The `#sleep` forever call can be used for example in the main fiber when we do
|
|
44
44
|
all our work in other fibers, since once the main fiber terminates the program
|
45
45
|
exits.
|
46
46
|
|
47
|
-
## Doing Work Later
|
47
|
+
## Doing Work Later
|
48
48
|
|
49
49
|
While `#sleep` allows you to block execution of the current fiber, sometimes you
|
50
50
|
want to perform some work later, while not blocking the current fiber. This is done simply by spinning off another fiber:
|
data/docs/api-reference/fiber.md
CHANGED
@@ -205,7 +205,7 @@ f.raise
|
|
205
205
|
Pops the first message from the fiber's mailbox. If no message is available,
|
206
206
|
`#receive` will block until a message is pushed to the mailbox. The received
|
207
207
|
message can be any kind of object. This method is complemented by
|
208
|
-
`Fiber#<<`/`Fiber#send`.
|
208
|
+
`Fiber#<<`/`Fiber#send`.
|
209
209
|
|
210
210
|
```ruby
|
211
211
|
spin { Fiber.current.parent << 'hello from child' }
|
@@ -328,7 +328,7 @@ Returns the fiber's current state, which can be any of the following:
|
|
328
328
|
Supervises all child fibers, optionally restarting any fiber that terminates.
|
329
329
|
|
330
330
|
The given `opts` argument controls the behaviour of the supervision. The
|
331
|
-
following options are currently supported:
|
331
|
+
following options are currently supported:
|
332
332
|
|
333
333
|
- `:restart`: restart options
|
334
334
|
- `nil` - Child fibers are not restarted (default behaviour).
|
data/docs/faq.md
CHANGED
@@ -99,7 +99,7 @@ In conclusion:
|
|
99
99
|
|
100
100
|
## If callbacks suck, why not use promises?
|
101
101
|
|
102
|
-
Promises have gained a lot of traction during the last few years as an
|
102
|
+
Promises have gained a lot of traction during the last few years as an
|
103
103
|
alternative to callbacks, above all in the Javascript community. While promises
|
104
104
|
have been at a certain point considered for use in Polyphony, they were not
|
105
105
|
found to offer enough of a benefit. Promises still cause split logic, are quite
|
@@ -114,7 +114,7 @@ single CPU core.
|
|
114
114
|
|
115
115
|
Nevertheless, Polyphony fully supports multithreading, with each thread having
|
116
116
|
its own fiber run queue and its own libev event loop. Polyphony even enables
|
117
|
-
cross-thread communication using [fiber messaging](#message-passing).
|
117
|
+
cross-thread communication using [fiber messaging](#message-passing).
|
118
118
|
|
119
119
|
## Fibers vs Callbacks
|
120
120
|
|
@@ -138,7 +138,7 @@ Fibers, in contrast, let the developer express the business logic in a
|
|
138
138
|
sequential, easy to read manner: do this, then that. State can be stored right
|
139
139
|
in the business logic, as local variables. And finally, the sequential
|
140
140
|
programming style makes it much easier to debug your code, since stack traces
|
141
|
-
contain the entire history of execution from the app's inception.
|
141
|
+
contain the entire history of execution from the app's inception.
|
142
142
|
|
143
143
|
## Structured Concurrency
|
144
144
|
|
@@ -229,7 +229,7 @@ normally or with an exception:
|
|
229
229
|
fiber1 = spin { sleep 1; raise 'foo' }
|
230
230
|
fiber2 = spin { sleep 1 }
|
231
231
|
|
232
|
-
supervise # blocks and then propagates the error raised in fiber1
|
232
|
+
supervise # blocks and then propagates the error raised in fiber1
|
233
233
|
```
|
234
234
|
|
235
235
|
## Message Passing
|
@@ -266,7 +266,7 @@ end
|
|
266
266
|
Notice how the state (the `subscribers` variable) stays local, and how the logic
|
267
267
|
of the chat room is expressed in a way that is both compact and easy to extend.
|
268
268
|
Also notice how the chat room is written as an infinite loop. This is a common
|
269
|
-
pattern in Polyphony, since fibers can always be stopped at any moment.
|
269
|
+
pattern in Polyphony, since fibers can always be stopped at any moment.
|
270
270
|
|
271
271
|
The code for handling a chat room user might be expressed as follows:
|
272
272
|
|
@@ -350,14 +350,14 @@ operations.
|
|
350
350
|
|
351
351
|
While a standard event loop-based solution would implement a blocking call
|
352
352
|
separately from the fiber scheduling, the system backend integrates the two to
|
353
|
-
create a blocking call that
|
353
|
+
create a blocking call that already knows how to switch and schedule fibers.
|
354
354
|
For example, in Polyphony all APIs having to do with reading from files or
|
355
355
|
sockets end up calling `Thread.current.backend.read`, which does all the work.
|
356
356
|
|
357
357
|
This design offers some major advantages over other designs. It minimizes memory
|
358
|
-
allocations
|
358
|
+
allocations of both Ruby objects and C structures. For example, instead of
|
359
359
|
having to allocate libev watchers on the heap and then pass them around, they
|
360
|
-
are allocated on the stack instead, which saves
|
360
|
+
are allocated on the stack instead, which saves both memory and CPU cycles.
|
361
361
|
|
362
362
|
In addition, the backend interface includes two methods that allow maximizing
|
363
363
|
server performance by accepting connections and reading from sockets in a tight
|
@@ -482,5 +482,5 @@ reach version 1.0. Here are some of the exciting directions we're working on.
|
|
482
482
|
|
483
483
|
- Support for more core and stdlib APIs
|
484
484
|
- More adapters for gems with C-extensions, such as `mysql`, `sqlite3` etc
|
485
|
-
- Use `io_uring` backend as alternative to the libev backend
|
485
|
+
- Use `io_uring` backend as alternative to the libev backend
|
486
486
|
- More concurrency constructs for building highly concurrent applications
|
@@ -51,7 +51,7 @@ multiple threads or processes, but this approach has numerous disavantages:
|
|
51
51
|
- Both threads and processes are limited to a few thousand at best on a single
|
52
52
|
machine. Trying to spawn a thread per client essentially limits the scaling
|
53
53
|
capacity of your system.
|
54
|
-
|
54
|
+
|
55
55
|
Polyphony eschews both threads and processes in favor of fibers as the basic
|
56
56
|
unit of concurrency. The idea is that any time a blocking I/O operation occurs,
|
57
57
|
the current fiber is paused, and another fiber which has been marked as
|
@@ -117,7 +117,7 @@ Here's the actual sequence of execution (in pseudo-code)
|
|
117
117
|
sleeper = spin { ... } # The main fiber spins up a new fiber marked as runnable
|
118
118
|
suspend # The main fiber suspends, waiting for all other work to finish
|
119
119
|
Thread.current.switch_fiber # Polyphony looks for other runnable fibers
|
120
|
-
|
120
|
+
|
121
121
|
# (sleeper fiber)
|
122
122
|
puts "Going to sleep..." # The sleeper fiber starts running
|
123
123
|
sleep 1 # The sleeper fiber goes to sleep
|
@@ -280,7 +280,7 @@ def handle_client(client)
|
|
280
280
|
rescue Polyphony::Cancel
|
281
281
|
client.puts 'Closing connection due to inactivity.'
|
282
282
|
rescue Polyphony::Terminate
|
283
|
-
# We add a handler for the Terminate exception, and give
|
283
|
+
# We add a handler for the Terminate exception, and give
|
284
284
|
client.puts 'Server is shutting down. You have 5 more seconds...'
|
285
285
|
move_on_after(5) do
|
286
286
|
client_loop(client)
|
@@ -133,7 +133,7 @@ fiber that's blocking on any arbitrary operation.
|
|
133
133
|
Some other constructs offered by Polyphony:
|
134
134
|
|
135
135
|
* `Mutex` - a mutex used to synchronize access to a single shared resource.
|
136
|
-
* `ResourcePool` - used for synchronizing access to a limited amount of shared
|
136
|
+
* `ResourcePool` - used for synchronizing access to a limited amount of shared
|
137
137
|
resources, for example a pool of database connections.
|
138
138
|
* `Throttler` - used for throttling repeating operations, for example throttling
|
139
139
|
access to a shared resource, or throttling incoming requests.
|
@@ -9,9 +9,9 @@ next_title: The Design of Polyphony
|
|
9
9
|
---
|
10
10
|
# Extending Polyphony
|
11
11
|
|
12
|
-
Polyphony was designed to ease the transition from blocking APIs and
|
12
|
+
Polyphony was designed to ease the transition from blocking APIs and
|
13
13
|
callback-based API to non-blocking, fiber-based ones. It is important to
|
14
|
-
understand that not all blocking calls can be easily converted into
|
14
|
+
understand that not all blocking calls can be easily converted into
|
15
15
|
non-blocking calls. That might be the case with Ruby gems based on C-extensions,
|
16
16
|
such as database libraries. In that case, Polyphony's built-in
|
17
17
|
[thread pool](#threadpool) might be used for offloading such blocking calls.
|
@@ -22,7 +22,7 @@ Some of the most common patterns in Ruby APIs is the callback pattern, in which
|
|
22
22
|
the API takes a block as a callback to be called upon completion of a task. One
|
23
23
|
such example can be found in the excellent
|
24
24
|
[http_parser.rb](https://github.com/tmm1/http_parser.rb/) gem, which is used by
|
25
|
-
Polyphony itself to provide HTTP 1 functionality. The `HTTP:Parser` provides
|
25
|
+
Polyphony itself to provide HTTP 1 functionality. The `HTTP:Parser` provides
|
26
26
|
multiple hooks, or callbacks, for being notified when an HTTP request is
|
27
27
|
complete. The typical callback-based setup is as follows:
|
28
28
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
# Kernel#spin starts a new fiber
|
7
|
+
@controller = spin do
|
8
|
+
@worker = spin do
|
9
|
+
loop do
|
10
|
+
# Each fiber has a mailbox for receiving messages
|
11
|
+
peer, op, x, y = receive
|
12
|
+
result = x.send(op, y)
|
13
|
+
# The result is sent back to the "client"
|
14
|
+
peer << result
|
15
|
+
end
|
16
|
+
end
|
17
|
+
# The controller fiber will block until the worker is done (but notice that
|
18
|
+
# the worker runs an infinite loop.)
|
19
|
+
@worker.await
|
20
|
+
end
|
21
|
+
|
22
|
+
def calc(op, x, y)
|
23
|
+
# Send the job to the worker fiber...
|
24
|
+
@worker << [Fiber.current, op, x, y]
|
25
|
+
# ... and wait for the result
|
26
|
+
receive
|
27
|
+
end
|
28
|
+
|
29
|
+
# wait for worker to start
|
30
|
+
snooze until @worker
|
31
|
+
|
32
|
+
p calc(:+, 2, 3)
|
33
|
+
p calc(:**, 2, 3)
|
34
|
+
p calc(:+, 2, nil)
|
35
|
+
|
36
|
+
# wait for the controller to terminate
|
37
|
+
@controller.await
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
# Kernel#spin starts a new fiber
|
7
|
+
@controller = spin do
|
8
|
+
@worker = spin do
|
9
|
+
loop do
|
10
|
+
# Each fiber has a mailbox for receiving messages
|
11
|
+
peer, op, x, y = receive
|
12
|
+
result = x.send(op, y)
|
13
|
+
# The result is sent back to the "client"
|
14
|
+
peer << result
|
15
|
+
end
|
16
|
+
end
|
17
|
+
# The controller fiber will block until the worker is done (but notice that
|
18
|
+
# the worker runs an infinite loop.)
|
19
|
+
@worker.await
|
20
|
+
rescue => e
|
21
|
+
puts "Uncaught exception in worker: #{e}. Restarting..."
|
22
|
+
@worker.restart
|
23
|
+
end
|
24
|
+
|
25
|
+
def calc(op, x, y)
|
26
|
+
# Send the job to the worker fiber...
|
27
|
+
@worker << [Fiber.current, op, x, y]
|
28
|
+
# ... and wait for the result
|
29
|
+
receive
|
30
|
+
end
|
31
|
+
|
32
|
+
# wait for worker to start
|
33
|
+
snooze until @worker
|
34
|
+
|
35
|
+
p calc(:+, 2, 3)
|
36
|
+
p calc(:**, 2, 3)
|
37
|
+
p calc(:+, 2, nil)
|
38
|
+
|
39
|
+
# wait for the controller to terminate
|
40
|
+
@controller.await
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
# Kernel#spin starts a new fiber
|
7
|
+
@controller = spin do
|
8
|
+
@worker = spin do
|
9
|
+
loop do
|
10
|
+
# Each fiber has a mailbox for receiving messages
|
11
|
+
peer, op, x, y = receive
|
12
|
+
result = x.send(op, y)
|
13
|
+
# The result is sent back to the "client"
|
14
|
+
peer << result
|
15
|
+
end
|
16
|
+
end
|
17
|
+
# The controller fiber will block until the worker is done (but notice that
|
18
|
+
# the worker runs an infinite loop.)
|
19
|
+
@worker.supervise(@worker, restart: :always)
|
20
|
+
end
|
21
|
+
|
22
|
+
def calc(op, x, y)
|
23
|
+
# Send the job to the worker fiber...
|
24
|
+
@worker << [Fiber.current, op, x, y]
|
25
|
+
# ... and wait for the result
|
26
|
+
receive
|
27
|
+
end
|
28
|
+
|
29
|
+
# wait for worker to start
|
30
|
+
snooze until @worker
|
31
|
+
|
32
|
+
p calc(:+, 2, 3)
|
33
|
+
p calc(:**, 2, 3)
|
34
|
+
p calc(:+, 2, nil)
|
35
|
+
|
36
|
+
# wait for the controller to terminate
|
37
|
+
@controller.await
|
data/examples/io/rack_server.rb
CHANGED
data/examples/io/tunnel.rb
CHANGED
@@ -34,7 +34,7 @@ inline void backend_base_mark(struct Backend_base *base) {
|
|
34
34
|
void backend_base_reset(struct Backend_base *base) {
|
35
35
|
runqueue_finalize(&base->runqueue);
|
36
36
|
runqueue_finalize(&base->parked_runqueue);
|
37
|
-
|
37
|
+
|
38
38
|
runqueue_initialize(&base->runqueue);
|
39
39
|
runqueue_initialize(&base->parked_runqueue);
|
40
40
|
|
@@ -46,13 +46,13 @@ void backend_base_reset(struct Backend_base *base) {
|
|
46
46
|
base->idle_gc_period = 0;
|
47
47
|
base->idle_gc_last_time = 0;
|
48
48
|
base->idle_proc = Qnil;
|
49
|
-
base->trace_proc = Qnil;
|
49
|
+
base->trace_proc = Qnil;
|
50
50
|
}
|
51
51
|
|
52
52
|
const unsigned int ANTI_STARVE_SWITCH_COUNT_THRESHOLD = 64;
|
53
53
|
|
54
54
|
inline void conditional_nonblocking_poll(VALUE backend, struct Backend_base *base, VALUE current, VALUE next) {
|
55
|
-
if ((base->switch_count % ANTI_STARVE_SWITCH_COUNT_THRESHOLD) == 0 || next == current)
|
55
|
+
if ((base->switch_count % ANTI_STARVE_SWITCH_COUNT_THRESHOLD) == 0 || next == current)
|
56
56
|
Backend_poll(backend, Qnil);
|
57
57
|
}
|
58
58
|
|
@@ -62,7 +62,7 @@ VALUE backend_base_switch_fiber(VALUE backend, struct Backend_base *base) {
|
|
62
62
|
unsigned int pending_ops_count = base->pending_count;
|
63
63
|
unsigned int backend_was_polled = 0;
|
64
64
|
unsigned int idle_tasks_run_count = 0;
|
65
|
-
|
65
|
+
|
66
66
|
base->switch_count++;
|
67
67
|
COND_TRACE(base, 2, SYM_fiber_switchpoint, current_fiber);
|
68
68
|
|
@@ -82,7 +82,7 @@ VALUE backend_base_switch_fiber(VALUE backend, struct Backend_base *base) {
|
|
82
82
|
|
83
83
|
break;
|
84
84
|
}
|
85
|
-
|
85
|
+
|
86
86
|
if (!idle_tasks_run_count) {
|
87
87
|
idle_tasks_run_count++;
|
88
88
|
backend_run_idle_tasks(base);
|
@@ -112,7 +112,7 @@ void backend_base_schedule_fiber(VALUE thread, VALUE backend, struct Backend_bas
|
|
112
112
|
|
113
113
|
COND_TRACE(base, 4, SYM_fiber_schedule, fiber, value, prioritize ? Qtrue : Qfalse);
|
114
114
|
|
115
|
-
runqueue_t *runqueue = rb_ivar_get(fiber, ID_ivar_parked) == Qtrue ?
|
115
|
+
runqueue_t *runqueue = rb_ivar_get(fiber, ID_ivar_parked) == Qtrue ?
|
116
116
|
&base->parked_runqueue : &base->runqueue;
|
117
117
|
|
118
118
|
(prioritize ? runqueue_unshift : runqueue_push)(runqueue, fiber, value, already_runnable);
|
@@ -300,7 +300,7 @@ inline void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking) {
|
|
300
300
|
int flags = fcntl(fptr->fd, F_GETFL);
|
301
301
|
if (flags == -1) return;
|
302
302
|
int is_nonblocking = flags & O_NONBLOCK;
|
303
|
-
|
303
|
+
|
304
304
|
if (blocking == Qtrue) {
|
305
305
|
if (!is_nonblocking) return;
|
306
306
|
flags &= ~O_NONBLOCK;
|
@@ -375,7 +375,7 @@ void backend_setup_stats_symbols() {
|
|
375
375
|
SYM_switch_count = ID2SYM(rb_intern("switch_count"));
|
376
376
|
SYM_poll_count = ID2SYM(rb_intern("poll_count"));
|
377
377
|
SYM_pending_ops = ID2SYM(rb_intern("pending_ops"));
|
378
|
-
|
378
|
+
|
379
379
|
rb_global_variable(&SYM_runqueue_size);
|
380
380
|
rb_global_variable(&SYM_runqueue_length);
|
381
381
|
rb_global_variable(&SYM_runqueue_max_length);
|