Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
SC::AsyncEventLoop Struct Reference

Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEventLoop pushes all AsyncRequest derived classes to I/O queues in the OS. More...

#include <Async.h>

Classes

struct  Options
 Options given to AsyncEventLoop::create. More...
 

Public Types

using InternalOpaque = OpaqueObject<InternalDefinition>
 

Public Member Functions

Result create (Options options=Options())
 Creates the event loop kernel object.
 
Result close ()
 Closes the event loop kernel object.
 
Result start (AsyncRequest &async)
 Queues an async request request that has been correctly setup.
 
void interrupt ()
 Interrupts the event loop even if it has active request on it.
 
bool isInitialized () const
 Returns true if create has been already called (successfully)
 
Result run ()
 Blocks until there are no more active queued requests, dispatching all completions.
 
Result runOnce ()
 Blocks until at least one request proceeds, ensuring forward progress, dispatching all completions.
 
Result runNoWait ()
 Process active requests if any, dispatching their completions, or returns immediately without blocking.
 
Result submitRequests (AsyncKernelEvents &kernelEvents)
 Submits all queued async requests.
 
Result blockingPoll (AsyncKernelEvents &kernelEvents)
 Blocks until at least one event happens, ensuring forward progress, without executing completions.
 
Result dispatchCompletions (AsyncKernelEvents &kernelEvents)
 Invokes completions for the AsyncKernelEvents collected by a call to AsyncEventLoop::blockingPoll.
 
Result wakeUpFromExternalThread (AsyncLoopWakeUp &wakeUp)
 Wake up the event loop from a thread different than the one where run() is called (and potentially blocked).
 
Result wakeUpFromExternalThread ()
 Wake up the event loop from a thread different than the one where run() is called (and potentially blocked)
 
Result createAsyncTCPSocket (SocketFlags::AddressFamily family, SocketDescriptor &outDescriptor)
 Helper to creates a TCP socket with AsyncRequest flags of the given family (IPV4 / IPV6).
 
Result associateExternallyCreatedTCPSocket (SocketDescriptor &outDescriptor)
 Associates a TCP Socket created externally (without using createAsyncTCPSocket) with the eventLoop.
 
Result associateExternallyCreatedFileDescriptor (FileDescriptor &outDescriptor)
 Associates a File descriptor created externally with the eventLoop.
 
void updateTime ()
 Updates loop time to "now".
 
Time::Monotonic getLoopTime () const
 Get Loop time.
 
int getNumberOfActiveRequests () const
 Obtain the total number of active requests.
 
int getNumberOfSubmittedRequests () const
 Obtain the total number of submitted requests.
 
AsyncLoopTimeoutfindEarliestLoopTimeout () const
 Returns the next AsyncLoopTimeout that will be executed (shortest relativeTimeout)
 
void excludeFromActiveCount (AsyncRequest &async)
 Excludes the request from active handles count (to avoid it keeping event loop alive)
 
void includeInActiveCount (AsyncRequest &async)
 Reverses the effect of excludeFromActiveCount for the request.
 
void enumerateRequests (Function< void(AsyncRequest &)> enumerationCallback)
 Enumerates all requests objects associated with this loop.
 
void setListeners (AsyncEventLoopListeners *listeners)
 Sets reference to listeners that will signal different events in loop lifetime.
 

Static Public Member Functions

static bool isExcludedFromActiveCount (const AsyncRequest &async)
 Checks if excludeFromActiveCount() has been called on the given request.
 
static bool tryLoadingLiburing ()
 Check if liburing is loadable (only on Linux)
 

Friends

struct AsyncRequest
 
struct AsyncFileWrite
 
struct AsyncFileRead
 

Detailed Description

Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEventLoop pushes all AsyncRequest derived classes to I/O queues in the OS.

See also
AsyncEventLoopMonitor can be used to integrate AsyncEventLoop with a GUI event loop

Basic lifetime for an event loop is:

