blob: d2a7eacfec9a8f15f64e3b4219999b095be7e8df [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/wait.h>
#ifdef __cplusplus
#include <fbl/function.h>
#include <fbl/macros.h>
namespace async {
// C++ wrapper for a pending wait operation which is automatically canceled
// when it goes out of scope.
//
// This class is NOT thread-safe; it can only be used with single-threaded
// asynchronous dispatchers.
class AutoWait 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 and binds it to an
// asynchronous dispatcher.
explicit AutoWait(async_t* async,
zx_handle_t object = ZX_HANDLE_INVALID,
zx_signals_t trigger = ZX_SIGNAL_NONE,
uint32_t flags = 0u);
// Destroys the wait operation.
//
// The wait is canceled automatically if it is still pending.
~AutoWait();
// Gets the asynchronous dispatcher to which this wait has been bound.
async_t* async() const { return async_; }
// Returns true if |Begin()| was called successfully but the wait has not
// completed or been canceled.
bool is_pending() const { return pending_; }
// 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.
//
// This method must not be called when the wait is already pending.
//
// See |async_begin_wait()| for details.
zx_status_t Begin();
// Cancels the wait.
//
// This method does nothing if the wait is not pending.
//
// See |async_cancel_wait()| for details.
void Cancel();
private:
static async_wait_result_t CallHandler(async_t* async, async_wait_t* wait,
zx_status_t status,
const zx_packet_signal_t* signal);
async_t* const async_;
Handler handler_;
bool pending_ = false;
DISALLOW_COPY_ASSIGN_AND_MOVE(AutoWait);
};
} // namespace async
#endif // __cplusplus