/*! \file * \brief \ref Bellringer that manages and activates time-triggered activities. */ #pragma once #include "../object/queue.h" #include "../thread/thread.h" #include "../types.h" struct Vault; /*! \brief Manages and activates time-triggered activities. * \ingroup ipc * * The Bellringer is regularly activated and checks whether any of the bells * should ring. The bells are stored in a Queue that is managed by the * Bellringer. A clever implementation avoids iterating through the whole list * for every iteration by keeping the bells sorted and storing delta times. This * approach leads to a complexity of O(1) for the method called by the timer * interrupt in case no bells need to be rung. */ class Bellringer { // Prevent copies and assignments Bellringer(const Bellringer&) = delete; Bellringer& operator=(const Bellringer&) = delete; /** * @brief Contains a Thread and its remaining waiting time in timer ticks * */ struct Bell { // link pointer to the next bell in the bellringer's bell list Bell* queue_link = nullptr; Thread* thread; size_t counter; }; /*! \brief List of bells currently managed. * * This list contains non-expired bells enqueued by job(). * These bells will be checked on every call to check(). * * All elements that should be inserted into a Queue instance * are required to be derived from Queue::Node. */ Queue bells; public: // constructor Bellringer() {} /*! \brief Checks whether there are bells to be rung. * * Every call to check elapses a tick. Once such a tick reduces a bell's * remaining time to zero, the bell will be rung (i.e., its thread is * ready). * * \param vault The vault containing the bellringer instance * */ void check(Vault& vault); /*! \brief Puts the calling thread to sleep for `ms` milliseconds by * enqueuing a \ref Bell. * * \param vault The vault containing the bellringer instance * \param ms Number of milliseconds that should be waited before * ringing the bell * */ void sleep(Vault& vault, unsigned int ms); /*! \brief Checks whether there are enqueued bells. * \return true if there are enqueued bells, false otherwise * */ bool bellPending() const; };