AsyncEventLoop eventLoop;
SC_TRY(eventLoop.create()); // Create OS specific queue handles
// ...
// Add all needed AsyncRequest
// ...
SC_TRY(eventLoop.run());
// ...
// Here all AsyncRequest have either finished or have been stopped
// ...
SC_TRY(eventLoop.close()); // Free OS specific queue handles

Member Function Documentation

◆ associateExternallyCreatedFileDescriptor()

Result SC::AsyncEventLoop::associateExternallyCreatedFileDescriptor ( FileDescriptor & outDescriptor)
nodiscard

Associates a File descriptor created externally with the eventLoop.

◆ associateExternallyCreatedTCPSocket()

Result SC::AsyncEventLoop::associateExternallyCreatedTCPSocket ( SocketDescriptor & outDescriptor)
nodiscard

Associates a TCP Socket created externally (without using createAsyncTCPSocket) with the eventLoop.

◆ blockingPoll()

Result SC::AsyncEventLoop::blockingPoll ( AsyncKernelEvents & kernelEvents)
nodiscard

Blocks until at least one event happens, ensuring forward progress, without executing completions.

It's one of the three building blocks of AsyncEventLoop::runOnce allowing co-operation of AsyncEventLoop within another event loop (for example a GUI event loop or another IO event loop).

One possible example of such integration with a GUI event loop could:

Waiting on requests blocks the current thread with 0% CPU utilization.

Parameters
kernelEventsMandatory parameter to store kernel IO events WITHOUT running their completions. In that case user is expected to run completions passing it to AsyncEventLoop::dispatchCompletions.
See also
AsyncEventLoop::submitRequests sends async requests to kernel before calling blockingPoll
AsyncEventLoop::dispatchCompletions invokes callbacks associated with kernel events after blockingPoll
AsyncEventLoop::setListeners sets function called before and after entering kernel poll

◆ close()

Result SC::AsyncEventLoop::close ( )
nodiscard

Closes the event loop kernel object.

◆ create()

Result SC::AsyncEventLoop::create ( Options options = Options())
nodiscard

Creates the event loop kernel object.

◆ createAsyncTCPSocket()

Result SC::AsyncEventLoop::createAsyncTCPSocket ( SocketFlags::AddressFamily family,
SocketDescriptor & outDescriptor )
nodiscard

Helper to creates a TCP socket with AsyncRequest flags of the given family (IPV4 / IPV6).

It also automatically registers the socket with the eventLoop (associateExternallyCreatedTCPSocket)

◆ dispatchCompletions()

Result SC::AsyncEventLoop::dispatchCompletions ( AsyncKernelEvents & kernelEvents)
nodiscard

Invokes completions for the AsyncKernelEvents collected by a call to AsyncEventLoop::blockingPoll.

This is typically done when user wants to pool for events on a thread (calling AsyncEventLoop::blockingPoll) and dispatch the callbacks on another thread (calling AsyncEventLoop::dispatchCompletions). The typical example would be integrating AsyncEventLoop with a GUI event loop.

See also
AsyncEventLoop::blockingPoll for a description on how to integrate AsyncEventLoop with another event loop

◆ enumerateRequests()

void SC::AsyncEventLoop::enumerateRequests ( Function< void(AsyncRequest &)> enumerationCallback)

Enumerates all requests objects associated with this loop.

◆ excludeFromActiveCount()

void SC::AsyncEventLoop::excludeFromActiveCount ( AsyncRequest & async)

Excludes the request from active handles count (to avoid it keeping event loop alive)

◆ findEarliestLoopTimeout()

AsyncLoopTimeout * SC::AsyncEventLoop::findEarliestLoopTimeout ( ) const
nodiscard

Returns the next AsyncLoopTimeout that will be executed (shortest relativeTimeout)

Returns
nullptr if no AsyncLoopTimeout has been started or scheduled

◆ getLoopTime()

Time::Monotonic SC::AsyncEventLoop::getLoopTime ( ) const
nodiscard

Get Loop time.

◆ getNumberOfActiveRequests()

int SC::AsyncEventLoop::getNumberOfActiveRequests ( ) const
nodiscard

Obtain the total number of active requests.

◆ getNumberOfSubmittedRequests()

int SC::AsyncEventLoop::getNumberOfSubmittedRequests ( ) const
nodiscard

Obtain the total number of submitted requests.

◆ includeInActiveCount()

void SC::AsyncEventLoop::includeInActiveCount ( AsyncRequest & async)

Reverses the effect of excludeFromActiveCount for the request.

◆ interrupt()

void SC::AsyncEventLoop::interrupt ( )

Interrupts the event loop even if it has active request on it.

◆ isExcludedFromActiveCount()

static bool SC::AsyncEventLoop::isExcludedFromActiveCount ( const AsyncRequest & async)
staticnodiscard

Checks if excludeFromActiveCount() has been called on the given request.

◆ isInitialized()

bool SC::AsyncEventLoop::isInitialized ( ) const
nodiscard

Returns true if create has been already called (successfully)

◆ run()

Result SC::AsyncEventLoop::run ( )
nodiscard

Blocks until there are no more active queued requests, dispatching all completions.

It's useful for applications where the eventLoop is the only (or the main) loop. One example could be a console based app doing socket IO or a web server. Waiting on kernel events blocks the current thread with 0% CPU utilization.

See also
AsyncEventLoop::blockingPoll to integrate the loop with a GUI event loop

◆ runNoWait()

Result SC::AsyncEventLoop::runNoWait ( )
nodiscard

Process active requests if any, dispatching their completions, or returns immediately without blocking.

It's useful for game-like applications where the event loop runs every frame and one would like to check and dispatch its I/O callbacks in-between frames. This call allows poll-checking I/O without blocking.

See also
AsyncEventLoop::blockingPoll to integrate the loop with a GUI event loop

◆ runOnce()

Result SC::AsyncEventLoop::runOnce ( )
nodiscard

Blocks until at least one request proceeds, ensuring forward progress, dispatching all completions.

It's useful for application where it's needed to run some idle work after every IO event. Waiting on requests blocks the current thread with 0% CPU utilization.

This function is a shortcut invoking async event loop building blocks:

◆ setListeners()

void SC::AsyncEventLoop::setListeners ( AsyncEventLoopListeners * listeners)

Sets reference to listeners that will signal different events in loop lifetime.

Note
The structure pointed by this pointer must be valid throughout loop lifetime

◆ start()

Result SC::AsyncEventLoop::start ( AsyncRequest & async)

Queues an async request request that has been correctly setup.

Note
The request will be validated immediately and activated during next event loop cycle

◆ submitRequests()

Result SC::AsyncEventLoop::submitRequests ( AsyncKernelEvents & kernelEvents)
nodiscard

Submits all queued async requests.

An AsyncRequest becomes queued after user calls its specific AsyncRequest::start method.

See also
AsyncEventLoop::blockingPoll for a description on how to integrate AsyncEventLoop with another event loop

◆ tryLoadingLiburing()

static bool SC::AsyncEventLoop::tryLoadingLiburing ( )
staticnodiscard

Check if liburing is loadable (only on Linux)

Returns
true if liburing has been loaded, false otherwise (and on any non-Linux os)

◆ updateTime()

void SC::AsyncEventLoop::updateTime ( )

Updates loop time to "now".

◆ wakeUpFromExternalThread() [1/2]

Result SC::AsyncEventLoop::wakeUpFromExternalThread ( )
nodiscard

Wake up the event loop from a thread different than the one where run() is called (and potentially blocked)

◆ wakeUpFromExternalThread() [2/2]

Result SC::AsyncEventLoop::wakeUpFromExternalThread ( AsyncLoopWakeUp & wakeUp)
nodiscard

Wake up the event loop from a thread different than the one where run() is called (and potentially blocked).

The parameter is an AsyncLoopWakeUp that must have been previously started (with AsyncLoopWakeUp::start).


The documentation for this struct was generated from the following file: