blob: ea193eeaa97db54216b26953b838d362c78965b8 [file] [log] [blame]
// Copyright 2018 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 <mutex>
#include <lib/async/cpp/task.h>
#include <lib/async/dispatcher.h>
#include <lib/async/task.h>
#include <lib/fidl/cpp/thread_safe_binding_set.h>
#include <lib/fit/function.h>
#include <zx/channel.h>
#include <zx/time.h>
namespace wlan {
namespace async {
template <typename I> class Dispatcher {
public:
Dispatcher(async_dispatcher_t* dispatcher) : dispatcher_(dispatcher) {}
// Start serving requests on the given channel.
// Fails if shutdown has been initiated.
zx_status_t AddBinding(zx::channel chan, I* intf) {
std::lock_guard<std::mutex> shutdown_guard(lock_);
if (shutdown_initiated_) { return ZX_ERR_PEER_CLOSED; }
fidl::InterfaceRequest<I> request(std::move(chan));
bindings_.AddBinding(intf, std::move(request), dispatcher_);
return ZX_OK;
}
// Stop accepting new requests initiate shutdown.
// If |ready_callback| is supplied, then it will be called from
// the event loop thread once shutdown is complete.
//
// If |InitiateShutdown| has been already called previously,
// then it returns immediately, and |ready_callback| is ignored.
void InitiateShutdown(fit::closure ready_callback) {
{
std::lock_guard<std::mutex> guard(lock_);
if (shutdown_initiated_) { return; }
shutdown_initiated_ = true;
}
// Release any FIDL bindings and close their channels. This ensures
// that no additional requests will be made via this dispatcher
bindings_.CloseAll();
// Submit a sentinel task. Since the event loop in our async_t is single-threaded,
// the execution of this task will guarantee that all in-flight requests have finished.
if (ready_callback) {
zx_status_t status = ::async::PostTask(dispatcher_, std::move(ready_callback));
ZX_DEBUG_ASSERT(status == ZX_OK);
}
}
private:
fidl::ThreadSafeBindingSet<I> bindings_;
async_dispatcher_t* dispatcher_;
std::mutex lock_;
bool shutdown_initiated_ __TA_GUARDED(lock_){false};
};
} // namespace async
} // namespace wlan