SW Task Event Loop Framework v1.0.0
High-performance C++ asynchronous event loop framework with timer management and promise-based programming
Loading...
Searching...
No Matches
Promise.tpp
Go to the documentation of this file.
1/**
2 * @file Promise.tpp
3 * @brief Template implementation for Promise class - asynchronous result handling with continuation chaining
4 * @author Tran Anh Tai
5 * @date 9/2025
6 * @version 1.0.0
7 */
8
9 #ifndef PROMISE_TPP
10 #define PROMISE_TPP
11
12 #include "Promise.h"
13 #include "State.h"
14
15 namespace swt {
16
17 // ========== Template implementation for Promise<tValue> ==========
18
19 /**
20 * @brief Default constructor - creates promise with shared state
21 * @tparam tValue Value type for promise result
22 *
23 * Initializes a new promise with a shared State object for
24 * communication between promise and future/continuation handlers.
25 *
26 * @see \ref swt::Promise "Promise", \ref swt::State "State"
27 */
28 template <typename tValue>
29 Promise<tValue>::Promise() : m_state(std::make_shared<State<tValue>>()) {}
30
31 /**
32 * @brief Set the promise value and trigger continuation chain
33 * @tparam tValue Value type being set
34 * @param value Value to set (moved into promise state)
35 *
36 * Resolves the promise with the provided value and triggers any
37 * registered continuation callbacks. This can only be called once
38 * per promise instance.
39 *
40 * @code{.cpp}
41 * Promise<int> promise;
42 * promise.set_value(42); // Resolves promise and triggers continuations
43 * @endcode
44 *
45 * @see \ref swt::Promise::set_value "set_value()"
46 */
47 template <typename tValue>
48 void Promise<tValue>::set_value(tValue value) {
49 m_state->setValue(std::move(value));
50 }
51
52 /**
53 * @brief Set exception state and trigger error handlers
54 * @tparam tValue Value type (not used for exception)
55 * @param exception Exception pointer to set
56 *
57 * Rejects the promise with the provided exception and triggers any
58 * registered error handlers. This can only be called once per promise.
59 *
60 * @code{.cpp}
61 * Promise<int> promise;
62 * try {
63 * // Some operation that may fail
64 * } catch (...) {
65 * promise.set_exception(std::current_exception());
66 * }
67 * @endcode
68 *
69 * @see \ref swt::Promise::set_exception "set_exception()"
70 */
71 template <typename tValue>
72 void Promise<tValue>::set_exception(std::exception_ptr exception) {
73 m_state->setException(exception);
74 }
75
76 /**
77 * @brief Chain continuation callback for promise resolution
78 * @tparam tValue Current promise value type
79 * @tparam F Function type for continuation callback
80 * @param looper_ SLLooper instance for callback execution
81 * @param func Continuation function to execute when promise resolves
82 * @return Promise<ReturnType> New promise for further chaining
83 *
84 * Registers a continuation callback that executes when the promise resolves
85 * successfully. The continuation function receives the resolved value and
86 * can return a new value, creating a chain of promise transformations.
87 *
88 * Key features:
89 * - **Type transformation**: Return type can differ from input type
90 * - **Exception handling**: Automatic exception propagation in continuation chain
91 * - **Void support**: Handles both value-returning and void continuations
92 * - **Asynchronous execution**: Callbacks execute via SLLooper message queue
93 *
94 * @code{.cpp}
95 * promise.then(looper, [](int x) {
96 * return x * 2;
97 * }).then(looper, [](int doubled) {
98 * std::cout << "Result: " << doubled << std::endl;
99 * });
100 * @endcode
101 *
102 * @see \ref swt::Promise::then "then()", \ref swt::SLLooper "SLLooper"
103 */
104 template <typename tValue>
105 template <typename F>
106 auto Promise<tValue>::then(std::shared_ptr<SLLooper>& looper_, F func) -> Promise<std::invoke_result_t<F, tValue>> {
107 using ReturnType = std::invoke_result_t<F, tValue>;
108 Promise<ReturnType> nextPromise;
109
110 // Set continuation that handles success case
111 m_state->setContinuation(looper_, [func = std::move(func), nextPromise](tValue value) mutable {
112 try {
113 if constexpr (std::is_void_v<ReturnType>) {
114 // Handle void-returning continuation
115 func(std::move(value));
116 nextPromise.set_value();
117 } else {
118 // Handle value-returning continuation
119 auto result = func(std::move(value));
120 nextPromise.set_value(std::move(result));
121 }
122 } catch (...) {
123 // Automatic exception propagation
124 nextPromise.set_exception(std::current_exception());
125 }
126 });
127
128 // Set error handler that propagates exception through chain
129 m_state->setErrorHandler(looper_, [nextPromise](std::exception_ptr exception) mutable {
130 nextPromise.set_exception(exception);
131 });
132
133 return nextPromise;
134 }
135
136 /**
137 * @brief Chain error handler for promise rejection
138 * @tparam tValue Current promise value type
139 * @tparam F Function type for error handler callback
140 * @param looper_ SLLooper instance for callback execution
141 * @param func Error handler function to execute when promise is rejected
142 * @return Promise<tValue> New promise for further chaining
143 *
144 * Registers an error handler that executes when the promise is rejected.
145 * The error handler can recover from the error by returning a value, or
146 * let the error propagate by throwing or not handling it.
147 *
148 * @code{.cpp}
149 * promise.catchError(looper, [](std::exception_ptr ex) -> int {
150 * try {
151 * std::rethrow_exception(ex);
152 * } catch (const MyException& e) {
153 * return 42; // Recovery value
154 * }
155 * // Other exceptions will be re-thrown
156 * });
157 * @endcode
158 *
159 * @see \ref swt::Promise::catchError "catchError()", \ref swt::SLLooper "SLLooper"
160 */
161 template <typename tValue>
162 template <typename F>
163 auto Promise<tValue>::catchError(std::shared_ptr<SLLooper>& looper_, F func) -> Promise<tValue> {
164 Promise<tValue> nextPromise;
165
166 // Set continuation that propagates success value
167 m_state->setContinuation(looper_, [nextPromise](tValue value) mutable {
168 nextPromise.set_value(std::move(value));
169 });
170
171 // Set error handler that calls the catch function
172 m_state->setErrorHandler(looper_, [func = std::move(func), nextPromise](std::exception_ptr exception) mutable {
173 try {
174 if constexpr (std::is_void_v<std::invoke_result_t<F, std::exception_ptr>>) {
175 // Void error handler - propagate original exception
176 func(exception);
177 nextPromise.set_exception(exception);
178 } else {
179 // Value-returning error handler - use result as recovery value
180 auto result = func(exception);
181 nextPromise.set_value(std::move(result));
182 }
183 } catch (...) {
184 // Error handler threw - propagate new exception
185 nextPromise.set_exception(std::current_exception());
186 }
187 });
188
189 return nextPromise;
190 }
191
192 // ========== Template specialization for Promise<void> ==========
193
194 /**
195 * @brief Chain continuation callback for void promise resolution
196 * @tparam F Function type for continuation callback
197 * @param looper_ SLLooper instance for callback execution
198 * @param func Continuation function (takes no parameters)
199 * @return Promise<ReturnType> New promise for further chaining
200 *
201 * Specialization for void promises that handles continuation chaining
202 * when the current promise doesn't produce a value. The continuation
203 * function takes no parameters and can return any type.
204 *
205 * @code{.cpp}
206 * voidPromise.then(looper, []() {
207 * return "Void promise completed!";
208 * }).then(looper, [](const std::string& msg) {
209 * std::cout << msg << std::endl;
210 * });
211 * @endcode
212 *
213 * @see \ref swt::Promise::then "then()", \ref swt::SLLooper "SLLooper"
214 */
215 template <typename F>
216 auto Promise<void>::then(std::shared_ptr<SLLooper>& looper_, F func) -> Promise<std::invoke_result_t<F>> {
217 using ReturnType = std::invoke_result_t<F>;
218 Promise<ReturnType> nextPromise;
219
220 // Set continuation that handles success case for void promise
221 m_state->setContinuation(looper_, [func = std::move(func), nextPromise]() mutable {
222 try {
223 if constexpr (std::is_void_v<ReturnType>) {
224 // Void -> Void continuation
225 func();
226 nextPromise.set_value();
227 } else {
228 // Void -> Value continuation
229 auto result = func();
230 nextPromise.set_value(std::move(result));
231 }
232 } catch (...) {
233 // Automatic exception propagation
234 nextPromise.set_exception(std::current_exception());
235 }
236 });
237
238 // Set error handler that propagates exception through chain
239 m_state->setErrorHandler(looper_, [nextPromise](std::exception_ptr exception) mutable {
240 nextPromise.set_exception(exception);
241 });
242
243 return nextPromise;
244 }
245
246 /**
247 * @brief Chain error handler for void promise rejection
248 * @tparam F Function type for error handler callback
249 * @param looper_ SLLooper instance for callback execution
250 * @param func Error handler function to execute when promise is rejected
251 * @return Promise<void> New void promise for further chaining
252 *
253 * Specialization for void promises that handles error recovery.
254 * If the error handler executes successfully (without throwing),
255 * the promise chain continues with success state.
256 *
257 * @code{.cpp}
258 * voidPromise.catchError(looper, [](std::exception_ptr ex) {
259 * std::cerr << "Error handled, continuing..." << std::endl;
260 * // Not throwing means error is handled
261 * }).then(looper, []() {
262 * std::cout << "Promise chain continues!" << std::endl;
263 * });
264 * @endcode
265 *
266 * @see \ref swt::Promise::catchError "catchError()", \ref swt::SLLooper "SLLooper"
267 */
268 template <typename F>
269 auto Promise<void>::catchError(std::shared_ptr<SLLooper>& looper_, F func) -> Promise<void> {
270 Promise<void> nextPromise;
271
272 // Set continuation that propagates success (no value)
273 m_state->setContinuation(looper_, [nextPromise]() mutable {
274 nextPromise.set_value();
275 });
276
277 // Set error handler that calls the catch function
278 m_state->setErrorHandler(looper_, [func = std::move(func), nextPromise](std::exception_ptr exception) mutable {
279 try {
280 // Call error handler
281 func(exception);
282 // If no exception thrown, error is handled - continue with success
283 nextPromise.set_value();
284 } catch (...) {
285 // Error handler threw - propagate new exception
286 nextPromise.set_exception(std::current_exception());
287 }
288 });
289
290 return nextPromise;
291 }
292
293 } // namespace swt
294
295 #endif // PROMISE_TPP