ifw-daq  1.0.0
IFW Data Acquisition modules
awaitState.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @ingroup daq_ocm_libdaq
4  * @copyright 2021 ESO - European Southern Observatory
5  *
6  * @brief Contains definitions for the AwaitStateAsync operation
7  */
8 #include <daq/op/awaitState.hpp>
9 
10 #include <log4cplus/loggingmacros.h>
11 #include <fmt/format.h>
12 #include <fmt/ostream.h>
13 
14 #include <daq/error.hpp>
15 
16 
17 namespace daq::op {
18 
19 
20 AwaitStateAsync::AwaitStateAsync(boost::asio::io_context& io_ctx,
21  std::shared_ptr<ObservableStatus> status,
22  State state,
23  std::chrono::milliseconds timeout)
24  : m_io_ctx(io_ctx)
25  , m_status(std::move(status))
26  , m_target(state)
27  , m_timeout(timeout)
28  , m_aborted(false)
29  , m_timer(m_io_ctx)
30  , m_logger(log4cplus::Logger::getInstance("daq.op.awaitstate")) {
31  assert(m_status);
32 }
33 
34 
35 boost::future<AwaitStateAsync::ResultType> AwaitStateAsync::Initiate() {
36  if (IsConditionSatisfied()) {
37  // Condition already satisfied
38  return boost::make_ready_future<ResultType>(ResultType{false, m_status->GetStatus()});
39  }
40 
41  // Set up status observer and timer
42 
43  m_connection = m_status->ConnectObserver([this](ObservableStatus const&) {
44  if (IsConditionSatisfied()) {
45  LOG4CPLUS_DEBUG(m_logger,
46  fmt::format(
47  "Await condition is satisfied by status change "
48  "-> setting promise: ",
49  *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](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("daq.op.awaitstate", "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("daq.op.awaitstate", "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 cb waiting for target state {}. "
78  "Current state is {}",
79  m_status->GetId(),
80  m_target,
81  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 
92 
93 void AwaitStateAsync::Abort() noexcept {
94  try {
95  LOG4CPLUS_INFO("daq.op.awaitstate", "Aborting operation.");
96  m_promise.set_exception(DaqOperationAborted(
97  fmt::format("AwaitStateAsync: {}: Operation aborted while waiting for target state {}. "
98  "Current state is {}",
99  m_status->GetId(),
100  m_target,
101  m_status->GetState())));
102  m_aborted = true;
103  // Might as well cancel timer and disconnect observer
104  m_timer.cancel();
105  m_connection.disconnect();
106  } catch (boost::promise_already_satisfied const&) {
107  }
108 }
109 
110 
111 bool AwaitStateAsync::IsConditionSatisfied() const {
112  return !IsSubsequentState(m_target, m_status->GetState());
113 }
114 
115 
116 } // namespace daq
daq::State
State
Observable states of the data acquisition process.
Definition: state.hpp:41
daq::op::AwaitStateAsync::Initiate
boost::future< ResultType > Initiate()
Initiates operation that await state.
Definition: awaitState.cpp:35
awaitState.hpp
Contains declaration for the AwaitStateAsync operation.
daq::op::AwaitStateAsync::AwaitStateAsync
AwaitStateAsync(boost::asio::io_context &io_ctx, std::shared_ptr< ObservableStatus > status, State state, std::chrono::milliseconds timeout)
Constructs operation with the privided parameters.
Definition: awaitState.cpp:20
daq::ObservableStatus
Stores data acquisition status and allows subscription to status changes.
Definition: status.hpp:68
daq::op::AwaitStateAsync::Abort
void Abort() noexcept
Aborts the operation and completes the operation with DaqOperationAborted.
Definition: awaitState.cpp:93
daq::op
Definition: abort.hpp:19
daq::IsSubsequentState
bool IsSubsequentState(State state, State after) noexcept
Compares states and returns whether state occurs after after.
Definition: state.cpp:25
daq::DaqOperationAborted
Started operation was aborted.
Definition: error.hpp:47
daq::Result
Utility class that represents a result and an error.
Definition: utility.hpp:17
error.hpp
Contains error related declarations for DAQ.