blob: 641d6a60497c9772d23d4725b94629cef082926e [file] [log] [blame]
#include <sdbusplus/async/fdio.hpp>
namespace sdbusplus::async
{
fdio::fdio(context& ctx, int fd) : context_ref(ctx), fd(fd)
{
static auto eventHandler =
[](sd_event_source*, int, uint32_t, void* data) noexcept {
static_cast<fdio*>(data)->handleEvent();
return 0;
};
try
{
source = event_loop().add_io(fd, EPOLLIN, eventHandler, this);
}
catch (...)
{
throw std::runtime_error("Failed to add fd to event loop");
}
}
void fdio::handleEvent() noexcept
{
std::unique_lock l{lock};
if (complete == nullptr)
{
return;
}
auto c = std::exchange(complete, nullptr);
l.unlock();
c->complete();
}
namespace fdio_ns
{
fdio_completion::~fdio_completion()
{
std::unique_lock l{fdioInstance.lock};
if (fdioInstance.complete == this)
{
std::exchange(fdioInstance.complete, nullptr);
}
}
void fdio_completion::arm() noexcept
{
// Set ourselves as the awaiting Receiver
std::unique_lock l{fdioInstance.lock};
if (std::exchange(fdioInstance.complete, this) != nullptr)
{
// We do not support two awaiters; throw exception. Since we are in
// a noexcept context this will std::terminate anyhow, which is
// approximately the same as 'assert' but with better information.
try
{
throw std::logic_error(
"fdio_completion started with another await already pending!");
}
catch (...)
{
std::terminate();
}
}
}
} // namespace fdio_ns
} // namespace sdbusplus::async