ifw-daq 3.1.0
IFW Data Acquisition modules
Loading...
Searching...
No Matches
awaitState.cpp
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup daq_common_libdaq
4 * @copyright 2022 ESO - European Southern Observatory
5 *
6 * @brief Contains definitions for the AwaitStateAsync operation
7 */
9
10#include <fmt/format.h>
11#include <fmt/ostream.h>
12#include <log4cplus/loggingmacros.h>
13
14#include <daq/error.hpp>
15
16namespace daq::op {
17
18AwaitStateAsync::AwaitStateAsync(boost::asio::io_context& io_ctx,
19 std::shared_ptr<ObservableStatus> status,
20 State state,
21 std::chrono::milliseconds timeout,
22 log4cplus::Logger const& logger)
23 : m_io_ctx(io_ctx)
24 , m_status(std::move(status))
25 , m_target(state)
26 , m_timeout(timeout)
27 , m_aborted(false)
28 , m_timer(m_io_ctx)
29 , m_logger(logger) {
30 assert(m_status);
31}
32
33boost::future<AwaitStateAsync::ResultType> AwaitStateAsync::Initiate() {
34 LOG4CPLUS_DEBUG(m_logger,
35 fmt::format("AwaitStateAsync::Initate(): Awaiting state {} with timeout {}ms",
36 fmt::streamed(m_target),
37 m_timeout.count()));
38 if (IsConditionSatisfied()) {
39 // Condition already satisfied
40 return boost::make_ready_future<ResultType>(ResultType{false, m_status->GetStatus()});
41 }
42
43 // Set up status observer and timer
44 m_connection = m_status->ConnectObserver([this](ObservableStatus const&) {
45 if (IsConditionSatisfied()) {
46 LOG4CPLUS_DEBUG(m_logger,
47 fmt::format("Await condition is satisfied by status change "
48 "-> setting promise: ",
49 fmt::streamed(*m_status)));
50 try {
51 m_promise.set_value(ResultType{false, m_status->GetStatus()});
52 m_timer.cancel();
53 } catch (boost::promise_already_satisfied const&) {
54 // Do nothing.
55 LOG4CPLUS_DEBUG(m_logger, "Promise already satisfied");
56 }
57 }
58 });
59
60 m_timer.expires_after(m_timeout);
61 m_timer.async_wait([this, logger = m_logger](boost::system::error_code const& error) {
62 if (error) {
63 // Timer was cancelled. This may mean the operation is no longer valid.
64 LOG4CPLUS_DEBUG(logger, "Timer cancelled: Doing nothing.");
65 return;
66 }
67 if (m_aborted) {
68 // Operation has been aborted. This may mean the operation is no longer valid.
69 LOG4CPLUS_INFO(logger, "Operation aborted: Doing nothing.");
70 return;
71 }
72 try {
73 // It is only considered a timeout if condition is still not satisfied
74 bool timeout = !IsConditionSatisfied();
75 LOG4CPLUS_DEBUG(
76 m_logger,
77 fmt::format("AwaitStateAsync: {}: Timer expired waiting for target state '{}'. "
78 "Current state is '{}'",
79 m_status->GetId(),
80 fmt::streamed(m_target),
81 fmt::streamed(m_status->GetState())));
82 m_promise.set_value(ResultType{timeout, m_status->GetStatus()});
83 } catch (boost::promise_already_satisfied const&) {
84 // May happen due to race-to-complete
85 LOG4CPLUS_DEBUG(m_logger, "Promise already satisfied");
86 }
87 });
88
89 return m_promise.get_future();
90}
91
92void AwaitStateAsync::Abort() noexcept {
93 try {
94 LOG4CPLUS_INFO(m_logger, "Aborting operation.");
95 m_promise.set_exception(DaqOperationAborted(
96 fmt::format("AwaitStateAsync: {}: Operation aborted while waiting for target state {}. "
97 "Current state is {}",
98 m_status->GetId(),
99 fmt::streamed(m_target),
100 fmt::streamed(m_status->GetState()))));
101 m_aborted = true;
102 // Might as well cancel timer and disconnect observer
103 m_timer.cancel();
104 m_connection.disconnect();
105 } catch (boost::promise_already_satisfied const&) {
106 }
107}
108
109bool AwaitStateAsync::IsConditionSatisfied() const {
110 return !IsSubsequentState(m_target, m_status->GetState());
111}
112
113} // namespace daq::op
Contains declaration for the AwaitStateAsync operation.
Started operation was aborted.
Definition: error.hpp:48
Stores data acquisition status and allows subscription to status changes.
Definition: status.hpp:224
Contains error related declarations for DAQ.
bool IsSubsequentState(State state1, State state2) noexcept
Compares states and returns whether state1 occurs after state2.
Definition: state.cpp:43
State
Observable states of the data acquisition process.
Definition: state.hpp:41
Utility class that represents a result and an error.
Definition: utility.hpp:17
Definition: main.cpp:24
boost::future< ResultType > Initiate()
Initiates operation that await state.
Definition: awaitState.cpp:33
void Abort() noexcept
Aborts the operation and completes the operation with DaqOperationAborted.
Definition: awaitState.cpp:92
AwaitStateAsync(boost::asio::io_context &io_ctx, std::shared_ptr< ObservableStatus > status, State state, std::chrono::milliseconds timeout, log4cplus::Logger const &logger)
Constructs operation with the privided parameters.
Definition: awaitState.cpp:18