def shutdown(self, timeout_sec: float = None) -> bool: """ Stop executing callbacks and wait for their completion. :param timeout_sec: Seconds to wait. Block forever if ``None`` or negative. Don't wait if 0. :return: ``True`` if all outstanding callbacks finished executing, or ``False`` if the timeot expires before all outstanding work is done. """ with self._shutdown_lock: if not self._is_shutdown: self._is_shutdown = True # Tell executor it's been shut down _rclpy.rclpy_trigger_guard_condition(self._guard_condition) if not self._work_tracker.wait(timeout_sec): return False # Clean up stuff that won't be used anymore with self._nodes_lock: self._nodes = set() with self._shutdown_lock: if self._guard_condition: _rclpy.rclpy_destroy_entity(self._guard_condition) self._guard_condition = None if self._sigint_gc: self._sigint_gc.destroy() self._sigint_gc = None self._cb_iter = None self._last_args = None self._last_kwargs = None return True
def test_waitable_with_guard_condition(self): self.waitable = GuardConditionWaitable(self.node) self.node.add_waitable(self.waitable) thr = self.start_spin_thread(self.waitable) _rclpy.rclpy_trigger_guard_condition(self.waitable.guard_condition) thr.join() assert self.waitable.future.done() assert self.waitable.future.result()['guard_condition']
def remove_node(self, node): """Stop managing this node's callbacks.""" with self._nodes_lock: try: self._nodes.remove(node) except KeyError: pass else: # Rebuild the wait set so it doesn't include this node _rclpy.rclpy_trigger_guard_condition(self._guard_condition)
def add_node(self, node): """ Add a node whose callbacks should be managed by this executor. Return true if the node was added. :rtype: bool """ with self._nodes_lock: self._nodes.add(node) # Rebuild the wait set so it includes this new node _rclpy.rclpy_trigger_guard_condition(self._guard_condition)
def remove_node(self, node: 'Node') -> None: """ Stop managing this node's callbacks. :param node: The node to remove from the executor. """ with self._nodes_lock: try: self._nodes.remove(node) except KeyError: pass else: # Rebuild the wait set so it doesn't include this node _rclpy.rclpy_trigger_guard_condition(self._guard_condition)
def add_node(self, node: 'Node') -> bool: """ Add a node whose callbacks should be managed by this executor. :param node: The node to add to the executor. :return: ``True`` if the node was added, ``False`` otherwise. """ with self._nodes_lock: if node not in self._nodes: self._nodes.add(node) node.executor = self # Rebuild the wait set so it includes this new node _rclpy.rclpy_trigger_guard_condition(self._guard_condition) return True return False
def create_task(self, callback: Union[Callable, Coroutine], *args, **kwargs) -> Task: """ Add a callback or coroutine to be executed during :meth:`spin` and return a Future. Arguments to this function are passed to the callback. :param callback: A callback to be run in the executor. """ task = Task(callback, args, kwargs, executor=self) with self._tasks_lock: self._tasks.append((task, None, None)) _rclpy.rclpy_trigger_guard_condition(self._guard_condition) # Task inherits from Future return task
async def handler(entity, gc, is_shutdown, work_tracker): if is_shutdown or not entity.callback_group.beginning_execution(entity): # Didn't get the callback, or the executor has been ordered to stop entity._executor_event = False _rclpy.rclpy_trigger_guard_condition(gc) return with work_tracker: arg = take_from_wait_list(entity) # Signal that this has been 'taken' and can be added back to the wait list entity._executor_event = False _rclpy.rclpy_trigger_guard_condition(gc) try: await call_coroutine(entity, arg) finally: entity.callback_group.ending_execution(entity) # Signal that work has been done so the next callback in a mutually exclusive # callback group can get executed _rclpy.rclpy_trigger_guard_condition(gc)
def trigger(self): _rclpy.rclpy_trigger_guard_condition(self.guard_handle)
def trigger(self): with self.handle as capsule: _rclpy.rclpy_trigger_guard_condition(capsule)