Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding callback groups in executor #1218

Merged
merged 79 commits into from
Sep 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
e5775b5
Initial version of callback-group-based Executor.
ralph-lange Jun 3, 2020
a5ced60
removed RealTimeClass
peterpena Jun 26, 2020
8a014d8
can add multiple cbgs and check if callback is owned by another exec …
peterpena Jun 26, 2020
3bea373
cbg var for option to add to executor
peterpena Jul 9, 2020
8145a3f
getter for callback groups in executor
peterpena Jul 10, 2020
6241e4d
test
peterpena Jul 10, 2020
00bef4b
add many nodes and callback groups together
peterpena Jul 10, 2020
a8b2f88
test for map of callback groups and nodes
peterpena Jul 11, 2020
547f977
added a test for map and callback group duplication
peterpena Jul 14, 2020
4b1dac8
add cbg that are not assign and allow to do so, only iterate through …
peterpena Jul 15, 2020
321cd92
memory strat should only add handles that belong to it
peterpena Jul 15, 2020
89345cd
fixed executor deconstructor seg fault bug
peterpena Jul 16, 2020
bc75d3a
fixed remove node and guard condition bug
peterpena Jul 16, 2020
37af5f5
fixed uncrustify
peterpena Jul 17, 2020
d5f7d46
cpplint
peterpena Jul 17, 2020
18b4d49
remove line break and add static executor in cmakelist
peterpena Jul 17, 2020
fbe586f
enabled static executor and added add callback group feature
peterpena Jul 20, 2020
106ef99
fixed test_allocator_memory_strategy
peterpena Jul 21, 2020
19216b5
test allocator
peterpena Jul 21, 2020
c2edc45
test mem strat with cbg feat
peterpena Jul 21, 2020
ac8f586
remove cbg in static executor
peterpena Jul 22, 2020
db2532b
adapted guard conditions
peterpena Jul 23, 2020
76e4344
collector deconstructor and remove cbg when remove node in static
peterpena Jul 23, 2020
649c800
fixed invalid group ptr seg fault introduced in wait for work
peterpena Jul 23, 2020
9795067
passes the test allocator mem strat
peterpena Jul 24, 2020
064e9e7
added weak node check in memory strategy; passes brawner unit tests
peterpena Jul 27, 2020
e3ae993
uncrustify for tests
peterpena Jul 28, 2020
356c2c1
lint and uncrustify
peterpena Jul 28, 2020
89b9623
exposed allowable state at the node level and added unit tests
peterpena Jul 28, 2020
691b082
unit test to add one node mult executors
peterpena Jul 29, 2020
4472e22
frixed allow executor reset bug
peterpena Jul 31, 2020
0f9c68d
code block for callback group and executor
peterpena Aug 1, 2020
d4b7e5a
add code block for add/remove cbg
peterpena Aug 1, 2020
1adfc9e
add comments for add/remove callback group
peterpena Aug 3, 2020
be2cbce
changed from atomic to const
peterpena Aug 4, 2020
72f308e
fixed test different cbgs for nodes
peterpena Aug 4, 2020
e212773
lint
peterpena Aug 5, 2020
cd96c57
added disabled nodes in services and map
peterpena Aug 5, 2020
d19866d
changed var name to suggestion
peterpena Aug 7, 2020
9deb47d
comment for callback group constructor
peterpena Aug 7, 2020
b46a9f0
header ordering
peterpena Aug 7, 2020
8cde317
Update rclcpp/include/rclcpp/executor.hpp
peterpena Aug 7, 2020
9be482e
removed const ref and made protected
peterpena Aug 7, 2020
0379c9e
removing internals in comments
peterpena Aug 11, 2020
9f4cdd7
Apply suggestions from code review
peterpena Aug 11, 2020
7c702cc
remove white space
peterpena Aug 11, 2020
5c2e03b
Apply suggestions from code review
peterpena Aug 11, 2020
52aae7c
fix comments
peterpena Aug 11, 2020
bf70092
Update rclcpp/include/rclcpp/executor.hpp
peterpena Aug 11, 2020
eefeca0
fix comments
peterpena Aug 11, 2020
c987bb1
fix comments
peterpena Aug 11, 2020
c869f09
general fixes
peterpena Aug 11, 2020
9d6c989
clang tidy and llvm deprecation and overriden fixes
peterpena Aug 13, 2020
ced0aba
made typedtests
peterpena Aug 13, 2020
6d12b11
add has callback method for static executor
peterpena Aug 14, 2020
1edb8b9
removed map function and added comment about remove callback group
peterpena Aug 14, 2020
e50a2b9
adding two different data structures for add_node and add_callback_group
peterpena Aug 14, 2020
8a3e30d
nitpick changes to documentation
wjwwood Aug 14, 2020
af3ca5e
move implementation out of header
wjwwood Aug 14, 2020
56da394
use const &
wjwwood Aug 14, 2020
c6353a4
splitting add node and add cbg in static executro
peterpena Aug 17, 2020
546beec
get cbgs for static executor and collector
peterpena Aug 17, 2020
701fe00
add weak nodes for nodes
peterpena Aug 17, 2020
841a209
get next ready executable with two maps
peterpena Aug 18, 2020
b04b1b9
passes tests
peterpena Aug 18, 2020
ec94f7e
Apply suggestions from code review
peterpena Aug 18, 2020
4a9244f
fixed has node function
peterpena Aug 18, 2020
e915c33
fixed collect entities
peterpena Aug 18, 2020
5c75d2e
added unit tests for removal and added 3rd data struct
peterpena Aug 19, 2020
9045be3
eliminated cbs vector
peterpena Aug 19, 2020
c43312e
reusing same functions and added comments
peterpena Aug 20, 2020
da4ea76
documentation, more exceptions, and name changes
peterpena Aug 21, 2020
4657798
Apply suggestions from code review
peterpena Aug 21, 2020
3ab9ad5
fixed deconstructor, first remove cbgs, then nodes
peterpena Aug 21, 2020
ffbae58
Apply suggestions from code review
peterpena Aug 21, 2020
03bc30d
fixed remove node issue
peterpena Aug 21, 2020
9219986
throw an exception in remove node of collector
peterpena Aug 21, 2020
f6c1b53
Update rclcpp/include/rclcpp/executor.hpp
peterpena Aug 21, 2020
c6772f5
Update rclcpp/include/rclcpp/executor.hpp
peterpena Aug 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion rclcpp/include/rclcpp/callback_group.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,44 @@ class CallbackGroup
public:
RCLCPP_SMART_PTR_DEFINITIONS(CallbackGroup)

