ifw-daq 3.1.0
IFW Data Acquisition modules
Loading...
Searching...
No Matches
initiate.hpp
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 declarations for the helper functions to initiate operations
7 */
8#ifndef OCM_DAQ_OP_INITIATE_HPP_
9#define OCM_DAQ_OP_INITIATE_HPP_
10#include "../config.hpp"
11
12#include <functional>
13#include <memory>
14#include <type_traits>
15#include <utility>
16
17#include <boost/thread/future.hpp>
18
19#include <rad/ioExecutor.hpp>
20
21namespace daq::op {
22
23/**
24 * Constructs and initiates `Op` and return the future result.
25 *
26 * InitiateOperation performs the following:
27 *
28 * 1. Constructs the operation by forwarding the parameters Params.
29 * 2. Invokes `Op::Initiate() -> boost::future<R>`
30 * 3. Returns result of `Op::Initiate()`.
31 * 4. Keeps Operation alive until result of `Op::Initiate()` is set, such that
32 * the operation itself does not have to manage this.
33 *
34 *
35 * Type Requirements:
36 *
37 * `Op`:
38 * `Op::Op(Params...)`
39 * `Op::Initiate() -> boost::future<R>`
40 */
41template <class Op, class R = decltype(std::declval<Op&>().Initiate()), class... Params>
42R InitiateOperation(rad::IoExecutor& ex, Params&&... params);
43
44/**
45 * Like InitiateOperation but in addition to returning the future
46 * it also returns an unspecified object @a Abort that can be invoked to abort the operation.
47 *
48 * If @a Abort return true it will have invoked `Op::Abort()`.
49 * If @a Abort return false the operation has already been completed and future value has been set.
50 *
51 * Type Requirements:
52 *
53 * `Op`:
54 * `Op::Op(Params...)`
55 * `Op::Initiate() -> boost::future<R>`
56 * `Op::Abort() -> void`
57 * note: It's not required that the future returned from Initiate() has a value set
58 * when returning from Abort.
59 */
60template <class Op, class R = decltype(std::declval<Op&>().Initiate()), class... Params>
61std::pair<R, std::function<bool()>>
62InitiateAbortableOperation(rad::IoExecutor& ex, Params&&... params);
63
64//
65// Implementation
66//
67template <class Op, class R, class... Params>
68R InitiateOperation(rad::IoExecutor& ex, Params&&... params) {
69 std::unique_ptr<Op> op = std::make_unique<Op>(std::forward<Params>(params)...);
70 auto* ptr = op.get();
71
72 // Add continuation that keeps operation alive
73 return ptr->Initiate().then(ex, [op = std::move(op)](auto f) { return f.get(); });
74}
75
76template <class Op, class R, class... Params>
77std::pair<R, std::function<bool()>>
79 // AbortOperation needs a handle to Op so it can abort it. So in this case
80 // we create a shared pointer instead of unique as in InitiateOperation.
81 std::shared_ptr<Op> op = std::make_shared<Op>(std::forward<Params>(params)...);
82 auto* ptr = op.get();
83 auto weak = std::weak_ptr<Op>(op);
84 return {// Add continuation that keeps operation alive
85 ptr->Initiate().then(ex, [op = std::move(op)](auto f) { return f.get(); }),
86 [weak = std::move(weak)]() mutable -> bool {
87 if (auto op = weak.lock(); op) {
88 // m_operation is still valid
89 op->Abort();
90 // reset so that abort is a one-shot action
91 weak.reset();
92 return true;
93 }
94 return false;
95 }};
96}
97
98} // namespace daq::op
99
100#endif // #ifndef OCM_DAQ_OP_INITIATE_HPP_
Adapts boost::asio::io_context into a compatible boost::thread Executor type.
Definition: ioExecutor.hpp:12
R InitiateOperation(rad::IoExecutor &ex, Params &&... params)
Constructs and initiates Op and return the future result.
Definition: initiate.hpp:68
std::pair< R, std::function< bool()> > InitiateAbortableOperation(rad::IoExecutor &ex, Params &&... params)
Like InitiateOperation but in addition to returning the future it also returns an unspecified object ...
Definition: initiate.hpp:78