From e4fa7990905486514cd163c7776aae5e9d1b1c4e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 19 Aug 2019 16:16:57 +0200 Subject: [PATCH] Use dummy guardcond to block on empty waitset Cyclone DDS always returns immediately from ``dds_waitset_wait`` when there are no entities in the waitset, but the rcl timer test implies that the expectation is that blocks. By adding a guard condition that is never triggered this expectation is met. Signed-off-by: Erik Boasson --- rmw_cyclonedds_cpp/src/rmw_node.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/rmw_cyclonedds_cpp/src/rmw_node.cpp b/rmw_cyclonedds_cpp/src/rmw_node.cpp index ed0ad6d..0ad4bb2 100644 --- a/rmw_cyclonedds_cpp/src/rmw_node.cpp +++ b/rmw_cyclonedds_cpp/src/rmw_node.cpp @@ -161,6 +161,11 @@ struct Cdds dds_entity_t ppant; dds_entity_t builtin_readers[sizeof(builtin_topics) / sizeof(builtin_topics[0])]; + /* special guard condition that gets attached to every waitset but that is never triggered: + this way, we can avoid Cyclone's behaviour of always returning immediately when no + entities are attached to a waitset */ + dds_entity_t gc_for_empty_waitset; + /* set of waitsets protected by lock, used to invalidate all waitsets caches when an entity is deleted */ std::unordered_set waitsets; @@ -326,6 +331,13 @@ static dds_entity_t ref_ppant() return gcdds.ppant; } + if ((gcdds.gc_for_empty_waitset = dds_create_guardcondition(gcdds.ppant)) < 0) { + RMW_SET_ERROR_MSG("failed to create guardcondition for handling empty waitsets"); + dds_delete(gcdds.ppant); + gcdds.ppant = 0; + return 0; + } + static_assert(sizeof(gcdds.builtin_readers) / sizeof(gcdds.builtin_readers[0]) == sizeof(builtin_topics) / sizeof(builtin_topics[0]), "mismatch between array of built-in topics and array of built-in readers"); @@ -1392,12 +1404,20 @@ extern "C" rmw_wait_set_t * rmw_create_wait_set(rmw_context_t * context, size_t RMW_SET_ERROR_MSG("failed to create waitset"); goto fail_waitset; } + // Attach never-triggered guard condition. As it will never be triggered, it will never be + // included in the result of dds_waitset_wait + if (dds_waitset_attach(ws->waitseth, gcdds.gc_for_empty_waitset, INTPTR_MAX) < 0) { + RMW_SET_ERROR_MSG("failed to attach dummy guard condition for blocking on empty waitset"); + goto fail_attach_dummy; + } { std::lock_guard lock(gcdds.lock); gcdds.waitsets.insert(ws); } return wait_set; +fail_attach_dummy: + dds_delete(ws->waitseth); fail_waitset: unref_ppant(); fail_ws: