blob: 94c79d17a09233ac89cbacb8addb4f1cc17191ff [file] [log] [blame]
Jagpal Singh Gill2a12ae12024-10-23 11:20:25 -07001#include <sdbusplus/async/fdio.hpp>
2
3namespace sdbusplus::async
4{
Jagpal Singh Gill5b543252025-07-22 18:25:36 -07005fdio::fdio(context& ctx, int fd, std::chrono::microseconds timeout) :
6 context_ref(ctx),
7 timeout(std::chrono::duration_cast<event_t::time_resolution>(timeout))
Jagpal Singh Gill2a12ae12024-10-23 11:20:25 -07008{
9 static auto eventHandler =
10 [](sd_event_source*, int, uint32_t, void* data) noexcept {
11 static_cast<fdio*>(data)->handleEvent();
12 return 0;
13 };
14
15 try
16 {
17 source = event_loop().add_io(fd, EPOLLIN, eventHandler, this);
18 }
19 catch (...)
20 {
21 throw std::runtime_error("Failed to add fd to event loop");
22 }
23}
24
25void fdio::handleEvent() noexcept
26{
27 std::unique_lock l{lock};
28 if (complete == nullptr)
29 {
30 return;
31 }
32 auto c = std::exchange(complete, nullptr);
33 l.unlock();
34 c->complete();
35}
36
Jagpal Singh Gill5b543252025-07-22 18:25:36 -070037void fdio::handleTimeout() noexcept
38{
39 std::unique_lock l{lock};
40 if (complete == nullptr)
41 {
42 return;
43 }
44 auto c = std::exchange(complete, nullptr);
45 l.unlock();
46 c->error(std::make_exception_ptr(fdio_timeout_exception()));
47}
48
Jagpal Singh Gill2a12ae12024-10-23 11:20:25 -070049namespace fdio_ns
50{
51
52fdio_completion::~fdio_completion()
53{
54 std::unique_lock l{fdioInstance.lock};
55
56 if (fdioInstance.complete == this)
57 {
58 std::exchange(fdioInstance.complete, nullptr);
59 }
60}
61
62void fdio_completion::arm() noexcept
63{
64 // Set ourselves as the awaiting Receiver
65 std::unique_lock l{fdioInstance.lock};
66
67 if (std::exchange(fdioInstance.complete, this) != nullptr)
68 {
69 // We do not support two awaiters; throw exception. Since we are in
70 // a noexcept context this will std::terminate anyhow, which is
71 // approximately the same as 'assert' but with better information.
72 try
73 {
74 throw std::logic_error(
75 "fdio_completion started with another await already pending!");
76 }
77 catch (...)
78 {
79 std::terminate();
80 }
81 }
Jagpal Singh Gill5b543252025-07-22 18:25:36 -070082
83 l.unlock();
84
85 // Schedule the timeout
86 if (fdioInstance.timeout != event_t::time_resolution::zero())
87 {
88 static auto eventHandler =
89 [](sd_event_source*, uint64_t, void* data) noexcept {
90 static_cast<fdio*>(data)->handleTimeout();
91 return 0;
92 };
93
94 try
95 {
96 source = fdioInstance.event_loop().add_oneshot_timer(
97 eventHandler, &fdioInstance, fdioInstance.timeout);
98 }
99 catch (...)
100 {
101 error(std::current_exception());
102 }
103 }
Jagpal Singh Gill2a12ae12024-10-23 11:20:25 -0700104}
105
106} // namespace fdio_ns
107
108} // namespace sdbusplus::async