由浅到深理解ROS(8)-线程管理
轉(zhuǎn)自
?
?
單線程Spinning
ros::spin()是最簡單的單線程自旋, 它會(huì)一直調(diào)用直到結(jié)束
用法: ?ros::spin();
另一個(gè)單線程spinning是ros::spinOnce(),它定期調(diào)用等待在那個(gè)點(diǎn)上的所有回調(diào)
用法: ?ros::spinOnce();
簡單的我們自己實(shí)現(xiàn)一個(gè)用法相同的ros::spin()
這樣: ?ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0.1));
ros::spinonce
這樣: ?ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0));
以上,是它的基礎(chǔ)用法,那么spin到底做了什么呢?
首先, 當(dāng)我們調(diào)用ros::spin時(shí), 會(huì)有一個(gè)互斥鎖, 把你的回調(diào)隊(duì)列加鎖, 防止執(zhí)行混亂.?
然后, 檢測(cè)如果回調(diào)隊(duì)列不為空, 則讀取回調(diào)隊(duì)列
最后,當(dāng)while(nh.ok())為true時(shí), 調(diào)用當(dāng)前隊(duì)列中的所有函數(shù),如果有不滿足的, 會(huì)重新放回隊(duì)列中
?
所以listener中, 就一直執(zhí)行這ros::spin來監(jiān)聽話題了.從這樣看來,spin和spinOnce的區(qū)別之一,就是while(nh::ok())執(zhí)行塊的大小了. 另一個(gè)是等待時(shí)間, spin在執(zhí)行時(shí), 會(huì)指定一個(gè)返回前可以等待調(diào)用的時(shí)間. spin會(huì)等待0.1s而spinonce不會(huì)
spinOnce使得pub/sub為非阻塞鎖?spin是客戶端的, 因此是阻塞的.
這樣就很好理解talker要用SpinOnce,有需要talk的時(shí)候發(fā)出,沒有的時(shí)候不發(fā)送.而listener一直在阻塞著聽
這樣,再來說之前很流傳的一句關(guān)于解釋spin的話, "所有的回調(diào)函數(shù)都是spin調(diào)用的". 這是一句形象而不準(zhǔn)確的話. 回調(diào)函數(shù)一直等待在回調(diào)隊(duì)列中, 只要條件一滿足就會(huì)發(fā)生回調(diào), 而spin的作用, 只是創(chuàng)建了線程給這個(gè)回調(diào)函數(shù)去執(zhí)行它, 這樣多線程就不會(huì)影響其他的作業(yè).
之所以用spin, 是因?yàn)閞ospy不愿指定線程模型, 在程序中將線程暴露出來, 而用spin來把它封裝起來. 但你可以用多線程調(diào)用任意數(shù)量的回調(diào)函數(shù).
沒有用戶訂閱, 服務(wù)和回調(diào)是不會(huì)被調(diào)用的.
?
?
多線程Spinning
多線程Spinning
roscpp內(nèi)部支持調(diào)用多線程, 有兩個(gè):
ros::MultiThreadedSpinner
ros::MultiThreadedSpinner是阻塞微調(diào), 類似于ros::spin(), 你可以在它的構(gòu)造函數(shù)中指定線程數(shù)量, 但如果不指定或者設(shè)為0, 它會(huì)根據(jù)你的CPU內(nèi)核數(shù)創(chuàng)建線程.
1 ros::MultiThreadedSpinner spinner(4); // Use 4 threads 2 spinner.spin(); // spin() will not return until the node has been shutdownros::AsyncSpinner?(since 0.10)
一個(gè)更有用的線程spinner是AsyncSpinner. 與阻塞的spin()不同, 它有start()和stop()調(diào)用, 并且在銷毀時(shí)自動(dòng)停止
1 ros::AsyncSpinner spinner(4); // Use 4 threads 2 spinner.start(); 3 ros::waitForShutdown();?
?
附官方說明:
?
Single-threaded Spinning
?
The simplest (and most common) version of single-threaded spinning is?ros::spin():?
?
切換行號(hào)顯示
1 ros::init(argc, argv, "my_node");2 ros::NodeHandle nh;3 ros::Subscriber sub = nh.subscribe(...);4 ...5 ros::spin();In this application all user callbacks will be called from within the?ros::spin()?call.?ros::spin()?will not return until the node has been shutdown, either through a call to?ros::shutdown()?or a?Ctrl-C.?
Another common pattern is to call?ros::spinOnce()?periodically:?
?
切換行號(hào)顯示
1 ros::Rate r(10); // 10 hz2 while (should_continue)3 {4 ... do some work, publish some messages, etc. ...5 ros::spinOnce();6 r.sleep();7 }ros::spinOnce()?will call all the callbacks waiting to be called at that point in time.?
Implementing a?spin()?of our own is quite simple:?
?
切換行號(hào)顯示
1 #include <ros/callback_queue.h>2 ros::NodeHandle n;3 while (ros::ok())4 {5 ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0.1));6 }and?spinOnce()?is simply:?
?
切換行號(hào)顯示
1 #include <ros/callback_queue.h>2 3 ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0));Note:?spin()?and?spinOnce()?are really meant forsingle-threaded applications(單線程的), and are not optimized for being called from multiple threads at once. See the multi-threaded spinning section for information on spinning from multiple threads.?
?
Multi-threaded Spinning
roscpp?provides some built-in support for calling callbacks from multiple threads. There are two built-in options for this:?
ros::MultiThreadedSpinner
-
MultiThreadedSpinner?is ablocking spinner(阻塞的), similar to?ros::spin(). You can specify a number of threads in its constructor, but if unspecified (or set to 0), it will use a thread for each CPU core.?
切換行號(hào)顯示 1 ros::MultiThreadedSpinner spinner(4); // Use 4 threads2 spinner.spin(); // spin() will not return until the node has been shutdown3
ros::AsyncSpinner?(since 0.10)
-
AsyncSpinner API (Jade)
- ?
-
A more useful threaded spinner is the?AsyncSpinner(異步的). Instead of a blocking?spin()?call, it has?start()?and?stop()calls, and will automatically stop when it is destroyed. An equivalent use of?AsyncSpinner?to the?MultiThreadedSpinner?example above, is:?
切換行號(hào)顯示 1 ros::AsyncSpinner spinner(4); // Use 4 threads2 spinner.start();3 ros::waitForShutdown();
總結(jié)
以上是生活随笔為你收集整理的由浅到深理解ROS(8)-线程管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一步步编写操作系统 54 CPL和DPL
- 下一篇: 信用卡注销后还可以再申请吗