1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <lib/async/cpp/wait.h> 6 7namespace async { 8 9WaitBase::WaitBase(zx_handle_t object, zx_signals_t trigger, async_wait_handler_t* handler) 10 : wait_{{ASYNC_STATE_INIT}, handler, object, trigger} {} 11 12WaitBase::~WaitBase() { 13 if (dispatcher_) { 14 // Failure to cancel here may result in a dangling pointer... 15 zx_status_t status = async_cancel_wait(dispatcher_, &wait_); 16 ZX_ASSERT_MSG(status == ZX_OK, "status=%d", status); 17 } 18} 19 20zx_status_t WaitBase::Begin(async_dispatcher_t* dispatcher) { 21 if (dispatcher_) 22 return ZX_ERR_ALREADY_EXISTS; 23 24 dispatcher_ = dispatcher; 25 zx_status_t status = async_begin_wait(dispatcher, &wait_); 26 if (status != ZX_OK) { 27 dispatcher_ = nullptr; 28 } 29 return status; 30} 31 32zx_status_t WaitBase::Cancel() { 33 if (!dispatcher_) 34 return ZX_ERR_NOT_FOUND; 35 36 async_dispatcher_t* dispatcher = dispatcher_; 37 dispatcher_ = nullptr; 38 39 zx_status_t status = async_cancel_wait(dispatcher, &wait_); 40 // |dispatcher| is required to be single-threaded, Cancel() is 41 // only supposed to be called on |dispatcher|'s thread, and 42 // we verified that the wait was pending before calling 43 // async_cancel_wait(). Assuming that |dispatcher| never queues 44 // a wait, |wait_| must have been pending with |dispatcher|. 45 ZX_DEBUG_ASSERT(status != ZX_ERR_NOT_FOUND); 46 return status; 47} 48 49Wait::Wait(zx_handle_t object, zx_signals_t trigger, Handler handler) 50 : WaitBase(object, trigger, &Wait::CallHandler), handler_(fbl::move(handler)) {} 51 52Wait::~Wait() = default; 53 54void Wait::CallHandler(async_dispatcher_t* dispatcher, async_wait_t* wait, 55 zx_status_t status, const zx_packet_signal_t* signal) { 56 auto self = Dispatch<Wait>(wait); 57 self->handler_(dispatcher, self, status, signal); 58} 59 60} // namespace async 61