Bug #18482
Updated by jakit (Jakit Liang) almost 3 years ago
class Fiber can not disable scheduler with it's parameter.
When parameter is false:
```
require 'fiber'
require 'io/nonblock'
class SimpleScheduler
def initialize
@readable = {}
@writable = {}
@waiting = {}
@ready = []
@blocking = 0
@urgent = IO.pipe
end
def run
while @readable.any? or @writable.any? or @waiting.any? or @blocking.positive? or @ready.any?
readable, writable = IO.select(@readable.keys + [@urgent.first], @writable.keys, [], 0)
readable&.each do |io|
if fiber = @readable.delete(io)
fiber.resume
end
end
writable&.each do |io|
if fiber = @writable.delete(io)
fiber.resume
end
end
@waiting.keys.each do |fiber|
if current_time > @waiting[fiber]
@waiting.delete(fiber)
fiber.resume
end
end
ready, @ready = @ready, []
ready.each do |fiber|
fiber.resume
end
end
end
def io_wait(io, events, timeout)
unless (events & IO::READABLE).zero?
@readable[io] = Fiber.current
end
unless (events & IO::WRITABLE).zero?
@writable[io] = Fiber.current
end
Fiber.yield
return events
end
def kernel_sleep(duration = nil)
block(:sleep, duration)
return true
end
def block(blocker, timeout = nil)
if timeout
@waiting[Fiber.current] = current_time + timeout
begin
Fiber.yield
ensure
@waiting.delete(Fiber.current)
end
else
@blocking += 1
begin
Fiber.yield
ensure
@blocking -= 1
end
end
end
def unblock(blocker, fiber)
@ready << fiber
io = @urgent.last
io.write_nonblock('.')
end
def close
run
@urgent.each(&:close)
@urgent = nil
end
private
def current_time
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
end
scheduler = SimpleScheduler.new
Fiber.set_scheduler(scheduler)
puts "Go to sleep!"
f = Fiber.new(false) do
puts "Going to sleep"
sleep(1)
puts "I slept well"
end
f.resume
puts "Wakey-wakey, sleepyhead"
```
Result:
```
Go to sleep!
Going to sleep
Wakey-wakey, sleepyhead
I slept well
```
And when parameter is true:
```
require 'fiber'
require 'io/nonblock'
class SimpleScheduler
def initialize
@readable = {}
@writable = {}
@waiting = {}
@ready = []
@blocking = 0
@urgent = IO.pipe
end
def run
while @readable.any? or @writable.any? or @waiting.any? or @blocking.positive? or @ready.any?
readable, writable = IO.select(@readable.keys + [@urgent.first], @writable.keys, [], 0)
readable&.each do |io|
if fiber = @readable.delete(io)
fiber.resume
end
end
writable&.each do |io|
if fiber = @writable.delete(io)
fiber.resume
end
end
@waiting.keys.each do |fiber|
if current_time > @waiting[fiber]
@waiting.delete(fiber)
fiber.resume
end
end
ready, @ready = @ready, []
ready.each do |fiber|
fiber.resume
end
end
end
def io_wait(io, events, timeout)
unless (events & IO::READABLE).zero?
@readable[io] = Fiber.current
end
unless (events & IO::WRITABLE).zero?
@writable[io] = Fiber.current
end
Fiber.yield
return events
end
def kernel_sleep(duration = nil)
block(:sleep, duration)
return true
end
def block(blocker, timeout = nil)
if timeout
@waiting[Fiber.current] = current_time + timeout
begin
Fiber.yield
ensure
@waiting.delete(Fiber.current)
end
else
@blocking += 1
begin
Fiber.yield
ensure
@blocking -= 1
end
end
end
def unblock(blocker, fiber)
@ready << fiber
io = @urgent.last
io.write_nonblock('.')
end
def close
run
@urgent.each(&:close)
@urgent = nil
end
private
def current_time
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
end
scheduler = SimpleScheduler.new
Fiber.set_scheduler(scheduler)
puts "Go to sleep!"
f = Fiber.new(true) do
puts "Going to sleep"
sleep(1)
puts "I slept well"
end
f.resume
puts "Wakey-wakey, sleepyhead"
```
Result (was still the same):
```
Go to sleep!
Going to sleep
Wakey-wakey, sleepyhead
I slept well
```
While make the set_scheduler line commented:
```
scheduler = SimpleScheduler.new
# Fiber.set_scheduler(scheduler) // Here is commented
puts "Go to sleep!"
f = Fiber.new(false) do
puts "Going to sleep"
sleep(1)
puts "I slept well"
end
```
Result is right:
```
Go to sleep!
Going to sleep
I slept well
Wakey-wakey, sleepyhead
```
Maybe in some situation.
I wrote my gem without Scheduler. But user defined its Scheduler for his or her logic code.
It will break the sequence of Fiber which was needed for my gem.