blob: d9eb8a7b02fdff8dd3af16d03372c737975f0e26 [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};
Patrick Williams095eff82022-09-22 17:44:30 -050019 started = true;
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050020 ++pending_count;
Patrick Williams0139cac2022-09-20 17:04:17 -050021}
22
Patrick Williams4cfc2842022-09-22 09:53:33 -050023void scope::ended_task(std::exception_ptr&& e) noexcept
Patrick Williams0139cac2022-09-20 17:04:17 -050024{
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050025 scope_ns::scope_completion* p = nullptr;
26
27 {
28 std::lock_guard l{lock};
Patrick Williams4cfc2842022-09-22 09:53:33 -050029 --pending_count; // decrement count.
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050030
Patrick Williams115e9b32022-09-23 16:20:59 -050031 if (e)
Patrick Williams4cfc2842022-09-22 09:53:33 -050032 {
Patrick Williams115e9b32022-09-23 16:20:59 -050033 pending_exceptions.emplace_back(std::exchange(e, {}));
Patrick Williams4cfc2842022-09-22 09:53:33 -050034 }
35
36 // If the scope is complete, get the pending completion, if it exists.
Patrick Williams115e9b32022-09-23 16:20:59 -050037 if (!pending_exceptions.empty() || (pending_count == 0))
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050038 {
39 p = std::exchange(pending, nullptr);
40 }
41 }
42
43 if (p)
44 {
Patrick Williams115e9b32022-09-23 16:20:59 -050045 std::exception_ptr fwd_exception = {};
46 if (!pending_exceptions.empty())
47 {
48 fwd_exception = pending_exceptions.front();
49 pending_exceptions.pop_front();
50 }
51 p->complete(std::move(fwd_exception));
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050052 }
Patrick Williams0139cac2022-09-20 17:04:17 -050053}
54
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050055scope_ns::scope_sender scope::empty() noexcept
56{
57 return scope_ns::scope_sender(*this);
58}
59
60namespace scope_ns
61{
62void scope_completion::arm() noexcept
63{
64 bool done = false;
Patrick Williams4cfc2842022-09-22 09:53:33 -050065 std::exception_ptr e{};
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050066
67 {
68 std::lock_guard l{s.lock};
Patrick Williams095eff82022-09-22 17:44:30 -050069 if (!s.started)
70 {
71 done = false;
72 }
Patrick Williams115e9b32022-09-23 16:20:59 -050073 else if (!s.pending_exceptions.empty())
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050074 {
Patrick Williams115e9b32022-09-23 16:20:59 -050075 e = s.pending_exceptions.front();
76 s.pending_exceptions.pop_front();
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050077 done = true;
78 }
Patrick Williams115e9b32022-09-23 16:20:59 -050079 else if (s.pending_count == 0)
Patrick Williams4cfc2842022-09-22 09:53:33 -050080 {
Patrick Williams4cfc2842022-09-22 09:53:33 -050081 done = true;
82 }
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050083 else
84 {
85 s.pending = this;
86 }
87 }
88
89 if (done)
90 {
Patrick Williams4cfc2842022-09-22 09:53:33 -050091 this->complete(std::move(e));
Patrick Williamsc5b5ff52022-09-21 08:34:22 -050092 }
93}
94} // namespace scope_ns
95
Patrick Williams0139cac2022-09-20 17:04:17 -050096} // namespace sdbusplus::async