diff --git a/doc/changes.qbk b/doc/changes.qbk index 4a1ccbb3..30c4a2c2 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -46,7 +46,10 @@ but did not lock it on construction. This facility has now been replaced with th * The `locked()` member function of the `scoped_lock` types has been renamed to __owns_lock_ref__. +* You can no longer obtain a __thread__ instance representing the current thread: a default-constructed __thread__ object is not +associated with any thread. The only use for such a thread object was to support the comparison operators: this functionality has +been moved to __thread_id__. + * The broken `boost::read_write_mutex` has been replaced with __shared_mutex__. - [endsect] diff --git a/include/boost/thread/detail/move.hpp b/include/boost/thread/detail/move.hpp index 99beb5bb..d4732317 100644 --- a/include/boost/thread/detail/move.hpp +++ b/include/boost/thread/detail/move.hpp @@ -18,6 +18,11 @@ namespace boost t(t_) {} + T& operator*() const + { + return t; + } + T* operator->() const { return &t; diff --git a/include/boost/thread/locks.hpp b/include/boost/thread/locks.hpp index 741a2a47..71ec5373 100644 --- a/include/boost/thread/locks.hpp +++ b/include/boost/thread/locks.hpp @@ -587,6 +587,68 @@ namespace boost } }; + namespace detail + { + template + class try_lock_wrapper: + private unique_lock + { + typedef unique_lock base; + public: + explicit try_lock_wrapper(Mutex& m): + base(m,try_to_lock) + {} + + try_lock_wrapper(Mutex& m_,adopt_lock_t): + base(m_,adopt_lock) + {} + try_lock_wrapper(Mutex& m_,defer_lock_t): + base(m_,defer_lock) + {} + try_lock_wrapper(Mutex& m_,try_to_lock_t): + base(m_,try_to_lock) + {} + try_lock_wrapper(detail::thread_move_t > other): + base(detail::thread_move_t(*other)) + {} + + operator detail::thread_move_t >() + { + return move(); + } + + detail::thread_move_t > move() + { + return detail::thread_move_t >(*this); + } + + try_lock_wrapper& operator=(detail::thread_move_t > other) + { + try_lock_wrapper temp(other); + swap(temp); + return *this; + } + + void swap(try_lock_wrapper& other) + { + base::swap(other); + } + void swap(detail::thread_move_t > other) + { + base::swap(*other); + } + + using base::lock; + using base::try_lock; + using base::unlock; + using base::owns_lock; + using base::operator!; + using base::mutex; + using base::release; + typedef typename base::bool_type bool_type; + using base::operator bool_type; + }; + } } #endif diff --git a/include/boost/thread/pthread/mutex.hpp b/include/boost/thread/pthread/mutex.hpp index 3044a25b..9a228817 100644 --- a/include/boost/thread/pthread/mutex.hpp +++ b/include/boost/thread/pthread/mutex.hpp @@ -69,7 +69,7 @@ namespace boost } typedef unique_lock scoped_lock; - typedef scoped_lock scoped_try_lock; + typedef detail::try_lock_wrapper scoped_try_lock; }; typedef mutex try_mutex; @@ -187,7 +187,7 @@ namespace boost #endif typedef unique_lock scoped_timed_lock; - typedef scoped_timed_lock scoped_try_lock; + typedef detail::try_lock_wrapper scoped_try_lock; typedef scoped_timed_lock scoped_lock; }; diff --git a/include/boost/thread/pthread/recursive_mutex.hpp b/include/boost/thread/pthread/recursive_mutex.hpp index f496822d..b19a1adf 100644 --- a/include/boost/thread/pthread/recursive_mutex.hpp +++ b/include/boost/thread/pthread/recursive_mutex.hpp @@ -77,7 +77,7 @@ namespace boost return !res; } typedef unique_lock scoped_lock; - typedef scoped_lock scoped_try_lock; + typedef detail::try_lock_wrapper scoped_try_lock; }; typedef recursive_mutex recursive_try_mutex; @@ -239,7 +239,7 @@ namespace boost #endif typedef unique_lock scoped_timed_lock; - typedef scoped_timed_lock scoped_try_lock; + typedef detail::try_lock_wrapper scoped_try_lock; typedef scoped_timed_lock scoped_lock; }; diff --git a/include/boost/thread/win32/condition_variable.hpp b/include/boost/thread/win32/condition_variable.hpp index bf597682..c74d3cc4 100644 --- a/include/boost/thread/win32/condition_variable.hpp +++ b/include/boost/thread/win32/condition_variable.hpp @@ -156,7 +156,7 @@ namespace boost { relocker locker(lock); - entry_manager entry=get_wait_entry(); + entry_manager entry(get_wait_entry()); locker.unlock(); diff --git a/include/boost/thread/win32/mutex.hpp b/include/boost/thread/win32/mutex.hpp index 29759a9a..41787559 100644 --- a/include/boost/thread/win32/mutex.hpp +++ b/include/boost/thread/win32/mutex.hpp @@ -32,7 +32,7 @@ namespace boost } typedef unique_lock scoped_lock; - typedef scoped_lock scoped_try_lock; + typedef detail::try_lock_wrapper scoped_try_lock; }; typedef mutex try_mutex; @@ -53,7 +53,7 @@ namespace boost } typedef unique_lock scoped_timed_lock; - typedef scoped_timed_lock scoped_try_lock; + typedef detail::try_lock_wrapper scoped_try_lock; typedef scoped_timed_lock scoped_lock; }; } diff --git a/include/boost/thread/win32/recursive_mutex.hpp b/include/boost/thread/win32/recursive_mutex.hpp index 855dd15b..7f7541a1 100644 --- a/include/boost/thread/win32/recursive_mutex.hpp +++ b/include/boost/thread/win32/recursive_mutex.hpp @@ -32,7 +32,7 @@ namespace boost } typedef unique_lock scoped_lock; - typedef scoped_lock scoped_try_lock; + typedef detail::try_lock_wrapper scoped_try_lock; }; typedef recursive_mutex recursive_try_mutex; @@ -52,7 +52,7 @@ namespace boost } typedef unique_lock scoped_timed_lock; - typedef scoped_timed_lock scoped_try_lock; + typedef detail::try_lock_wrapper scoped_try_lock; typedef scoped_timed_lock scoped_lock; }; } diff --git a/test/test_lock_concept.cpp b/test/test_lock_concept.cpp index b0f5dc72..e9f0cf0a 100644 --- a/test/test_lock_concept.cpp +++ b/test/test_lock_concept.cpp @@ -7,7 +7,9 @@ #include #include #include +#include #include +#include template struct test_initially_locked @@ -22,6 +24,64 @@ struct test_initially_locked } }; +template +struct test_initially_unlocked_if_other_thread_has_lock +{ + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_initially_unlocked_if_other_thread_has_lock(): + done(false),locked(false) + {} + + void locking_thread() + { + Lock lock(m); + + boost::lock_guard lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + bool is_done() const + { + return done; + } + + + void operator()() + { + Lock lock(m); + + typedef test_initially_unlocked_if_other_thread_has_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 struct test_initially_unlocked_with_defer_lock_parameter { @@ -144,6 +204,7 @@ BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_try_lock_concept,Mutex) typedef typename Mutex::scoped_try_lock Lock; test_initially_locked()(); + test_initially_unlocked_if_other_thread_has_lock()(); test_initially_unlocked_with_defer_lock_parameter()(); test_initially_locked_with_adopt_lock_parameter()(); test_unlocked_after_unlock_called()();