diff options
author | Samuel Williams <samuel.williams@oriontransfer.co.nz> | 2021-12-18 18:19:30 +1300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-18 18:19:30 +1300 |
commit | 42d32311541e58503b885b09b469948922650c66 (patch) | |
tree | 235c0405be8a02e2fb2612b5daf9694d01ebd2fe /test/fiber/scheduler.rb | |
parent | 922a81a99418c992f4039b27a8341f2ee96d2d0c (diff) |
Introduce io_result wrapper for passing `[-errno, size]` in VALUE.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/5287
Merged-By: ioquatix <samuel@codeotaku.com>
Diffstat (limited to 'test/fiber/scheduler.rb')
-rw-r--r-- | test/fiber/scheduler.rb | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/test/fiber/scheduler.rb b/test/fiber/scheduler.rb index a6e1325259..0e352a1cc9 100644 --- a/test/fiber/scheduler.rb +++ b/test/fiber/scheduler.rb @@ -192,6 +192,9 @@ class Scheduler end Fiber.yield + ensure + @readable.delete(io) + @writable.delete(io) end # Used for Kernel#sleep and Thread::Mutex#sleep @@ -257,6 +260,85 @@ class Scheduler end end +class IOBufferScheduler < Scheduler + EAGAIN = Errno::EAGAIN::Errno + + def io_read(io, buffer, length) + offset = 0 + + while true + maximum_size = buffer.size - offset + result = blocking{io.read_nonblock(maximum_size, exception: false)} + + # blocking{pp read: maximum_size, result: result, length: length} + + case result + when :wait_readable + if length > 0 + self.io_wait(io, IO::READABLE, nil) + else + return -EAGAIN + end + when :wait_writable + if length > 0 + self.io_wait(io, IO::WRITABLE, nil) + else + return -EAGAIN + end + else + break unless result + + buffer.copy(result, offset) + + size = result.bytesize + offset += size + break if size >= length + length -= size + end + end + + return offset + end + + def io_write(io, buffer, length) + offset = 0 + + while true + maximum_size = buffer.size - offset + + chunk = buffer.to_str(offset, maximum_size) + result = blocking{io.write_nonblock(chunk, exception: false)} + + # blocking{pp write: maximum_size, result: result, length: length} + + case result + when :wait_readable + if length > 0 + self.io_wait(io, IO::READABLE, nil) + else + return -EAGAIN + end + when :wait_writable + if length > 0 + self.io_wait(io, IO::WRITABLE, nil) + else + return -EAGAIN + end + else + offset += result + break if result >= length + length -= result + end + end + + return offset + end + + def blocking(&block) + Fiber.new(blocking: true, &block).resume + end +end + class BrokenUnblockScheduler < Scheduler def unblock(blocker, fiber) super |