回调函数队列
首先, 通过ros::init()
函数会创建一个回调函数队列, 即g_global_queue
, 而该队列会在spin函数和spinOnce函数中被轮询检测是否需要有消息到达, 有回调函数需要执行, 回调函数的定义的数据类型为 struct CallbackInfo
。
Subcribe函数和Advitise函数会将回调添加到队列中
该队列会将nodeHandle下的回调函数, 以及NodeHandle::subscribe()/NodeHandle::advertise()的回调函数添加到回调函数队列当中。
例如,在subcribe_options.h头文件的实现, 将helper函数添加到队列当中。
bool was_full = false;
info->subscription_queue_->push(info->helper_, des, info->has_tracked_object_, info->tracked_object_, true, latch_info.receipt_time, &was_full);
if (!was_full)
{
info->callback_queue_->addCallback(info->subscription_queue_, (uint64_t)info.get());
} // info的数据类型为struct CallbackInfo
回调函数如何被调用
回调函数本质上,都在是spin()
或者spinOnce()
函数内通过函数callOneCB(TLS* tls)
来实现, 该函数是一种单线程的实现,内部添加了对应的线程锁, 然后通过BOOST_SCOPE_EXIT() BOOST_SCOPE_EXIT_END
来实现函数的回调。spin和spinOnce二者的区别就在于前者是阻塞等待, 而后者是只执行一次就结束。