Skip to content

Commit 5dabe7e

Browse files
committed
Improve docstrings
1 parent 8a13678 commit 5dabe7e

5 files changed

Lines changed: 127 additions & 103 deletions

File tree

‎coroio/corochain.hpp‎

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,12 @@ struct TFutureBase {
172172
template<> struct TFuture<void>;
173173

174174
/**
175-
* @brief Future type for coroutines returning a value of type T.
175+
* @brief Owned coroutine handle that carries a result of type T.
176176
*
177-
* Provides mechanisms to await and retrieve the result of a coroutine.
177+
* RAII: destroys the coroutine frame in `~TFuture`. Move-only.
178+
* `co_await future` suspends the caller until the coroutine finishes, then
179+
* returns `T` or rethrows a stored exception. `future.done()` polls
180+
* completion without suspending.
178181
*
179182
* @tparam T The type of the result.
180183
*/
@@ -236,7 +239,11 @@ struct TPromise<void>: public TPromiseBase<void> {
236239
};
237240

238241
/**
239-
* @brief Future specialization for coroutines that return void.
242+
* @brief Owned coroutine handle for coroutines that return void.
243+
*
244+
* Same ownership and exception-propagation semantics as `TFuture<T>`.
245+
* `co_await future` suspends the caller until done, then rethrows any
246+
* stored exception. Provides `Accept(func)` to chain a continuation.
240247
*/
241248
template<>
242249
struct TFuture<void> : public TFutureBase<void> {
@@ -297,11 +304,14 @@ template<typename T>
297304
TFinalAwaiter<T> TPromiseBase<T>::final_suspend() noexcept { return {}; }
298305

299306
/**
300-
* @brief Awaits the completion of all futures and collects their results.
307+
* @brief Awaits every future in order and collects their results.
308+
*
309+
* Futures are `co_await`-ed sequentially (not concurrently). The caller
310+
* suspends until each future finishes before moving to the next.
301311
*
302312
* @tparam T The type of each coroutine's result.
303-
* @param futures A vector of TFuture<T> objects.
304-
* @return TFuture<std::vector<T>> containing the results from all coroutines.
313+
* @param futures A vector of TFuture<T> objects (moved in).
314+
* @return TFuture<std::vector<T>> containing results in input order.
305315
*/
306316
template<typename T>
307317
TFuture<std::vector<T>> All(std::vector<TFuture<T>>&& futures) {
@@ -314,10 +324,10 @@ TFuture<std::vector<T>> All(std::vector<TFuture<T>>&& futures) {
314324
}
315325

316326
/**
317-
* @brief Awaits the completion of all void-returning coroutines.
327+
* @brief Awaits every void future in order until all have completed.
318328
*
319-
* @param futures A vector of TFuture<void> objects.
320-
* @return TFuture<void> representing the completion of all coroutines.
329+
* @param futures A vector of TFuture<void> objects (moved in).
330+
* @return TFuture<void> that completes after all futures finish.
321331
*/
322332
inline TFuture<void> All(std::vector<TFuture<void>>&& futures) {
323333
auto waiting = std::move(futures);
@@ -328,14 +338,16 @@ inline TFuture<void> All(std::vector<TFuture<void>>&& futures) {
328338
}
329339

330340
/**
331-
* @brief Awaits the completion of any one of the given futures and returns its result.
341+
* @brief Returns the result of whichever future completes first.
332342
*
333-
* If one of the futures has already finished, its result is returned immediately.
334-
* Otherwise, the current coroutine is suspended until one of the futures completes.
343+
* If one future is already done, its result is returned without suspension.
344+
* Otherwise, all futures register this coroutine as their continuation; when
345+
* the first one resumes it, the remaining futures are abandoned (their frames
346+
* are destroyed when the vector goes out of scope).
335347
*
336-
* @tparam T The type of the coroutine's result.
337-
* @param futures A vector of TFuture<T> objects.
338-
* @return TFuture<T> with the result from the first completed coroutine.
348+
* @tparam T The type of each coroutine's result.
349+
* @param futures A vector of TFuture<T> objects (moved in).
350+
* @return TFuture<T> with the result from the first completed future.
339351
*/
340352
template<typename T>
341353
TFuture<T> Any(std::vector<TFuture<T>>&& futures) {
@@ -355,10 +367,10 @@ TFuture<T> Any(std::vector<TFuture<T>>&& futures) {
355367
}
356368

357369
/**
358-
* @brief Awaits the completion of any one of the void-returning coroutines.
370+
* @brief Completes when the first void future finishes; others are abandoned.
359371
*
360-
* @param futures A vector of TFuture<void> objects.
361-
* @return TFuture<void> representing the completion of one of the coroutines.
372+
* @param futures A vector of TFuture<void> objects (moved in).
373+
* @return TFuture<void> that completes as soon as one future finishes.
362374
*/
363375
inline TFuture<void> Any(std::vector<TFuture<void>>&& futures) {
364376
std::vector<TFuture<void>> all = std::move(futures);

‎coroio/loop.hpp‎

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,30 @@
11
namespace NNet {
22

33
/**
4-
* @class TLoop
5-
* @brief A generic event loop wrapper that uses TSelect as its poller.
4+
* @brief Event loop that drives a poller backend.
65
*
7-
* The event loop continuously calls @ref Step() until explicitly stopped via
8-
* @ref Stop().
6+
* Each call to `Step()` runs one polling round: it calls `Poller_.Poll()` to
7+
* collect ready I/O events and timers, then `Poller_.WakeupReadyHandles()` to
8+
* resume the waiting coroutines.
99
*
10-
* ### Example Usage
11-
* @code{.cpp}
12-
* #include <iostream>
10+
* `Loop()` repeats `Step()` until `Stop()` is called. For manual control (e.g.
11+
* driving the loop until a specific `TFuture` completes), use `Step()` directly:
1312
*
14-
* int main() {
15-
* // Instantiate the event loop with TSelect
16-
* TLoop<TSelect> loop;
17-
*
18-
* // Run a single iteration of polling and wakeup
13+
* @code
14+
* TLoop<TDefaultPoller> loop;
15+
* TFuture<void> task = my_coroutine(loop.Poller());
16+
* while (!task.done())
1917
* loop.Step();
18+
* @endcode
2019
*
21-
* // Stop the loop
22-
* loop.Stop();
23-
*
24-
* // Alternatively, to run continuously:
25-
* // loop.Loop(); // Will keep calling Step() until Stop() is called
26-
*
27-
* return 0;
28-
* }
20+
* For server-style programs with detached `TVoidTask` coroutines:
21+
* @code
22+
* TLoop<TDefaultPoller> loop;
23+
* server(loop.Poller(), TAddress{"::", 8888}); // returns TVoidTask
24+
* loop.Loop(); // runs until Stop() is called
2925
* @endcode
3026
*
31-
* @tparam TPoller A type that provides polling and wakeup mechanisms (TSelect here).
27+
* @tparam TPoller Polling backend: TEPoll, TKqueue, TIOCp, TUring, TPoll, TSelect, etc.
3228
*/
3329
template<typename TPoller>
3430
class TLoop {
@@ -48,7 +44,8 @@ class TLoop {
4844
Running_ = false;
4945
}
5046
/**
51-
* @brief Performs a single iteration of polling and waking up ready handles.
47+
* @brief Runs one event-loop iteration: polls for I/O/timer events then
48+
* resumes all coroutines whose events fired.
5249
*/
5350
void Step() {
5451
Poller_.Poll();

‎coroio/poller.hpp‎

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,16 @@
2424
namespace NNet {
2525

2626
/**
27-
* @class TPollerBase
28-
* @brief Base class for pollers managing asynchronous I/O events and timers.
27+
* @brief Backend-independent base for I/O pollers.
2928
*
30-
* TPollerBase provides the common interface and functionality for pollers that drive asynchronous
31-
* operations. It allows scheduling timers, registering I/O events (read, write, remote hang-up) on file
32-
* descriptors, and waking up waiting coroutines. It also offers convenience methods such as @ref Sleep()
33-
* (and its overload accepting a std::chrono::duration) and @ref Yield().
29+
* Manages three concerns shared by all poller backends:
30+
* - **Timers** — `AddTimer` / `RemoveTimer` / `ProcessTimers`
31+
* - **I/O event registration** — `AddRead`, `AddWrite`, `AddRemoteHup`, `RemoveEvent`
32+
* - **Coroutine scheduling** — `Sleep`, `Yield`, `Wakeup`, `WakeupReadyHandles`
3433
*
35-
* The class maintains internal collections for pending changes (events), ready events, and timers.
36-
* It also keeps track of the maximum file descriptor, which is used in system-level polling calls.
37-
*
38-
* Key methods include:
39-
* - @ref AddTimer() to schedule a timer.
40-
* - @ref RemoveTimer() to cancel a timer.
41-
* - @ref AddRead(), @ref AddWrite(), @ref AddRemoteHup() to register I/O events.
42-
* - @ref RemoveEvent() to deregister events.
43-
* - @ref Sleep() and @ref Yield() to suspend execution until a specified time or until the next
44-
* polling round.
45-
* - @ref Wakeup() and @ref WakeupReadyHandles() to resume waiting coroutines when events occur.
46-
*
47-
* The class also provides helper methods for computing timeout values (via @ref GetTimeout()).
48-
*
49-
* The detailed comment inside @ref Wakeup() describes how a waiting coroutine is resumed and how new
50-
* event registrations are matched.
34+
* Concrete backends (TEPoll, TKqueue, …) inherit from this class and implement
35+
* `Poll()` to fill `ReadyEvents_` using the OS-specific mechanism, then call
36+
* `WakeupReadyHandles()` (provided here) to resume waiting coroutines.
5137
*/
5238
class TPollerBase {
5339
public:
@@ -91,20 +77,26 @@ class TPollerBase {
9177
}
9278

9379
/**
94-
* @brief Registers a read event on a file descriptor.
80+
* @brief Registers a read interest on a file descriptor.
9581
*
96-
* @param fd The file descriptor.
97-
* @param h The coroutine handle to resume when data is available.
82+
* `h` will be resumed by `WakeupReadyHandles()` on the next loop iteration
83+
* after the fd becomes readable.
84+
*
85+
* @param fd File descriptor to watch.
86+
* @param h Coroutine to resume when data is available.
9887
*/
9988
void AddRead(int fd, THandle h) {
10089
MaxFd_ = std::max(MaxFd_, fd);
10190
Changes_.emplace_back(TEvent{fd, TEvent::READ, h});
10291
}
10392
/**
104-
* @brief Registers a write event on a file descriptor.
93+
* @brief Registers a write interest on a file descriptor.
10594
*
106-
* @param fd The file descriptor.
107-
* @param h The coroutine handle to resume when ready for writing.
95+
* `h` will be resumed by `WakeupReadyHandles()` on the next loop iteration
96+
* after the fd becomes writable.
97+
*
98+
* @param fd File descriptor to watch.
99+
* @param h Coroutine to resume when ready for writing.
108100
*/
109101
void AddWrite(int fd, THandle h) {
110102
MaxFd_ = std::max(MaxFd_, fd);
@@ -133,12 +125,12 @@ class TPollerBase {
133125
Changes_.emplace_back(TEvent{fd, TEvent::READ|TEvent::WRITE|TEvent::RHUP, {}});
134126
}
135127
/**
136-
* @brief Removes events associated with a given coroutine handle.
128+
* @brief No-op placeholder for future cleanup by handle.
137129
*
138-
* This overload will be called by destructors of unfinished futures.
139-
* Unimplemented.
130+
* Intended to be called by destructors of unfinished futures so that
131+
* pending waits can be unregistered. Currently unimplemented.
140132
*
141-
* @param h The coroutine handle.
133+
* @param h The coroutine handle (unused).
142134
*/
143135
void RemoveEvent(THandle /*h*/) {
144136
// TODO: Add new vector for this type of removing
@@ -204,11 +196,13 @@ class TPollerBase {
204196
return Sleep(TClock::now() + duration);
205197
}
206198
/**
207-
* @brief Yields execution to the next event loop iteration.
199+
* @brief Suspends the coroutine until the next event-loop iteration.
208200
*
209-
* Equivalent to calling Sleep() with a default zero time.
201+
* Equivalent to `Sleep(TTime{})`, which fires immediately on the next
202+
* `ProcessTimers()` call. Use when you want to give other coroutines a
203+
* chance to run before continuing.
210204
*
211-
* @return An awaitable object for yielding execution.
205+
* @return An awaitable that resumes on the next loop tick.
212206
*/
213207
auto Yield() {
214208
return Sleep(TTime{});

‎coroio/promises.hpp‎

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ namespace NNet {
55

66
struct TVoidPromise;
77

8+
/**
9+
* @brief Fire-and-forget coroutine handle.
10+
*
11+
* Cannot be `co_await`-ed. Self-destructs on completion (`final_suspend →
12+
* suspend_never`). Unhandled exceptions are silently swallowed.
13+
*
14+
* Use for detached tasks that outlive their caller — e.g. per-connection
15+
* handlers spawned inside an accept loop.
16+
*
17+
* @code
18+
* TVoidTask handle_client(TSocket sock) {
19+
* char buf[4096]; ssize_t n;
20+
* while ((n = co_await sock.ReadSome(buf, sizeof(buf))) > 0)
21+
* co_await sock.WriteSome(buf, n);
22+
* }
23+
* @endcode
24+
*/
825
struct TVoidTask : std::coroutine_handle<TVoidPromise>
926
{
1027
using promise_type = TVoidPromise;
@@ -21,6 +38,12 @@ struct TVoidPromise
2138

2239
struct TVoidSuspendedPromise;
2340

41+
/**
42+
* @brief Like TVoidTask but suspends at final_suspend instead of self-destructing.
43+
*
44+
* Used internally where the caller needs to manually destroy the coroutine
45+
* after it completes. Not for general use — prefer TVoidTask or TFuture<void>.
46+
*/
2447
struct TVoidSuspendedTask : std::coroutine_handle<TVoidSuspendedPromise>
2548
{
2649
using promise_type = TVoidSuspendedPromise;
@@ -36,25 +59,11 @@ struct TVoidSuspendedPromise
3659
};
3760

3861
/**
39-
* @class Self
40-
* @brief A minimal example of a coroutine "awaitable" object.
41-
*
42-
* This structure stores a coroutine handle and demonstrates how a coroutine
43-
* can be suspended and resumed.
44-
*
45-
* ### Example Usage
46-
* @code{.cpp}
47-
* // A simple coroutine that uses 'Self' as an awaitable:
48-
* std::coroutine_handle<> exampleCoroutine() {
49-
* // co_await our custom awaitable
50-
* auto handle = co_await Self{};
51-
* // 'handle' is a std::coroutine_handle to this coroutine.
52-
* // You can perform actions like handle.destroy(), handle.resume(), etc.
53-
* ...
54-
* }
55-
* @endcode
62+
* @brief Awaitable that resumes immediately and yields this coroutine's own handle.
5663
*
57-
* @note Internally, it captures the coroutine handle in its await_suspend step.
64+
* `co_await Self{}` never actually suspends (`await_suspend` returns `false`),
65+
* but it captures the current coroutine handle via `await_suspend`. Used by
66+
* `Any()` to register the same coroutine as the continuation of multiple futures.
5867
*
5968
* @cond INTERNAL
6069
*/

0 commit comments

Comments
 (0)