Skip to content

Commit 6a6cefd

Browse files
Add io_select hook.
1 parent 837a6d6 commit 6a6cefd

3 files changed

Lines changed: 51 additions & 0 deletions

File tree

lib/async/scheduler.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,16 @@ def process_wait(pid, flags)
414414
return @selector.process_wait(Fiber.current, pid, flags)
415415
end
416416

417+
# Wait for the specified IOs to become ready for the specified events.
418+
#
419+
# @public Since *Async v2.25*.
420+
# @asynchronous May be non-blocking.
421+
def io_select(...)
422+
Thread.new do
423+
::IO.select(...)
424+
end.value
425+
end
426+
417427
# Run one iteration of the event loop.
418428
#
419429
# When terminating the event loop, we already know we are finished. So we don't need to check the task tree. This is a logical requirement because `run_once` ignores transient tasks. For example, a single top level transient task is not enough to keep the reactor running, but during termination we must still process it in order to terminate child tasks.

releases.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- Added support for `io_select` hook in the fiber scheduler, allowing non-blocking `IO.select` operations. This enables better integration with code that uses `IO.select` for multiplexing IO operations.
6+
57
### Use `IO::Event::WorkerPool` for Blocking Operations
68

79
The `Async::WorkerPool` implementation has been removed in favor of using `IO::Event::WorkerPool` directly. This change simplifies the codebase by delegating worker pool functionality to the `io-event` gem, which provides a more efficient and well-tested implementation.

test/io.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,4 +217,43 @@
217217
read_thread.value
218218
end
219219
end
220+
221+
describe ".select" do
222+
it "can select readable IO" do
223+
expect(Fiber.scheduler).to receive(:io_select)
224+
225+
input, output = IO.pipe
226+
227+
begin
228+
# Write some data to make it readable
229+
output.write("Hello World")
230+
231+
readables, writables, errorables = IO.select([input], nil, nil, 0.1)
232+
233+
expect(readables).to have_value(be == input)
234+
expect(writables).to be(:empty?)
235+
expect(errorables).to be(:empty?)
236+
ensure
237+
input.close
238+
output.close
239+
end
240+
end
241+
242+
it "can select writable IO" do
243+
expect(Fiber.scheduler).to receive(:io_select)
244+
245+
input, output = IO.pipe
246+
247+
begin
248+
readables, writables, errorables = IO.select(nil, [output], nil, 0.1)
249+
250+
expect(readables).to be(:empty?)
251+
expect(writables).to have_value(be == output)
252+
expect(errorables).to be(:empty?)
253+
ensure
254+
input.close
255+
output.close
256+
end
257+
end
258+
end
220259
end

0 commit comments

Comments
 (0)