blob: 353c52b061425746f5dfe14aa913999e9d1d17f9 [file] [log] [blame]
Patrick Williams0139cac2022-09-20 17:04:17 -05001#include <sdbusplus/async/scope.hpp>
2
3#include <exception>
4
5namespace sdbusplus::async
6{
7scope::~scope() noexcept(false)
8{
Patrick Williamsc5b5ff52022-09-21 08:34:22 -05009 if (pending_count != 0)
Patrick Williams0139cac2022-09-20 17:04:17 -050010 {
11 throw std::logic_error(
12 "sdbusplus::async::scope destructed while tasks are pending.");
13 }
14}
15
16void scope::started_task() noexcept
17{
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050018 std::lock_guard l{lock};
19 ++pending_count;
Patrick Williams0139cac2022-09-20 17:04:17 -050020}
21
Patrick Williams4cfc2842022-09-22 09:53:33 -050022void scope::ended_task(std::exception_ptr&& e) noexcept
Patrick Williams0139cac2022-09-20 17:04:17 -050023{
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050024 scope_ns::scope_completion* p = nullptr;
25
26 {
27 std::lock_guard l{lock};
Patrick Williams4cfc2842022-09-22 09:53:33 -050028 --pending_count; // decrement count.
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050029
Patrick Williams4cfc2842022-09-22 09:53:33 -050030 if (e && pending_exception)
31 {
32 // Received a second exception without delivering the first
33 // to a pending completion. Terminate using the first one.
34 try
35 {
36 std::rethrow_exception(std::exchange(pending_exception, {}));
37 }
38 catch (...)
39 {
40 std::terminate();
41 }
42 }
43
44 // If the scope is complete, get the pending completion, if it exists.
45 if (e || (pending_count == 0))
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050046 {
47 p = std::exchange(pending, nullptr);
48 }
Patrick Williams4cfc2842022-09-22 09:53:33 -050049
50 // If we have an exception but no pending completion, save it away.
51 if (e && !p)
52 {
53 pending_exception = std::move(e);
54 }
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050055 }
56
57 if (p)
58 {
Patrick Williams4cfc2842022-09-22 09:53:33 -050059 p->complete(std::move(e));
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050060 }
Patrick Williams0139cac2022-09-20 17:04:17 -050061}
62
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050063scope_ns::scope_sender scope::empty() noexcept
64{
65 return scope_ns::scope_sender(*this);
66}
67
68namespace scope_ns
69{
70void scope_completion::arm() noexcept
71{
72 bool done = false;
Patrick Williams4cfc2842022-09-22 09:53:33 -050073 std::exception_ptr e{};
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050074
75 {
76 std::lock_guard l{s.lock};
77 if (s.pending_count == 0)
78 {
79 done = true;
80 }
Patrick Williams4cfc2842022-09-22 09:53:33 -050081 else if (s.pending_exception)
82 {
83 e = std::exchange(s.pending_exception, {});
84 done = true;
85 }
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050086 else
87 {
88 s.pending = this;
89 }
90 }
91
92 if (done)
93 {
Patrick Williams4cfc2842022-09-22 09:53:33 -050094 this->complete(std::move(e));
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050095 }
96}
97} // namespace scope_ns
98
Patrick Williams0139cac2022-09-20 17:04:17 -050099} // namespace sdbusplus::async