@@ -47,109 +47,109 @@ namespace sdbus {
4747 class Proxy ;
4848 } // namespace internal
4949
50- /* *******************************************/ /* *
51- * @enum AwaitableState
52- *
53- * Represents the lifecycle state of an asynchronous
54- * operation in the coroutine awaitable protocol.
55- * Used for atomic coordination between the coroutine
56- * and the D-Bus callback thread.
57- *
58- ***********************************************/
59- enum class AwaitableState : uint8_t
60- {
61- NotReady, // Initial state: callback hasn't fired yet
62- Waiting, // Coroutine is suspended and waiting for callback
63- Completed // Callback completed, result is ready
64- };
65-
66- // Shared data
67- template <typename T>
68- struct AwaitableData
69- {
70- using result_type = std::conditional_t <std::is_void_v<T>, std::monostate, T>;
71- std::variant<result_type, std::exception_ptr> result;
72- #ifdef __cpp_lib_coroutine
73- std::coroutine_handle<> handle;
74- #endif // __cpp_lib_coroutine
75- std::atomic<AwaitableState> status{AwaitableState::NotReady};
76-
77- void resumeCoroutine ()
50+ /* *******************************************/ /* *
51+ * @enum AwaitableState
52+ *
53+ * Represents the lifecycle state of an asynchronous
54+ * operation in the coroutine awaitable protocol.
55+ * Used for atomic coordination between the coroutine
56+ * and the D-Bus callback thread.
57+ *
58+ ***********************************************/
59+ enum class AwaitableState : uint8_t
7860 {
61+ NotReady, // Initial state: callback hasn't fired yet
62+ Waiting, // Coroutine is suspended and waiting for callback
63+ Completed // Callback completed, result is ready
64+ };
65+
66+ // Shared data
67+ template <typename T>
68+ struct AwaitableData
69+ {
70+ using result_type = std::conditional_t <std::is_void_v<T>, std::monostate, T>;
71+ std::variant<result_type, std::exception_ptr> result;
7972#ifdef __cpp_lib_coroutine
80- handle. resume () ;
73+ std::coroutine_handle<> handle;
8174#endif // __cpp_lib_coroutine
82- }
83- };
75+ std::atomic<AwaitableState> status{AwaitableState::NotReady};
8476
85- /* *******************************************/ /* *
86- * @class Awaitable
87- *
88- * A C++20 coroutine awaitable that represents an asynchronous
89- * operation. Allows suspending a coroutine until a D-Bus method
90- * call completes, then resuming with the result or exception.
91- *
92- * This is not a full-fledged coroutine type, but a simple awaitable
93- * that can be used with `co_await` to retrieve results of async D-Bus calls.
94- * This is independent of any specific coroutine framework or scheduler,
95- * as it relies on the D-Bus callback mechanism to resume the coroutine.
96- *
97- * You most likely don't need to use this class directly. Instead, use the
98- * respective low-level or high-level API functions that return an Awaitable
99- * instance, such as IProxy::callMethodAsync with with_awaitable_t tag,
100- * or the .getResultAsAwaitable() methods of the high-level API.
101- *
102- * The class represents nothing, i.e. is a simple placeholder class, if the API
103- * is used as C++17 or with a standard library not supporting coroutines.
104- *
105- ***********************************************/
106- template <typename T>
107- class Awaitable
108- {
77+ void resumeCoroutine ()
78+ {
10979#ifdef __cpp_lib_coroutine
110- public:
111- // Called when the coroutine is co_await'ed. Returns true if the coroutine should be suspended.
112- [[nodiscard]] bool await_ready () const noexcept
113- {
114- return data_->status .load (std::memory_order_acquire) == AwaitableState::Completed;
115- }
116-
117- // Called when the coroutine is suspended, returning false here will immediately
118- // resume the coroutine.
119- bool await_suspend (std::coroutine_handle<> handle) noexcept
120- {
121- data_->handle = handle;
122-
123- // Attempt transition from NotReady to Waiting.
124- AwaitableState expected = AwaitableState::NotReady;
125- return data_->status .compare_exchange_strong (expected, AwaitableState::Waiting, std::memory_order_acq_rel);
126- }
127-
128- // Called when the coroutine is resumed. Returns the result or throws the exception.
129- T await_resume () const
80+ handle.resume ();
81+ #endif // __cpp_lib_coroutine
82+ }
83+ };
84+
85+ /* *******************************************/ /* *
86+ * @class Awaitable
87+ *
88+ * A C++20 coroutine awaitable that represents an asynchronous
89+ * operation. Allows suspending a coroutine until a D-Bus method
90+ * call completes, then resuming with the result or exception.
91+ *
92+ * This is not a full-fledged coroutine type, but a simple awaitable
93+ * that can be used with `co_await` to retrieve results of async D-Bus calls.
94+ * This is independent of any specific coroutine framework or scheduler,
95+ * as it relies on the D-Bus callback mechanism to resume the coroutine.
96+ *
97+ * You most likely don't need to use this class directly. Instead, use the
98+ * respective low-level or high-level API functions that return an Awaitable
99+ * instance, such as IProxy::callMethodAsync with with_awaitable_t tag,
100+ * or the .getResultAsAwaitable() methods of the high-level API.
101+ *
102+ * The class represents nothing, i.e. is a simple placeholder class, if the API
103+ * is used as C++17 or with a standard library not supporting coroutines.
104+ *
105+ ***********************************************/
106+ template <typename T>
107+ class Awaitable
130108 {
131- if (auto * exception = std::get_if<std::exception_ptr>(&data_->result ); exception != nullptr )
132- std::rethrow_exception (*exception);
133-
134- if constexpr (std::is_void_v<T>)
135- return ;
136- else
137- return std::get<T>(std::move (data_->result ));
138- }
109+ #ifdef __cpp_lib_coroutine
110+ public:
111+ // Called when the coroutine is co_await'ed. Returns true if the coroutine should be suspended.
112+ [[nodiscard]] bool await_ready () const noexcept
113+ {
114+ return data_->status .load (std::memory_order_acquire) == AwaitableState::Completed;
115+ }
116+
117+ // Called when the coroutine is suspended, returning false here will immediately
118+ // resume the coroutine.
119+ bool await_suspend (std::coroutine_handle<> handle) noexcept
120+ {
121+ data_->handle = handle;
122+
123+ // Attempt transition from NotReady to Waiting.
124+ AwaitableState expected = AwaitableState::NotReady;
125+ return data_->status .compare_exchange_strong (expected, AwaitableState::Waiting, std::memory_order_acq_rel);
126+ }
127+
128+ // Called when the coroutine is resumed. Returns the result or throws the exception.
129+ T await_resume () const
130+ {
131+ if (auto * exception = std::get_if<std::exception_ptr>(&data_->result ); exception != nullptr )
132+ std::rethrow_exception (*exception);
133+
134+ if constexpr (std::is_void_v<T>)
135+ return ;
136+ else
137+ return std::get<T>(std::move (data_->result ));
138+ }
139139#endif // __cpp_lib_coroutine
140140
141- private:
142- friend internal::Proxy;
143- friend AsyncMethodInvoker;
141+ private:
142+ friend internal::Proxy;
143+ friend AsyncMethodInvoker;
144144
145- explicit Awaitable (std::shared_ptr<AwaitableData<T>> data)
146- : data_(std::move(data))
147- {
148- assert (data_ != nullptr );
149- }
145+ explicit Awaitable (std::shared_ptr<AwaitableData<T>> data)
146+ : data_(std::move(data))
147+ {
148+ assert (data_ != nullptr );
149+ }
150150
151- std::shared_ptr<AwaitableData<T>> data_;
152- };
151+ std::shared_ptr<AwaitableData<T>> data_;
152+ };
153153
154154} // namespace sdbus
155155
0 commit comments