# abstract class Crystal::EventLoop::Polling

- Crystal::EventLoop::Polling
- Crystal::EventLoop
- Reference
- Object

##
Overview

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.

##
Direct Known Subclasses

- Crystal::EventLoop::Kqueue

##
Defined in:

crystal/event_loop/polling.cr:2
crystal/event_loop/polling.cr:58

##
Class Method Summary

- .default_file_blocking?
- .default_socket_blocking?

##
Instance Method Summary

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

  Accepts an incoming TCP connection on the socket.

- #after_fork : Nil

  no parallelism issues, but let's clean-up anyway

- #after_fork_before_exec : Nil

  reset the mutexes since another thread may have acquired the lock of one event loop, which would prevent closing file descriptors for example.

- #close(file_descriptor : System::FileDescriptor) : Nil

  Closes the file descriptor resource.

- #close(socket : ::Socket) : Nil

  Closes the socket.

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

  Opens a connection on socket to the target address.

- #create_timeout_event(fiber : Fiber) : FiberEvent

  Creates a timeout_event.

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

  Opens a file at path.

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

  Opens an unidirectional pipe.

- #read(file_descriptor : System::FileDescriptor, slice : Bytes) : Int32

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

- #read(socket : ::Socket, slice : Bytes) : Int32

  Reads at least one byte from the socket into slice.

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

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

- #reopened(file_descriptor : System::FileDescriptor) : Nil

  Hook to react on the file descriptor after it has been reopened.

- #run(blocking : Bool) : Bool

  thread unsafe

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

- #sleep(duration : Time::Span) : Nil

  Suspend the current fiber for duration.

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

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

- #wait_readable(file_descriptor : System::FileDescriptor) : Nil

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

- #wait_readable(socket : ::Socket) : Nil

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

- #wait_writable(file_descriptor : System::FileDescriptor) : Nil

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

- #wait_writable(socket : ::Socket) : Nil

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

- #write(file_descriptor : System::FileDescriptor, slice : Bytes) : Int32

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

- #write(socket : ::Socket, slice : Bytes) : Int32

  Writes at least one byte from slice to the socket.

### Instance methods inherited from class `Crystal::EventLoop`

create_resume_event(fiber : Fiber) : Event create_resume_event, create_timeout_event(fiber : Fiber) : Event create_timeout_event, interrupt : Nil interrupt, run(blocking : Bool) : Bool run, sleep(duration : Time::Span) : Nil sleep

### Constructor methods inherited from class `Crystal::EventLoop`

create : self create, current : self current

### Class methods inherited from class `Crystal::EventLoop`

backend_class backend_class, current? : self | Nil current?, default_file_blocking? : Bool default_file_blocking?, default_socket_blocking? : Bool default_socket_blocking?, remove(file_descriptor : Crystal::System::FileDescriptor) : Nil
remove(socket : ::Socket) : Nil remove

### Instance methods inherited from module `Crystal::EventLoop::Socket`

accept(socket : ::Socket) : Tuple(::Socket::Handle, Bool) | Nil accept, close(socket : ::Socket) : Nil close, connect(socket : ::Socket, address : ::Socket::Addrinfo | ::Socket::Address, timeout : Time::Span | Nil) : IO::Error | Nil connect, read(socket : ::Socket, slice : Bytes) : Int32 read, receive_from(socket : ::Socket, slice : Bytes) : Tuple(Int32, ::Socket::Address) receive_from, send_to(socket : ::Socket, slice : Bytes, address : ::Socket::Address) : Int32 send_to, socket(family : ::Socket::Family, type : ::Socket::Type, protocol : ::Socket::Protocol, blocking : Bool | Nil) : Tuple(::Socket::Handle, Bool) socket, socketpair(type : ::Socket::Type, protocol : ::Socket::Protocol) : Tuple(Tuple(::Socket::Handle, ::Socket::Handle), Bool) socketpair, wait_readable(socket : ::Socket) : Nil wait_readable, wait_writable(socket : ::Socket) : Nil wait_writable, write(socket : ::Socket, slice : Bytes) : Int32 write

### Instance methods inherited from module `Crystal::EventLoop::FileDescriptor`

close(file_descriptor : Crystal::System::FileDescriptor) : Nil close, open(path : String, flags : Int32, permissions : File::Permissions, blocking : Bool | Nil) : Tuple(System::FileDescriptor::Handle, Bool) | Errno | WinError open, pipe(read_blocking : Bool | Nil, write_blocking : Bool | Nil) : Tuple(IO::FileDescriptor, IO::FileDescriptor) pipe, read(file_descriptor : Crystal::System::FileDescriptor, slice : Bytes) : Int32 read, reopened(file_descriptor : Crystal::System::FileDescriptor) : Nil reopened, wait_readable(file_descriptor : Crystal::System::FileDescriptor) : Nil wait_readable, wait_writable(file_descriptor : Crystal::System::FileDescriptor) : Nil wait_writable, write(file_descriptor : Crystal::System::FileDescriptor, slice : Bytes) : Int32 write

