mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2025-10-16 10:01:47 +00:00
fix(control): Honor SIGINT and SIGTERM in more places
* Queue next transition for long-running states (fix #421) * Add *OrCustom/Push/Locked family of functions to StateQueue to enable composition with custom signals
This commit is contained in:
committed by
Dennis Klein
parent
27277b11b4
commit
6780b7452c
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2019-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -9,16 +9,14 @@
|
||||
#ifndef FAIRMQSTATEQUEUE_H_
|
||||
#define FAIRMQSTATEQUEUE_H_
|
||||
|
||||
#include <fairmq/States.h>
|
||||
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
#include <utility> // pair
|
||||
#include <condition_variable>
|
||||
#include <fairmq/States.h>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <utility> // pair
|
||||
|
||||
namespace fair::mq
|
||||
{
|
||||
namespace fair::mq {
|
||||
|
||||
class StateQueue
|
||||
{
|
||||
@@ -33,41 +31,47 @@ class StateQueue
|
||||
fair::mq::State WaitForNext()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fMtx);
|
||||
while (fStates.empty()) {
|
||||
fCV.wait_for(lock, std::chrono::milliseconds(50));
|
||||
}
|
||||
|
||||
fair::mq::State state = fStates.front();
|
||||
|
||||
if (state == fair::mq::State::Error) {
|
||||
throw DeviceErrorState("Controlled device transitioned to error state.");
|
||||
}
|
||||
|
||||
fStates.pop();
|
||||
return state;
|
||||
fCV.wait(lock, [this] { return Predicate(); });
|
||||
return PopFrontUnsafe();
|
||||
}
|
||||
|
||||
template<typename Rep, typename Period>
|
||||
std::pair<bool, fair::mq::State> WaitForNext(std::chrono::duration<Rep, Period> const& duration)
|
||||
template<typename Timeout>
|
||||
std::pair<bool, fair::mq::State> WaitForNext(Timeout&& duration)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fMtx);
|
||||
fCV.wait_for(lock, duration);
|
||||
|
||||
if (fStates.empty()) {
|
||||
return { false, fair::mq::State::Ok };
|
||||
}
|
||||
|
||||
fair::mq::State state = fStates.front();
|
||||
|
||||
if (state == fair::mq::State::Error) {
|
||||
throw DeviceErrorState("Controlled device transitioned to error state.");
|
||||
}
|
||||
|
||||
fStates.pop();
|
||||
return { true, state };
|
||||
fCV.wait_for(lock, std::forward<Timeout>(duration), [this] { return Predicate(); });
|
||||
return ReturnPairUnsafe();
|
||||
}
|
||||
|
||||
void WaitForState(fair::mq::State state) { while (WaitForNext() != state) {} }
|
||||
template<typename CustomPredicate>
|
||||
std::pair<bool, fair::mq::State> WaitForNextOrCustom(CustomPredicate&& customPredicate)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fMtx);
|
||||
fCV.wait(lock, [this, cp = std::move(customPredicate)] { return Predicate() || cp(); });
|
||||
return ReturnPairUnsafe();
|
||||
}
|
||||
|
||||
template<typename CustomPredicate>
|
||||
std::pair<bool, fair::mq::State> WaitForCustom(CustomPredicate&& customPredicate)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fMtx);
|
||||
fCV.wait(lock, [cp = std::move(customPredicate)] { return cp(); });
|
||||
return ReturnPairUnsafe();
|
||||
}
|
||||
|
||||
void WaitForState(fair::mq::State state)
|
||||
{
|
||||
while (WaitForNext() != state) {}
|
||||
}
|
||||
|
||||
template<typename CustomPredicate>
|
||||
void WaitForStateOrCustom(fair::mq::State state, CustomPredicate customPredicate)
|
||||
{
|
||||
auto next = WaitForNextOrCustom(customPredicate);
|
||||
while (!customPredicate() && (next.first && next.second != state)) {
|
||||
next = WaitForNextOrCustom(customPredicate);
|
||||
}
|
||||
}
|
||||
|
||||
void Push(fair::mq::State state)
|
||||
{
|
||||
@@ -75,7 +79,35 @@ class StateQueue
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
fStates.push(state);
|
||||
}
|
||||
fCV.notify_all();
|
||||
fCV.notify_one();
|
||||
}
|
||||
|
||||
template<typename CustomSignal>
|
||||
void Push(fair::mq::State state, CustomSignal&& signal)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
fStates.push(state);
|
||||
signal();
|
||||
}
|
||||
fCV.notify_one();
|
||||
}
|
||||
|
||||
template<typename CustomSignal>
|
||||
void Notify(CustomSignal&& signal)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
signal();
|
||||
}
|
||||
fCV.notify_one();
|
||||
}
|
||||
|
||||
template<typename CustomSignal>
|
||||
void Locked(CustomSignal&& signal)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fMtx);
|
||||
signal();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
@@ -88,8 +120,29 @@ class StateQueue
|
||||
std::queue<fair::mq::State> fStates;
|
||||
std::mutex fMtx;
|
||||
std::condition_variable fCV;
|
||||
|
||||
// must be called under locked fMtx
|
||||
fair::mq::State PopFrontUnsafe()
|
||||
{
|
||||
fair::mq::State state = fStates.front();
|
||||
if (state == fair::mq::State::Error) {
|
||||
throw DeviceErrorState("Controlled device transitioned to error state.");
|
||||
}
|
||||
fStates.pop();
|
||||
return state;
|
||||
}
|
||||
|
||||
// must be called under locked fMtx
|
||||
std::pair<bool, fair::mq::State> ReturnPairUnsafe()
|
||||
{
|
||||
auto const pred = Predicate();
|
||||
return {pred, pred ? PopFrontUnsafe() : fair::mq::State::Ok};
|
||||
}
|
||||
|
||||
// must be called under locked fMtx
|
||||
bool Predicate() { return !fStates.empty(); }
|
||||
};
|
||||
|
||||
} // namespace fair::mq
|
||||
} // namespace fair::mq
|
||||
|
||||
#endif /* FAIRMQSTATEQUEUE_H_ */
|
||||
|
Reference in New Issue
Block a user