SkillExecutionHandle.h
Go to the documentation of this file.
1/**
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @author Fabian Reister ( fabian dot reister at kit dot edu )
17 * @date 2025
18 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19 * GNU General Public License
20 */
21
22#pragma once
23
24#include <map>
25#include <memory>
26#include <optional>
27#include <vector>
28
32
33namespace armarx::skills
34{
35
36 using SkillProxyPtr = std::unique_ptr<class SkillProxy>;
37
38 /**
39 * @brief RAII handle for a running subskill.
40 *
41 * Represents an asynchronously started subskill. The handle owns the
42 * information required to control and query the subskill (a SkillProxy and
43 * the subskill's execution id). To ensure that the subskill is properly
44 * cleaned up, the handle should be destroyed (or explicitly abort()/join())
45 * before the parent skill exits.
46 *
47 * The handle provides:
48 * - join(): block until the subskill terminates and get its terminated status
49 * - abort(): request asynchronous abortion of the subskill
50 *
51 * Copies of the handle will each hold their own proxy+execution id (shallow copies
52 * of the proxy). Destruction of any handle will trigger a best-effort abort request;
53 * therefore lifetime management should be done carefully by the caller.
54 */
56 {
57 public:
58 /**
59 * @brief Construct a handle for an executing subskill.
60 * @param proxy A SkillProxy configured to control the subskill.
61 * @param executionId The execution id returned when starting the subskill.
62 */
64
65 /**
66 * @brief Destructor requests cleanup of the subskill.
67 *
68 * As a safety measure, the destructor issues an asynchronous abort request
69 * for the associated subskill. This is a best-effort request and may be
70 * a no-op if the subskill already finished. If the caller needs to wait
71 * for the subskill to finish cleanly, call join() before destruction.
72 */
74
75 /**
76 * @brief Block until the subskill terminates and return its status.
77 *
78 * This call will block the caller until the subskill execution finishes.
79 * On success it returns a TerminatedSkillStatusUpdate describing the final
80 * state of the subskill. If the subskill information cannot be retrieved
81 * an empty optional may be returned (depending on SkillProxy semantics).
82 *
83 * @return optional containing TerminatedSkillStatusUpdate if available.
84 */
85 std::optional<TerminatedSkillStatusUpdate> join();
86
87 /**
88 * @brief Request an asynchronous abort of the subskill.
89 *
90 * This sends an abort request to the subskill but does not wait for it
91 * to terminate. Use join() to wait for completion after calling abort()
92 * if synchronous behavior is required.
93 */
94 bool abortAsync();
95
96 /**
97 * @brief Get the current execution status of the subskill.
98 *
99 * @return optional containing SkillStatusUpdate if available.
100 */
101 std::optional<SkillStatusUpdate> getExecutionStatus();
102
104
105 private:
106 SkillProxyPtr proxy_;
107 skills::SkillExecutionID executionId_;
108
109 bool isJoined_ = false;
110 };
111
112 namespace util
113 {
115 {
116 operator bool() const;
117
118 std::vector<armarx::skills::SkillExecutionID> failedSkillExecutionIDs() const;
119 std::vector<armarx::skills::SkillID> failedSkillIDs() const;
120
122 std::optional<armarx::skills::TerminatedSkillStatusUpdate>>;
123
125 };
126
127 // Helper to extract raw pointer from any supported type
128 template <typename T>
130 to_raw_ptr(T* ptr) noexcept
131 {
132 return ptr;
133 }
134
135 template <typename T>
137 to_raw_ptr(const std::unique_ptr<T>& ptr) noexcept
138 {
139 return ptr.get();
140 }
141
142 template <typename T>
144 to_raw_ptr(const std::shared_ptr<T>& ptr) noexcept
145 {
146 return ptr.get();
147 }
148
149 JoinAllResult joinAll(const std::vector<armarx::skills::SkillExecutionHandle*>& handles);
150 JoinAllResult joinAll(const std::vector<std::unique_ptr<SkillExecutionHandle>>& handles);
151 JoinAllResult joinAll(const std::vector<std::shared_ptr<SkillExecutionHandle>>& handles);
152
153 // Variadic wrapper
154 template <typename... Args>
156 joinAllAny(Args&&... args)
157 {
158 static_assert(
159 (... && (std::is_convertible_v<decltype(to_raw_ptr(std::forward<Args>(args))),
161 "All arguments to joinAll must be SkillExecutionHandle pointers or smart "
162 "pointers");
163
164 std::vector<SkillExecutionHandle*> rawHandles{to_raw_ptr(std::forward<Args>(args))...};
165 return static_cast<JoinAllResult (*)(const std::vector<SkillExecutionHandle*>&)>(
166 joinAll)(rawHandles);
167 }
168 } // namespace util
169
170
171} // namespace armarx::skills
RAII handle for a running subskill.
bool abortAsync()
Request an asynchronous abort of the subskill.
std::optional< TerminatedSkillStatusUpdate > join()
Block until the subskill terminates and return its status.
~SkillExecutionHandle()
Destructor requests cleanup of the subskill.
SkillExecutionHandle(SkillProxyPtr proxy, skills::SkillExecutionID executionId)
Construct a handle for an executing subskill.
const skills::SkillExecutionID & executionId() const
std::optional< SkillStatusUpdate > getExecutionStatus()
Get the current execution status of the subskill.
JoinAllResult joinAll(const std::vector< armarx::skills::SkillExecutionHandle * > &handles)
JoinAllResult joinAllAny(Args &&... args)
SkillExecutionHandle * to_raw_ptr(T *ptr) noexcept
This file is part of ArmarX.
std::unique_ptr< class SkillProxy > SkillProxyPtr
std::vector< armarx::skills::SkillID > failedSkillIDs() const
std::map< armarx::skills::SkillExecutionID, std::optional< armarx::skills::TerminatedSkillStatusUpdate > > UpdatesMap
std::vector< armarx::skills::SkillExecutionID > failedSkillExecutionIDs() const