@@ -165,13 +165,37 @@ class AsioConditionVariable
165165/* *
166166 * I/O timeout emulator
167167 *
168+ * This class provides a workaround for Boost.ASIO's lack of built-in timeout support.
169+ * While Boost.ASIO handles asynchronous operations, it does not natively support timeouts for these operations.
170+ * This class uses a boost::asio::deadline_timer to emulate a timeout by scheduling a callback to be triggered
171+ * after a specified duration, effectively adding timeout behavior where none exists.
172+ * The callback is executed within the provided strand, ensuring thread-safety.
173+ *
174+ * The constructor returns immediately after scheduling the timeout callback.
175+ * The callback itself is invoked asynchronously when the timeout occurs.
176+ * This allows the caller to continue execution while the timeout is running in the background.
177+ *
178+ * The class provides a Cancel() method to unschedule any pending callback. If the callback has already been run,
179+ * calling Cancel() has no effect. This method can be used to abort the timeout early if the monitored operation
180+ * completes before the callback has been run. The Timeout destructor also automatically cancels any pending callback.
181+ * A callback is considered pending even if the timeout has already expired,
182+ * but the callback has not been executed yet due to a busy strand.
183+ *
168184 * @ingroup base
169185 */
170186class Timeout
171187{
172188public:
173189 using Timer = boost::asio::deadline_timer;
174190
191+ /* *
192+ * Schedules onTimeout to be triggered after timeoutFromNow on strand.
193+ *
194+ * @param strand The strand in which the callback will be executed.
195+ * The caller must also run in this strand, as well as Cancel() and the destructor!
196+ * @param timeoutFromNow The duration after which the timeout callback will be triggered.
197+ * @param onTimeout The callback to invoke when the timeout occurs.
198+ */
175199 template <class OnTimeout >
176200 Timeout (boost::asio::io_context::strand& strand, const Timer::duration_type& timeoutFromNow, OnTimeout onTimeout)
177201 : m_Timer(strand.context(), timeoutFromNow), m_Cancelled(Shared<Atomic<bool >>::Make(false ))
@@ -192,6 +216,11 @@ class Timeout
192216 Timeout& operator =(const Timeout&) = delete ;
193217 Timeout& operator =(Timeout&&) = delete ;
194218
219+ /* *
220+ * Cancels any pending timeout callback.
221+ *
222+ * Must be called in the strand in which the callback was scheduled!
223+ */
195224 ~Timeout ()
196225 {
197226 Cancel ();
@@ -201,6 +230,14 @@ class Timeout
201230
202231private:
203232 Timer m_Timer;
233+
234+ /* *
235+ * Indicates whether the Timeout has been cancelled.
236+ *
237+ * This must be Shared<> between the lambda in the constructor and Cancel() for the case
238+ * the destructor calls Cancel() while the lambda is already queued in the strand.
239+ * The whole Timeout instance can't be kept alive by the lambda because this would delay the destructor.
240+ */
204241 Shared<Atomic<bool >>::Ptr m_Cancelled;
205242};
206243
0 commit comments