61 #ifndef SRC_VAULT_GEAR_SCHEDULER_COMMUTATOR_H_ 62 #define SRC_VAULT_GEAR_SCHEDULER_COMMUTATOR_H_ 85 using std::memory_order::memory_order_relaxed;
86 using std::memory_order::memory_order_acquire;
87 using std::memory_order::memory_order_release;
88 using std::chrono_literals::operator
""us;
89 using std::chrono::microseconds;
96 auto inline thisThread() {
return std::this_thread::get_id(); }
112 using ThreadID = std::thread::id;
113 atomic<ThreadID> groomingToken_{};
130 ThreadID expect_noThread;
131 return groomingToken_.compare_exchange_strong (expect_noThread,
thisThread()
132 ,memory_order_acquire
133 ,memory_order_relaxed
146 REQUIRE (groomingToken_.load(memory_order_relaxed) ==
thisThread());
147 const ThreadID noThreadHoldsIt;
148 groomingToken_.store (noThreadHoldsIt, memory_order_release);
158 return id == groomingToken_.load (memory_order_relaxed);
172 if (layer1.hasPendingInput()
208 ALERT (engine,
"MISSED compulsory job -- should raise Scheduler-Emergency");
210 if (layer1.
isDue (now))
239 return activity::PASS;
248 template<
class DISPATCH,
class CLOCK>
261 ensureDroppedGroomingToken()
280 return activity::SKIP == lastResult? activity::PASS
286 performStep (FUN step)
288 if (activity::PASS == lastResult)
318 template<
class DISPATCH,
class CLOCK>
322 ,DISPATCH executeActivity
330 Time now = getSchedTime();
336 Time now = getSchedTime();
337 auto toDispatch =
findWork (layer1,now);
338 if (not toDispatch)
return activity::KICK;
339 return executeActivity (toDispatch);
343 Time now = getSchedTime();
350 if (res != activity::PASS)
351 ensureDroppedGroomingToken();
356 ensureDroppedGroomingToken();
381 auto doTargetedSleep = [&]
383 ensureDroppedGroomingToken();
386 std::this_thread::sleep_for (std::chrono::microseconds (_raw(targetedDelay)));
388 auto doTendNextHead = [&]
398 return activity::PASS;
400 std::this_thread::yield();
401 return activity::SKIP;
403 return activity::WAIT;
407 return activity::SKIP;
410 return activity::SKIP;
422 bool handledActively_;
437 : commutator_(layer2)
438 , handledActively_{ensureHoldsToken()}
443 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
bool maintainQueueHead(SchedulerInvocation &layer1, Time now)
update queue head to discard obsolete content.
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.