Skip to content

Source · fairmq/

StateQueue.hpublic header

Defines class fair::mq::StateQueue.

Described in Control a device from code.

fairmq/StateQueue.h148 lines · C++API: StateQueueGitHub ↗
1/********************************************************************************2 * Copyright (C) 2019-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH  *3 *                                                                              *4 *              This software is distributed under the terms of the             *5 *              GNU Lesser General Public Licence (LGPL) version 3,             *6 *                  copied verbatim in the file "LICENSE"                       *7 ********************************************************************************/8 9#ifndef FAIRMQSTATEQUEUE_H_10#define FAIRMQSTATEQUEUE_H_11 12#include <chrono>13#include <condition_variable>14#include <fairmq/States.h>15#include <mutex>16#include <queue>17#include <utility>   // pair18 19namespace fair::mq {20 21class StateQueue22{23  public:24    StateQueue() = default;25    StateQueue(const StateQueue&) = delete;26    StateQueue(StateQueue&&) = delete;27    StateQueue& operator=(const StateQueue&) = delete;28    StateQueue& operator=(StateQueue&&) = delete;29    ~StateQueue() = default;30 31    fair::mq::State WaitForNext()32    {33        std::unique_lock<std::mutex> lock(fMtx);34        fCV.wait(lock, [this] { return Predicate(); });35        return PopFrontUnsafe();36    }37 38    template<typename Timeout>39    std::pair<bool, fair::mq::State> WaitForNext(Timeout&& duration)40    {41        std::unique_lock<std::mutex> lock(fMtx);42        fCV.wait_for(lock, std::forward<Timeout>(duration), [this] { return Predicate(); });43        return ReturnPairUnsafe();44    }45 46    template<typename CustomPredicate>47    std::pair<bool, fair::mq::State> WaitForNextOrCustom(CustomPredicate&& customPredicate)48    {49        std::unique_lock<std::mutex> lock(fMtx);50        fCV.wait(lock, [this, cp = std::move(customPredicate)] { return Predicate() || cp(); });51        return ReturnPairUnsafe();52    }53 54    template<typename CustomPredicate>55    std::pair<bool, fair::mq::State> WaitForCustom(CustomPredicate&& customPredicate)56    {57        std::unique_lock<std::mutex> lock(fMtx);58        fCV.wait(lock, [cp = std::move(customPredicate)] { return cp(); });59        return ReturnPairUnsafe();60    }61 62    void WaitForState(fair::mq::State state)63    {64        while (WaitForNext() != state) {}65    }66 67    template<typename CustomPredicate>68    void WaitForStateOrCustom(fair::mq::State state, CustomPredicate customPredicate)69    {70        auto next = WaitForNextOrCustom(customPredicate);71        while (!customPredicate() && (next.first && next.second != state)) {72            next = WaitForNextOrCustom(customPredicate);73        }74    }75 76    void Push(fair::mq::State state)77    {78        {79            std::lock_guard<std::mutex> lock(fMtx);80            fStates.push(state);81        }82        fCV.notify_one();83    }84 85    template<typename CustomSignal>86    void Push(fair::mq::State state, CustomSignal&& signal)87    {88        {89            std::lock_guard<std::mutex> lock(fMtx);90            fStates.push(state);91            signal();92        }93        fCV.notify_one();94    }95 96    template<typename CustomSignal>97    void Notify(CustomSignal&& signal)98    {99        {100            std::lock_guard<std::mutex> lock(fMtx);101            signal();102        }103        fCV.notify_one();104    }105 106    template<typename CustomSignal>107    void Locked(CustomSignal&& signal)108    {109        std::lock_guard<std::mutex> lock(fMtx);110        signal();111    }112 113    void Clear()114    {115        std::lock_guard<std::mutex> lock(fMtx);116        fStates = std::queue<fair::mq::State>();117    }118 119  private:120    std::queue<fair::mq::State> fStates;121    std::mutex fMtx;122    std::condition_variable fCV;123 124    // must be called under locked fMtx125    fair::mq::State PopFrontUnsafe()126    {127        fair::mq::State state = fStates.front();128        if (state == fair::mq::State::Error) {129            throw DeviceErrorState("Controlled device transitioned to error state.");130        }131        fStates.pop();132        return state;133    }134 135    // must be called under locked fMtx136    std::pair<bool, fair::mq::State> ReturnPairUnsafe()137    {138        auto const pred = Predicate();139        return {pred, pred ? PopFrontUnsafe() : fair::mq::State::Ok};140    }141 142    // must be called under locked fMtx143    bool Predicate() { return !fStates.empty(); }144};145 146}   // namespace fair::mq147 148#endif /* FAIRMQSTATEQUEUE_H_ */