recursive mutex and condition

hey, I was wondering if any of the boost developers could tell me if recursive mutexes are supposed to work with conditions? From the code, it would seem to be the case, however in reality things aren't so happy. I have a fairly small test case which shows that the locking doesn't work if you recursively lock a mutex and then try to do a condition wait/notify. I'm testing this on red hat 7.3 and fedora core 2. My guess as to why it's broken is because the boost condition uses posix recursive mutexes internally, which also seem to fail the recursive mutex/condition test (at least on the OS's mentioned above). Anyone have any thoughts on this? I'll include my test case below. The error (for me) happens that when Thread2 releases the "inner" lock, Thread1 proceeds, even though Thread2 should still be holding the lock. (ps- i'm aware that there are some mem leaks in the program, i just simplified it for testing). thanks, -james ------------------------------------------------------- #include <string> #include <iostream.h> #include <boost/thread.hpp> #include <boost/smart_ptr.hpp> #include <boost/bind.hpp> using namespace boost; using namespace boost::detail::thread; class ThreadBase : private boost::noncopyable { public: void start() { m_thread.reset(new boost::thread(boost::bind(&ThreadBase::run, m_weakThis.lock()))); } void join() { m_thread->join(); } protected: virtual void run() = 0; ThreadBase() : m_thread(), m_weakThis() {} virtual ~ThreadBase() {} void initWeakThis(boost::weak_ptr<ThreadBase> weakThis) { m_weakThis = weakThis; } boost::shared_ptr<boost::thread> m_thread; boost::weak_ptr<ThreadBase> m_weakThis; private: }; class Thread2 : public ThreadBase { recursive_mutex* _mutex; condition* _cond; protected: Thread2(recursive_mutex* mutex, condition* cond) : ThreadBase(), _mutex(mutex), _cond(cond) {} public: static shared_ptr<Thread2> create(recursive_mutex* mutex, condition* cond) { shared_ptr<Thread2> tmp(new Thread2(mutex, cond)); tmp->initWeakThis(tmp); return tmp; } virtual ~Thread2() { cerr << "Thread2 dying\n"; } virtual void run() { cerr << "Thread2 acquiring lock(1)\n"; recursive_mutex::scoped_lock sl1(*_mutex); cerr << "Thread2 acquiring lock(2)\n"; { recursive_mutex::scoped_lock sl2(*_mutex); cerr << "Thread2 sleeping...\n"; ::sleep(5); cerr << "Thread2 signalling...\n"; _cond->notify_all(); cerr << "Thread2 releasing lock(2)\n"; } cerr << "Thread2 sleeping (again)...\n"; ::sleep(5); cerr << "Thread2 releasing lock(1)\n"; } }; class Thread1 : public ThreadBase { recursive_mutex _mutex; condition _cond; protected: Thread1() : ThreadBase() {} public: static shared_ptr<Thread1> create() { shared_ptr<Thread1> tmp(new Thread1()); tmp->initWeakThis(tmp); return tmp; } virtual ~Thread1() { cerr << "Thread1 dying\n"; } virtual void run() { cerr << "Thread1 acquiring lock(1)\n"; scoped_lock<recursive_mutex> sl1(_mutex); cerr << "Thread1 acquiring lock(2)\n"; { scoped_lock<recursive_mutex> sl2(_mutex); cerr << "Thread1 starting Thread2\n"; shared_ptr<Thread2> t2 = Thread2::create(&_mutex, &_cond); t2->start(); t2.reset(); cerr << "Thread1 waiting\n"; _cond.wait(sl2); cerr << "Thread1 releasing lock(2)\n"; } cerr << "Thread1 releasing lock(1)\n"; } }; int main(int argc, char** argv) { cerr << "Main Starting...\n"; shared_ptr<Thread1> t1 = Thread1::create(); t1->start(); t1->join(); cerr << "Main First Run\n"; // run it again t1->start(); t1->join(); t1.reset(); cerr << "Main Done\n"; return 0; }
participants (1)
-
James Ahlborn