Skip to content

Commit 191f47a

Browse files
committed
cleanup events executor class
Signed-off-by: Alberto Soragna <[email protected]>
1 parent bb491bd commit 191f47a

File tree

5 files changed

+39
-62
lines changed

5 files changed

+39
-62
lines changed

rclcpp/include/rclcpp/executors/events_executor.hpp

+9-10
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,16 @@ namespace executors
3737

3838
/// Events executor implementation
3939
/**
40-
* This executor is a variation of the standard one that does not uses a waitset.
41-
* The executor uses an events queue and a timers manager to execute entities from its
40+
* This executor uses an events queue and a timers manager to execute entities from its
4241
* associated nodes and callback groups.
43-
* This provides improved performance as it allows to skip all the waitset maintenance operations.
42+
* The RMW listener APIs are used to collect new events.
43+
*
44+
* This executor tries to reduce as much as possible the amount of maintenance operations.
45+
* This allows to use customized `EventsQueue` classes to achieve different goals such
46+
* as very low CPU usage, bounded memory requirement, determinism, etc.
47+
*
48+
* The executor uses a weak ownership model and it locks entities only while executing
49+
* their related events.
4450
*
4551
* To run this executor:
4652
* rclcpp::executors::EventsExecutor executor;
@@ -204,8 +210,6 @@ class EventsExecutor : public rclcpp::Executor
204210
private:
205211
RCLCPP_DISABLE_COPY(EventsExecutor)
206212

207-
using EventQueue = std::queue<rmw_listener_event_t>;
208-
209213
// Executor callback: Push new events into the queue and trigger cv.
210214
// This function is called by the DDS entities when an event happened,
211215
// like a subscription receiving a message.
@@ -229,11 +233,6 @@ class EventsExecutor : public rclcpp::Executor
229233
this_executor->events_queue_cv_.notify_one();
230234
}
231235

232-
/// Extract and execute events from the queue until it is empty
233-
RCLCPP_PUBLIC
234-
void
235-
consume_all_events(EventQueue & queue);
236-
237236
// Execute a single event
238237
RCLCPP_PUBLIC
239238
void

rclcpp/include/rclcpp/experimental/buffers/events_queue.hpp

+12-11
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717

1818
#include <queue>
1919

20-
#include "rclcpp/executors/events_executor_entities_collector.hpp"
2120
#include "rclcpp/macros.hpp"
21+
#include "rclcpp/visibility_control.hpp"
2222

2323
#include "rmw/listener_event_types.h"
2424

@@ -30,10 +30,14 @@ namespace buffers
3030
{
3131

3232
/**
33-
* @brief This abstract class is intended to be used as
34-
* a wrapper around a queue. The derived classes should chose
35-
* which container to use and the strategies for push and prune
36-
* events from the queue.
33+
* @brief This abstract class can be used to implement different types of queues
34+
* where `rmw_listener_event_t` can be stored.
35+
* The derived classes should choose which underlying container to use and
36+
* the strategy for pushing and popping events.
37+
* For example a queue implementation may be bounded or unbounded and have
38+
* different pruning strategies.
39+
* Implementations may or may not check the validity of events and decide how to handle
40+
* the situation where an event is not valid anymore (e.g. a subscription history cache overruns)
3741
*/
3842
class EventsQueue
3943
{
@@ -56,9 +60,7 @@ class EventsQueue
5660
push(const rmw_listener_event_t & event) = 0;
5761

5862
/**
59-
* @brief removes front element from the queue
60-
* The element removed is the "oldest" element in the queue whose
61-
* value can be retrieved by calling member front().
63+
* @brief removes front element from the queue.
6264
*/
6365
RCLCPP_PUBLIC
6466
virtual
@@ -101,14 +103,13 @@ class EventsQueue
101103
init() = 0;
102104

103105
/**
104-
* @brief gets a queue with all events accumulated on it since
105-
* the last call. The member queue is empty when the call returns.
106+
* @brief pops out all events stored in the object into an output queue.
106107
* @return queue with events
107108
*/
108109
RCLCPP_PUBLIC
109110
virtual
110111
std::queue<rmw_listener_event_t>
111-
get_all_events() = 0;
112+
pop_all_events() = 0;
112113
};
113114

114115
} // namespace buffers

rclcpp/include/rclcpp/experimental/buffers/simple_events_queue.hpp

