class

Crystal::EventLoop::Polling

Inherits Crystal::EventLoop::Lock / Crystal::EventLoop / Crystal::EventLoop::Socket / Crystal::EventLoop::FileDescriptor / Reference / Object

Polling EventLoop.

This is the abstract interface that implements Crystal::EventLoop for polling based UNIX targets, such as epoll (linux), kqueue (bsd), or poll (posix) syscalls. This class only implements the generic parts for the external world to interact with the loop. A specific implementation is required to handle the actual syscalls. See Crystal::Epoll::EventLoop and Crystal::Kqueue::EventLoop.

The event loop registers the fd into the kernel data structures when an IO operation would block, then keeps it there until the fd is closed.

NOTE: the fds must have O_NONBLOCK set.

It is possible to have multiple event loop instances, but an fd can only be in one instance at a time. When trying to block from another loop, the fd will be removed from its associated loop and added to the current one (this is automatic). Trying to move a fd to another loop with pending waiters is unsupported and will raise an exception. See PollDescriptor#remove.

A timed event such as sleep or select timeout follows the following logic:

  1. create an Event (actually reuses it, see FiberChannel);
  2. register the event in @timers;
  3. supend the current fiber.

The timer will eventually trigger and resume the fiber. When an IO operation on fd would block, the loop follows the following logic:

  1. register the fd (once);
  2. create an Event;
  3. suspend the current fiber;

When the IO operation is ready, the fiber will eventually be resumed (one fiber at a time). If it's an IO operation, the operation is tried again which may block again, until the operation succeeds or an error occurred (e.g. closed, broken pipe).

If the IO operation has a timeout, the event is also registered into @timers before suspending the fiber, then after resume it will raise IO::TimeoutError if the event timed out, and continue otherwise.

Class methods

default_file_blocking?
Source
default_socket_blocking?
Source

Instance methods

accept(socket : ::Socket) : Tuple(::Socket::Handle, Bool) | Nil

Accepts an incoming TCP connection on the socket.

Blocks the current fiber if no connection is waiting, continuing when one becomes available. Otherwise returns immediately.

Returns a handle to the socket for the new connection.

Source
close(file_descriptor : System::FileDescriptor) : Nil

Closes the system fd or handle.

Source
close(socket : ::Socket) : Nil

Closes the system socket fd or handle.

Source
connect(socket : ::Socket, address : ::Socket::Addrinfo | ::Socket::Address, timeout : Time::Span | Nil) : IO::Error | Nil

Opens a connection on socket to the target address.

Blocks the current fiber and continues when the connection is established.

Returns IO::Error in case of an error. The caller is responsible for raising it as an exception if necessary.

Source
create_timeout_event(fiber : Fiber) : FiberEvent

Creates a timeout_event.

Source
open(path : String, flags : Int32, permissions : File::Permissions, blocking : Bool | Nil) : Tuple(System::FileDescriptor::Handle, Bool) | Errno

Opens a file at path.

Blocks the current fiber until the file has been opened. Avoids blocking the current thread if possible, especially when blocking is false or nil.

Returns the system file descriptor or handle, or a system error.

Source
pipe(read_blocking : Bool | Nil, write_blocking : Bool | Nil) : Tuple(IO::FileDescriptor, IO::FileDescriptor)

Opens an unidirectional pipe.

The implementation shall respect the specified blocking arguments for each end of the pipe, and follow its internal blocking requirements when a blocking arg is nil.

Returns a tuple with the reader and writer IO objects.

Source
pread(file_descriptor : System::FileDescriptor, slice : Bytes, offset : Int64) : Int32

Identical to #read but takes an offset into the file to read at, instead of the current position. Doesn't affect the current position.

Source
read(file_descriptor : System::FileDescriptor, slice : Bytes) : Int32

Reads at least one byte from the file descriptor into slice.

Blocks the current fiber if no data is available for reading, continuing when available. Otherwise returns immediately.

Returns the number of bytes read (up to slice.size). Returns 0 when EOF is reached.

Source
read(socket : ::Socket, slice : Bytes) : Int32

Reads at least one byte from the socket into slice.

Blocks the current fiber if no data is available for reading, continuing when available. Otherwise returns immediately.

