Boost logo

Boost :

Subject: [boost] [thread] Moving a `recursive_lock`
From: Daniel Trebbien (dtrebbien_at_[hidden])
Date: 2010-02-13 21:50:05


Hello all,

I have been working on a project that uses the Boost Thread library, and I
realized that there is a part of the code that needs to transfer a lock to
a thread that has just been started. My idea for implementing this was to
use a `boost::recursive_mutex` and pass a non-`const` reference to a
`boost::recursive_mutex::scoped_lock` to the thread via `boost::ref`.
Also, to ensure that the `scoped_lock` does not go out of scope until
until the lock is moved, I thought to use a `boost::barrier`.

After writing some test code, I find it interesting that if I use a
`recursive_mutex`, then an assertion fails, but if I use a `boost::mutex`,
then the code seems to work fine.

Here is the test code that I have been experimenting with (the
`recursive_mutex` version, which is also attached):

#include <iostream>
#include <boost/ref.hpp>
#include <boost/thread.hpp>

static boost::recursive_mutex s_mutex;
static boost::barrier s_lockMoveBarrier(2);

void thread_fun1(boost::recursive_mutex::scoped_lock& lock_)
{
    //boost::recursive_mutex::scoped_lock testLock(s_mutex); //
uncommenting this causes deadlock, as expected

    std::cout << "in `void thread_fun1(...)`: moving lock...";
    boost::recursive_mutex::scoped_lock lock2(boost::move(lock_));
    std::cout << "done" << std::endl;
    s_lockMoveBarrier.wait();
    std::cout << "in `void thread_fun1(...)`: after the barrier" <<
std::endl;
}

int main()
{
    boost::recursive_mutex::scoped_lock lock(s_mutex);
    std::cout << "in `int main()`: lock on `s_mutex` acquired" << std::endl;
    boost::thread(&thread_fun1, boost::ref(lock));
    s_lockMoveBarrier.wait();
    std::cout << "in `int main()`: after the barrier" << std::endl;
}

After compiling and running this on Debian Squeeze with Boost 1.42.0, I
get:
in `int main()`: lock on `s_mutex` acquired
in `void thread_fun1(...)`: moving lock...done
in `int main()`: after the barrier
a.out: /usr/local/include/boost/thread/pthread/recursive_mutex.hpp:62:
boost::recursive_mutex::~recursive_mutex(): Assertion
`!pthread_mutex_destroy(&m)' failed.
Aborted

After replacing "boost::recursive_mutex" with "boost::mutex", however, the
output is:
in `int main()`: lock on `s_mutex` acquired
in `void thread_fun1(...)`: moving lock...done
in `void thread_fun1(...)`: after the barrier
in `int main()`: after the barrier

This leads me to wondering:
  1. Is it correct and/or safe to move a lock to a new thread in this way?

  2. Why does the `recursive_mutex` version fail and the `mutex` version
succeed?

Daniel Trebbien




Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk