Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add #wait_readable and #wait_writable to IO::FileDescriptor and Socket #15377

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Add #wait_[readable|writable] to IO::FileDescriptor and Socket
ysbaddaden committed Jan 27, 2025
commit 930d52151c7fb6e3e3be5a9d31ee0900f343e044
6 changes: 6 additions & 0 deletions src/crystal/event_loop/socket.cr
Original file line number Diff line number Diff line change
@@ -15,6 +15,9 @@ abstract class Crystal::EventLoop
# Use `#receive_from` for capturing the source address of a message.
abstract def read(socket : ::Socket, slice : Bytes) : Int32

# Blocks the current fiber until the socket is ready for read.
abstract def wait_readable(socket : ::Socket) : Nil

# Writes at least one byte from *slice* to the socket.
#
# Blocks the current fiber if the socket is not ready for writing,
@@ -25,6 +28,9 @@ abstract class Crystal::EventLoop
# Use `#send_to` for sending a message to a specific target address.
abstract def write(socket : ::Socket, slice : Bytes) : Int32

# Blocks the current fiber until the file descriptor is ready for write.
abstract def wait_writable(socket : ::Socket) : Nil

# Accepts an incoming TCP connection on the socket.
#
# Blocks the current fiber if no connection is waiting, continuing when one
8 changes: 8 additions & 0 deletions src/crystal/system/file_descriptor.cr
Original file line number Diff line number Diff line change
@@ -39,6 +39,14 @@ module Crystal::System::FileDescriptor
event_loop.write(self, slice)
end

private def system_wait_readable : Nil
event_loop.wait_readable(self)
end

private def system_wait_writable : Nil
event_loop.wait_writable(self)
end

private def event_loop? : Crystal::EventLoop::FileDescriptor?
Crystal::EventLoop.current?
end
14 changes: 14 additions & 0 deletions src/io/file_descriptor.cr
Original file line number Diff line number Diff line change
@@ -315,4 +315,18 @@ class IO::FileDescriptor < IO
private def unbuffered_flush : Nil
# Nothing
end

# Blocks the current fiber until the socket is ready for read. Raises
# `TimeoutError` when the configured `#read_timeout` has elapsed, otherwise
# returns normally.
def wait_readable : Nil
system_wait_readable
end

# Blocks the current fiber until the socket is ready for write. Raises
# `TimeoutError` when the configured `#write_timeout` has elapsed, otherwise
# returns normally.
def wait_writable : Nil
system_wait_writable
end
end
14 changes: 14 additions & 0 deletions src/socket.cr
Original file line number Diff line number Diff line change
@@ -467,6 +467,20 @@ class Socket < IO
private def unbuffered_flush : Nil
# Nothing
end

# Blocks the current fiber until the socket is ready for read. Raises
# `TimeoutError` when the configured `#read_timeout` has elapsed, otherwise
# returns normally.
def wait_readable : Nil
system_wait_readable
end

# Blocks the current fiber until the socket is ready for write. Raises
# `TimeoutError` when the configured `#write_timeout` has elapsed, otherwise
# returns normally.
def wait_writable : Nil
system_wait_writable
end
end

require "./socket/*"