FastMM documentation
FastMM C++ API 0.6.0
Public headers, tier 1 and tier 2
Loading...
Searching...
No Matches
fastmm::net::Reactor Class Reference

#include <fastmm/net/reactor.hpp>

Public Types

using TimerCallback = InplaceCallback
 Stored inline (no heap): captures up to InplaceCallback::kCapacity bytes.
 
using Task = std::function< void()>
 
using EventHook = void(*)(void *ctx)
 Called on the reactor thread after the handler of each I/O event, between one socket's event and the next of the same wait: work that must not wait for the whole batch to be handled (the engine's orders behind a burst of market data, live/venue_slot.cpp) goes here.
 

Public Member Functions

 Reactor ()
 
 Reactor (ReactorBackend backend)
 Throws std::runtime_error if the backend (epoll_create1 / io_uring_setup) or the eventfd cannot be created.
 
 ~Reactor ()
 
 Reactor (const Reactor &)=delete
 
Reactor & operator= (const Reactor &)=delete
 
ReactorBackend backend () const noexcept
 
bool add (int fd, IoHandler &handler, IoEvent events) noexcept
 fd registration (reactor thread only).
 
bool modify (int fd, IoHandler &handler, IoEvent events) noexcept
 
bool remove (int fd) noexcept
 
bool is_registered (int fd) const noexcept
 
TimerId add_timer (std::int64_t deadline_ns, TimerCallback cb)
 Timers (reactor thread only).
 
TimerId add_timer_after (std::int64_t delay_ns, TimerCallback cb)
 
bool cancel_timer (TimerId id) noexcept
 
std::size_t active_timers () const noexcept
 
void post (Task task)
 Thread-safe: queue a task for the reactor thread and wake it.
 
void wake () noexcept
 Thread-safe: interrupt a blocking wait in run_once().
 
int wake_fd () const noexcept
 The eventfd wake() writes.
 
int run_once (int max_wait_ms)
 One iteration: wait for I/O at most min(next timer, max_wait_ms), dispatch I/O, posted tasks, expired timers.
 
void run (const std::atomic< bool > &stop)
 Loop until stop becomes true (checked once per iteration; call wake() after setting it).
 
void set_busy_poll (bool enabled) noexcept
 Busy polling: never block, pause instruction between empty polls.
 
bool busy_poll () const noexcept
 
void set_after_event (EventHook fn, void *ctx) noexcept
 
bool event_hangup () const noexcept
 True while a handler runs for an event that also reported a hang-up or an error (RDHUP/HUP/ERR).
 
int epoll_fd () const noexcept
 The epoll descriptor, or -1 with the io_uring backend.
 

Static Public Member Functions

static bool io_uring_supported () noexcept
 True when this kernel lets the process create an io_uring with everything the backend uses (multishot poll, poll update, EXT_ARG timeouts).
 
static ReactorBackend resolve_backend (ReactorBackend requested) noexcept
 requested, or Epoll when io_uring was requested but is not supported.
 
static std::int64_t now_ns () noexcept
 CLOCK_MONOTONIC.
 

Member Typedef Documentation

◆ TimerCallback

using fastmm::net::Reactor::TimerCallback = InplaceCallback

Stored inline (no heap): captures up to InplaceCallback::kCapacity bytes.

◆ Task

using fastmm::net::Reactor::Task = std::function<void()>

◆ EventHook

using fastmm::net::Reactor::EventHook = void (*)(void* ctx)

Called on the reactor thread after the handler of each I/O event, between one socket's event and the next of the same wait: work that must not wait for the whole batch to be handled (the engine's orders behind a burst of market data, live/venue_slot.cpp) goes here.

Null: none.

Constructor & Destructor Documentation

◆ Reactor() [1/3]

fastmm::net::Reactor::Reactor ( )
inline

◆ Reactor() [2/3]

fastmm::net::Reactor::Reactor ( ReactorBackend  backend)
explicit

Throws std::runtime_error if the backend (epoll_create1 / io_uring_setup) or the eventfd cannot be created.

Check io_uring_supported() before asking for IoUring.

◆ ~Reactor()

fastmm::net::Reactor::~Reactor ( )

◆ Reactor() [3/3]

fastmm::net::Reactor::Reactor ( const Reactor &  )
delete

Member Function Documentation

◆ operator=()

Reactor & fastmm::net::Reactor::operator= ( const Reactor &  )
delete

◆ backend()