/// Constructor for CallbackGroup.
/**
* Callback Groups have a type, either 'Mutually Exclusive' or 'Reentrant'
* and when creating one the type must be specified.
*
* Callbacks in Reentrant Callback Groups must be able to:
* - run at the same time as themselves (reentrant)
* - run at the same time as other callbacks in their group
* - run at the same time as other callbacks in other groups
*
* Callbacks in Mutually Exclusive Callback Groups:
* - will not be run multiple times simultaneously (non-reentrant)
* - will not be run at the same time as other callbacks in their group
* - but must run at the same time as callbacks in other groups
*
* Additiionally, callback groups have a property which determines whether or
* not they are added to an executor with their associated node automatically.
* When creating a callback group the automatically_add_to_executor_with_node
* argument determines this behavior, and if true it will cause the newly
* created callback group to be added to an executor with the node when the
* Executor::add_node method is used.
* If false, this callback group will not be added automatically and would
* have to be added to an executor manually using the
* Executor::add_callback_group method.
*
* Whether the node was added to the executor before creating the callback
* group, or after, is irrelevant; the callback group will be automatically
* added to the executor in either case.
*
* \param[in] group_type They type of the callback group.
* \param[in] automatically_add_to_executor_with_node a boolean which
* determines whether a callback group is automatically added to an executor
* with the node with which it is associated.
*/
RCLCPP_PUBLIC
explicit CallbackGroup(CallbackGroupType group_type);
explicit CallbackGroup(
wjwwood marked this conversation as resolved.
Show resolved Hide resolved
CallbackGroupType group_type,
bool automatically_add_to_executor_with_node = true);

