blob: a1d022e2562c324160f37547628c28d2d62bf879 [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.
#pragma once
#include <async/dispatcher.h>
__BEGIN_CDECLS
// Return codes for |async_wait_handler_t|.
typedef enum {
// The handler has finished waiting; it may immediately destroy or
// reuse the associated wait context for another purpose.
ASYNC_WAIT_FINISHED = 0,
// The handler is requesting for the wait to be reiussed upon return;
// it may modify the wait's properties before returning.
ASYNC_WAIT_AGAIN = 1,
} async_wait_result_t;
// Handles completion of asynchronous wait operations.
//
// Reports the |status| of the wait. If the status is |ZX_OK| then |signal|
// describes the signal which was received, otherwise |signal| is null.
//
// The result indicates whether the wait should be repeated; it may
// modify the wait's properties (such as the trigger) before returning.
//
// The result must be |ASYNC_WAIT_FINISHED| if |status| was not |ZX_OK|.
//
// It is safe for the handler to destroy itself when returning |ASYNC_WAIT_FINISHED|.
typedef async_wait_result_t(async_wait_handler_t)(async_t* async,
async_wait_t* wait,
zx_status_t status,
const zx_packet_signal_t* signal);
// Context for an asynchronous wait operation.
// A separate instance must be used for each wait.
//
// It is customary to aggregate (in C) or subclass (in C++) this structure
// to allow the wait context to retain additional state for its handler.
//
// See also |async::Task|.
typedef struct async_wait async_wait_t;
struct async_wait {
// Private state owned by the dispatcher, initialize to zero with |ASYNC_STATE_INIT|.
async_state_t state;
// The handler to invoke on completion of the wait.
async_wait_handler_t* handler;
// The object to wait for signals on.
zx_handle_t object;
// The set of signals to wait for.
zx_signals_t trigger;
// Valid flags: |ASYNC_FLAG_HANDLE_SHUTDOWN|.
uint32_t flags;
// Reserved for future use, set to zero.
uint32_t reserved;
};
// Begins asynchronously waiting for an object to receive one or more signals
// specified in |wait|. Invokes the handler when the wait completes.
//
// The client is responsible for allocating and retaining the wait context
// until the handler runs or the wait is successfully canceled using
// `async_cancel_wait()`.
//
// When the dispatcher is shutting down (being destroyed), attempting to
// begin new waits will fail but previously begun waits can still be canceled
// successfully.
//
// Returns |ZX_OK| if the wait has been successfully started.
// Returns |ZX_ERR_BAD_STATE| if the dispatcher shut down.
// Returns |ZX_ERR_NOT_SUPPORTED| if not supported by the dispatcher.
//
// See |zx_object_wait_async()|.
inline zx_status_t async_begin_wait(async_t* async, async_wait_t* wait) {
return async->ops->begin_wait(async, wait);
}
// Cancels the wait associated with |wait|.
//
// When the dispatcher is shutting down (being destroyed), attempting to
// begin new waits will fail but previously begun waits can still be canceled
// successfully.
//
// Returns |ZX_OK| if there was a pending wait and it has been successfully
// canceled; its handler will not run again and can be released immediately.
// Returns |ZX_ERR_NOT_FOUND| if there was no pending wait either because it
// already completed, had not been started, or its completion packet has been
// dequeued and is pending delivery to its handler (perhaps on another thread).
// Returns |ZX_ERR_NOT_SUPPORTED| if not supported by the dispatcher.
//
// See |zx_port_cancel()|.
inline zx_status_t async_cancel_wait(async_t* async, async_wait_t* wait) {
return async->ops->cancel_wait(async, wait);
}
__END_CDECLS
#ifdef __cplusplus
#include <fbl/function.h>
#include <fbl/macros.h>
namespace async {
// C++ wrapper for a pending wait operation.
//
// This class is thread-safe.
class Wait final : private async_wait_t {
public:
// Handles completion of asynchronous wait operations.
//
// Reports the |status| of the wait. If the status is |ZX_OK| then |signal|
// describes the signal which was received, otherwise |signal| is null.
//
// The result indicates whether the wait should be repeated; it may
// modify the wait's properties (such as the trigger) before returning.
//
// The result must be |ASYNC_WAIT_FINISHED| if |status| was not |ZX_OK|.
//
// It is safe for the handler to destroy itself when returning |ASYNC_WAIT_FINISHED|.
using Handler = fbl::Function<async_wait_result_t(async_t* async,
zx_status_t status,
const zx_packet_signal_t* signal)>;
// Initializes the properties of the wait operation.
explicit Wait(zx_handle_t object = ZX_HANDLE_INVALID,
zx_signals_t trigger = ZX_SIGNAL_NONE, uint32_t flags = 0u);
// Destroys the wait operation.
//
// This object must not be destroyed until the wait has completed, been
// successfully canceled, or the asynchronous dispatcher itself has
// been destroyed.
~Wait();
// Gets or sets the handler to invoke when the wait completes.
// Must be set before beginning the wait.
const Handler& handler() const { return handler_; }
void set_handler(Handler handler) { handler_ = fbl::move(handler); }
// The object to wait for signals on.
zx_handle_t object() const { return async_wait_t::object; }
void set_object(zx_handle_t object) { async_wait_t::object = object; }
// The set of signals to wait for.
zx_signals_t trigger() const { return async_wait_t::trigger; }
void set_trigger(zx_signals_t trigger) { async_wait_t::trigger = trigger; }
// Valid flags: |ASYNC_FLAG_HANDLE_SHUTDOWN|.
uint32_t flags() const { return async_wait_t::flags; }
void set_flags(uint32_t flags) { async_wait_t::flags = flags; }
// Begins asynchronously waiting for the object to receive one or more of
// the trigger signals.
//
// See |async_begin_wait()| for details.
zx_status_t Begin(async_t* async);
// Cancels the wait.
//
// See |async_cancel_wait()| for details.
zx_status_t Cancel(async_t* async);
private:
static async_wait_result_t CallHandler(async_t* async, async_wait_t* wait,
zx_status_t status, const zx_packet_signal_t* signal);
Handler handler_;
DISALLOW_COPY_ASSIGN_AND_MOVE(Wait);
};
} // namespace async
#endif // __cplusplus