ReactorBackend fastmm::net::Reactor::backend ( ) const
inlinenoexcept

◆ io_uring_supported()

static bool fastmm::net::Reactor::io_uring_supported ( )
staticnoexcept

True when this kernel lets the process create an io_uring with everything the backend uses (multishot poll, poll update, EXT_ARG timeouts).

Probed once, then cached. False on ENOSYS, EPERM (kernel.io_uring_disabled, seccomp), ENOMEM and kernels older than 5.13.

◆ resolve_backend()

static ReactorBackend fastmm::net::Reactor::resolve_backend ( ReactorBackend  requested)
staticnoexcept

requested, or Epoll when io_uring was requested but is not supported.

◆ add()

bool fastmm::net::Reactor::add ( int  fd,
IoHandler &  handler,
IoEvent  events 
)
noexcept

fd registration (reactor thread only).

Registrations always include RDHUP so half-closes surface as on_readable() (read returns EOF). add() fails for an fd that is already registered, a closed fd and (like epoll) regular files and directories.

◆ modify()

bool fastmm::net::Reactor::modify ( int  fd,
IoHandler &  handler,
IoEvent  events 
)
noexcept

◆ remove()

bool fastmm::net::Reactor::remove ( int  fd)
noexcept

◆ is_registered()

bool fastmm::net::Reactor::is_registered ( int  fd) const
noexcept

◆ add_timer()

TimerId fastmm::net::Reactor::add_timer ( std::int64_t  deadline_ns,
TimerCallback  cb 
)

Timers (reactor thread only).

Deadlines are on the now_ns() clock. Arming a timer allocates only when more timers are live than ever before (slot and heap growth).

◆ add_timer_after()

TimerId fastmm::net::Reactor::add_timer_after ( std::int64_t  delay_ns,
TimerCallback  cb 
)
inline

◆ cancel_timer()

bool fastmm::net::Reactor::cancel_timer ( TimerId  id)
noexcept

◆ active_timers()

std::size_t fastmm::net::Reactor::active_timers ( ) const
inlinenoexcept

◆ post()

void fastmm::net::Reactor::post ( Task  task)

Thread-safe: queue a task for the reactor thread and wake it.

◆ wake()

void fastmm::net::Reactor::wake ( )
noexcept

Thread-safe: interrupt a blocking wait in run_once().

◆ wake_fd()

int fastmm::net::Reactor::wake_fd ( ) const
inlinenoexcept

The eventfd wake() writes.

Another process that holds a duplicate (the gateway passes it to the strategy with SCM_RIGHTS) wakes this reactor by writing 1 to it.

◆ run_once()

int fastmm::net::Reactor::run_once ( int  max_wait_ms)

One iteration: wait for I/O at most min(next timer, max_wait_ms), dispatch I/O, posted tasks, expired timers.

max_wait_ms < 0 blocks until something happens. Returns the number of I/O events (epoll) or completions (io_uring) dispatched, or -1 on a wait error other than EINTR. epoll rounds the timer bound up to whole milliseconds; io_uring waits in nanoseconds.

◆ run()

void fastmm::net::Reactor::run ( const std::atomic< bool > &  stop)

Loop until stop becomes true (checked once per iteration; call wake() after setting it).

◆ set_busy_poll()

void fastmm::net::Reactor::set_busy_poll ( bool  enabled)
inlinenoexcept

Busy polling: never block, pause instruction between empty polls.

epoll calls epoll_wait with a zero timeout; io_uring reads the completion ring without a system call unless the kernel flags pending work.

◆ busy_poll()

bool fastmm::net::Reactor::busy_poll ( ) const
inlinenoexcept

◆ set_after_event()

void fastmm::net::Reactor::set_after_event ( EventHook  fn,
void *  ctx 
)
inlinenoexcept

◆ event_hangup()

bool fastmm::net::Reactor::event_hangup ( ) const
inlinenoexcept

True while a handler runs for an event that also reported a hang-up or an error (RDHUP/HUP/ERR).

Only when it is false may a handler take a short read as "socket drained" and skip the read that would return EAGAIN: edge-triggered readiness reports data that arrives later with a new event, but an end of stream already reported has no second event.

◆ now_ns()

static std::int64_t fastmm::net::Reactor::now_ns ( )
staticnoexcept

CLOCK_MONOTONIC.

◆ epoll_fd()

int fastmm::net::Reactor::epoll_fd ( ) const
inlinenoexcept

The epoll descriptor, or -1 with the io_uring backend.