+6-10
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@ namespace buffers
2828
{
2929

3030
/**
31-
* @brief This class provides a simple queue implementation
32-
* based on a std::queue. As the objective is having a CPU peformant
33-
* queue, it does not performs any checks about the size of
34-
* the queue, so the queue size could grow unbounded.
35-
* It does not implement any pruning mechanisms.
31+
* @brief This class implements an EventsQueue as a simple wrapper around a std::queue.
32+
* It does not perform any checks about the size of queue, which can grow
33+
* unbounded without being pruned.
34+
* The simplicity of this implementation makes it suitable for optimizing CPU usage.
3635
*/
3736
class SimpleEventsQueue : public EventsQueue
3837
{
@@ -53,9 +52,7 @@ class SimpleEventsQueue : public EventsQueue
5352
}
5453

5554
/**
56-
* @brief removes front element from the queue
57-
* The element removed is the "oldest" element in the queue whose
58-
* value can be retrieved by calling member front().
55+
* @brief removes front event from the queue.
5956
*/
6057
RCLCPP_PUBLIC
6158
virtual
@@ -114,7 +111,6 @@ class SimpleEventsQueue : public EventsQueue
114111
std::swap(event_queue_, local_queue);
115112
}
116113

117-
118114
/**
119115
* @brief gets a queue with all events accumulated on it since
120116
* the last call. The member queue is empty when the call returns.
@@ -123,7 +119,7 @@ class SimpleEventsQueue : public EventsQueue
123119
RCLCPP_PUBLIC
124120
virtual
125121
std::queue<rmw_listener_event_t>
126-
get_all_events()
122+
pop_all_events()
127123
{
128124
std::queue<rmw_listener_event_t> local_queue;
129125
std::swap(event_queue_, local_queue);

rclcpp/src/rclcpp/executors/events_executor.cpp

+10-15
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,19 @@ EventsExecutor::spin()
6666
std::unique_lock<std::mutex> push_lock(push_mutex_);
6767
// We wait here until something has been pushed to the event queue
6868
events_queue_cv_.wait(push_lock, has_event_predicate);
69-
// Local event queue to allow entities to push events while we execute them
70-
EventQueue execution_event_queue = events_queue_->get_all_events();
69+
// Move all events into a local events queue to allow entities to push while we execute them
70+
std::queue<rmw_listener_event_t> execution_events_queue = events_queue_->pop_all_events();
7171
// Unlock the mutex
7272
push_lock.unlock();
73-
// Consume all available events, this queue will be empty at the end of the function
74-
this->consume_all_events(execution_event_queue);
73+
// Consume all available events
74+
while (!execution_events_queue.empty()) {
75+
rmw_listener_event_t event = execution_events_queue.front();
76+
execution_events_queue.pop();
77+
this->execute_event(event);
78+
}
7579
}
80+
81+
// Stop the timers manager thread when we are done spinning
7682
timers_manager_->stop();
7783
}
7884

@@ -235,17 +241,6 @@ EventsExecutor::remove_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify)
235241
this->remove_node(node_ptr->get_node_base_interface(), notify);
236242
}
237243

238-
void
239-
EventsExecutor::consume_all_events(EventQueue & event_queue)
240-
{
241-
while (!event_queue.empty()) {
242-
rmw_listener_event_t event = event_queue.front();
243-
event_queue.pop();
244-
245-
this->execute_event(event);
246-
}
247-
}
248-
249244
void
250245
EventsExecutor::execute_event(const rmw_listener_event_t & event)
251246
{

rclcpp/test/rclcpp/executors/test_events_queue.cpp

+2-16
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,7 @@
2121

2222
using namespace std::chrono_literals;
2323

24-
class TestEventsQueue : public ::testing::Test
25-
{
26-
public:
27-
void SetUp()
28-
{
29-
rclcpp::init(0, nullptr);
30-
}
31-
32-
void TearDown()
33-
{
34-
rclcpp::shutdown();
35-
}
36-
};
37-
38-
TEST_F(TestEventsQueue, SimpleQueueTest)
24+
TEST(TestEventsQueue, SimpleQueueTest)
3925
{
4026
// Create a SimpleEventsQueue and a local queue
4127
auto simple_queue = std::make_unique<rclcpp::experimental::buffers::SimpleEventsQueue>();
@@ -54,7 +40,7 @@ TEST_F(TestEventsQueue, SimpleQueueTest)
5440
// Pop one message
5541
simple_queue->pop();
5642

57-
local_events_queue = simple_queue->get_all_events();
43+
local_events_queue = simple_queue->pop_all_events();
5844

5945
// We should have (11 - 1) events in the local queue
6046
size_t local_queue_size = local_events_queue.size();

0 commit comments

Comments
 (0)