Skip to content

Commit bfc11bd

Browse files
committed
📝 Document scheduled_context constructor and methods
Add comprehensive Doxygen documentation for: - scheduled_context constructor: explains listener registration and wake deadline initialization - refresh(Clock): documents wake deadline recalculation based on blocking state - refresh(Clock, time_point&): documents deadline refresh with global soonest time update - resume(Clock, time_point&): clarifies deadline checking, context resumption, and state refresh - is_ready(): explains readiness check for contexts not blocked by time or I/O Also remove the unused assign() and operator< functions, move soonest wake time tracking into resume() and refresh(), and add clarifying comments to run_until_done_impl's scheduling loop.
1 parent 7e6571d commit bfc11bd

1 file changed

Lines changed: 89 additions & 39 deletions

File tree

modules/schedulers.cppm

Lines changed: 89 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,22 @@ struct scheduled_context
104104
std::reference_wrapper<context> ctx;
105105
time_point wake_time = time_point::max();
106106

107+
/**
108+
* @brief Construct a new scheduled context object.
109+
*
110+
* Initializes a scheduler entry by registering the unblock listener on the
111+
* context and computing the initial wake deadline based on the context's
112+
* current blocking state. If the context is time-blocked, the wake deadline
113+
* is set to the current time plus the context's sleep duration. Otherwise,
114+
* the wake deadline is set to time_point::max() (never).
115+
*
116+
* @param p_ctx The execution context to manage in the scheduler.
117+
* @param p_listener Unblock listener to register on the context for
118+
* notification when the context becomes ready to resume. May be nullptr if
119+
* event-driven wakeup is not needed.
120+
* @param p_clock Clock instance used to compute wake deadlines when
121+
* the context is time-blocked.
122+
*/
107123
scheduled_context(async::context& p_ctx,
108124
async::unblock_listener* p_listener,
109125
Clock const& p_clock)
@@ -113,20 +129,19 @@ struct scheduled_context
113129
refresh(p_clock);
114130
}
115131