Returns the number of bytes read (up to slice.size). Returns 0 when the socket is closed and no data available.

Use #receive_from for capturing the source address of a message.

Source
receive_from(socket : ::Socket, slice : Bytes) : Tuple(Int32, ::Socket::Address)

Receives at least one byte from the socket into slice, capturing the source address.

Blocks the current fiber if no data is available for reading, continuing when available. Otherwise returns immediately.

Returns a tuple containing the number of bytes received (up to slice.size) and the source address.

Source
recvmsg(socket : ::Socket, message : Pointer(LibC::Msghdr), flags : Int32) : Int32 | Errno

Extension to support Kernel TLS in OpenSSL::BIO.

Source
reopened(file_descriptor : System::FileDescriptor) : Nil

Hook to react on the file descriptor after it has been reopened. For example we might want to resume all pending operations to act on the new file descriptor.

Source
run(queue : Pointer(Fiber::List), blocking : Bool) : Nil

thread unsafe

Source
run(blocking : Bool) : Bool

thread unsafe

Source
send_to(socket : ::Socket, slice : Bytes, address : ::Socket::Address) : Int32

Sends at least one byte from slice to the socket with a target address address.

Blocks the current fiber if the socket is not ready for writing, continuing when ready. Otherwise returns immediately.

Returns the number of bytes sent (up to slice.size).

Source
sendfile(socket : ::Socket, fd : System::FileDescriptor::Handle, offset : Int64, count : Int64, flags : Int32) : Int64 | Errno

Writes up to count bytes from the input file fd to socket starting from the byte at offset, avoiding copying data between the kernel and user spaces (aka zerocopy).

Returns the number of bytes sent (up to count).

Source
sendmsg(socket : ::Socket, message : Pointer(LibC::Msghdr), flags : Int32) : Int32 | Errno

Extension to support Kernel TLS in OpenSSL::BIO.

Source
shutdown(file_descriptor : System::FileDescriptor) : Nil

Internal shutdown of the file descriptor. Called after the IO::FileDescriptor has been marked closed but before calling #close to actually close the system fd or handle.

Implementations shall resume all pending waiters and let them fail because the IO has been closed.

Source
shutdown(socket : ::Socket) : Nil

Internal shutdown of the socket. Called after the Socket has been marked closed but before calling #close to actually close the system socket fd or handle.

Implementations shall resume all pending waiters and let them fail because the IO has been closed. They don't have to call the shutdown syscall.

Source
sleep(duration : Time::Span) : Nil

Suspend the current fiber for duration.

Source
socket(family : ::Socket::Family, type : ::Socket::Type, protocol : ::Socket::Protocol, blocking : Bool | Nil) : Tuple(::Socket::Handle, Bool)

Creates a new socket file descriptor or handle and returns it, along with whether the blocking flag has been set.

Source
socketpair(type : ::Socket::Type, protocol : ::Socket::Protocol) : Tuple(Tuple(::Socket::Handle, ::Socket::Handle), Bool)

Creates a pair of UNIX socket file descriptors or handles and returns them, along with whether the blocking mode has been set.

Source
wait_readable(file_descriptor : System::FileDescriptor) : Nil

Blocks the current fiber until the file descriptor is ready for read.

Source
wait_readable(socket : ::Socket) : Nil

Blocks the current fiber until the socket is ready for read.

Source
wait_writable(file_descriptor : System::FileDescriptor) : Nil

Blocks the current fiber until the file descriptor is ready for write.

Source
wait_writable(socket : ::Socket) : Nil

Blocks the current fiber until the socket is ready for write.

Source
write(file_descriptor : System::FileDescriptor, slice : Bytes) : Int32

Writes at least one byte from slice to the file descriptor.

Blocks the current fiber if the file descriptor isn't ready for writing, continuing when ready. Otherwise returns immediately.

Returns the number of bytes written (up to slice.size).

Source
write(socket : ::Socket, slice : Bytes) : Int32

Writes at least one byte from slice to the socket.

Blocks the current fiber if the socket is not ready for writing, continuing when ready. Otherwise returns immediately.

Returns the number of bytes written (up to slice.size).

Use #send_to for sending a message to a specific target address.

Source

Nested types