template<typename Function>
rclcpp::SubscriptionBase::SharedPtr
Expand Down Expand Up @@ -102,6 +138,31 @@ class CallbackGroup
const CallbackGroupType &
type() const;

/// Return a reference to the 'associated with executor' atomic boolean.
/**
* When a callback group is added to an executor this boolean is checked
* to ensure it has not already been added to another executor.
* If it has not been, then this boolean is set to true to indicate it is
* now associated with an executor.
*
* When the callback group is removed from the executor, this atomic boolean
* is set back to false.
*
* \return the 'associated with executor' atomic boolean
*/
RCLCPP_PUBLIC
peterpena marked this conversation as resolved.
Show resolved Hide resolved
std::atomic_bool &
get_associated_with_executor_atomic();

/// Return true if this callback group should be automatically added to an executor by the node.
/**
* \return boolean true if this callback group should be automatically added
* to an executor when the associated node is added, otherwise false.
*/
RCLCPP_PUBLIC
peterpena marked this conversation as resolved.
Show resolved Hide resolved
bool
automatically_add_to_executor_with_node() const;

protected:
RCLCPP_DISABLE_COPY(CallbackGroup)

Expand Down Expand Up @@ -136,12 +197,14 @@ class CallbackGroup
CallbackGroupType type_;
// Mutex to protect the subsequent vectors of pointers.
mutable std::mutex mutex_;
std::atomic_bool associated_with_executor_;
std::vector<rclcpp::SubscriptionBase::WeakPtr> subscription_ptrs_;
std::vector<rclcpp::TimerBase::WeakPtr> timer_ptrs_;
std::vector<rclcpp::ServiceBase::WeakPtr> service_ptrs_;
std::vector<rclcpp::ClientBase::WeakPtr> client_ptrs_;
std::vector<rclcpp::Waitable::WeakPtr> waitable_ptrs_;
std::atomic_bool can_be_taken_from_;
const bool automatically_add_to_executor_with_node_;

private:
template<typename TypeT, typename Function>
Expand Down
199 changes: 196 additions & 3 deletions rclcpp/include/rclcpp/executor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <cstdlib>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <string>
Expand All @@ -42,6 +43,10 @@
namespace rclcpp
{

typedef std::map<rclcpp::CallbackGroup::WeakPtr,
rclcpp::node_interfaces::NodeBaseInterface::WeakPtr,
std::owner_less<rclcpp::CallbackGroup::WeakPtr>> WeakCallbackGroupsToNodesMap;

// Forward declaration is used in convenience method signature.
class Node;

Expand Down Expand Up @@ -76,13 +81,118 @@ class Executor
virtual void
spin() = 0;

/// Add a callback group to an executor.
/**
* An executor can have zero or more callback groups which provide work during `spin` functions.
* When an executor attempts to add a callback group, the executor checks to see if it is already
* associated with another executor, and if it has been, then an exception is thrown.
* Otherwise, the callback group is added to the executor.
*
* Adding a callback group with this method does not associate its node with this executor
* in any way
*
* \param[in] group_ptr a shared ptr that points to a callback group
peterpena marked this conversation as resolved.
Show resolved Hide resolved
* \param[in] node_ptr a shared pointer that points to a node base interface
* \param[in] notify True to trigger the interrupt guard condition during this function. If
* the executor is blocked at the rmw layer while waiting for work and it is notified that a new
* callback group was added, it will wake up.
* \throw std::runtime_error if the callback group is associated to an executor
*/
RCLCPP_PUBLIC
virtual void
add_callback_group(
rclcpp::CallbackGroup::SharedPtr group_ptr,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
bool notify = true);

peterpena marked this conversation as resolved.
Show resolved Hide resolved
/// Get callback groups that belong to executor.
/**
* This function returns a vector of weak pointers that point to callback groups that were
* associated with the executor.
* The callback groups associated with this executor may have been added with
* `add_callback_group`, or added when a node was added to the executor with `add_node`, or
* automatically added when it created by a node already associated with this executor and the
* automatically_add_to_executor_with_node parameter was true.
*
* \return a vector of weak pointers that point to callback groups that are associated with
* the executor
*/
RCLCPP_PUBLIC
virtual std::vector<rclcpp::CallbackGroup::WeakPtr>
get_all_callback_groups();

/// Get callback groups that belong to executor.
/**
* This function returns a vector of weak pointers that point to callback groups that were
* associated with the executor.
* The callback groups associated with this executor have been added with
* `add_callback_group`.
*
* \return a vector of weak pointers that point to callback groups that are associated with
* the executor
*/
RCLCPP_PUBLIC
virtual std::vector<rclcpp::CallbackGroup::WeakPtr>
get_manually_added_callback_groups();

/// Get callback groups that belong to executor.
/**
* This function returns a vector of weak pointers that point to callback groups that were
* added from a node that is associated with the executor.
* The callback groups are added when a node is added to the executor with `add_node`, or
* automatically if they are created in the future by that node and have the
* automatically_add_to_executor_with_node argument set to true.
*
* \return a vector of weak pointers that point to callback groups from a node associated with
* the executor
*/
RCLCPP_PUBLIC
virtual std::vector<rclcpp::CallbackGroup::WeakPtr>
get_automatically_added_callback_groups_from_nodes();

/// Remove a callback group from the executor.
/**
* The callback group is removed from and disassociated with the executor.
* If the callback group removed was the last callback group from the node
* that is associated with the executor, the interrupt guard condition
* is triggered and node's guard condition is removed from the executor.
*
* This function only removes a callback group that was manually added with
* rclcpp::Executor::add_callback_group.
* To remove callback groups that were added from a node using
* rclcpp::Executor::add_node, use rclcpp::Executor::remove_node instead.
*
* \param[in] group_ptr Shared pointer to the callback group to be added.
peterpena marked this conversation as resolved.
Show resolved Hide resolved
* \param[in] notify True to trigger the interrupt guard condition during this function. If
* the executor is blocked at the rmw layer while waiting for work and it is notified that a
* callback group was removed, it will wake up.
* \throw std::runtime_error if node is deleted before callback group
* \throw std::runtime_error if the callback group is not associated with the executor
*/
peterpena marked this conversation as resolved.
Show resolved Hide resolved
RCLCPP_PUBLIC
virtual void
remove_callback_group(
peterpena marked this conversation as resolved.
Show resolved Hide resolved
rclcpp::CallbackGroup::SharedPtr group_ptr,
bool notify = true);

/// Add a node to the executor.
/**
* An executor can have zero or more nodes which provide work during `spin` functions.
* Nodes have associated callback groups, and this method adds any of those callback groups
* to this executor which have their automatically_add_to_executor_with_node parameter true.
* The node is also associated with the executor so that future callback groups which are
* created on the node with the automatically_add_to_executor_with_node parameter set to true
* are also automatically associated with this executor.
*
* Callback groups with the automatically_add_to_executor_with_node parameter set to false must
* be manually added to an executor using the rclcpp::Executor::add_callback_group method.
*
* If a node is already associated with an executor, this method throws an exception.
peterpena marked this conversation as resolved.
Show resolved Hide resolved
*
* \param[in] node_ptr Shared pointer to the node to be added.
* \param[in] notify True to trigger the interrupt guard condition during this function. If
* the executor is blocked at the rmw layer while waiting for work and it is notified that a new
* node was added, it will wake up.
* \throw std::runtime_error if a node is already associated to an executor
*/
RCLCPP_PUBLIC
virtual void
Expand All @@ -98,10 +208,19 @@ class Executor

/// Remove a node from the executor.
/**
* Any callback groups automatically added when this node was added with
* rclcpp::Executor::add_node are automatically removed, and the node is no longer associated
* with this executor.
*
* This also means that future callback groups created by the given node are no longer
* automatically added to this executor.
*
* \param[in] node_ptr Shared pointer to the node to remove.
* \param[in] notify True to trigger the interrupt guard condition and wake up the executor.
* This is useful if the last node was removed from the executor while the executor was blocked
* waiting for work in another thread, because otherwise the executor would never be notified.
* \throw std::runtime_error if the node is not associated with an executor.
* \throw std::runtime_error if the node is not associated with this executor.
*/
RCLCPP_PUBLIC
virtual void
Expand Down Expand Up @@ -327,22 +446,79 @@ class Executor

RCLCPP_PUBLIC
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
get_node_by_group(rclcpp::CallbackGroup::SharedPtr group);
get_node_by_group(
WeakCallbackGroupsToNodesMap weak_groups_to_nodes,
rclcpp::CallbackGroup::SharedPtr group);

/// Return true if the node has been added to this executor.
/**
* \param[in] node_ptr a shared pointer that points to a node base interface
* \return true if the node is associated with the executor, otherwise false
*/
RCLCPP_PUBLIC
bool
has_node(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
WeakCallbackGroupsToNodesMap weak_groups_to_nodes) const;

RCLCPP_PUBLIC
rclcpp::CallbackGroup::SharedPtr
get_group_by_timer(rclcpp::TimerBase::SharedPtr timer);

/// Add a callback group to an executor
/**
* \see rclcpp::Executor::add_callback_group
*/
RCLCPP_PUBLIC
virtual void
add_callback_group_to_map(
rclcpp::CallbackGroup::SharedPtr group_ptr,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
WeakCallbackGroupsToNodesMap & weak_groups_to_nodes,
bool notify = true);

/// Remove a callback group from the executor.
/**
* \see rclcpp::Executor::remove_callback_group
*/
RCLCPP_PUBLIC
virtual void
remove_callback_group_from_map(
rclcpp::CallbackGroup::SharedPtr group_ptr,
WeakCallbackGroupsToNodesMap & weak_groups_to_nodes,
bool notify = true);

RCLCPP_PUBLIC
bool
get_next_ready_executable(AnyExecutable & any_executable);

RCLCPP_PUBLIC
bool
get_next_ready_executable_from_map(
AnyExecutable & any_executable,
WeakCallbackGroupsToNodesMap weak_groups_to_nodes);

RCLCPP_PUBLIC
bool
get_next_executable(
AnyExecutable & any_executable,
std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));

