morph 0.1.0
Asynchronous bridge between GUI thread and business models
Loading...
Searching...
No Matches
morph::exec::IoLoop Class Reference

Owns a core::net::PlatformLoop and, for IoLoopDriver::OwnThread natively, the one thread that runs it. More...

#include <io_loop.hpp>

Classes

class  Weak
 A non-owning handle that posts to the loop only while it exists. More...

Public Member Functions

 IoLoop (IoLoopDriver driver=IoLoopDriver::OwnThread)
 Creates the loop and, with IoLoopDriver::OwnThread, starts the thread that runs it.
 ~IoLoop ()
 Stops the loop and joins its thread; a Caller loop is destroyed in place.
 IoLoop (const IoLoop &)=delete
IoLoop & operator= (const IoLoop &)=delete
 IoLoop (IoLoop &&)=delete
IoLoop & operator= (IoLoop &&)=delete
::core::net::EventLoop & loop () noexcept
 The loop itself, for a component arming timers or opening sockets from inside one of its tasks, and for the driving thread of a Caller loop to turn it.
IoLoopDriver driver () const noexcept
 Who turns this loop.
bool runningHere () const noexcept
 Whether the calling thread may touch the loop's state directly.
template<class F>
void post (F &&task)
 Queues task to run on the loop thread, in a later turn.
template<class F>
void runAndWait (F &&task)
 Runs task on the loop and returns once it has run.
Weak weak () const
 A handle that posts only while this loop exists.

Detailed Description

Owns a core::net::PlatformLoop and, for IoLoopDriver::OwnThread natively, the one thread that runs it.

Cross-thread surface: post(), runAndWait(), runningHere(), driver() and weak(). Everything else about the loop — timers, sockets, flows — is touched only in tasks it runs, or, for a Caller loop, on its driving thread.

Lifetime
Must outlive every component built on it: a component's destructor runs its close on the loop and waits for it, which a stopped loop would never run. Destroy the components first, then the IoLoop. A Caller loop and its components are destroyed on the driving thread, outside a turn.

Definition at line 74 of file io_loop.hpp.

Constructor & Destructor Documentation

◆ IoLoop()

morph::exec::IoLoop::IoLoop ( IoLoopDriver driver = IoLoopDriver::OwnThread)
inlineexplicit

Creates the loop and, with IoLoopDriver::OwnThread, starts the thread that runs it.

Parameters
driverWho turns the loop. Caller starts no thread and makes the constructing thread the loop's.

Definition at line 118 of file io_loop.hpp.

◆ ~IoLoop()

morph::exec::IoLoop::~IoLoop ( )
inline

Stops the loop and joins its thread; a Caller loop is destroyed in place.

Work still queued is dropped by the loop's own teardown, not run. On the loop's own thread — a task that dropped the last owner — an OwnThread loop cannot join: it asks the loop to stop and lets the thread end with the turn it is in, the loop kept alive by the thread's own share of it. A Caller loop has no thread to stop: destroyed outside a turn nothing is running it, so its teardown is serialised with dispatch. Destroyed inside one of its own turns, that turn would return into a destroyed loop; an assertion refuses it.

Definition at line 142 of file io_loop.hpp.

Member Function Documentation

◆ loop()

::core::net::EventLoop & morph::exec::IoLoop::loop ( )
inlinenodiscardnoexcept

The loop itself, for a component arming timers or opening sockets from inside one of its tasks, and for the driving thread of a Caller loop to turn it.

Returns
The platform loop; valid for this object's lifetime.

Definition at line 176 of file io_loop.hpp.

◆ driver()

IoLoopDriver morph::exec::IoLoop::driver ( ) const
inlinenodiscardnoexcept

Who turns this loop.

Returns
The driver passed at construction.

Definition at line 180 of file io_loop.hpp.

◆ runningHere()

bool morph::exec::IoLoop::runningHere ( ) const
inlinenodiscardnoexcept

Whether the calling thread may touch the loop's state directly.

Natively that is the loop's own ExecutorScope, stated for every turn, and — for a Caller loop — also the driving thread between turns, where nothing else can be running the loop. Under single-threaded WebAssembly there is one thread, so the answer is always yes.

Returns
True inside one of the loop's tasks, or on a Caller loop's driving thread.

Definition at line 190 of file io_loop.hpp.

◆ post()

template<class F>
void morph::exec::IoLoop::post ( F && task)
inline

Queues task to run on the loop thread, in a later turn.

A throw out of task is logged and swallowed: one escaping a turn would end the loop's thread.

Template Parameters
FA copyable callable taking no arguments.
Parameters
taskWhat to run.

Definition at line 207 of file io_loop.hpp.

◆ runAndWait()

template<class F>
void morph::exec::IoLoop::runAndWait ( F && task)
inline

Runs task on the loop and returns once it has run.

Inline where runningHere() holds, so a task of the loop — or a Caller loop's driving thread — never waits on itself; inline on a Caller loop's driving thread between turns, it runs inside the loop's ExecutorScope, so runningOn() agrees with runningHere() there. For teardown and for the few verbs that must answer with the loop's own result.

A throw out of task reaches the caller, inline or not. A task the loop drops unrun — it was destroyed first — ends the wait rather than hanging it, and the call returns without task having run.

Template Parameters
FA copyable callable taking no arguments.
Parameters
taskWhat to run.

Definition at line 226 of file io_loop.hpp.

◆ weak()

Weak morph::exec::IoLoop::weak ( ) const
inlinenodiscard

A handle that posts only while this loop exists.

Returns
The weak handle.

Definition at line 262 of file io_loop.hpp.


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