1 #include <sdbusplus/async/fdio.hpp> 2 3 namespace sdbusplus::async 4 { 5 fdio::fdio(context& ctx, int fd) : context_ref(ctx) 6 { 7 static auto eventHandler = 8 [](sd_event_source*, int, uint32_t, void* data) noexcept { 9 static_cast<fdio*>(data)->handleEvent(); 10 return 0; 11 }; 12 13 try 14 { 15 source = event_loop().add_io(fd, EPOLLIN, eventHandler, this); 16 } 17 catch (...) 18 { 19 throw std::runtime_error("Failed to add fd to event loop"); 20 } 21 } 22 23 void fdio::handleEvent() noexcept 24 { 25 std::unique_lock l{lock}; 26 if (complete == nullptr) 27 { 28 return; 29 } 30 auto c = std::exchange(complete, nullptr); 31 l.unlock(); 32 c->complete(); 33 } 34 35 namespace fdio_ns 36 { 37 38 fdio_completion::~fdio_completion() 39 { 40 std::unique_lock l{fdioInstance.lock}; 41 42 if (fdioInstance.complete == this) 43 { 44 std::exchange(fdioInstance.complete, nullptr); 45 } 46 } 47 48 void fdio_completion::arm() noexcept 49 { 50 // Set ourselves as the awaiting Receiver 51 std::unique_lock l{fdioInstance.lock}; 52 53 if (std::exchange(fdioInstance.complete, this) != nullptr) 54 { 55 // We do not support two awaiters; throw exception. Since we are in 56 // a noexcept context this will std::terminate anyhow, which is 57 // approximately the same as 'assert' but with better information. 58 try 59 { 60 throw std::logic_error( 61 "fdio_completion started with another await already pending!"); 62 } 63 catch (...) 64 { 65 std::terminate(); 66 } 67 } 68 } 69 70 } // namespace fdio_ns 71 72 } // namespace sdbusplus::async 73