### Instance methods inherited from class `Reference`

==(other : self)
==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil) same?, to_s(io : IO) : Nil to_s

### Constructor methods inherited from class `Reference`

new new, unsafe_construct(address : Pointer, *args, **opts) : self unsafe_construct

### Class methods inherited from class `Reference`

pre_initialize(address : Pointer) pre_initialize

### Instance methods inherited from class `Object`

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

### Class methods inherited from class `Object`

from_json(string_or_io, root : String)
from_json(string_or_io) from_json, from_yaml(string_or_io : String | IO) from_yaml

### Macros inherited from class `Object`

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

##
Class Method Detail

def self.default_file_blocking? #
def self.default_socket_blocking? #

##
Instance Method Detail

def accept(socket : ::Socket) : Tuple(::Socket::Handle, Bool) | Nil #
Description copied from module Crystal::EventLoop::Socket

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.

def after_fork : Nil #

no parallelism issues, but let's clean-up anyway

def after_fork_before_exec : Nil #

reset the mutexes since another thread may have acquired the lock of one event loop, which would prevent closing file descriptors for example.

def close(file_descriptor : System::FileDescriptor) : Nil #
Description copied from module Crystal::EventLoop::FileDescriptor

Closes the file descriptor resource.

def close(socket : ::Socket) : Nil #
Description copied from module Crystal::EventLoop::Socket

Closes the socket.

def connect(socket : ::Socket, address : ::Socket::Addrinfo | ::Socket::Address, timeout : Time::Span | Nil) : IO::Error | Nil #
Description copied from module Crystal::EventLoop::Socket

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.

def create_timeout_event(fiber : Fiber) : FiberEvent #
Description copied from class Crystal::EventLoop

Creates a timeout_event.

def open(path : String, flags : Int32, permissions : File::Permissions, blocking : Bool | Nil) : Tuple(System::FileDescriptor::Handle, Bool) | Errno #
Description copied from module Crystal::EventLoop::FileDescriptor

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.

def pipe(read_blocking : Bool | Nil, write_blocking : Bool | Nil) : Tuple(IO::FileDescriptor, IO::FileDescriptor) #
Description copied from module Crystal::EventLoop::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.

def read(file_descriptor : System::FileDescriptor, slice : Bytes) : Int32 #
Description copied from module Crystal::EventLoop::FileDescriptor

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.

def read(socket : ::Socket, slice : Bytes) : Int32 #
Description copied from module Crystal::EventLoop::Socket

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.

def receive_from(socket : ::Socket, slice : Bytes) : Tuple(Int32, ::Socket::Address) #
Description copied from module Crystal::EventLoop::Socket

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.

def reopened(file_descriptor : System::FileDescriptor) : Nil #
Description copied from module Crystal::EventLoop::FileDescriptor

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.

def run(blocking : Bool) : Bool #

thread unsafe

def send_to(socket : ::Socket, slice : Bytes, address : ::Socket::Address) : Int32 #
Description copied from module Crystal::EventLoop::Socket

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

def sleep(duration : Time::Span) : Nil #
Description copied from class Crystal::EventLoop

Suspend the current fiber for duration.

def socket(family : ::Socket::Family, type : ::Socket::Type, protocol : ::Socket::Protocol, blocking : Bool | Nil) : Tuple(::Socket::Handle, Bool) #
Description copied from module Crystal::EventLoop::Socket

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

def socketpair(type : ::Socket::Type, protocol : ::Socket::Protocol) : Tuple(Tuple(::Socket::Handle, ::Socket::Handle), Bool) #
Description copied from module Crystal::EventLoop::Socket

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

def wait_readable(file_descriptor : System::FileDescriptor) : Nil #
Description copied from module Crystal::EventLoop::FileDescriptor

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

def wait_readable(socket : ::Socket) : Nil #
Description copied from module Crystal::EventLoop::Socket

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

def wait_writable(file_descriptor : System::FileDescriptor) : Nil #
Description copied from module Crystal::EventLoop::FileDescriptor

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

def wait_writable(socket : ::Socket) : Nil #
Description copied from module Crystal::EventLoop::Socket

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

def write(file_descriptor : System::FileDescriptor, slice : Bytes) : Int32 #
Description copied from module Crystal::EventLoop::FileDescriptor

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

def write(socket : ::Socket, slice : Bytes) : Int32 #
Description copied from module Crystal::EventLoop::Socket

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.