Executor and Spin Explained
This tutorial is based on ROS2 Humble and the behavior described in this tutorial is subject to change in future releases.
Related Readings
Introduction
In this tutorial, we aim to clarify the difference between spin_once, spin_some, spin_until_future_complete, and spin. However, due to limited official documentation, the accuracy of our explanations and interpretations is not guaranteed. We've include code at the end of the tutorial for you to independently verify the behaviors. Please note, this content is specifically tailored to ROS2 Humble; other version may exhibit different behaviors.
A Few Words on Concurrency
It's highly recommended to read the discussion ROS2: multi nodes, each on a thread in same process.
By default, ROS 2 is thread safe:
Each node's callbacks are called mutually exclusive (i.e. only one callback per node is called at a time, there is no concurrence within a node),
Different nodes' callbacks can be executed concurrently:
If they run in different processes, or
If they are in the same process and spun by a MultiThreadedExecutor, or
If they are in the same process and you use multiple threads each running a SingleThreadedExecutor,
But even in those cases, the active callbacks cannot access another nodes' data, and only one callback per node is being executed, so there are no concurrency issues.
In this tutorial, we will not focus on the callback group.
Experiment Setup
The experimental system consists of
A publisher that simultaneously publishes the same messages to two different topics.
A subscriber that subscribes to these two topics. The callback function is used to simulate the task execution and the execution time can be adjusted via a parameter.
Parameters that control the start-up time of the publisher and subscriber. If the subscriber activates before the publisher, the the executor queue is empty because no messages are published yet. Conversely, if the publisher starts first, the subscriber may see a non-empty queue.
Parameters that control the message publication rate and task execution time. An execution time longer than the publication interval leads to buildup of tasks in the executor queue. Conversely, if the execution time is shorter, the queue gets drained.
Spin Once and Spin Some
spin_once
and spin_some
have similar behaviors. Upon invocation, the executor inspects the work queue. If the queue is empty, the function returns immediately. If tasks are present, spin_once
executes a single task, whereas spin_some
can handle one or more tasks. It's important to note that although new tasks may arrive during execution, the execution will not address them in the current cycle since task collection occurs only once.
Experiment 1
In this experiment, we demonstrate the call returns immediately if there is no work in the queue. We will introduce a delay in starting the publisher. Consequently, when the subscriber is initiated, no messages have been published yet, resulting in an empty work queue.
First, let's launch the system with spin_once
:
ros2 launch bringup spin_once_repeat.launch.py publisher_warmup_time:=10 publication_interval:=1 subscriber_warmup_time:=1 task_running_time:=5
Here is the output of the program:
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [publisher-1]: process started with pid [104870]
[INFO] [spin_once_repeat-2]: process started with pid [104872]
[spin_once_repeat-2] [INFO] [1703721523.286740357] [subscriber-main-thread]: ----- start to create the subscriber node
[spin_once_repeat-2] [INFO] [1703721524.292396398] [subscriber-main-thread]: ----- subscriber node is created
[spin_once_repeat-2] [INFO] [1703721524.292595346] [subscriber-main-thread]: ----- start spin_once
[spin_once_repeat-2] [INFO] [1703721524.292609020] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703721525.292906999] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703721526.293163103] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703721527.293488979] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703721528.293822772] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703721529.294154032] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703721530.294414491] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703721531.294735447] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703721532.294992828] [subscriber-main-thread]: ----- call spin_once
[publisher-1] [INFO] [1703721533.290849977] [task_publisher]: creating publisher and timer
[spin_once_repeat-2] [INFO] [1703721533.295210474] [subscriber-main-thread]: ----- call spin_once
[publisher-1] [INFO] [1703721534.292651668] [task_publisher]: Publishing: 'task 1'
[spin_once_repeat-2] [INFO] [1703721534.295465766] [subscriber-main-thread]: ----- spin_once ends
[INFO] [spin_once_repeat-2]: process has finished cleanly [pid 104872]
[publisher-1] [INFO] [1703721535.292633903] [task_publisher]: Publishing: 'task 2'
[publisher-1] [INFO] [1703721536.292643748] [task_publisher]: Publishing: 'task 3'
[publisher-1] [INFO] [1703721537.292647627] [task_publisher]: Publishing: 'task 4'
[publisher-1] [INFO] [1703721538.292668753] [task_publisher]: Publishing: 'task 5'
The log message confirms that the subscriber is created before the first message is published. Moreover, the spin_once
call returns immediately.
Let's try spin_some
:
ros2 launch bringup spin_some_repeat.launch.py publisher_warmup_time:=10 publication_interval:=1 subscriber_warmup_time:=1 task_running_time:=5
Similar results are produced:
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [publisher-1]: process started with pid [106002]
[INFO] [spin_some_repeat-2]: process started with pid [106004]
[spin_some_repeat-2] [INFO] [1703721861.285776631] [subscriber-main-thread]: ----- start to create the subscriber node
[spin_some_repeat-2] [INFO] [1703721862.291873202] [subscriber-main-thread]: ----- subscriber node is created
[spin_some_repeat-2] [INFO] [1703721862.292095052] [subscriber-main-thread]: ----- start spin_some
[spin_some_repeat-2] [INFO] [1703721862.292110432] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703721863.292420633] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703721864.292675445] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703721865.292924385] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703721866.293178492] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703721867.293437536] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703721868.293725006] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703721869.293870219] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703721870.294132843] [subscriber-main-thread]: ----- call spin_some
[publisher-1] [INFO] [1703721871.288962120] [task_publisher]: creating publisher and timer
[spin_some_repeat-2] [INFO] [1703721871.294388290] [subscriber-main-thread]: ----- call spin_some
[publisher-1] [INFO] [1703721872.290757235] [task_publisher]: Publishing: 'task 1'
[spin_some_repeat-2] [INFO] [1703721872.294619692] [subscriber-main-thread]: ----- spin_some ends
[INFO] [spin_some_repeat-2]: process has finished cleanly [pid 106004]
[publisher-1] [INFO] [1703721873.290692259] [task_publisher]: Publishing: 'task 2'
[publisher-1] [INFO] [1703721874.290768198] [task_publisher]: Publishing: 'task 3'
Experiment 2
In this experiment, we demonstrate the difference between spin_once
and spin_some
. Specifically, spin_once
only processes a single task in the queue while spin_some
can handle multiple tasks. To illustrate this, we start the publisher before the subscribing, ensuring that by the time the subscriber is initiated, messages have already been published to the topics. Additionally, the message publication rate is set to be slower than the rate at which tasks can be competed.
Let's start with spin_once
:
ros2 launch bringup spin_once_repeat.launch.py publisher_warmup_time:=1 publication_interval:=3 subscriber_warmup_time:=10 task_running_time:=1
As we can see in the output below, between two calls of spin_once
, at most one callback is executed:
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [publisher-1]: process started with pid [106255]
[INFO] [spin_once_repeat-2]: process started with pid [106257]
[spin_once_repeat-2] [INFO] [1703722264.902515185] [subscriber-main-thread]: ----- start to create the subscriber node
[publisher-1] [INFO] [1703722265.906442638] [task_publisher]: creating publisher and timer
[publisher-1] [INFO] [1703722268.908613701] [task_publisher]: Publishing: 'task 1'
[publisher-1] [INFO] [1703722271.908610507] [task_publisher]: Publishing: 'task 2'
[spin_once_repeat-2] [INFO] [1703722274.906863820] [subscriber-main-thread]: ----- subscriber node is created
[spin_once_repeat-2] [INFO] [1703722274.907071708] [subscriber-main-thread]: ----- start spin_once
[spin_once_repeat-2] [INFO] [1703722274.907087350] [subscriber-main-thread]: ----- call spin_once
[publisher-1] [INFO] [1703722274.908598651] [task_publisher]: Publishing: 'task 3'
[spin_once_repeat-2] [INFO] [1703722275.907374781] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703722276.907591243] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703722276.907733630] [task_subscriber]: start the task task 3
[spin_once_repeat-2] [INFO] [1703722277.907985576] [task_subscriber]: task is complete task 3
[publisher-1] [INFO] [1703722277.908628763] [task_publisher]: Publishing: 'task 4'
[spin_once_repeat-2] [INFO] [1703722278.908218273] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703722278.908302400] [task_subscriber]: start the task task 3
[spin_once_repeat-2] [INFO] [1703722279.908425731] [task_subscriber]: task is complete task 3
[publisher-1] [INFO] [1703722280.908625705] [task_publisher]: Publishing: 'task 5'
[spin_once_repeat-2] [INFO] [1703722280.908680301] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703722281.908934264] [subscriber-main-thread]: ----- call spin_once
[spin_once_repeat-2] [INFO] [1703722281.909057961] [task_subscriber]: start the task task 4
[spin_once_repeat-2] [INFO] [1703722282.909210972] [task_subscriber]: task is complete task 4
[publisher-1] [INFO] [1703722283.908633067] [task_publisher]: Publishing: 'task 6'
Now let's check the behavior of spin_some
:
ros2 launch bringup spin_some_repeat.launch.py publisher_warmup_time:=1 publication_interval:=3 subscriber_warmup_time:=10 task_running_time:=1
Here is the output:
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [publisher-1]: process started with pid [106414]
[INFO] [spin_some_repeat-2]: process started with pid [106416]
[spin_some_repeat-2] [INFO] [1703722411.352279678] [subscriber-main-thread]: ----- start to create the subscriber node
[publisher-1] [INFO] [1703722412.355485901] [task_publisher]: creating publisher and timer
[publisher-1] [INFO] [1703722415.357177825] [task_publisher]: Publishing: 'task 1'
[publisher-1] [INFO] [1703722418.357209205] [task_publisher]: Publishing: 'task 2'
[spin_some_repeat-2] [INFO] [1703722421.357183365] [subscriber-main-thread]: ----- subscriber node is created
[publisher-1] [INFO] [1703722421.357189710] [task_publisher]: Publishing: 'task 3'
[spin_some_repeat-2] [INFO] [1703722421.357378437] [subscriber-main-thread]: ----- start spin_some
[spin_some_repeat-2] [INFO] [1703722421.357391962] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703722422.357763617] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703722422.357974239] [task_subscriber]: start the task task 3
[spin_some_repeat-2] [INFO] [1703722423.358207789] [task_subscriber]: task is complete task 3
[spin_some_repeat-2] [INFO] [1703722423.358434326] [task_subscriber]: start the task task 3
[publisher-1] [INFO] [1703722424.357224667] [task_publisher]: Publishing: 'task 4'
[spin_some_repeat-2] [INFO] [1703722424.358609446] [task_subscriber]: task is complete task 3
[spin_some_repeat-2] [INFO] [1703722425.358905006] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703722425.359112045] [task_subscriber]: start the task task 4
[spin_some_repeat-2] [INFO] [1703722426.359259373] [task_subscriber]: task is complete task 4
[spin_some_repeat-2] [INFO] [1703722426.359453598] [task_subscriber]: start the task task 4
Let's examine the log more closely. The snippet below shows that between two spin_some
calls, two task 3 are executed. This is expected since the same message is published to two topics. This shows spin_some
can execute multiple tasks.
Interestingly, despite using a multi-thread executor, the two tasks are executed sequentially. This behavior suggests that the system operates as though only a single thread is allocated to the node.
We also notice that the interval between the two spin_some
call is approximately 2 seconds, aligning with the combined execution time of two tasks, where each takes about 1 second. This observation highlights the "blocking" nature of the spin_some
method.
[spin_some_repeat-2] [INFO] [1703722422.357763617] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703722422.357974239] [task_subscriber]: start the task task 3
[spin_some_repeat-2] [INFO] [1703722423.358207789] [task_subscriber]: task is complete task 3
[spin_some_repeat-2] [INFO] [1703722423.358434326] [task_subscriber]: start the task task 3
[publisher-1] [INFO] [1703722424.357224667] [task_publisher]: Publishing: 'task 4'
[spin_some_repeat-2] [INFO] [1703722424.358609446] [task_subscriber]: task is complete task 3
[spin_some_repeat-2] [INFO] [1703722425.358905006] [subscriber-main-thread]: ----- call spin_some
Experiment 3
This experiment, focused on spin_some
, demonstrates that the executor collects work only once per spin_some
call. We configure tasks to run for 3 seconds and publish messages every 1 second. Given that work arrives faster than it can be processed, we will see accumulation of tasks in the queue.
Launch the system using the following command:
ros2 launch bringup spin_some_repeat.launch.py publisher_warmup_time:=1 publication_interval:=1 subscriber_warmup_time:=10 task_running_time:=3
It produces the following outputs: (the key is that there are multiple call spin_some
messages)
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [publisher-1]: process started with pid [107142]
[INFO] [spin_some_repeat-2]: process started with pid [107144]
[spin_some_repeat-2] [INFO] [1703723176.275294226] [subscriber-main-thread]: ----- start to create the subscriber node
[publisher-1] [INFO] [1703723177.279028661] [task_publisher]: creating publisher and timer
[publisher-1] [INFO] [1703723178.280777602] [task_publisher]: Publishing: 'task 1'
[publisher-1] [INFO] [1703723179.280792555] [task_publisher]: Publishing: 'task 2'
[publisher-1] [INFO] [1703723180.280780229] [task_publisher]: Publishing: 'task 3'
[publisher-1] [INFO] [1703723181.280840609] [task_publisher]: Publishing: 'task 4'
[publisher-1] [INFO] [1703723182.280792853] [task_publisher]: Publishing: 'task 5'
[publisher-1] [INFO] [1703723183.280864991] [task_publisher]: Publishing: 'task 6'
[publisher-1] [INFO] [1703723184.280812151] [task_publisher]: Publishing: 'task 7'
[publisher-1] [INFO] [1703723185.280807081] [task_publisher]: Publishing: 'task 8'
[spin_some_repeat-2] [INFO] [1703723186.280558357] [subscriber-main-thread]: ----- subscriber node is created
[spin_some_repeat-2] [INFO] [1703723186.280754425] [subscriber-main-thread]: ----- start spin_some
[spin_some_repeat-2] [INFO] [1703723186.280769249] [subscriber-main-thread]: ----- call spin_some
[publisher-1] [INFO] [1703723186.280767472] [task_publisher]: Publishing: 'task 9'
[publisher-1] [INFO] [1703723187.280827878] [task_publisher]: Publishing: 'task 10'
[spin_some_repeat-2] [INFO] [1703723187.281134662] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703723187.281333990] [task_subscriber]: start the task task 9
[publisher-1] [INFO] [1703723188.280855246] [task_publisher]: Publishing: 'task 11'
[publisher-1] [INFO] [1703723189.280850277] [task_publisher]: Publishing: 'task 12'
[publisher-1] [INFO] [1703723190.280844620] [task_publisher]: Publishing: 'task 13'
[spin_some_repeat-2] [INFO] [1703723190.281558348] [task_subscriber]: task is complete task 9
[spin_some_repeat-2] [INFO] [1703723190.281732216] [task_subscriber]: start the task task 11
[publisher-1] [INFO] [1703723191.280854109] [task_publisher]: Publishing: 'task 14'
[publisher-1] [INFO] [1703723192.280859971] [task_publisher]: Publishing: 'task 15'
[publisher-1] [INFO] [1703723193.280857388] [task_publisher]: Publishing: 'task 16'
[spin_some_repeat-2] [INFO] [1703723193.281838492] [task_subscriber]: task is complete task 11
[publisher-1] [INFO] [1703723194.280880210] [task_publisher]: Publishing: 'task 17'
[spin_some_repeat-2] [INFO] [1703723194.282059193] [subscriber-main-thread]: ----- call spin_some
[spin_some_repeat-2] [INFO] [1703723194.282234788] [task_subscriber]: start the task task 15
Spin Until Future is Complete
In the previous section, we observed that both spin_once
and spin_some
methods return either when the queue is empty or after the collected work is done. In particular, experiment 3 shows that spin_some
returns even when there is more work in the queue. You may wonder how can we keep the executor continuously working on new tasks in the queue?
One approach involves manually wrapping the spin_once
and spin_some
methods within a loop. Alternatively, you can use the built-in methods spin_until_future_complete
or spin
. The difference between spin_until_future_complete
and spin
methods is that the "focus time" is bounded by the future argument in spin_until_future_complete
whereas the "focus time" is unbounded in spin
.
Experiment 4
In this experiment, we run a long-running task in a future and pass it to the spin_until_future_complete
method. Due to a pending issue, additional setup is required to wake up the executor, allowing the executor to exit from the spin_until_future_complete
method.
To launch the experiment, use the command below:
ros2 launch bringup spin_until_future_complete.launch.py publisher_warmup_time:=1 publication_interval:=2 subscriber_warmup_time:=5 task_running_time:=1
The output of the program is presented as follows:
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [publisher-1]: process started with pid [112108]
[INFO] [spin_until_future_complete-2]: process started with pid [112110]
[spin_until_future_complete-2] [INFO] [1703727953.315024507] [subscriber-main-thread]: ----- start to create the subscriber node
[publisher-1] [INFO] [1703727954.318600781] [task_publisher]: creating publisher and timer
[publisher-1] [INFO] [1703727956.320320568] [task_publisher]: Publishing: 'task 1'
[spin_until_future_complete-2] [INFO] [1703727958.320232632] [subscriber-main-thread]: ----- subscriber node is created
[publisher-1] [INFO] [1703727958.320275752] [task_publisher]: Publishing: 'task 2'
[spin_until_future_complete-2] [INFO] [1703727958.320647246] [subscriber-main-thread]: ----- start spin_some
[spin_until_future_complete-2] [INFO] [1703727958.320657151] [subscriber-main-thread]: doing some work [0]
[spin_until_future_complete-2] [INFO] [1703727958.320914234] [task_subscriber]: start the task task 2
[spin_until_future_complete-2] [INFO] [1703727959.321089551] [task_subscriber]: task is complete task 2
[spin_until_future_complete-2] [INFO] [1703727959.321303642] [task_subscriber]: start the task task 2
[publisher-1] [INFO] [1703727960.320299603] [task_publisher]: Publishing: 'task 3'
[spin_until_future_complete-2] [INFO] [1703727960.321402142] [task_subscriber]: task is complete task 2
[spin_until_future_complete-2] [INFO] [1703727960.321625114] [task_subscriber]: start the task task 3
[spin_until_future_complete-2] [INFO] [1703727961.321797323] [task_subscriber]: task is complete task 3
[spin_until_future_complete-2] [INFO] [1703727961.321989861] [task_subscriber]: start the task task 3
[publisher-1] [INFO] [1703727962.320294331] [task_publisher]: Publishing: 'task 4'
[spin_until_future_complete-2] [INFO] [1703727962.322159138] [task_subscriber]: task is complete task 3
[spin_until_future_complete-2] [INFO] [1703727962.322412436] [task_subscriber]: start the task task 4
[spin_until_future_complete-2] [INFO] [1703727963.320893505] [subscriber-main-thread]: doing some work [1]
[spin_until_future_complete-2] [INFO] [1703727963.322512534] [task_subscriber]: task is complete task 4
[spin_until_future_complete-2] [INFO] [1703727963.322717466] [task_subscriber]: start the task task 4
[publisher-1] [INFO] [1703727964.320283152] [task_publisher]: Publishing: 'task 5'
[spin_until_future_complete-2] [INFO] [1703727964.322817282] [task_subscriber]: task is complete task 4
[spin_until_future_complete-2] [INFO] [1703727964.323053314] [task_subscriber]: start the task task 5
[spin_until_future_complete-2] [INFO] [1703727965.323226421] [task_subscriber]: task is complete task 5
[spin_until_future_complete-2] [INFO] [1703727965.323427751] [task_subscriber]: start the task task 5
[publisher-1] [INFO] [1703727966.320294448] [task_publisher]: Publishing: 'task 6'
[spin_until_future_complete-2] [INFO] [1703727966.323529903] [task_subscriber]: task is complete task 5
[spin_until_future_complete-2] [INFO] [1703727966.323760117] [task_subscriber]: start the task task 6
[spin_until_future_complete-2] [INFO] [1703727967.323863154] [task_subscriber]: task is complete task 6
[spin_until_future_complete-2] [INFO] [1703727967.324076546] [task_subscriber]: start the task task 6
[publisher-1] [INFO] [1703727968.320294840] [task_publisher]: Publishing: 'task 7'
[spin_until_future_complete-2] [INFO] [1703727968.321037042] [subscriber-main-thread]: doing some work [2]
[spin_until_future_complete-2] [INFO] [1703727968.324188134] [task_subscriber]: task is complete task 6
[spin_until_future_complete-2] [INFO] [1703727968.324408263] [task_subscriber]: start the task task 7
[spin_until_future_complete-2] [INFO] [1703727969.324533568] [task_subscriber]: task is complete task 7
[spin_until_future_complete-2] [INFO] [1703727969.324728485] [task_subscriber]: start the task task 7
[publisher-1] [INFO] [1703727970.320293347] [task_publisher]: Publishing: 'task 8'
[spin_until_future_complete-2] [INFO] [1703727970.324830376] [task_subscriber]: task is complete task 7
[spin_until_future_complete-2] [INFO] [1703727970.325058938] [task_subscriber]: start the task task 8
[spin_until_future_complete-2] [INFO] [1703727971.325161432] [task_subscriber]: task is complete task 8
[spin_until_future_complete-2] [INFO] [1703727971.325351216] [task_subscriber]: start the task task 8
[publisher-1] [INFO] [1703727972.320277252] [task_publisher]: Publishing: 'task 9'
[spin_until_future_complete-2] [INFO] [1703727972.325452600] [task_subscriber]: task is complete task 8
[spin_until_future_complete-2] [INFO] [1703727972.325691728] [task_subscriber]: start the task task 9
[spin_until_future_complete-2] [INFO] [1703727973.321177505] [subscriber-main-thread]: ----- !!! ----- all the side word is done.
[spin_until_future_complete-2] [INFO] [1703727973.325863001] [task_subscriber]: task is complete task 9
[spin_until_future_complete-2] [INFO] [1703727973.326011324] [subscriber-main-thread]: ----- spin_some ends
[INFO] [spin_until_future_complete-2]: process has finished cleanly [pid 112110]
[publisher-1] [INFO] [1703727974.320284937] [task_publisher]: Publishing: 'task 10'
[publisher-1] [INFO] [1703727976.320347662] [task_publisher]: Publishing: 'task 11'
The key part in the output is highlighted in the section below:
[spin_until_future_complete-2] [INFO] [1703727972.325452600] [task_subscriber]: task is complete task 8
[spin_until_future_complete-2] [INFO] [1703727972.325691728] [task_subscriber]: start the task task 9
[spin_until_future_complete-2] [INFO] [1703727973.321177505] [subscriber-main-thread]: ----- !!! ----- all the side word is done.
[spin_until_future_complete-2] [INFO] [1703727973.325863001] [task_subscriber]: task is complete task 9
[spin_until_future_complete-2] [INFO] [1703727973.326011324] [subscriber-main-thread]: ----- spin_some ends
It shows that the spin_until_future_complete
exits when the work in the future is done.
Spin
spin
is the most common one among these variants. According to the code comments, it does work periodically as it becomes available to the executor. It's a blocking call and may block indefinitely. Unlike other method, the spin
method does not return when the work queue is empty. It always waits for additional tasks.
Download Code
The code is available for download at this link.
©2023 - 2024 all rights reserved
Last updated