70 #ifndef SRC_VAULT_GEAR_SCHEDULER_COMMUTATOR_H_ 71 #define SRC_VAULT_GEAR_SCHEDULER_COMMUTATOR_H_ 94 using std::memory_order::memory_order_relaxed;
95 using std::memory_order::memory_order_acquire;
96 using std::memory_order::memory_order_release;
97 using std::chrono_literals::operator
""us;
98 using std::chrono::microseconds;
105 auto inline thisThread() {
return std::this_thread::get_id(); }
121 using ThreadID = std::thread::id;
122 atomic<ThreadID> groomingToken_{};
139 ThreadID expect_noThread;
140 return groomingToken_.compare_exchange_strong (expect_noThread,
thisThread()
141 ,memory_order_acquire
142 ,memory_order_relaxed
155 REQUIRE (groomingToken_.load(memory_order_relaxed) ==
thisThread());
156 const ThreadID noThreadHoldsIt;
157 groomingToken_.store (noThreadHoldsIt, memory_order_release);
167 return id == groomingToken_.load (memory_order_relaxed);
181 if (layer1.hasPendingInput()
201 if (layer1.
isDue (now))
204 UNIMPLEMENTED (
"how to trigger a Scheduler-Emergency from here");
233 return activity::PASS;
242 template<
class DISPATCH,
class CLOCK>
255 ensureDroppedGroomingToken()
274 return activity::SKIP == lastResult? activity::PASS
280 performStep (FUN step)
282 if (activity::PASS == lastResult)
312 template<
class DISPATCH,
class CLOCK>
316 ,DISPATCH executeActivity
324 Time now = getSchedTime();
330 Time now = getSchedTime();
331 auto toDispatch =
findWork (layer1,now);
332 if (not toDispatch)
return activity::KICK;
333 return executeActivity (toDispatch);
337 Time now = getSchedTime();
344 if (res != activity::PASS)
345 ensureDroppedGroomingToken();
350 ensureDroppedGroomingToken();
375 auto doTargetedSleep = [&]
377 ensureDroppedGroomingToken();
380 std::this_thread::sleep_for (std::chrono::microseconds (_raw(targetedDelay)));
382 auto doTendNextHead = [&]
392 return activity::PASS;
394 std::this_thread::yield();
395 return activity::SKIP;
397 return activity::WAIT;
401 return activity::SKIP;
404 return activity::SKIP;
416 bool handledActively_;
431 : commutator_(layer2)
432 , handledActively_{ensureHoldsToken()}
437 if (handledActively_ and
bool tendedNext(Time nextHead) const
did we already tend for the indicated next relevant head time?
activity::Proc postChain(ActivationEvent event, SchedulerInvocation &layer1)
This is the primary entrance point to the Scheduler.
Scheduler resource usage coordination.
activity::Proc scatteredDelay(Time now, Time head, LoadController &loadController, LoadController::Capacity capacity)
A worker asking for work constitutes free capacity, which can be redirected into a focused zone of th...
bool holdsGroomingToken(ThreadID id) noexcept
check if the indicated thread currently holds the right to conduct internal state transitions...
microseconds GROOMING_WAIT_CYCLE
wait-sleep in case a thread must forcibly acquire the Grooming-Token
void dropGroomingToken() noexcept
relinquish the right for internal state transitions.
Any copy and copy construction prohibited.
Scheduler Layer-2 : execution of Scheduler Activities.
auto thisThread()
convenient short-notation, also used by SchedulerService
Types marked with this mix-in may be moved but not copied.
ScopedGroomingGuard(SchedulerCommutator &layer2)
Capacity markIncomingCapacity(Time head, Time now)
decide how this thread's capacity shall be used when returning from idle wait and asking for work ...
ActivationEvent findWork(SchedulerInvocation &layer1, Time now)
Look into the queues and possibly retrieve work due by now.
Lumiera's internal time value datatype.
Controller to coordinate resource usage related to the Scheduler.
void instruct(ActivationEvent actEvent)
Accept an ActivationEvent with an Activity for time-bound execution.
Layer-1 of the Scheduler: queueing and prioritisation of activities.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
bool isOutdated(Time now) const
determine if Activity at scheduler is outdated and should be discarded
Offset scatteredDelayTime(Time now, Capacity capacity)
Generate a time offset to relocate currently unused capacity to a time range where it's likely to be ...
A language framework to define and interconnect scheduler activity verbs.
boost::rational< int64_t > FSecs
rational representation of fractional seconds
void tendNext(Time nextHead)
Mark the indicated next head time as tended.
monad-like step sequence: perform sequence of steps, as long as the result remains activity::PASS ...
Basic set of definitions and includes commonly used together (Vault).
bool isOutOfTime(Time now) const
detect a compulsory Activity at scheduler head with missed deadline
Offset measures a distance in time.
awaiting imminent activities
ScopedGroomingGuard requireGroomingTokenHere()
a scope guard to force acquisition of the GroomingToken
Proc
Result instruction from Activity activation.
ActivationEvent pullHead()
Retrieve from the scheduling queue the entry with earliest start time.
Capacity markOutgoingCapacity(Time head, Time now)
decide how this thread's capacity shall be used after it returned from being actively employed ...
a family of time value like entities and their relationships.
void feedPrioritisation()
Pick up all new events from the entrance queue and enqueue them to be retrieved ordered by start time...
Capacity
Allocation of capacity to time horizon of expected work.
void maybeFeed(SchedulerInvocation &layer1)
tend to the input queue if possible
Vault-Layer implementation namespace root.
bool isDue(Time now) const
Determine if there is work to do right now.
bool acquireGoomingToken() noexcept
acquire the right to perform internal state transitions.
Scheduler Layer-1 : time based dispatch.
activity::Proc dispatchCapacity(SchedulerInvocation &, LoadController &, DISPATCH, CLOCK)
Implementation of the worker-Functor:
Descriptor for a piece of operational logic performed by the scheduler.