feat!: Remove Device::TransitionTo() without replacement

BREAKING CHANGE

However, this API was never advertised nor used by anyone.
This commit is contained in:
Dennis Klein 2023-02-28 16:36:31 +01:00 committed by Dennis Klein
parent c2fa2e8848
commit c35d35a3c3
3 changed files with 1 additions and 150 deletions

View File

@ -91,7 +91,6 @@ Device::Device(ProgOptions* config, tools::Version version)
, fVersion(version) , fVersion(version)
, fRate(DefaultRate) , fRate(DefaultRate)
, fInitializationTimeoutInS(DefaultInitTimeout) , fInitializationTimeoutInS(DefaultInitTimeout)
, fTransitioning(false)
{ {
SubscribeToNewTransition("device", [&](Transition transition) { SubscribeToNewTransition("device", [&](Transition transition) {
LOG(trace) << "device notified on new transition: " << transition; LOG(trace) << "device notified on new transition: " << transition;
@ -143,73 +142,6 @@ Device::Device(ProgOptions* config, tools::Version version)
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
void Device::TransitionTo(State s)
{
{
lock_guard<mutex> lock(fTransitionMtx);
if (fTransitioning) {
LOG(debug) << "Attempting a transition with TransitionTo() while another one is already in progress";
throw OngoingTransition("Attempting a transition with TransitionTo() while another one is already in progress");
}
fTransitioning = true;
}
using mq::State;
StateQueue sq;
StateSubscription ss(tools::ToString(fId, ".TransitionTo"), fStateMachine, sq);
State currentState = GetCurrentState();
while (s != currentState) {
switch (currentState) {
case State::Idle:
if (s == State::Exiting) { ChangeStateOrThrow(Transition::End); }
else { ChangeStateOrThrow(Transition::InitDevice); }
break;
case State::InitializingDevice:
ChangeStateOrThrow(Transition::CompleteInit);
break;
case State::Initialized:
if (s == State::Exiting || s == State::Idle) { ChangeStateOrThrow(Transition::ResetDevice); }
else { ChangeStateOrThrow(Transition::Bind); }
break;
case State::Bound:
if (s == State::DeviceReady || s == State::Ready || s == State::Running) { ChangeStateOrThrow(Transition::Connect); }
else { ChangeStateOrThrow(Transition::ResetDevice); }
break;
case State::DeviceReady:
if (s == State::Running || s == State::Ready) { ChangeStateOrThrow(Transition::InitTask); }
else { ChangeStateOrThrow(Transition::ResetDevice); }
break;
case State::Ready:
if (s == State::Running) { ChangeStateOrThrow(Transition::Run); }
else { ChangeStateOrThrow(Transition::ResetTask); }
break;
case State::Running:
ChangeStateOrThrow(Transition::Stop);
break;
case State::Binding:
case State::Connecting:
case State::InitializingTask:
case State::ResettingDevice:
case State::ResettingTask:
LOG(debug) << "TransitionTo ignoring state: " << currentState << " (expected, automatic transition).";
break;
default:
LOG(debug) << "TransitionTo ignoring state: " << currentState;
break;
}
currentState = sq.WaitForNext();
}
{
lock_guard<mutex> lock(fTransitionMtx);
fTransitioning = false;
}
}
void Device::InitWrapper() void Device::InitWrapper()
{ {
// run initialization once CompleteInit transition is requested // run initialization once CompleteInit transition is requested

View File

@ -552,8 +552,6 @@ class Device
/// @param state state to wait for /// @param state state to wait for
void WaitForState(const std::string& state) { WaitForState(GetState(state)); } void WaitForState(const std::string& state) { WaitForState(GetState(state)); }
void TransitionTo(State state);
/// @brief Subscribe with a callback to state changes /// @brief Subscribe with a callback to state changes
/// @param key id to identify your subscription /// @param key id to identify your subscription
/// @param callback callback (called with the new state as the parameter) /// @param callback callback (called with the new state as the parameter)
@ -683,8 +681,6 @@ class Device
StateQueue fStateQueue; StateQueue fStateQueue;
std::mutex fTransportMtx; ///< guards access to transports container std::mutex fTransportMtx; ///< guards access to transports container
std::mutex fTransitionMtx;
bool fTransitioning;
}; };
} // namespace fair::mq } // namespace fair::mq

View File

@ -1,5 +1,5 @@
/******************************************************************************** /********************************************************************************
* Copyright (C) 2014-2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * * Copyright (C) 2014-2023 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* * * *
* This software is distributed under the terms of the * * This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, * * GNU Lesser General Public Licence (LGPL) version 3, *
@ -20,83 +20,6 @@ namespace
using namespace std; using namespace std;
using namespace fair::mq; using namespace fair::mq;
class SlowDevice : public Device
{
public:
SlowDevice() = default;
protected:
void Init() override
{
this_thread::sleep_for(chrono::milliseconds(100));
}
};
void transitionTo(const vector<State>& states, int numExpectedStates)
{
Device device;
thread t([&] {
for (const auto& s : states) {
device.TransitionTo(s);
}
});
int numStates = 0;
device.SubscribeToStateChange("testRunner", [&numStates](State /* state */) {
numStates++;
});
device.RunStateMachine();
if (t.joinable()) {
t.join();
}
LOG(info) << "expected " << numExpectedStates << ", encountered " << numStates << " states";
EXPECT_EQ(numStates, numExpectedStates);
}
TEST(Transitions, TransitionTo)
{
transitionTo({State::Exiting}, 2);
transitionTo({State::InitializingDevice, State::Initialized, State::Exiting}, 6);
transitionTo({State::Initialized, State::Exiting}, 6);
transitionTo({State::DeviceReady, State::Bound, State::Running, State::Exiting}, 24);
transitionTo({State::Ready, State::Exiting}, 14);
transitionTo({State::Running, State::Exiting}, 16);
}
TEST(Transitions, ConcurrentTransitionTos)
{
fair::Logger::SetConsoleSeverity("debug");
SlowDevice slowDevice;
vector<State> states({State::Ready, State::Exiting});
thread t1([&] {
for (const auto& s : states) {
slowDevice.TransitionTo(s);
}
});
thread t2([&] {
this_thread::sleep_for(chrono::milliseconds(50));
ASSERT_THROW(slowDevice.TransitionTo(State::Exiting), OngoingTransition);
});
slowDevice.RunStateMachine();
if (t1.joinable()) {
t1.join();
}
if (t2.joinable()) {
t2.join();
}
}
TEST(Transitions, InvalidChangeState) TEST(Transitions, InvalidChangeState)
{ {
Device device; Device device;