Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/async/scheduler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,16 @@ def process_wait(pid, flags)
return @selector.process_wait(Fiber.current, pid, flags)
end

# Wait for the specified IOs to become ready for the specified events.
#
# @public Since *Async v2.25*.
# @asynchronous May be non-blocking.
def io_select(...)
Thread.new do
::IO.select(...)
end.value
end

# Run one iteration of the event loop.
#
# 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.
Expand Down
2 changes: 2 additions & 0 deletions releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- 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.

### Use `IO::Event::WorkerPool` for Blocking Operations

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.
Expand Down
39 changes: 39 additions & 0 deletions test/io.rb
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,43 @@
read_thread.value
end
end

describe ".select" do
it "can select readable IO" do
expect(Fiber.scheduler).to receive(:io_select)

input, output = IO.pipe

begin
# Write some data to make it readable
output.write("Hello World")

readables, writables, errorables = IO.select([input], nil, nil, 0.1)

expect(readables).to have_value(be == input)
expect(writables).to be(:empty?)
expect(errorables).to be(:empty?)
ensure
input.close
output.close
end
end

it "can select writable IO" do
expect(Fiber.scheduler).to receive(:io_select)

input, output = IO.pipe

begin
readables, writables, errorables = IO.select(nil, [output], nil, 0.1)

expect(readables).to be(:empty?)
expect(writables).to have_value(be == output)
expect(errorables).to be(:empty?)
ensure
input.close
output.close
end
end
end
end
Loading