ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

Thread safe spinning with Mutex and boost::threads

asked 2016-02-14 04:53:40 -0600

user23fj239 gravatar image

updated 2016-02-15 08:13:14 -0600

I have several threads accessing the same function. To guarantee safe spinning, which means none of the threads calls ros::spinOnce() at the same time I used a regular mutex. So if the threads wants to spin he has to lock it before, so in case he gets interrupted another thread cannot spin meanwhile, until the locking thread gets cpu-time again and releases the lock.
Is this approach good/bad Idea?

    boost::mutex safespinmutex;
    #include <boost/algorithm/string.hpp>
    #include <boost/thread/thread.hpp>
    #include <boost/thread/mutex.hpp>
    boost::mutex mtx_spin;           //shared by publisher threads

    //thread safe regular mutex spin
    mtx_spin.lock();
    ros::spinOnce();
    mtx_spin.unlock();
    loop_rate.sleep();
}

It is similar to c11 mutex, just here I use c98 syntax with boost::threads and boost::mutex :)
Edit more Info
I spawn a maximum of 13 threads each dedicated to publishing, which is a lot, but I dont see any problem: The call to lock() blocks the thread if another thread is inside the spinOnce() but yet not finished. Once done this thread unlocks the mutex and unblocks the waiting thread. voila or am I conceptually wrong?
This is how I start the publishing threads

      boost::thread tpool[14]; //thread pool
      int pool = 0;

  for (unsigned i=0; i<13; i++){
        if(rate_eff[i]!=0) {
            tpool[pool++] = boost::thread(publisher,(i+1), use_def);
        }
    }
    cout<<"        publishing on "<<(pool-1)<<" topics:"<<endl;


Benchmark
To confirm what said above I spawned 9 topics each managed by their own publisher thread. One Incoming thread sorts stuff into the internal vectors rate(100Hz) and the 9 publisher threads read it with 1000Hz rate and push it onto their topic. Does it run safe: Yes.
I am glad about suggestions and improvements but please fortify your statement.
image description
In case you want to have a look at the complete code here.

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
1

answered 2016-02-15 01:46:45 -0600

ahendrix gravatar image

Spinning from multiple threads seems like a complex solution to a simple problem. Why not just have a separate thread dedicated to spinning?

edit flag offensive delete link more

Comments

I do have seperate threads dedicated to spinning, BUT if two threads call spinOnce() at the same time needs to be avoided at all time. That's why each thread who wants to spin first accquires a mutx shared by all threads, so he knows he's the only one and allowed to do so. Am I conceptually wrong?

user23fj239 gravatar image user23fj239  ( 2016-02-15 07:31:08 -0600 )edit

If you mean with a separate thread just one thread, is what I try to avoid as it might be too much to process before spinning

user23fj239 gravatar image user23fj239  ( 2016-02-15 07:39:36 -0600 )edit
1

Each publish thread does not need to call spinOnce(). I would create a thread which does nothing but call ros::spin() and which does not do any other processing. ROS publishers are thread-safe, so there are no issues with calling publish() in one thread and spinning in another thread.

ahendrix gravatar image ahendrix  ( 2016-02-15 15:56:44 -0600 )edit

I wish I knew this before that publish and spin could be seperated.

user23fj239 gravatar image user23fj239  ( 2016-02-15 16:34:11 -0600 )edit

The C++ Publisher Tutorial is pretty clear about ros::spinOnce() being unrelated to publish, and only required for callbacks.

ahendrix gravatar image ahendrix  ( 2016-02-16 11:05:28 -0600 )edit
0

answered 2016-02-14 23:40:03 -0600

dcconner gravatar image

I'm not an expert w.r.t what ROS is doing under the hood, but I'd be concerned that since you don't know how ROS is handling their spin queue with their messaging, you have the potential for a creating deadlock.

Here is link to thread where I initially posted a related question and recently updated with what we did. http://answers.ros.org/question/56275...

I suggest you keep all locks only within your code with minimal overhead. Spinning from multiple threads sounds dangerous IMHO.

edit flag offensive delete link more

Comments

thanks, I had a look at the link and the concept sounds good and same to what I want to do, but unfortunately there is no code.

user23fj239 gravatar image user23fj239  ( 2016-02-15 07:35:59 -0600 )edit

Unfortunately I can't release the code in question, and it is rather involved.

I have NOT seen issues calling a publisher from within a worker thread. I think you want 1 spin loop that is handling incoming ROS subscriptions. Don't do significant processing in your subscription callbacks.

dcconner gravatar image dcconner  ( 2016-02-15 09:19:34 -0600 )edit

Just use call backs to copy data to lock protected data structure. In worker thread, get a copy of data from with lock, but release the lock quickly. Passing around the ConstPtr 's of the messages works well for this.

dcconner gravatar image dcconner  ( 2016-02-15 09:21:21 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-02-14 04:53:40 -0600

Seen: 4,727 times

Last updated: Feb 15 '16