32 #include <boost/thread/thread.hpp> 33 #include <boost/thread/mutex.hpp> 37 const std::string DEFAULT_ERROR_MESSAGE =
38 "Attempt to spin a callback queue from two spinners, one of them being single-threaded." 39 "\nIn the future this will throw an exception!";
63 Entry(
const boost::thread::id &tid,
64 const boost::thread::id &initial_tid) : tid(tid), initial_tid(initial_tid), num(0) {}
66 boost::thread::id tid;
67 boost::thread::id initial_tid;
74 boost::mutex::scoped_lock lock(mutex_);
76 boost::thread::id current_tid = boost::this_thread::get_id();
77 boost::thread::id tid;
81 std::map<ros::CallbackQueue*, Entry>::iterator it = spinning_queues_.find(queue);
82 bool can_spin = ( it == spinning_queues_.end() ||
83 it->second.tid == tid );
92 if (it->second.initial_tid == tid)
94 ROS_ERROR_STREAM(
"SpinnerMonitor: single-threaded spinner after multi-threaded one(s)." 95 << DEFAULT_ERROR_MESSAGE
96 <<
" Only allowed for backwards compatibility.");
103 if (it == spinning_queues_.end())
104 it = spinning_queues_.insert(it, std::make_pair(queue, Entry(tid, current_tid)));
115 boost::mutex::scoped_lock lock(mutex_);
116 std::map<ros::CallbackQueue*, Entry>::iterator it = spinning_queues_.find(queue);
117 ROS_ASSERT_MSG(it != spinning_queues_.end(),
"Call to SpinnerMonitor::remove() without matching call to add().");
119 if (it->second.tid != boost::thread::id() && it->second.tid != boost::this_thread::get_id())
123 ROS_WARN(
"SpinnerMonitor::remove() called from different thread than add().");
126 ROS_ASSERT_MSG(it->second.num > 0,
"SpinnerMonitor::remove(): Invalid spinner count (0) encountered.");
128 if (it->second.num == 0)
129 spinning_queues_.erase(it);
132 std::map<ros::CallbackQueue*, Entry> spinning_queues_;
136 SpinnerMonitor spinner_monitor;
150 if (!spinner_monitor.add(queue,
true))
152 ROS_ERROR_STREAM(
"SingleThreadedSpinner: " << DEFAULT_ERROR_MESSAGE +
" You might want to use a MultiThreadedSpinner instead.");
162 spinner_monitor.remove(queue);
165 MultiThreadedSpinner::MultiThreadedSpinner(uint32_t thread_count)
166 : thread_count_(thread_count)
204 , callback_queue_(queue)
207 if (thread_count == 0)
235 boost::mutex::scoped_lock lock(
mutex_);
256 boost::mutex::scoped_lock lock(
mutex_);
268 disableAllSignalsInThisThread();
276 if (use_call_available)
299 return impl_->canStart();
This is the default implementation of the ros::CallbackQueueInterface.
AsyncSpinnerImpl(uint32_t thread_count, CallbackQueue *queue)
ROSCPP_DECL void start()
Actually starts the internals of the node (spins up threads, starts the network polling and xmlrpc lo...
CallbackQueue * callback_queue_
CallOneResult callOne()
Pop a single callback off the front of the queue and invoke it. If the callback was not ready to be c...
AsyncSpinner(uint32_t thread_count)
Simple constructor. Uses the global callback queue.
ROSCPP_DECL CallbackQueue * getGlobalCallbackQueue()
Returns a pointer to the global default callback queue.
void start()
Start this spinner spinning asynchronously.
void callAvailable()
Invoke all callbacks currently in the queue. If a callback was not ready to be called, pushes it back onto the queue.
#define ROS_ASSERT_MSG(cond,...)
roscpp's interface for creating subscribers, publishers, etc.
void threadFunc(boost::barrier *b)
ROSCPP_DECL void spin()
Enter simple event loop.
virtual void spin(CallbackQueue *queue=0)
Spin on a callback queue (defaults to the global one). Blocks until roscpp has been shutdown...
bool canStart()
Check if the spinner can be started. The spinner shouldn't be started if another single-threaded spin...
AsyncSpinnerImplPtr impl_
boost::thread_group threads_
bool ok() const
Check whether it's time to exit.
#define ROS_ERROR_STREAM(args)
void stop()
Stop this spinner from running.
ROSCPP_DECL void waitForShutdown()
Wait for this node to be shutdown, whether through Ctrl-C, ros::shutdown(), or similar.
AsyncSpinner is a spinner that does not conform to the abstract Spinner interface. Instead, it spins asynchronously when you call start(), and stops when either you call stop(), ros::shutdown() is called, or its destructor is called.