polyphony 0.71 → 0.72

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/CHANGELOG.md +18 -4
  4. data/Gemfile.lock +1 -1
  5. data/TODO.md +1 -1
  6. data/bin/pdbg +1 -1
  7. data/bin/polyphony-debug +0 -0
  8. data/bin/stress.rb +0 -0
  9. data/bin/test +0 -0
  10. data/docs/_user-guide/all-about-timers.md +1 -1
  11. data/docs/api-reference/fiber.md +2 -2
  12. data/docs/faq.md +1 -1
  13. data/docs/getting-started/overview.md +8 -8
  14. data/docs/getting-started/tutorial.md +3 -3
  15. data/docs/main-concepts/concurrency.md +1 -1
  16. data/docs/main-concepts/extending.md +3 -3
  17. data/docs/main-concepts/fiber-scheduling.md +1 -1
  18. data/examples/core/calc.rb +37 -0
  19. data/examples/core/calc_with_restart.rb +40 -0
  20. data/examples/core/calc_with_supervise.rb +37 -0
  21. data/examples/core/message_based_supervision.rb +1 -1
  22. data/examples/io/rack_server.rb +1 -1
  23. data/examples/io/tunnel.rb +1 -1
  24. data/examples/performance/fiber_transfer.rb +1 -1
  25. data/examples/performance/line_splitting.rb +1 -1
  26. data/examples/performance/thread-vs-fiber/compare.rb +1 -1
  27. data/ext/polyphony/backend_common.c +8 -8
  28. data/ext/polyphony/backend_io_uring.c +26 -33
  29. data/ext/polyphony/backend_io_uring_context.c +1 -1
  30. data/ext/polyphony/backend_io_uring_context.h +1 -1
  31. data/ext/polyphony/backend_libev.c +11 -11
  32. data/ext/polyphony/extconf.rb +24 -13
  33. data/ext/polyphony/queue.c +2 -2
  34. data/ext/polyphony/runqueue_ring_buffer.c +3 -2
  35. data/lib/polyphony/adapters/irb.rb +11 -1
  36. data/lib/polyphony/core/global_api.rb +3 -3
  37. data/lib/polyphony/core/timer.rb +2 -2
  38. data/lib/polyphony/debugger.rb +3 -3
  39. data/lib/polyphony/extensions/fiber.rb +19 -8
  40. data/lib/polyphony/extensions/io.rb +2 -2
  41. data/lib/polyphony/extensions/openssl.rb +20 -5
  42. data/lib/polyphony/extensions/socket.rb +3 -4
  43. data/lib/polyphony/version.rb +1 -1
  44. data/polyphony.gemspec +1 -1
  45. data/test/coverage.rb +2 -2
  46. data/test/test_backend.rb +12 -12
  47. data/test/test_event.rb +1 -1
  48. data/test/test_ext.rb +1 -1
  49. data/test/test_fiber.rb +31 -7
  50. data/test/test_global_api.rb +2 -2
  51. data/test/test_io.rb +3 -3
  52. data/test/test_queue.rb +6 -6
  53. data/test/test_socket.rb +12 -10
  54. data/test/test_supervise.rb +85 -0
  55. data/test/test_sync.rb +2 -2
  56. data/test/test_thread.rb +22 -2
  57. data/test/test_thread_pool.rb +1 -1
  58. data/test/test_throttler.rb +1 -1
  59. data/test/test_timer.rb +2 -2
  60. data/test/test_trace.rb +1 -1
  61. metadata +7 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36566e2f3d8ca8535569ec2766183295a6b17f3af67123a6442242881b004ef8
4
- data.tar.gz: d38059a39ce762cb043c68374829050b6abd4596fc900f68d24120e843efa9db
3
+ metadata.gz: 2af189faeecbe2eecb367a7400005306ab74370e56c61de1d703edd40d851d92
4
+ data.tar.gz: c0888b10d03b9bf29f1d10a41b0050231db655c587d06035039b4c09e1c68baa
5
5
  SHA512:
6
- metadata.gz: 4d85656e6ca42458d262433bed6817e6fe5d60b194fddce269fae9ab9d479a7167b3460ac01cdb3c3018d9e3bf3b61ea5560aa2f186dedb841ac81dec311ffb5
7
- data.tar.gz: 6db9f437744ece1eeae09c738ac31172439472acd21e8956e75defbdf4b113b5fd61e04ff73ef9f29046b54baf44e0064350b6c04df9883c34b16efd9bad35e1
6
+ metadata.gz: b86fd5682ce52e635658a8d620031f8ae841ef5f7876d6239f74772d8f700054eb3bb7732488e246433a91e5ab4279479c6f18bb0d1a154172d90f351ab8149e
7
+ data.tar.gz: 713ba61a64ef73c5c16971bd0d678d6575b7bd37062a29348f02ec8e0578821d7ec41f826f1868cd017bede9c70d47192e19a0217469b331f17ff66afac21054
@@ -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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.71)
4
+ polyphony (0.72)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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
@@ -89,7 +89,7 @@ def get_user_cmd
89
89
  STDOUT << "(pdbg) "
90
90
  cmd = parse_command(STDIN.gets)
91
91
  next unless cmd
92
-
92
+
93
93
  if cmd[:cmd] == :help
94
94
  print_help
95
95
  else
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:
@@ -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 is already knows how to switch and schedule fibers.
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, of both Ruby objects and C structures. For example, instead of
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 up on both memory and CPU cycles.
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
 
@@ -145,7 +145,7 @@ def with_timeout(duration)
145
145
  sleep duration
146
146
  interruptible_fiber.raise 'timeout'
147
147
  end
148
-
148
+
149
149
  # do work
150
150
  yield
151
151
  ensure
@@ -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
@@ -45,7 +45,7 @@ def start_worker(id)
45
45
  sleep duration
46
46
  raise 'foo' if rand > 0.7
47
47
  break if rand > 0.6
48
- end
48
+ end
49
49
  end
50
50
 
51
51
  supervise(start_worker(1), start_worker(2))
@@ -14,7 +14,7 @@ module RackAdapter
14
14
  def env(req)
15
15
  {}
16
16
  end
17
-
17
+
18
18
  def respond(socket, request, (status_code, headers, body))
19
19
  body = body.join
20
20
  headers = "Content-Type: text/plain\r\nContent-Length: #{body.bytesize}\r\n"
@@ -21,7 +21,7 @@ def endpoint_loop(idx, peer_idx)
21
21
  '0.0.0.0',
22
22
  port,
23
23
  reuse_addr: true
24
- )
24
+ )
25
25
  # server = TCPServer.open('0.0.0.0', port)
26
26
  log "Listening on port #{port}"
27
27
  loop do
@@ -35,7 +35,7 @@ def run(num_fibers)
35
35
  end
36
36
 
37
37
  last.next = first
38
-
38
+
39
39
  t0 = Time.now
40
40
  puts "start transfer..."
41
41
  first.transfer
@@ -8,7 +8,7 @@ def slice
8
8
  while true
9
9
  idx = str.index("\n")
10
10
  break unless idx
11
-
11
+
12
12
  lines << str.slice!(0, idx + 1)
13
13
  end
14
14
  raise unless lines.size == 4
@@ -27,7 +27,7 @@ def run_test(name, port, cmd, setting)
27
27
  puts "*" * 80
28
28
  puts "Run #{name} (#{port}): #{setting}"
29
29
  puts "*" * 80
30
-
30
+
31
31
  pid = spawn("#{cmd} > /dev/null 2>&1")
32
32
  sleep 1
33
33
 
@@ -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);