|
Boost-Commit : |
From: anthony_at_[hidden]
Date: 2008-07-07 18:04:10
Author: anthonyw
Date: 2008-07-07 18:04:10 EDT (Mon, 07 Jul 2008)
New Revision: 47197
URL: http://svn.boost.org/trac/boost/changeset/47197
Log:
test and fix for issue #2081
Text files modified:
trunk/boost/thread/locks.hpp | 63 +++++++++++++++++
trunk/libs/thread/test/test_lock_concept.cpp | 144 +++++++++++++++++++++++++++++++++++++++
2 files changed, 205 insertions(+), 2 deletions(-)
Modified: trunk/boost/thread/locks.hpp
==============================================================================
--- trunk/boost/thread/locks.hpp (original)
+++ trunk/boost/thread/locks.hpp 2008-07-07 18:04:10 EDT (Mon, 07 Jul 2008)
@@ -186,6 +186,11 @@
swap(temp);
return *this;
}
+ void swap(unique_lock&& other)
+ {
+ std::swap(m,other.m);
+ std::swap(is_locked,other.is_locked);
+ }
#else
unique_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
@@ -218,7 +223,6 @@
swap(temp);
return *this;
}
-#endif
void swap(unique_lock& other)
{
std::swap(m,other.m);
@@ -229,6 +233,7 @@
std::swap(m,other->m);
std::swap(is_locked,other->is_locked);
}
+#endif
~unique_lock()
{
@@ -313,11 +318,19 @@
friend class upgrade_lock<Mutex>;
};
+#ifdef BOOST_HAS_RVALUE_REFS
+ template<typename Mutex>
+ void swap(unique_lock<Mutex>&& lhs,unique_lock<Mutex>&& rhs)
+ {
+ lhs.swap(rhs);
+ }
+#else
template<typename Mutex>
void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs)
{
lhs.swap(rhs);
}
+#endif
#ifdef BOOST_HAS_RVALUE_REFS
template<typename Mutex>
@@ -424,11 +437,29 @@
return *this;
}
+#ifdef BOOST_HAS_RVALUE_REFS
+ void swap(shared_lock&& other)
+ {
+ std::swap(m,other.m);
+ std::swap(is_locked,other.is_locked);
+ }
+#else
void swap(shared_lock& other)
{
std::swap(m,other.m);
std::swap(is_locked,other.is_locked);
}
+ void swap(boost::detail::thread_move_t<shared_lock> other)
+ {
+ std::swap(m,other->m);
+ std::swap(is_locked,other->is_locked);
+ }
+#endif
+
+ Mutex* mutex() const
+ {
+ return m;
+ }
~shared_lock()
{
@@ -490,6 +521,20 @@
};
+#ifdef BOOST_HAS_RVALUE_REFS
+ template<typename Mutex>
+ void swap(shared_lock<Mutex>&& lhs,shared_lock<Mutex>&& rhs)
+ {
+ lhs.swap(rhs);
+ }
+#else
+ template<typename Mutex>
+ void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs)
+ {
+ lhs.swap(rhs);
+ }
+#endif
+
template<typename Mutex>
class upgrade_lock
{
@@ -743,6 +788,12 @@
return *this;
}
+#ifdef BOOST_HAS_RVALUE_REFS
+ void swap(try_lock_wrapper&& other)
+ {
+ base::swap(other);
+ }
+#else
void swap(try_lock_wrapper& other)
{
base::swap(other);
@@ -751,6 +802,7 @@
{
base::swap(*other);
}
+#endif
void lock()
{
@@ -788,11 +840,19 @@
}
};
+#ifdef BOOST_HAS_RVALUE_REFS
+ template<typename Mutex>
+ void swap(try_lock_wrapper<Mutex>&& lhs,try_lock_wrapper<Mutex>&& rhs)
+ {
+ lhs.swap(rhs);
+ }
+#else
template<typename Mutex>
void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs)
{
lhs.swap(rhs);
}
+#endif
template<typename MutexType1,typename MutexType2>
unsigned try_lock_internal(MutexType1& m1,MutexType2& m2)
@@ -1189,5 +1249,6 @@
}
#include <boost/config/abi_suffix.hpp>
+#include <boost/mpl/identity.hpp>
#endif
Modified: trunk/libs/thread/test/test_lock_concept.cpp
==============================================================================
--- trunk/libs/thread/test/test_lock_concept.cpp (original)
+++ trunk/libs/thread/test/test_lock_concept.cpp 2008-07-07 18:04:10 EDT (Mon, 07 Jul 2008)
@@ -84,6 +84,122 @@
};
template<typename Mutex,typename Lock>
+struct test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock
+{
+ Mutex m;
+ boost::mutex done_mutex;
+ bool done;
+ bool locked;
+ boost::condition_variable done_cond;
+
+ test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock():
+ done(false),locked(false)
+ {}
+
+ void locking_thread()
+ {
+ Lock lock(m,boost::try_to_lock);
+
+ boost::lock_guard<boost::mutex> lk(done_mutex);
+ locked=lock.owns_lock();
+ done=true;
+ done_cond.notify_one();
+ }
+
+ bool is_done() const
+ {
+ return done;
+ }
+
+
+ void operator()()
+ {
+ boost::unique_lock<Mutex> lock(m);
+
+ typedef test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,Lock> this_type;
+
+ boost::thread t(&this_type::locking_thread,this);
+
+ try
+ {
+ {
+ boost::mutex::scoped_lock lk(done_mutex);
+ BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
+ boost::bind(&this_type::is_done,this)));
+ BOOST_CHECK(!locked);
+ }
+
+ lock.unlock();
+ t.join();
+ }
+ catch(...)
+ {
+ lock.unlock();
+ t.join();
+ throw;
+ }
+ }
+};
+
+template<typename Mutex,typename Lock>
+struct test_initially_locked_if_other_thread_has_shared_lock
+{
+ Mutex m;
+ boost::mutex done_mutex;
+ bool done;
+ bool locked;
+ boost::condition_variable done_cond;
+
+ test_initially_locked_if_other_thread_has_shared_lock():
+ done(false),locked(false)
+ {}
+
+ void locking_thread()
+ {
+ Lock lock(m);
+
+ boost::lock_guard<boost::mutex> lk(done_mutex);
+ locked=lock.owns_lock();
+ done=true;
+ done_cond.notify_one();
+ }
+
+ bool is_done() const
+ {
+ return done;
+ }
+
+
+ void operator()()
+ {
+ boost::shared_lock<Mutex> lock(m);
+
+ typedef test_initially_locked_if_other_thread_has_shared_lock<Mutex,Lock> this_type;
+
+ boost::thread t(&this_type::locking_thread,this);
+
+ try
+ {
+ {
+ boost::mutex::scoped_lock lk(done_mutex);
+ BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
+ boost::bind(&this_type::is_done,this)));
+ BOOST_CHECK(locked);
+ }
+
+ lock.unlock();
+ t.join();
+ }
+ catch(...)
+ {
+ lock.unlock();
+ t.join();
+ throw;
+ }
+ }
+};
+
+template<typename Mutex,typename Lock>
struct test_initially_unlocked_with_defer_lock_parameter
{
void operator()() const
@@ -263,6 +379,8 @@
{
Mutex m1;
Mutex m2;
+ Mutex m3;
+
Lock l1(m1);
Lock l2(m2);
@@ -278,7 +396,10 @@
BOOST_CHECK_EQUAL(l1.mutex(),&m1);
BOOST_CHECK_EQUAL(l2.mutex(),&m2);
-
+
+ l1.swap(Lock(m3));
+
+ BOOST_CHECK_EQUAL(l1.mutex(),&m3);
}
};
@@ -333,6 +454,26 @@
test_locks_can_be_swapped<Mutex,Lock>()();
}
+void test_shared_lock()
+{
+ typedef boost::shared_mutex Mutex;
+ typedef boost::shared_lock<Mutex> Lock;
+
+ test_default_constructed_has_no_mutex_and_unlocked<Lock>()();
+ test_initially_locked<Mutex,Lock>()();
+ test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,Lock>()();
+ test_initially_locked_if_other_thread_has_shared_lock<Mutex,Lock>()();
+ test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()();
+ test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()();
+ test_unlocked_after_unlock_called<Mutex,Lock>()();
+ test_locked_after_lock_called<Mutex,Lock>()();
+ test_locked_after_try_lock_called<Mutex,Lock>()();
+ test_throws_if_lock_called_when_already_locked<Mutex,Lock>()();
+ test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()();
+ test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()();
+ test_locks_can_be_swapped<Mutex,Lock>()();
+}
+
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test =
@@ -352,6 +493,7 @@
boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types;
test->add(BOOST_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,all_mutex_types));
+ test->add(BOOST_TEST_CASE(&test_shared_lock));
return test;
}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk