From: "mame (Yusuke Endoh)" Date: 2022-01-12T17:53:20+00:00 Subject: [ruby-core:107078] [Ruby master Bug#18482] Fiber can not disable scheduler Issue #18482 has been updated by mame (Yusuke Endoh). Assignee set to ioquatix (Samuel Williams) ---------------------------------------- Bug #18482: Fiber can not disable scheduler https://bugs.ruby-lang.org/issues/18482#change-95917 * Author: jakit (Jakit Liang) * Status: Open * Priority: Normal * Assignee: ioquatix (Samuel Williams) * ruby -v: ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [arm64-darwin20] * Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN ---------------------------------------- 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 ``` -- https://bugs.ruby-lang.org/ Unsubscribe: