Skip to content

Commit 34c59bf

Browse files
committed
add: wait for clients, servers
Signed-off-by: Minju, Lee <[email protected]>
1 parent 408c58d commit 34c59bf

File tree

3 files changed

+196
-0
lines changed

3 files changed

+196
-0
lines changed

rcl/include/rcl/graph.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,80 @@ rcl_wait_for_subscribers(
775775
rcutils_duration_value_t timeout,
776776
bool * success);
777777

778+
/// Wait for there to be a specified number of clients on a given service.
779+
/**
780+
* \see rcl_wait_for_publishers
781+
*
782+
* <hr>
783+
* Attribute | Adherence
784+
* ------------------ | -------------
785+
* Allocates Memory | Yes
786+
* Thread-Safe | No
787+
* Uses Atomics | No
788+
* Lock-Free | Maybe [1]
789+
* <i>[1] implementation may need to protect the data structure with a lock</i>
790+
*
791+
* \param[in] node the handle to the node being used to query the ROS graph
792+
* \param[in] allocator to allocate space for the rcl_wait_set_t used to wait for graph events
793+
* \param[in] service_name the name of the topic in question
794+
* \param[in] count number of clients to wait for
795+
* \param[in] timeout maximum duration to wait for clients
796+
* \param[out] success `true` if the number of clients is equal to or greater than count, or
797+
* `false` if a timeout occurred waiting for clients.
798+
* \return #RCL_RET_OK if there was no errors, or
799+
* \return #RCL_RET_NODE_INVALID if the node is invalid, or
800+
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
801+
* \return #RCL_RET_TIMEOUT if a timeout occurs before the number of clients is detected, or
802+
* \return #RCL_RET_ERROR if an unspecified error occurred.
803+
*/
804+
RCL_PUBLIC
805+
RCL_WARN_UNUSED
806+
rcl_ret_t
807+
rcl_wait_for_clients(
808+
const rcl_node_t * node,
809+
rcl_allocator_t * allocator,
810+
const char * service_name,
811+
const size_t count,
812+
rcutils_duration_value_t timeout,
813+
bool * success);
814+
815+
/// Wait for there to be a specified number of servers on a given service.
816+
/**
817+
* \see rcl_wait_for_publishers
818+
*
819+
* <hr>
820+
* Attribute | Adherence
821+
* ------------------ | -------------
822+
* Allocates Memory | Yes
823+
* Thread-Safe | No
824+
* Uses Atomics | No
825+
* Lock-Free | Maybe [1]
826+
* <i>[1] implementation may need to protect the data structure with a lock</i>
827+
*
828+
* \param[in] node the handle to the node being used to query the ROS graph
829+
* \param[in] allocator to allocate space for the rcl_wait_set_t used to wait for graph events
830+
* \param[in] service_name the name of the topic in question
831+
* \param[in] count number of servers to wait for
832+
* \param[in] timeout maximum duration to wait for servers
833+
* \param[out] success `true` if the number of servers is equal to or greater than count, or
834+
* `false` if a timeout occurred waiting for servers.
835+
* \return #RCL_RET_OK if there was no errors, or
836+
* \return #RCL_RET_NODE_INVALID if the node is invalid, or
837+
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
838+
* \return #RCL_RET_TIMEOUT if a timeout occurs before the number of servers is detected, or
839+
* \return #RCL_RET_ERROR if an unspecified error occurred.
840+
*/
841+
RCL_PUBLIC
842+
RCL_WARN_UNUSED
843+
rcl_ret_t
844+
rcl_wait_for_services(
845+
const rcl_node_t * node,
846+
rcl_allocator_t * allocator,
847+
const char * service_name,
848+
const size_t count,
849+
rcutils_duration_value_t timeout,
850+
bool * success);
851+
778852
/// Return a list of all publishers to a topic.
779853
/**
780854
* The `node` parameter must point to a valid node.

rcl/src/rcl/graph.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,44 @@ rcl_wait_for_subscribers(
667667
rcl_count_subscribers);
668668
}
669669

670+
rcl_ret_t
671+
rcl_wait_for_clients(
672+
const rcl_node_t * node,
673+
rcl_allocator_t * allocator,
674+
const char * service_name,
675+
const size_t expected_count,
676+
rcutils_duration_value_t timeout,
677+
bool * success)
678+
{
679+
return _rcl_wait_for_entities(
680+
node,
681+
allocator,
682+
service_name,
683+
expected_count,
684+
timeout,
685+
success,
686+
rcl_count_clients);
687+
}
688+
689+
rcl_ret_t
690+
rcl_wait_for_services(
691+
const rcl_node_t * node,
692+
rcl_allocator_t * allocator,
693+
const char * service_name,
694+
const size_t expected_count,
695+
rcutils_duration_value_t timeout,
696+
bool * success)
697+
{
698+
return _rcl_wait_for_entities(
699+
node,
700+
allocator,
701+
service_name,
702+
expected_count,
703+
timeout,
704+
success,
705+
rcl_count_services);
706+
}
707+
670708
typedef rmw_ret_t (* get_topic_endpoint_info_func_t)(
671709
const rmw_node_t * node,
672710
rcutils_allocator_t * allocator,

rcl/test/rcl/test_graph.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,90 @@ TEST_F(TestGraphFixture, test_rcl_wait_for_subscribers) {
834834
rcl_reset_error();
835835
}
836836

837+
/* Test the rcl_wait_for_clients function.
838+
*/
839+
TEST_F(TestGraphFixture, test_rcl_wait_for_clients) {
840+
rcl_ret_t ret;
841+
rcl_node_t zero_node = rcl_get_zero_initialized_node();
842+
rcl_allocator_t zero_allocator = static_cast<rcl_allocator_t>(
843+
rcutils_get_zero_initialized_allocator());
844+
rcl_allocator_t allocator = rcl_get_default_allocator();
845+
const char * service_name = "/topic_test_rcl_wait_for_clients";
846+
bool success = false;
847+
848+
// Invalid node
849+
ret = rcl_wait_for_clients(nullptr, &allocator, service_name, 1u, 100, &success);
850+
EXPECT_EQ(RCL_RET_NODE_INVALID, ret);
851+
rcl_reset_error();
852+
ret = rcl_wait_for_clients(&zero_node, &allocator, service_name, 1u, 100, &success);
853+
EXPECT_EQ(RCL_RET_NODE_INVALID, ret);
854+
rcl_reset_error();
855+
ret = rcl_wait_for_clients(this->old_node_ptr, &allocator, service_name, 1u, 100, &success);
856+
EXPECT_EQ(RCL_RET_NODE_INVALID, ret) << rcl_get_error_string().str;
857+
rcl_reset_error();
858+
// Invalid allocator
859+
ret = rcl_wait_for_clients(this->node_ptr, nullptr, service_name, 1u, 100, &success);
860+
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str;
861+
rcl_reset_error();
862+
ret = rcl_wait_for_clients(this->node_ptr, &zero_allocator, service_name, 1u, 100, &success);
863+
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str;
864+
rcl_reset_error();
865+
// Invalid topic name
866+
ret = rcl_wait_for_clients(this->node_ptr, &allocator, nullptr, 1u, 100, &success);
867+
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str;
868+
rcl_reset_error();
869+
// Invalid output arg
870+
ret = rcl_wait_for_clients(this->node_ptr, &allocator, service_name, 1u, 100, nullptr);
871+
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str;
872+
rcl_reset_error();
873+
// Valid call (expect timeout since there are no clients)
874+
ret = rcl_wait_for_clients(this->node_ptr, &allocator, service_name, 1u, 100, &success);
875+
EXPECT_EQ(RCL_RET_TIMEOUT, ret) << rcl_get_error_string().str;
876+
rcl_reset_error();
877+
}
878+
879+
/* Test the rcl_wait_for_clients function.
880+
*/
881+
TEST_F(TestGraphFixture, test_rcl_wait_for_services) {
882+
rcl_ret_t ret;
883+
rcl_node_t zero_node = rcl_get_zero_initialized_node();
884+
rcl_allocator_t zero_allocator = static_cast<rcl_allocator_t>(
885+
rcutils_get_zero_initialized_allocator());
886+
rcl_allocator_t allocator = rcl_get_default_allocator();
887+
const char * service_name = "/topic_test_rcl_wait_for_services";
888+
bool success = false;
889+
890+
// Invalid node
891+
ret = rcl_wait_for_services(nullptr, &allocator, service_name, 1u, 100, &success);
892+
EXPECT_EQ(RCL_RET_NODE_INVALID, ret);
893+
rcl_reset_error();
894+
ret = rcl_wait_for_services(&zero_node, &allocator, service_name, 1u, 100, &success);
895+
EXPECT_EQ(RCL_RET_NODE_INVALID, ret);
896+
rcl_reset_error();
897+
ret = rcl_wait_for_services(this->old_node_ptr, &allocator, service_name, 1u, 100, &success);
898+
EXPECT_EQ(RCL_RET_NODE_INVALID, ret) << rcl_get_error_string().str;
899+
rcl_reset_error();
900+
// Invalid allocator
901+
ret = rcl_wait_for_services(this->node_ptr, nullptr, service_name, 1u, 100, &success);
902+
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str;
903+
rcl_reset_error();
904+
ret = rcl_wait_for_services(this->node_ptr, &zero_allocator, service_name, 1u, 100, &success);
905+
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str;
906+
rcl_reset_error();
907+
// Invalid topic name
908+
ret = rcl_wait_for_services(this->node_ptr, &allocator, nullptr, 1u, 100, &success);
909+
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str;
910+
rcl_reset_error();
911+
// Invalid output arg
912+
ret = rcl_wait_for_services(this->node_ptr, &allocator, service_name, 1u, 100, nullptr);
913+
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str;
914+
rcl_reset_error();
915+
// Valid call (expect timeout since there are no servers)
916+
ret = rcl_wait_for_services(this->node_ptr, &allocator, service_name, 1u, 100, &success);
917+
EXPECT_EQ(RCL_RET_TIMEOUT, ret) << rcl_get_error_string().str;
918+
rcl_reset_error();
919+
}
920+
837921
void
838922
check_entity_count(
839923
const rcl_node_t * node_ptr,

0 commit comments

Comments
 (0)