/// Add all callback groups that can be automatically added from associated nodes.
/**
* The executor, before collecting entities, verifies if any callback group from
* nodes associated with the executor, which is not already associated to an executor,
* can be automatically added to this executor.
* This takes care of any callback group that has been added to a node but not explicitly added
* to the executor.
* It is important to note that in order for the callback groups to be automatically added to an
* executor through this function, the node of the callback groups needs to have been added
* through the `add_node` method.
*/
RCLCPP_PUBLIC
virtual void
add_callback_groups_from_nodes_associated_to_executor();

/// Spinning state, used to prevent multi threaded calls to spin and to cancel blocking spins.
std::atomic_bool spinning;

Expand All @@ -367,8 +543,25 @@ class Executor
void
spin_once_impl(std::chrono::nanoseconds timeout);

typedef std::map<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr,
const rcl_guard_condition_t *,
std::owner_less<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>>
WeakNodesToGuardConditionsMap;

/// maps nodes to guard conditions
WeakNodesToGuardConditionsMap weak_nodes_to_guard_conditions_;

/// maps callback groups associated to nodes
WeakCallbackGroupsToNodesMap weak_groups_associated_with_executor_to_nodes_;

/// maps callback groups to nodes associated with executor
WeakCallbackGroupsToNodesMap weak_groups_to_nodes_associated_with_executor_;

/// maps all callback groups to nodes
WeakCallbackGroupsToNodesMap weak_groups_to_nodes_;

/// nodes that are associated with the executor
std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
std::list<const rcl_guard_condition_t *> guard_conditions_;
};

namespace executor
Expand Down
Loading