116-
// Bind this entry to p_ctx, register p_listener (may be nullptr), and
117-
// compute the initial wake_time. Must be called exactly once before any
118-
// other method.
119-
void assign(async::context& p_ctx,
120-
async::unblock_listener* p_listener,
121-
Clock const& p_clock)
122-
{
123-
ctx = p_ctx;
124-
p_ctx.on_unblock(p_listener);
125-
refresh(p_clock);
126-
}
127-
128-
// Recompute wake_time from the context's current sleep_time. Called after
129-
// every resume because the blocking state may have changed.
132+
/**
133+
* @brief Recompute wake_time from the context's current blocking state.
134+
*
135+
* Updates the wake deadline based on the context's current blocking state.
136+
* If the context is time-blocked, computes an absolute deadline by adding
137+
* the context's sleep duration to the current time. Otherwise, sets the
138+
* deadline to time_point::max() (never wake).
139+
*
140+
* Called after every context resume because the blocking state may have
141+
* changed.
142+
*
143+
* @param p_clock Clock instance used to compute absolute wake times.
144+
*/
130145
void refresh(Clock const& p_clock)
131146
{
132147
if (ctx.get().state() == blocked_by::time) {
@@ -137,42 +152,75 @@ struct scheduled_context
137152
}
138153

139154
/**
140-
* @brief Resume the context if its deadline has elapsed or it is otherwise
141-
* ready, then refresh wake_time to reflect the new state.
155+
* @brief Recompute wake_time and update the soonest wake deadline.
142156
*
143-
* @param p_clock - clock to get the current time from
144-
* @return true - context was resumed
145-
* @return false - context is done
157+
* Refreshes the wake deadline from the context's current blocking state,
158+
* then updates the global soonest wake deadline if this entry's deadline
159+
* is earlier.
160+
*
161+
* Called after every context resume because the blocking state may have
162+
* changed.
163+
*
164+
* @param p_clock Clock instance used to compute absolute wake times.
165+
* @param p_soonest_time Reference to the global soonest wake deadline,
166+
* updated if this entry's deadline is earlier.
146167
*/
147-
void resume(Clock const& p_clock)
168+
void refresh(Clock const& p_clock, time_point& p_soonest_time)
148169
{
149-
if (ctx.get().state() == blocked_by::time && wake_time <= p_clock.now()) {
170+
refresh(p_clock);
171+
172+
if (wake_time < p_soonest_time) {
173+
p_soonest_time = wake_time;
174+
}
175+
}
176+
177+
/**
178+
* @brief Resume the context if its deadline has elapsed or it is ready,
179+
* then refresh wake_time to reflect the new state.
180+
*
181+
* If the context is time-blocked and its deadline has elapsed, unblocks and
182+
* resumes the context. Otherwise, if the context is ready (not blocked by
183+
* time or I/O), resumes it immediately. After resuming, refreshes the wake
184+
* deadline and updates the global soonest wake deadline.
185+
*
186+
* @param p_clock Clock instance used to get the current time and compute
187+
* wake deadlines.
188+
* @param p_soonest_time Reference to the global soonest wake deadline,
189+
* updated if this entry's deadline is earlier.
190+
*/
191+
void resume(Clock const& p_clock, time_point& p_soonest_time)
192+
{
193+
if (ctx.get().state() == blocked_by::time and wake_time <= p_clock.now()) {
150194
// Deadline elapsed — unblock without triggering scheduler notification,
151195
// since we are the scheduler, then resume.
196+
// We skip calling the unblock listener because this scheduler
152197
ctx.get().unblock_without_notification();
153198
ctx.get().resume();
154199
// Recompute after resume — state may have changed.
155-
refresh(p_clock);
200+
refresh(p_clock, p_soonest_time);
156201
} else if (is_ready()) {
157202
ctx.get().resume();
158203
// Recompute after resume — state may have changed.
159-
refresh(p_clock);
204+
refresh(p_clock, p_soonest_time);
160205
}
161206
}
162207

163-
// Returns true if the context is not blocked by time or I/O and can be
164-
// resumed immediately.
208+
/**
209+
* @brief Check if the context is ready to resume immediately.
210+
*
211+
* Returns true if the context is not blocked by time or I/O, indicating
212+
* it can be resumed without waiting for a deadline to elapse or for an
213+
* external I/O event to complete.
214+
*
215+
* @return true if the context is not blocked by time or I/O.
216+
* @return false if the context is blocked by time or I/O.
217+
*/
165218
[[nodiscard]] bool is_ready() const noexcept
166219
{
167220
return ctx.get().state() != blocked_by::io &&
168221
ctx.get().state() != blocked_by::time;
169222
}
170223

171-
[[nodiscard]] bool operator<(time_point const& p_other) const noexcept
172-
{
173-
return wake_time < p_other;
174-
}
175-
176224
// Clear the unblock listener so the context does not hold a pointer into
177225
// this stack frame after run_until_done_impl returns.
178226
~scheduled_context()
@@ -224,30 +272,32 @@ void run_until_done_impl(
224272
bool can_sleep = true;
225273

226274
for (auto& task : tasks) {
275+
// Skip performing any of the following steps if the context is done
227276
if (task.ctx.get().done()) {
228277
continue;
229278
}
230279

231280
all_done = false;
232281

233-
task.resume(p_clock);
234-
235-
// After resuming, re-evaluate whether we can sleep and what the
236-
// soonest deadline is
237-
if (task.wake_time < soonest_wake_time) {
238-
soonest_wake_time = task.wake_time;
239-
}
282+
// This resumes the context if it is elidible to be resumed. It is
283+
// elidible if it's wake time has expired or its in a pollable blocked by
284+
// state. This function also updates the `soonest_wake_time` variable if
285+
// this task could be awaken sooner than the previous.
286+
task.resume(p_clock, soonest_wake_time);
240287

288+
// Before we move on to the next task, check if the task was blocked by
289+
// something.
241290
if (task.is_ready()) {
242291
can_sleep = false;
243292
}
244293
}
245294

295+
// No more work needs to be done, this is how the scheduler exits.
246296
if (all_done) {
247-
break;
297+
return;
248298
}
249299

250-
if (can_sleep && soonest_wake_time < max_wake) {
300+
if (can_sleep and soonest_wake_time < max_wake) {
251301
p_sleep_until(soonest_wake_time);
252302
}
253303
}

0 commit comments

Comments
 (0)