blob: 70285cdde303f91ecd208d8bf3d13a99127bb4a9 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIB_ASYNC_LOOP_CPP_LOOP_H_
#define LIB_ASYNC_LOOP_CPP_LOOP_H_
#include <lib/async-loop/loop.h>
#include <lib/async/default.h>
#include <lib/zx/time.h>
#include <stdbool.h>
#include <stddef.h>
#include <threads.h>
#include <zircon/compiler.h>
namespace async {
// C++ wrapper for an asynchronous dispatch loop.
//
// This class is thread-safe.
class Loop {
public:
// 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
// upon which it was created.
//
// |config| provides configuration for the message loop. Must not be null.
//
// See also |kAsyncLoopConfigAttachToThread| and |kAsyncLoopConfigNoAttachToThread|.
explicit Loop(const async_loop_config_t* config);
Loop(const Loop&) = delete;
Loop(Loop&&) = delete;
Loop& operator=(const Loop&) = delete;
Loop& operator=(Loop&&) = delete;
// Destroys the message loop.
// Implicitly calls |Shutdown()|.
~Loop();
// Gets the underlying message loop structure.
async_loop_t* loop() const { return loop_; }
// Gets the loop's asynchronous dispatch interface.
async_dispatcher_t* dispatcher() const { return async_loop_get_dispatcher(loop_); }
// 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.
//
// Does nothing if already shutting down.
void Shutdown();
// 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()|.
zx_status_t Run(zx::time deadline = zx::time::infinite(), bool once = false);
// 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.
//
// 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()|.
zx_status_t RunUntilIdle();
// 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.
void Quit();
// 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.
zx_status_t ResetQuit();
// Returns the current state of the message loop.
async_loop_state_t GetState() const;
// 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.
zx_status_t StartThread(const char* name = nullptr, thrd_t* out_thread = nullptr);
// Blocks until all dispatch threads started with |StartThread()|
// have terminated.
void JoinThreads();
private:
async_loop_t* loop_;
};
} // namespace async
#endif // LIB_ASYNC_LOOP_CPP_LOOP_H_