async::Loop

#include <loop.h>

C++ wrapper for an asynchronous dispatch loop.

Summary

This class is thread-safe.

Constructors and Destructors

Loop(const async_loop_config_t *config)
Creates a message loop.
Loop(const Loop &)
Loop(Loop &&)
~Loop()
Destroys the message loop. Implicitly calls |Shutdown()|.

Public functions

GetState() const
async_loop_state_t
Returns the current state of the message loop.
JoinThreads()
void
Blocks until all dispatch threads started with |StartThread()| have terminated.
Quit()
void
Quits the message loop.
ResetQuit()
zx_status_t
Resets the quit state of the message loop so that it can be restarted using |Run()| or |StartThread()|.
Run(zx::time deadline, bool once)
zx_status_t
Runs the message loop on the current thread.
RunUntilIdle()
zx_status_t
Runs the message loop on the current thread.
Shutdown()
void
Shuts down the message loop, notifies handlers which asked to handle shutdown.
StartThread(const char *name, thrd_t *out_thread)
zx_status_t
Starts a message loop running on a new thread.
dispatcher() const
async_dispatcher_t *
Gets the loop's asynchronous dispatch interface.
loop() const
async_loop_t *
Gets the underlying message loop structure.
operator=(const Loop &)=delete
Loop &
operator=(Loop &&)=delete
Loop &

Public functions

GetState

async_loop_state_t GetState() const 

Returns the current state of the message loop.

JoinThreads

void JoinThreads()

Blocks until all dispatch threads started with |StartThread()| have terminated.

Loop

 Loop(
  const async_loop_config_t *config
)

Creates a message loop.

All operations on the message loop are thread-safe (except destroy).

Note that it's ok to run the loop on a different thread from the one on which it was created.

|config| provides configuration for the message loop. Must not be null.

See also: |kAsyncLoopConfigNeverAttachToThread| |kAsyncLoopConfigAttachToCurrentThread| |kAsyncLoopConfigNoAttachToCurrentThread|

Loop

 Loop(
  const Loop &
)=delete

Loop

 Loop(
  Loop &&
)=delete

Quit

void Quit()

Quits the message loop.

Active invocations of |Run()| and threads started using |StartThread()| will eventually terminate upon completion of their current unit of work.

Subsequent calls to |Run()| or |StartThread()| will return immediately until |ResetQuit()| is called.

ResetQuit

zx_status_t ResetQuit()

Resets the quit state of the message loop so that it can be restarted using |Run()| or |StartThread()|.

This function must only be called when the message loop is not running. The caller must ensure all active invocations of |Run()| and threads started using |StartThread()| have terminated before resetting the quit state.

Returns |ZX_OK| if the loop's state was |ASYNC_LOOP_RUNNABLE| or |ASYNC_LOOP_QUIT|. Returns |ZX_ERR_BAD_STATE| if the loop's state was |ASYNC_LOOP_SHUTDOWN| or if the message loop is currently active on one or more threads.

Run

zx_status_t Run(
  zx::time deadline,
  bool once
)

Runs the message loop on the current thread.

This function can be called on multiple threads to setup a multi-threaded dispatcher.

Dispatches events until the |deadline| expires or the loop is quitted. Use |ZX_TIME_INFINITE| to dispatch events indefinitely.

If |once| is true, performs a single unit of work then returns.

Returns |ZX_OK| if the dispatcher returns after one cycle. Returns |ZX_ERR_TIMED_OUT| if the deadline expired. Returns |ZX_ERR_CANCELED| if the loop quitted. Returns |ZX_ERR_BAD_STATE| if the loop was shut down with |Shutdown()|.

RunUntilIdle

zx_status_t RunUntilIdle()

Runs the message loop on the current thread.

Dispatches events until there are none remaining, and then returns without waiting. This is useful for unit testing, because the behavior doesn't depend on time.

WARNING: Calling RunUntilIdle() with a dispatcher that runs on a separate thread or a multi-threaded dispatcher (common outside single-threaded tests) can have subtle unexpected consequences: 1) This may return before newly queued work is completed, because the work may be dispatched to a different thread. The calling thread will not wait on that work to complete, only for it to be removed from the pending work queue (roughly speaking). 2) Work that was previously queued, prior to calling RunUntilIdle(), is also not guaranteed to have completed when RunUntilIdle() finishes.

Returns |ZX_OK| if the dispatcher reaches an idle state. Returns |ZX_ERR_CANCELED| if the loop quitted. Returns |ZX_ERR_BAD_STATE| if the loop was shut down with |Shutdown()|.

Shutdown

void Shutdown()

Shuts down the message loop, notifies handlers which asked to handle shutdown.

The message loop must not currently be running on any threads other than those started by |StartThread()| which this function will join.

Any tasks still queued when |Shutdown()| is called will be immediately completed with the ZX_ERR_CANCELLED status. Callbacks will called on one of the loop's worker threads (i.e., a thread created by |StartThread()|) if such a thread exists. If no worker threads have been created, callbacks will be called by the current thread.

Does nothing if already shutting down.

StartThread

zx_status_t StartThread(
  const char *name,
  thrd_t *out_thread
)

Starts a message loop running on a new thread.

The thread will run until the loop quits.

|name| is the desired name for the new thread, may be NULL. If |out_thread| is not NULL, it is set to the new thread identifier.

Returns |ZX_OK| on success. Returns |ZX_ERR_BAD_STATE| if the loop was shut down with |async_loop_shutdown()|. Returns |ZX_ERR_NO_MEMORY| if allocation or thread creation failed.

dispatcher

async_dispatcher_t * dispatcher() const 

Gets the loop's asynchronous dispatch interface.

loop

async_loop_t * loop() const 

Gets the underlying message loop structure.

operator=

Loop & operator=(
  const Loop &
)=delete

operator=

Loop & operator=(
  Loop &&
)=delete

~Loop

 ~Loop()

Destroys the message loop. Implicitly calls |Shutdown()|.