32 #include <boost/thread/thread.hpp> 33 #include <boost/thread/mutex.hpp> 59 Entry(
const boost::thread::id &tid) : tid(tid), num(0) {}
61 boost::thread::id tid;
68 boost::mutex::scoped_lock lock(mutex_);
70 boost::thread::id tid;
72 tid = boost::this_thread::get_id();
74 std::map<ros::CallbackQueue*, Entry>::iterator it = spinning_queues_.find(queue);
75 bool can_spin = ( it == spinning_queues_.end() ||
76 it->second.tid == tid );
81 if (it == spinning_queues_.end())
82 it = spinning_queues_.insert(it, std::make_pair(queue, Entry(tid)));
93 boost::mutex::scoped_lock lock(mutex_);
94 std::map<ros::CallbackQueue*, Entry>::iterator it = spinning_queues_.find(queue);
95 ROS_ASSERT_MSG(it != spinning_queues_.end(),
"Call to SpinnerMonitor::remove() without matching call to add().");
97 if (it->second.tid != boost::thread::id() && it->second.tid != boost::this_thread::get_id())
101 ROS_WARN(
"SpinnerMonitor::remove() called from different thread than add().");
104 ROS_ASSERT_MSG(it->second.num > 0,
"SpinnerMonitor::remove(): Invalid spinner count (0) encountered.");
106 if (it->second.num == 0)
107 spinning_queues_.erase(it);
110 std::map<ros::CallbackQueue*, Entry> spinning_queues_;
114 SpinnerMonitor spinner_monitor;
115 const std::string DEFAULT_ERROR_MESSAGE =
116 "Attempt to spin a callback queue from two spinners, one of them being single-threaded.";
130 if (!spinner_monitor.add(queue,
true))
132 std::string errorMessage =
"SingleThreadedSpinner: " + DEFAULT_ERROR_MESSAGE +
" You might want to use a MultiThreadedSpinner instead.";
134 throw std::runtime_error(errorMessage);
143 spinner_monitor.remove(queue);
146 MultiThreadedSpinner::MultiThreadedSpinner(uint32_t thread_count)
147 : thread_count_(thread_count)
185 , callback_queue_(queue)
188 if (thread_count == 0)
216 boost::mutex::scoped_lock lock(
mutex_);
223 std::string errorMessage =
"AsyncSpinnerImpl: " + DEFAULT_ERROR_MESSAGE;
225 throw std::runtime_error(errorMessage);
238 boost::mutex::scoped_lock lock(
mutex_);
250 disableAllSignalsInThisThread();
258 if (use_call_available)
281 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_FATAL_STREAM(args)
#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.
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.