/*! * * Copyright (c) 2023 Diality Inc. - All Rights Reserved. * * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * \file EventWait.h * \author (last) Phil Braica * \date (last) 23-Jan-2023 * \author (original) Phil Braica * \date (original) 23-Jan-2023 * */ #ifndef EVENT_WAIT_H_ #define EVENT_WAIT_H_ #include #include #include /*! * An object that waits till condition variable fired OR timeout. */ class EventWait { public: /*! \brief Constructor. */ EventWait(uint32 msec = 1) : _msec(msec < MaxPeriodicMsec ? msec : MaxPeriodicMsec), _fired(false) { } /*! \brief Destructor. */ virtual ~EventWait() { this->fireEvent(); } /** *! \brief Re-arm for refire. */ virtual void re_arm() { _fired = false; } /*! * \brief Wait. * * \return True if a message received, false if timed out. */ virtual bool wait() { std::unique_lock lock(_mutex); // Note the current implimentation using wait_for could // be replaced with a secondary event waking thread and then // use a smaller wakeup, but the added overhead would reduce // any benefit. This is suitable for events in the 1-2ms // regime for retries such as for CAN bus traffic. const std::chrono::duration ms_sleep(_msec); return _cv.wait_for(lock, ms_sleep, [&] { return this->_fired; }); } /*! * \brief Sleep for a given number of milliseconds. * * \param msec Milliseconds, this is a uint8 so no more than 256ms. */ virtual void sleep(uint16 msec) { const std::chrono::duration ms_sleep(msec); std::this_thread::sleep_for(ms_sleep); } /*! \brief Fire event. */ virtual void fireEvent() { std::lock_guard lock(_mutex); _fired = true; _cv.notify_all(); } /*! * \brief Get the time in _msec to sleep. * * \return Time we sleep in msec. */ uint32 sleepScheduleMs() { return _msec; } protected: // This guards against any API / memory leaks causing a potential // deadlocked or extremely slow thread response. static const uint32 MaxPeriodicMsec = 1000; ///< Max allowed periodic. std::mutex _mutex; ///< Mutex. std::condition_variable _cv; ///< Condition to fire. uint32 _msec; ///< Msec to sleep. bool _fired; ///< Event fired. }; #endif // EVENT_WAIT_H_