Skip to content

Commit ed6c50d

Browse files
author
Janosch Machowinski
committed
Reworked code to use way less shared ptr locks
Signed-off-by: Janosch Machowinski <[email protected]>
1 parent 4f13c4d commit ed6c50d

File tree

5 files changed

+210
-146
lines changed

5 files changed

+210
-146
lines changed

rclcpp/include/rclcpp/executors/cbg_executor.hpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <deque>
2222
#include <unordered_map>
2323

24+
#include "rclcpp/executors/detail/any_executable_weak_ref.hpp"
2425
#include "rclcpp/executor.hpp"
2526
#include "rclcpp/executors/callback_group_state.hpp"
2627
#include "rclcpp/macros.hpp"
@@ -48,19 +49,20 @@ class ExecutionGroup
4849
next_unprocessed_ready_executable = 0;
4950
}
5051

51-
void add_ready_executable(const Executable & e)
52+
void add_ready_executable(AnyExecutableWeakRef & e)
5253
{
53-
ready_executables.push_back(e);
54+
ready_executables.push_back(&e);
55+
// ready_executables.push_back(std::get<const Executable>(e.executable));
5456
}
5557

5658
bool has_unprocessed_executables()
5759
{
5860
for (; next_unprocessed_ready_executable < ready_executables.size();
5961
next_unprocessed_ready_executable++)
6062
{
61-
const auto & ready_executable = ready_executables[next_unprocessed_ready_executable];
63+
auto & ready_executable = ready_executables[next_unprocessed_ready_executable];
6264

63-
if (ready_executable.lock()) {
65+
if (ready_executable->executable_alive()) {
6466
return true;
6567
}
6668
}
@@ -74,7 +76,7 @@ class ExecutionGroup
7476
{
7577
const auto & ready_executable = ready_executables[next_unprocessed_ready_executable];
7678

77-
if (fill_any_executable(any_executable, ready_executable)) {
79+
if (fill_any_executable(any_executable, std::get<const Executable>(ready_executable->executable))) {
7880
// mark the current element as processed
7981
next_unprocessed_ready_executable++;
8082

@@ -108,7 +110,7 @@ class ExecutionGroup
108110
return false;
109111
}
110112

111-
any_executable.data = *data;
113+
// any_executable.data = *data;
112114

113115
return true;
114116
//RCUTILS_LOG_INFO("Executing timer");
@@ -142,7 +144,7 @@ class ExecutionGroup
142144
return false;
143145
}
144146

145-
std::vector<Executable> ready_executables;
147+
std::vector<AnyExecutableWeakRef *> ready_executables;
146148
size_t next_unprocessed_ready_executable = 0;
147149

148150
};
@@ -166,11 +168,11 @@ class CallbackGroupScheduler
166168

167169
void clear_and_prepare(const CallbackGroupState & cb_elements);
168170

169-
void add_ready_executable(const rclcpp::SubscriptionBase::WeakPtr & executable);
170-
void add_ready_executable(const rclcpp::ServiceBase::WeakPtr & executable);
171-
void add_ready_executable(const rclcpp::TimerBase::WeakPtr & executable);
172-
void add_ready_executable(const rclcpp::ClientBase::WeakPtr & executable);
173-
void add_ready_executable(const rclcpp::Waitable::WeakPtr & executable);
171+
void add_ready_timer(AnyExecutableWeakRef & executable);
172+
void add_ready_subscription(AnyExecutableWeakRef & executable);
173+
void add_ready_service(AnyExecutableWeakRef & executable);
174+
void add_ready_client(AnyExecutableWeakRef & executable);
175+
void add_ready_waitable(AnyExecutableWeakRef & executable);
174176

175177
enum Priorities
176178
{

rclcpp/include/rclcpp/executors/detail/any_executable_weak_ref.hpp

Lines changed: 128 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "rclcpp/client.hpp"
66
#include "rclcpp/waitable.hpp"
77
#include "rclcpp/guard_condition.hpp"
8+
#include "rclcpp/executors/callback_group_state.hpp"
89

910
namespace rclcpp::executors
1011
{
@@ -17,27 +18,72 @@ struct AnyExecutableWeakRef
1718
AnyExecutableWeakRef(const rclcpp::SubscriptionBase::WeakPtr & p, int16_t callback_group_index)
1819
: executable(p),
1920
callback_group_index(callback_group_index)
20-
{}
21+
{
22+
if(auto shr = p.lock())
23+
{
24+
rcl_handle_shr_ptr = shr->get_subscription_handle();
25+
}
26+
else
27+
{
28+
rcl_handle_shr_ptr = std::monostate();
29+
}
30+
}
2131

2232
AnyExecutableWeakRef(const rclcpp::TimerBase::WeakPtr & p, int16_t callback_group_index)
2333
: executable(p),
2434
callback_group_index(callback_group_index)
25-
{}
35+
{
36+
if(auto shr = p.lock())
37+
{
38+
rcl_handle_shr_ptr = shr->get_timer_handle();
39+
}
40+
else
41+
{
42+
rcl_handle_shr_ptr = std::monostate();
43+
}
44+
}
2645

2746
AnyExecutableWeakRef(const rclcpp::ServiceBase::WeakPtr & p, int16_t callback_group_index)
2847
: executable(p),
2948
callback_group_index(callback_group_index)
30-
{}
49+
{
50+
if(auto shr = p.lock())
51+
{
52+
rcl_handle_shr_ptr = shr->get_service_handle();
53+
}
54+
else
55+
{
56+
rcl_handle_shr_ptr = std::monostate();
57+
}
58+
}
3159

3260
AnyExecutableWeakRef(const rclcpp::ClientBase::WeakPtr & p, int16_t callback_group_index)
3361
: executable(p),
3462
callback_group_index(callback_group_index)
35-
{}
63+
{
64+
if(auto shr = p.lock())
65+
{
66+
rcl_handle_shr_ptr = shr->get_client_handle();
67+
}
68+
else
69+
{
70+
rcl_handle_shr_ptr = std::monostate();
71+
}
72+
}
3673

3774
AnyExecutableWeakRef(const rclcpp::Waitable::WeakPtr & p, int16_t callback_group_index)
3875
: executable(p),
3976
callback_group_index(callback_group_index)
40-
{}
77+
{
78+
if(auto shr = p.lock())
79+
{
80+
rcl_handle_shr_ptr = shr;
81+
}
82+
else
83+
{
84+
rcl_handle_shr_ptr = std::monostate();
85+
}
86+
}
4187

4288
AnyExecutableWeakRef(
4389
const rclcpp::GuardCondition::WeakPtr & p,
@@ -49,6 +95,76 @@ struct AnyExecutableWeakRef
4995
{
5096
//special case, guard conditions are auto processed by waking up the wait set
5197
// therefore they shall never create a real executable
98+
99+
{
100+
if(auto shr = p.lock())
101+
{
102+
rcl_handle_shr_ptr = shr;
103+
}
104+
else
105+
{
106+
rcl_handle_shr_ptr = std::monostate();
107+
}
108+
}
109+
110+
111+
}
112+
113+
/**
114+
* Checks, if the executable still exists, or if was deleted
115+
*/
116+
bool executable_alive()
117+
{
118+
auto check_valid = [this] (const auto &shr_ptr)
119+
{
120+
auto use_cnt = shr_ptr.use_count();
121+
if(use_cnt <= 1)
122+
{
123+
rcl_handle_shr_ptr = std::monostate();
124+
return false;
125+
}
126+
127+
return true;
128+
};
129+
130+
switch(rcl_handle_shr_ptr.index()) {
131+
case AnyExecutableWeakRef::ExecutableIndex::Subscription:
132+
{
133+
return check_valid(std::get<std::shared_ptr<rcl_subscription_t>>(rcl_handle_shr_ptr));
134+
}
135+
break;
136+
case AnyExecutableWeakRef::ExecutableIndex::Timer:
137+
{
138+
return check_valid(std::get<std::shared_ptr<const rcl_timer_t>>(rcl_handle_shr_ptr));
139+
}
140+
break;
141+
case AnyExecutableWeakRef::ExecutableIndex::Service:
142+
{
143+
return check_valid(std::get<std::shared_ptr<rcl_service_t>>(rcl_handle_shr_ptr));
144+
}
145+
break;
146+
case AnyExecutableWeakRef::ExecutableIndex::Client:
147+
{
148+
return check_valid(std::get<std::shared_ptr<rcl_client_t>>(rcl_handle_shr_ptr));
149+
}
150+
break;
151+
case AnyExecutableWeakRef::ExecutableIndex::Waitable:
152+
{
153+
return check_valid(std::get<std::shared_ptr<rclcpp::Waitable>>(rcl_handle_shr_ptr));
154+
}
155+
break;
156+
case AnyExecutableWeakRef::ExecutableIndex::GuardCondition:
157+
{
158+
return check_valid(std::get<std::shared_ptr<rclcpp::GuardCondition>>(rcl_handle_shr_ptr));
159+
}
160+
case AnyExecutableWeakRef::ExecutableIndex::Deleted:
161+
{
162+
return false;
163+
}
164+
break;
165+
166+
}
167+
return false;
52168
}
53169

54170
AnyExecutableWeakRef(const AnyExecutableWeakRef &) = delete;
@@ -69,10 +185,16 @@ struct AnyExecutableWeakRef
69185
Client,
70186
Waitable,
71187
GuardCondition,
188+
Deleted,
72189
};
73190

74191
// shared_ptr holding the rcl handle during wait
75-
std::shared_ptr<const void> rcl_handle_shr_ptr;
192+
193+
using RclHandleVariant = std::variant<std::shared_ptr<rcl_subscription_t>, std::shared_ptr<const rcl_timer_t>,
194+
std::shared_ptr<rcl_service_t>, std::shared_ptr<rcl_client_t>,
195+
rclcpp::Waitable::SharedPtr, rclcpp::GuardCondition::SharedPtr, std::monostate>;
196+
197+
RclHandleVariant rcl_handle_shr_ptr;
76198

77199
// A function that should be executed if the executable is a guard condition and ready
78200
std::function<void(void)> handle_guard_condition_fun;

0 commit comments

Comments
 (0)