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: `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 When parameter is true: `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) Fiber.new(false) 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 ```