blob: 764dc0ad71242298bc3dd5fe46d1aced7c5bd0f9 [file] [log] [blame]
// Copyright 2022 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.
#include <lib/fdf/cpp/internal.h>
#include <zircon/assert.h>
namespace fdf_internal {
DriverShutdown::DriverShutdown() : fdf_internal_driver_shutdown_observer_t{CallHandler} {}
zx_status_t DriverShutdown::Begin(const void* driver, Handler shutdown_handler) {
// Since calls to the driver runtime are non-reentrant we can safely hold the lock.
std::lock_guard<std::mutex> lock(lock_);
if (handler_) {
return ZX_ERR_BAD_STATE;
}
driver_ = driver;
handler_ = std::move(shutdown_handler);
fdf_status_t status = fdf_internal_shutdown_dispatchers_async(driver_, this);
if (status != ZX_OK) {
driver_ = nullptr;
handler_ = nullptr;
return status;
}
return ZX_OK;
}
DriverShutdown::~DriverShutdown() {
std::lock_guard<std::mutex> lock(lock_);
ZX_ASSERT(!handler_);
}
// static
void DriverShutdown::CallHandler(const void* driver,
fdf_internal_driver_shutdown_observer_t* observer) {
Handler handler;
{
auto self = static_cast<DriverShutdown*>(observer);
std::lock_guard<std::mutex> lock(self->lock_);
// Move the handler to the stack prior to calling.
handler = std::move(self->handler_);
}
ZX_ASSERT(handler);
handler(driver);
}
} // namespace fdf_internal