|
Boost-Commit : |
From: anthony_at_[hidden]
Date: 2008-07-08 03:44:57
Author: anthonyw
Date: 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
New Revision: 47211
URL: http://svn.boost.org/trac/boost/changeset/47211
Log:
Merged thread changes from trunk
Text files modified:
branches/release/boost/thread/detail/platform.hpp | 6
branches/release/boost/thread/detail/thread.hpp | 4
branches/release/boost/thread/locks.hpp | 135 +++++++++++++++++
branches/release/boost/thread/pthread/condition_variable.hpp | 11 +
branches/release/boost/thread/pthread/condition_variable_fwd.hpp | 10 +
branches/release/boost/thread/pthread/mutex.hpp | 5
branches/release/boost/thread/tss.hpp | 221 ++++++++++++++--------------
branches/release/boost/thread/win32/basic_timed_mutex.hpp | 6
branches/release/boost/thread/win32/mutex.hpp | 2
branches/release/boost/thread/win32/shared_mutex.hpp | 209 ++++++++------------------
branches/release/boost/thread/win32/thread_primitives.hpp | 23 +-
branches/release/libs/thread/test/test_condition_timed_wait_times_out.cpp | 88 +++++++++++
branches/release/libs/thread/test/test_lock_concept.cpp | 310 ++++++++++++++++++++++++++++++++++++++-
branches/release/libs/thread/test/test_shared_mutex.cpp | 10
branches/release/libs/thread/test/test_shared_mutex_part_2.cpp | 115 ++++++++++++++
branches/release/libs/thread/test/test_thread_mf.cpp | 94 +++++------
branches/release/libs/thread/test/test_xtime.cpp | 44 +++++
17 files changed, 957 insertions(+), 336 deletions(-)
Modified: branches/release/boost/thread/detail/platform.hpp
==============================================================================
--- branches/release/boost/thread/detail/platform.hpp (original)
+++ branches/release/boost/thread/detail/platform.hpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -42,9 +42,9 @@
#elif defined(__QNXNTO__)
# define BOOST_THREAD_QNXNTO
#elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)
-# if defined(BOOST_HAS_PTHREADS) && !defined(BOOST_THREAD_POSIX)
-# define BOOST_THREAD_POSIX
-# endif
+# if defined(BOOST_HAS_PTHREADS) && !defined(BOOST_THREAD_POSIX)
+# define BOOST_THREAD_POSIX
+# endif
#endif
// For every supported platform add a new entry into the dispatch table below.
Modified: branches/release/boost/thread/detail/thread.hpp
==============================================================================
--- branches/release/boost/thread/detail/thread.hpp (original)
+++ branches/release/boost/thread/detail/thread.hpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -163,7 +163,7 @@
thread& operator=(thread&& other)
{
thread_info=other.thread_info;
- other.thread_info.reset((detail::thread_data_base*)0);
+ other.thread_info.reset();
return *this;
}
@@ -190,7 +190,7 @@
thread(detail::thread_move_t<thread> x)
{
thread_info=x->thread_info;
- x->thread_info.reset((detail::thread_data_base*)0);
+ x->thread_info.reset();
}
thread& operator=(detail::thread_move_t<thread> x)
Modified: branches/release/boost/thread/locks.hpp
==============================================================================
--- branches/release/boost/thread/locks.hpp (original)
+++ branches/release/boost/thread/locks.hpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -16,6 +16,8 @@
namespace boost
{
+ struct xtime;
+
namespace detail
{
template<typename T>
@@ -126,8 +128,10 @@
private:
Mutex* m;
bool is_locked;
- explicit unique_lock(unique_lock&);
+ unique_lock(unique_lock&);
+ explicit unique_lock(upgrade_lock<Mutex>&);
unique_lock& operator=(unique_lock&);
+ unique_lock& operator=(upgrade_lock<Mutex>& other);
public:
unique_lock():
m(0),is_locked(false)
@@ -154,6 +158,40 @@
{
timed_lock(target_time);
}
+#ifdef BOOST_HAS_RVALUE_REFS
+ unique_lock(unique_lock&& other):
+ m(other.m),is_locked(other.is_locked)
+ {
+ other.is_locked=false;
+ other.m=0;
+ }
+ explicit unique_lock(upgrade_lock<Mutex>&& other);
+
+ unique_lock<Mutex>&& move()
+ {
+ return static_cast<unique_lock<Mutex>&&>(*this);
+ }
+
+
+ unique_lock& operator=(unique_lock<Mutex>&& other)
+ {
+ unique_lock temp(other);
+ swap(temp);
+ return *this;
+ }
+
+ unique_lock& operator=(upgrade_lock<Mutex>&& other)
+ {
+ unique_lock temp(other);
+ 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)
{
@@ -185,7 +223,6 @@
swap(temp);
return *this;
}
-
void swap(unique_lock& other)
{
std::swap(m,other.m);
@@ -196,6 +233,7 @@
std::swap(m,other->m);
std::swap(is_locked,other->is_locked);
}
+#endif
~unique_lock()
{
@@ -234,6 +272,11 @@
is_locked=m->timed_lock(absolute_time);
return is_locked;
}
+ bool timed_lock(::boost::xtime const& absolute_time)
+ {
+ is_locked=m->timed_lock(absolute_time);
+ return is_locked;
+ }
void unlock()
{
if(!owns_lock())
@@ -275,11 +318,27 @@
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>
+ inline unique_lock<Mutex>&& move(unique_lock<Mutex>&& ul)
+ {
+ return ul;
+ }
+#endif
template<typename Mutex>
class shared_lock
@@ -378,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()
{
@@ -418,6 +495,16 @@
is_locked=m->timed_lock_shared(target_time);
return is_locked;
}
+ template<typename Duration>
+ bool timed_lock(Duration const& target_time)
+ {
+ if(owns_lock())
+ {
+ throw boost::lock_error();
+ }
+ is_locked=m->timed_lock_shared(target_time);
+ return is_locked;
+ }
void unlock()
{
if(!owns_lock())
@@ -444,6 +531,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
{
@@ -576,6 +677,18 @@
};
+#ifdef BOOST_HAS_RVALUE_REFS
+ template<typename Mutex>
+ unique_lock<Mutex>::unique_lock(upgrade_lock<Mutex>&& other):
+ m(other.m),is_locked(other.is_locked)
+ {
+ other.is_locked=false;
+ if(is_locked)
+ {
+ m.unlock_upgrade_and_lock();
+ }
+ }
+#else
template<typename Mutex>
unique_lock<Mutex>::unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
@@ -586,7 +699,7 @@
m->unlock_upgrade_and_lock();
}
}
-
+#endif
template <class Mutex>
class upgrade_to_unique_lock
{
@@ -685,6 +798,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);
@@ -693,6 +812,7 @@
{
base::swap(*other);
}
+#endif
void lock()
{
@@ -730,11 +850,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)
@@ -1131,5 +1259,6 @@
}
#include <boost/config/abi_suffix.hpp>
+#include <boost/mpl/identity.hpp>
#endif
Modified: branches/release/boost/thread/pthread/condition_variable.hpp
==============================================================================
--- branches/release/boost/thread/pthread/condition_variable.hpp (original)
+++ branches/release/boost/thread/pthread/condition_variable.hpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -121,6 +121,17 @@
}
return true;
}
+ template<typename lock_type>
+ bool timed_wait(lock_type& m,xtime const& wait_until)
+ {
+ return timed_wait(m,system_time(wait_until));
+ }
+
+ template<typename lock_type,typename duration_type>
+ bool timed_wait(lock_type& m,duration_type const& wait_duration)
+ {
+ return timed_wait(m,get_system_time()+wait_duration);
+ }
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
Modified: branches/release/boost/thread/pthread/condition_variable_fwd.hpp
==============================================================================
--- branches/release/boost/thread/pthread/condition_variable_fwd.hpp (original)
+++ branches/release/boost/thread/pthread/condition_variable_fwd.hpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -47,6 +47,16 @@
}
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until);
+ bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until)
+ {
+ return timed_wait(m,system_time(wait_until));
+ }
+
+ template<typename duration_type>
+ bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
+ {
+ return timed_wait(m,get_system_time()+wait_duration);
+ }
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
Modified: branches/release/boost/thread/pthread/mutex.hpp
==============================================================================
--- branches/release/boost/thread/pthread/mutex.hpp (original)
+++ branches/release/boost/thread/pthread/mutex.hpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -10,6 +10,7 @@
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
+#include <boost/thread/xtime.hpp>
#include <boost/assert.hpp>
#include <errno.h>
#include "timespec.hpp"
@@ -113,6 +114,10 @@
{
return timed_lock(get_system_time()+relative_time);
}
+ bool timed_lock(boost::xtime const & absolute_time)
+ {
+ return timed_lock(system_time(absolute_time));
+ }
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
void lock()
Modified: branches/release/boost/thread/tss.hpp
==============================================================================
--- branches/release/boost/thread/tss.hpp (original)
+++ branches/release/boost/thread/tss.hpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -1,110 +1,111 @@
-#ifndef BOOST_THREAD_TSS_HPP
-#define BOOST_THREAD_TSS_HPP
-// Distributed under the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-// (C) Copyright 2007-8 Anthony Williams
-
-#include <boost/shared_ptr.hpp>
-#include <boost/thread/detail/thread_heap_alloc.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost
-{
- namespace detail
- {
- struct tss_cleanup_function
- {
- virtual ~tss_cleanup_function()
- {}
-
- virtual void operator()(void* data)=0;
- };
-
- BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
- BOOST_THREAD_DECL void* get_tss_data(void const* key);
- }
-
- template <typename T>
- class thread_specific_ptr
- {
- private:
- thread_specific_ptr(thread_specific_ptr&);
- thread_specific_ptr& operator=(thread_specific_ptr&);
-
- struct delete_data:
- detail::tss_cleanup_function
- {
- void operator()(void* data)
- {
- delete static_cast<T*>(data);
- }
- };
-
- struct run_custom_cleanup_function:
- detail::tss_cleanup_function
- {
- void (*cleanup_function)(T*);
-
- explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
- cleanup_function(cleanup_function_)
- {}
-
- void operator()(void* data)
- {
- cleanup_function(static_cast<T*>(data));
- }
- };
-
-
- boost::shared_ptr<detail::tss_cleanup_function> cleanup;
-
- public:
- thread_specific_ptr():
- cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
- {}
- explicit thread_specific_ptr(void (*func_)(T*))
- {
- if(func_)
- {
- cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
- }
- }
- ~thread_specific_ptr()
- {
- reset();
- }
-
- T* get() const
- {
- return static_cast<T*>(detail::get_tss_data(this));
- }
- T* operator->() const
- {
- return get();
- }
- T& operator*() const
- {
- return *get();
- }
- T* release()
- {
- T* const temp=get();
- detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
- return temp;
- }
- void reset(T* new_value=0)
- {
- T* const current_value=get();
- if(current_value!=new_value)
- {
- detail::set_tss_data(this,cleanup,new_value,true);
- }
- }
- };
-}
-
-#include <boost/config/abi_suffix.hpp>
-
-#endif
+#ifndef BOOST_THREAD_TSS_HPP
+#define BOOST_THREAD_TSS_HPP
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+// (C) Copyright 2007-8 Anthony Williams
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/detail/thread_heap_alloc.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ namespace detail
+ {
+ struct tss_cleanup_function
+ {
+ virtual ~tss_cleanup_function()
+ {}
+
+ virtual void operator()(void* data)=0;
+ };
+
+ BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
+ BOOST_THREAD_DECL void* get_tss_data(void const* key);
+ }
+
+ template <typename T>
+ class thread_specific_ptr
+ {
+ private:
+ thread_specific_ptr(thread_specific_ptr&);
+ thread_specific_ptr& operator=(thread_specific_ptr&);
+
+ struct delete_data:
+ detail::tss_cleanup_function
+ {
+ void operator()(void* data)
+ {
+ delete static_cast<T*>(data);
+ }
+ };
+
+ struct run_custom_cleanup_function:
+ detail::tss_cleanup_function
+ {
+ void (*cleanup_function)(T*);
+
+ explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
+ cleanup_function(cleanup_function_)
+ {}
+
+ void operator()(void* data)
+ {
+ cleanup_function(static_cast<T*>(data));
+ }
+ };
+
+
+ boost::shared_ptr<detail::tss_cleanup_function> cleanup;
+
+ public:
+ thread_specific_ptr():
+ cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
+ {}
+ explicit thread_specific_ptr(void (*func_)(T*))
+ {
+ if(func_)
+ {
+ cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
+ }
+ }
+ ~thread_specific_ptr()
+ {
+ reset();
+ }
+
+ T* get() const
+ {
+ return static_cast<T*>(detail::get_tss_data(this));
+ }
+ T* operator->() const
+ {
+ return get();
+ }
+ T& operator*() const
+ {
+ return *get();
+ }
+ T* release()
+ {
+ T* const temp=get();
+ detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
+ return temp;
+ }
+ void reset(T* new_value=0)
+ {
+ T* const current_value=get();
+ if(current_value!=new_value)
+ {
+ detail::set_tss_data(this,cleanup,new_value,true);
+ }
+ }
+ };
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
Modified: branches/release/boost/thread/win32/basic_timed_mutex.hpp
==============================================================================
--- branches/release/boost/thread/win32/basic_timed_mutex.hpp (original)
+++ branches/release/boost/thread/win32/basic_timed_mutex.hpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -13,6 +13,7 @@
#include "thread_primitives.hpp"
#include "interlocked_read.hpp"
#include <boost/thread/thread_time.hpp>
+#include <boost/thread/xtime.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -117,6 +118,11 @@
return timed_lock(get_system_time()+timeout);
}
+ bool timed_lock(boost::xtime const& timeout)
+ {
+ return timed_lock(system_time(timeout));
+ }
+
long get_active_count()
{
return ::boost::detail::interlocked_read_acquire(&active_count);
Modified: branches/release/boost/thread/win32/mutex.hpp
==============================================================================
--- branches/release/boost/thread/win32/mutex.hpp (original)
+++ branches/release/boost/thread/win32/mutex.hpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -20,7 +20,7 @@
}
class mutex:
- boost::noncopyable,
+ boost::noncopyable,
public ::boost::detail::underlying_mutex
{
public:
Modified: branches/release/boost/thread/win32/shared_mutex.hpp
==============================================================================
--- branches/release/boost/thread/win32/shared_mutex.hpp (original)
+++ branches/release/boost/thread/win32/shared_mutex.hpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -91,7 +91,7 @@
bool try_lock_shared()
{
state_data old_state=state;
- do
+ for(;;)
{
state_data new_state=old_state;
if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
@@ -106,14 +106,6 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
return !(old_state.exclusive| old_state.exclusive_waiting_blocked);
}
@@ -130,17 +122,10 @@
bool timed_lock_shared(boost::system_time const& wait_until)
{
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true)
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
+ for(;;)
{
state_data old_state=state;
- do
+ for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
@@ -159,14 +144,6 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
@@ -176,7 +153,7 @@
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,::boost::detail::get_milliseconds_until(wait_until));
if(res==detail::win32::timeout)
{
- do
+ for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
@@ -198,14 +175,6 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
@@ -221,7 +190,7 @@
void unlock_shared()
{
state_data old_state=state;
- do
+ for(;;)
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
@@ -262,14 +231,6 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
}
void lock()
@@ -283,20 +244,39 @@
return timed_lock(get_system_time()+relative_time);
}
+ bool try_lock()
+ {
+ state_data old_state=state;
+ for(;;)
+ {
+ state_data new_state=old_state;
+ if(new_state.shared_count || new_state.exclusive)
+ {
+ return false;
+ }
+ else
+ {
+ new_state.exclusive=true;
+ }
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ break;
+ }
+ old_state=current_state;
+ }
+ return true;
+ }
+
+
bool timed_lock(boost::system_time const& wait_until)
{
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true)
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
+ for(;;)
{
state_data old_state=state;
- do
+ for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
@@ -316,14 +296,6 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
if(!old_state.shared_count && !old_state.exclusive)
{
@@ -332,7 +304,7 @@
unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,true,::boost::detail::get_milliseconds_until(wait_until));
if(wait_res==detail::win32::timeout)
{
- do
+ for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
@@ -357,14 +329,6 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
@@ -378,7 +342,7 @@
void unlock()
{
state_data old_state=state;
- do
+ for(;;)
{
state_data new_state=old_state;
new_state.exclusive=false;
@@ -396,30 +360,15 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
release_waiters(old_state);
}
void lock_upgrade()
{
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true)
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
+ for(;;)
{
state_data old_state=state;
- do
+ for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
@@ -439,14 +388,6 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade))
{
@@ -457,10 +398,36 @@
}
}
+ bool try_lock_upgrade()
+ {
+ state_data old_state=state;
+ for(;;)
+ {
+ state_data new_state=old_state;
+ if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
+ {
+ return false;
+ }
+ else
+ {
+ ++new_state.shared_count;
+ new_state.upgrade=true;
+ }
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ break;
+ }
+ old_state=current_state;
+ }
+ return true;
+ }
+
void unlock_upgrade()
{
state_data old_state=state;
- do
+ for(;;)
{
state_data new_state=old_state;
new_state.upgrade=false;
@@ -487,20 +454,12 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
}
void unlock_upgrade_and_lock()
{
state_data old_state=state;
- do
+ for(;;)
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
@@ -522,20 +481,12 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
}
void unlock_and_lock_upgrade()
{
state_data old_state=state;
- do
+ for(;;)
{
state_data new_state=old_state;
new_state.exclusive=false;
@@ -555,21 +506,13 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
release_waiters(old_state);
}
void unlock_and_lock_shared()
{
state_data old_state=state;
- do
+ for(;;)
{
state_data new_state=old_state;
new_state.exclusive=false;
@@ -588,21 +531,13 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
release_waiters(old_state);
}
void unlock_upgrade_and_lock_shared()
{
state_data old_state=state;
- do
+ for(;;)
{
state_data new_state=old_state;
new_state.upgrade=false;
@@ -620,14 +555,6 @@
}
old_state=current_state;
}
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
release_waiters(old_state);
}
Modified: branches/release/boost/thread/win32/thread_primitives.hpp
==============================================================================
--- branches/release/boost/thread/win32/thread_primitives.hpp (original)
+++ branches/release/boost/thread/win32/thread_primitives.hpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -64,7 +64,7 @@
# ifdef UNDER_CE
# ifndef WINAPI
# ifndef _WIN32_WCE_EMULATION
-# define WINAPI __cdecl // Note this doesn't match the desktop definition
+# define WINAPI __cdecl // Note this doesn't match the desktop definition
# else
# define WINAPI __stdcall
# endif
@@ -282,16 +282,6 @@
}
#if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE)
-#if _MSC_VER==1400
-extern "C" unsigned char _interlockedbittestandset(long *a,long b);
-extern "C" unsigned char _interlockedbittestandreset(long *a,long b);
-#else
-extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b);
-extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b);
-#endif
-
-#pragma intrinsic(_interlockedbittestandset)
-#pragma intrinsic(_interlockedbittestandreset)
namespace boost
{
@@ -299,6 +289,17 @@
{
namespace win32
{
+#if _MSC_VER==1400
+ extern "C" unsigned char _interlockedbittestandset(long *a,long b);
+ extern "C" unsigned char _interlockedbittestandreset(long *a,long b);
+#else
+ extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b);
+ extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b);
+#endif
+
+#pragma intrinsic(_interlockedbittestandset)
+#pragma intrinsic(_interlockedbittestandreset)
+
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
return _interlockedbittestandset(x,bit)!=0;
Modified: branches/release/libs/thread/test/test_condition_timed_wait_times_out.cpp
==============================================================================
--- branches/release/libs/thread/test/test_condition_timed_wait_times_out.cpp (original)
+++ branches/release/libs/thread/test/test_condition_timed_wait_times_out.cpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007 Anthony Williams
+// Copyright (C) 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,7 +16,7 @@
return false;
}
-unsigned const timeout_seconds=5;
+unsigned const timeout_seconds=2;
unsigned const timeout_grace=1;
boost::posix_time::milliseconds const timeout_resolution(100);
@@ -70,12 +70,96 @@
BOOST_CHECK((delay-timeout_resolution)<=(end-start));
}
+void do_test_timed_wait_relative_times_out()
+{
+ boost::condition_variable cond;
+ boost::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+
+ while(cond.timed_wait(lock,delay));
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+void do_test_cv_any_timed_wait_times_out()
+{
+ boost::condition_variable_any cond;
+ boost::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+ boost::system_time const timeout=start+delay;
+
+ while(cond.timed_wait(lock,timeout));
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+void do_test_cv_any_timed_wait_with_predicate_times_out()
+{
+ boost::condition_variable_any cond;
+ boost::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+ boost::system_time const timeout=start+delay;
+
+ bool const res=cond.timed_wait(lock,timeout,fake_predicate);
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK(!res);
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+void do_test_cv_any_relative_timed_wait_with_predicate_times_out()
+{
+ boost::condition_variable_any cond;
+ boost::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+
+ bool const res=cond.timed_wait(lock,delay,fake_predicate);
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK(!res);
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+void do_test_cv_any_timed_wait_relative_times_out()
+{
+ boost::condition_variable_any cond;
+ boost::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+
+ while(cond.timed_wait(lock,delay));
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
void test_timed_wait_times_out()
{
timed_test(&do_test_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
timed_test(&do_test_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
timed_test(&do_test_relative_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_cv_any_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_cv_any_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_cv_any_relative_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_cv_any_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
Modified: branches/release/libs/thread/test/test_lock_concept.cpp
==============================================================================
--- branches/release/libs/thread/test/test_lock_concept.cpp (original)
+++ branches/release/libs/thread/test/test_lock_concept.cpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -7,6 +7,7 @@
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/thread/mutex.hpp>
+#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/condition_variable.hpp>
@@ -83,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
@@ -150,6 +267,64 @@
};
template<typename Mutex,typename Lock>
+struct test_unlocked_after_try_lock_if_other_thread_has_lock
+{
+ Mutex m;
+ boost::mutex done_mutex;
+ bool done;
+ bool locked;
+ boost::condition_variable done_cond;
+
+ test_unlocked_after_try_lock_if_other_thread_has_lock():
+ done(false),locked(false)
+ {}
+
+ void locking_thread()
+ {
+ Lock lock(m,boost::defer_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()()
+ {
+ Lock lock(m);
+
+ typedef test_unlocked_after_try_lock_if_other_thread_has_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_throws_if_lock_called_when_already_locked
{
void operator()() const
@@ -204,6 +379,8 @@
{
Mutex m1;
Mutex m2;
+ Mutex m3;
+
Lock l1(m1);
Lock l2(m2);
@@ -219,34 +396,135 @@
BOOST_CHECK_EQUAL(l1.mutex(),&m1);
BOOST_CHECK_EQUAL(l2.mutex(),&m2);
-
+
+ l1.swap(Lock(m3));
+
+ BOOST_CHECK_EQUAL(l1.mutex(),&m3);
}
};
+template<typename Mutex,typename Lock>
+void test_lock_is_scoped_lock_concept_for_mutex()
+{
+ test_default_constructed_has_no_mutex_and_unlocked<Lock>()();
+ test_initially_locked<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_throws_if_lock_called_when_already_locked<Mutex,Lock>()();
+ test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()();
+ test_locks_can_be_swapped<Mutex,Lock>()();
+ test_locked_after_try_lock_called<Mutex,Lock>()();
+ test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()();
+ test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()();
+}
BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_lock_concept,Mutex)
{
typedef typename Mutex::scoped_lock Lock;
+
+ test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();
+}
+
+BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_unique_lock_is_scoped_lock,Mutex)
+{
+ typedef boost::unique_lock<Mutex> Lock;
+
+ test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();
+}
+
+BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_try_lock_concept,Mutex)
+{
+ typedef typename Mutex::scoped_try_lock Lock;
test_default_constructed_has_no_mutex_and_unlocked<Lock>()();
test_initially_locked<Mutex,Lock>()();
+ test_initially_unlocked_if_other_thread_has_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_unlocked_after_try_lock_if_other_thread_has_lock<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_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_try_lock_concept,Mutex)
+struct dummy_shared_mutex
{
- typedef typename Mutex::scoped_try_lock Lock;
+ bool locked;
+ bool shared_locked;
+ bool shared_unlocked;
+ bool shared_timed_locked_relative;
+ bool shared_timed_locked_absolute;
+ bool timed_locked_relative;
+ bool timed_locked_absolute;
+
+ dummy_shared_mutex():
+ locked(false),shared_locked(false),shared_unlocked(false),
+ shared_timed_locked_relative(false),
+ shared_timed_locked_absolute(false),
+ timed_locked_relative(false),
+ timed_locked_absolute(false)
+ {}
+
+ void lock()
+ {
+ locked=true;
+ }
+
+ void lock_shared()
+ {
+ shared_locked=true;
+ }
+
+ void unlock()
+ {}
+
+ void unlock_shared()
+ {
+ shared_unlocked=true;
+ }
+
+ bool timed_lock_shared(boost::system_time)
+ {
+ shared_timed_locked_absolute=true;
+ return false;
+ }
+ template<typename Duration>
+ bool timed_lock_shared(Duration)
+ {
+ shared_timed_locked_relative=true;
+ return false;
+ }
+ bool timed_lock(boost::system_time)
+ {
+ timed_locked_absolute=true;
+ return false;
+ }
+ template<typename Duration>
+ bool timed_lock(Duration)
+ {
+ timed_locked_relative=true;
+ return false;
+ }
+
+};
+
+
+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_if_other_thread_has_lock<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>()();
@@ -256,6 +534,16 @@
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>()();
+
+ dummy_shared_mutex dummy;
+ boost::shared_lock<dummy_shared_mutex> lk(dummy);
+ BOOST_CHECK(dummy.shared_locked);
+ lk.unlock();
+ BOOST_CHECK(dummy.shared_unlocked);
+ lk.timed_lock(boost::posix_time::milliseconds(5));
+ BOOST_CHECK(dummy.shared_timed_locked_relative);
+ lk.timed_lock(boost::get_system_time());
+ BOOST_CHECK(dummy.shared_timed_locked_absolute);
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
@@ -264,14 +552,20 @@
BOOST_TEST_SUITE("Boost.Threads: lock concept test suite");
typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
- boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types;
+ boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock;
- test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types));
+ test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types_with_scoped_lock));
typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
- boost::recursive_try_mutex,boost::recursive_timed_mutex> try_mutex_types;
+ boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock;
- test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,try_mutex_types));
+ test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,mutex_types_with_scoped_try_lock));
+
+ typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
+ 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;
}
Modified: branches/release/libs/thread/test/test_shared_mutex.cpp
==============================================================================
--- branches/release/libs/thread/test/test_shared_mutex.cpp (original)
+++ branches/release/libs/thread/test/test_shared_mutex.cpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -17,7 +17,7 @@
void test_multiple_readers()
{
- unsigned const number_of_threads=100;
+ unsigned const number_of_threads=10;
boost::thread_group pool;
@@ -64,7 +64,7 @@
void test_only_one_writer_permitted()
{
- unsigned const number_of_threads=100;
+ unsigned const number_of_threads=10;
boost::thread_group pool;
@@ -164,7 +164,7 @@
boost::mutex finish_mutex;
boost::mutex::scoped_lock finish_lock(finish_mutex);
- unsigned const reader_count=100;
+ unsigned const reader_count=10;
try
{
@@ -218,8 +218,8 @@
boost::mutex finish_writing_mutex;
boost::mutex::scoped_lock finish_writing_lock(finish_writing_mutex);
- unsigned const reader_count=100;
- unsigned const writer_count=100;
+ unsigned const reader_count=10;
+ unsigned const writer_count=10;
try
{
Modified: branches/release/libs/thread/test/test_shared_mutex_part_2.cpp
==============================================================================
--- branches/release/libs/thread/test/test_shared_mutex_part_2.cpp (original)
+++ branches/release/libs/thread/test/test_shared_mutex_part_2.cpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -15,10 +15,41 @@
BOOST_CHECK_EQUAL(value,expected_value); \
}
+class simple_upgrade_thread
+{
+ boost::shared_mutex& rwm;
+ boost::mutex& finish_mutex;
+ boost::mutex& unblocked_mutex;
+ unsigned& unblocked_count;
+
+ void operator=(simple_upgrade_thread&);
+
+public:
+ simple_upgrade_thread(boost::shared_mutex& rwm_,
+ boost::mutex& finish_mutex_,
+ boost::mutex& unblocked_mutex_,
+ unsigned& unblocked_count_):
+ rwm(rwm_),finish_mutex(finish_mutex_),
+ unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
+ {}
+
+ void operator()()
+ {
+ boost::upgrade_lock<boost::shared_mutex> lk(rwm);
+
+ {
+ boost::mutex::scoped_lock ulk(unblocked_mutex);
+ ++unblocked_count;
+ }
+
+ boost::mutex::scoped_lock flk(finish_mutex);
+ }
+};
+
void test_only_one_upgrade_lock_permitted()
{
- unsigned const number_of_threads=100;
+ unsigned const number_of_threads=10;
boost::thread_group pool;
@@ -71,7 +102,7 @@
boost::mutex finish_mutex;
boost::mutex::scoped_lock finish_lock(finish_mutex);
- unsigned const reader_count=100;
+ unsigned const reader_count=10;
try
{
@@ -130,6 +161,29 @@
writer.join();
}
+void test_if_other_thread_has_write_lock_try_lock_upgrade_returns_false()
+{
+
+ boost::shared_mutex rw_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex unblocked_mutex;
+ unsigned unblocked_count=0;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+ boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
+ boost::this_thread::sleep(boost::posix_time::seconds(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
+
+ bool const try_succeeded=rw_mutex.try_lock_upgrade();
+ BOOST_CHECK(!try_succeeded);
+ if(try_succeeded)
+ {
+ rw_mutex.unlock_upgrade();
+ }
+
+ finish_lock.unlock();
+ writer.join();
+}
+
void test_if_no_thread_has_lock_try_lock_shared_returns_true()
{
boost::shared_mutex rw_mutex;
@@ -141,6 +195,17 @@
}
}
+void test_if_no_thread_has_lock_try_lock_upgrade_returns_true()
+{
+ boost::shared_mutex rw_mutex;
+ bool const try_succeeded=rw_mutex.try_lock_upgrade();
+ BOOST_CHECK(try_succeeded);
+ if(try_succeeded)
+ {
+ rw_mutex.unlock_upgrade();
+ }
+}
+
void test_if_other_thread_has_shared_lock_try_lock_shared_returns_true()
{
@@ -164,6 +229,52 @@
writer.join();
}
+void test_if_other_thread_has_shared_lock_try_lock_upgrade_returns_true()
+{
+
+ boost::shared_mutex rw_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex unblocked_mutex;
+ unsigned unblocked_count=0;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+ boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
+ boost::thread::sleep(delay(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
+
+ bool const try_succeeded=rw_mutex.try_lock_upgrade();
+ BOOST_CHECK(try_succeeded);
+ if(try_succeeded)
+ {
+ rw_mutex.unlock_upgrade();
+ }
+
+ finish_lock.unlock();
+ writer.join();
+}
+
+void test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false()
+{
+
+ boost::shared_mutex rw_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex unblocked_mutex;
+ unsigned unblocked_count=0;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+ boost::thread writer(simple_upgrade_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
+ boost::this_thread::sleep(boost::posix_time::seconds(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
+
+ bool const try_succeeded=rw_mutex.try_lock_upgrade();
+ BOOST_CHECK(!try_succeeded);
+ if(try_succeeded)
+ {
+ rw_mutex.unlock_upgrade();
+ }
+
+ finish_lock.unlock();
+ writer.join();
+}
+
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test =
Modified: branches/release/libs/thread/test/test_thread_mf.cpp
==============================================================================
--- branches/release/libs/thread/test/test_thread_mf.cpp (original)
+++ branches/release/libs/thread/test/test_thread_mf.cpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -45,92 +45,90 @@
int main()
{
- using namespace boost;
-
X x;
// 0
- thread( &X::f0, &x ).join();
- thread( &X::f0, ref(x) ).join();
+ boost::thread( &X::f0, &x ).join();
+ boost::thread( &X::f0, boost::ref(x) ).join();
- thread( &X::g0, &x ).join();
- thread( &X::g0, x ).join();
- thread( &X::g0, ref(x) ).join();
+ boost::thread( &X::g0, &x ).join();
+ boost::thread( &X::g0, x ).join();
+ boost::thread( &X::g0, boost::ref(x) ).join();
// 1
- thread( &X::f1, &x, 1 ).join();
- thread( &X::f1, ref(x), 1 ).join();
+ boost::thread( &X::f1, &x, 1 ).join();
+ boost::thread( &X::f1, boost::ref(x), 1 ).join();
- thread( &X::g1, &x, 1 ).join();
- thread( &X::g1, x, 1 ).join();
- thread( &X::g1, ref(x), 1 ).join();
+ boost::thread( &X::g1, &x, 1 ).join();
+ boost::thread( &X::g1, x, 1 ).join();
+ boost::thread( &X::g1, boost::ref(x), 1 ).join();
// 2
- thread( &X::f2, &x, 1, 2 ).join();
- thread( &X::f2, ref(x), 1, 2 ).join();
+ boost::thread( &X::f2, &x, 1, 2 ).join();
+ boost::thread( &X::f2, boost::ref(x), 1, 2 ).join();
- thread( &X::g2, &x, 1, 2 ).join();
- thread( &X::g2, x, 1, 2 ).join();
- thread( &X::g2, ref(x), 1, 2 ).join();
+ boost::thread( &X::g2, &x, 1, 2 ).join();
+ boost::thread( &X::g2, x, 1, 2 ).join();
+ boost::thread( &X::g2, boost::ref(x), 1, 2 ).join();
// 3
- thread( &X::f3, &x, 1, 2, 3 ).join();
- thread( &X::f3, ref(x), 1, 2, 3 ).join();
+ boost::thread( &X::f3, &x, 1, 2, 3 ).join();
+ boost::thread( &X::f3, boost::ref(x), 1, 2, 3 ).join();
- thread( &X::g3, &x, 1, 2, 3 ).join();
- thread( &X::g3, x, 1, 2, 3 ).join();
- thread( &X::g3, ref(x), 1, 2, 3 ).join();
+ boost::thread( &X::g3, &x, 1, 2, 3 ).join();
+ boost::thread( &X::g3, x, 1, 2, 3 ).join();
+ boost::thread( &X::g3, boost::ref(x), 1, 2, 3 ).join();
// 4
- thread( &X::f4, &x, 1, 2, 3, 4 ).join();
- thread( &X::f4, ref(x), 1, 2, 3, 4 ).join();
+ boost::thread( &X::f4, &x, 1, 2, 3, 4 ).join();
+ boost::thread( &X::f4, boost::ref(x), 1, 2, 3, 4 ).join();
- thread( &X::g4, &x, 1, 2, 3, 4 ).join();
- thread( &X::g4, x, 1, 2, 3, 4 ).join();
- thread( &X::g4, ref(x), 1, 2, 3, 4 ).join();
+ boost::thread( &X::g4, &x, 1, 2, 3, 4 ).join();
+ boost::thread( &X::g4, x, 1, 2, 3, 4 ).join();
+ boost::thread( &X::g4, boost::ref(x), 1, 2, 3, 4 ).join();
// 5
- thread( &X::f5, &x, 1, 2, 3, 4, 5 ).join();
- thread( &X::f5, ref(x), 1, 2, 3, 4, 5 ).join();
+ boost::thread( &X::f5, &x, 1, 2, 3, 4, 5 ).join();
+ boost::thread( &X::f5, boost::ref(x), 1, 2, 3, 4, 5 ).join();
- thread( &X::g5, &x, 1, 2, 3, 4, 5 ).join();
- thread( &X::g5, x, 1, 2, 3, 4, 5 ).join();
- thread( &X::g5, ref(x), 1, 2, 3, 4, 5 ).join();
+ boost::thread( &X::g5, &x, 1, 2, 3, 4, 5 ).join();
+ boost::thread( &X::g5, x, 1, 2, 3, 4, 5 ).join();
+ boost::thread( &X::g5, boost::ref(x), 1, 2, 3, 4, 5 ).join();
// 6
- thread( &X::f6, &x, 1, 2, 3, 4, 5, 6 ).join();
- thread( &X::f6, ref(x), 1, 2, 3, 4, 5, 6 ).join();
+ boost::thread( &X::f6, &x, 1, 2, 3, 4, 5, 6 ).join();
+ boost::thread( &X::f6, boost::ref(x), 1, 2, 3, 4, 5, 6 ).join();
- thread( &X::g6, &x, 1, 2, 3, 4, 5, 6 ).join();
- thread( &X::g6, x, 1, 2, 3, 4, 5, 6 ).join();
- thread( &X::g6, ref(x), 1, 2, 3, 4, 5, 6 ).join();
+ boost::thread( &X::g6, &x, 1, 2, 3, 4, 5, 6 ).join();
+ boost::thread( &X::g6, x, 1, 2, 3, 4, 5, 6 ).join();
+ boost::thread( &X::g6, boost::ref(x), 1, 2, 3, 4, 5, 6 ).join();
// 7
- thread( &X::f7, &x, 1, 2, 3, 4, 5, 6, 7).join();
- thread( &X::f7, ref(x), 1, 2, 3, 4, 5, 6, 7).join();
+ boost::thread( &X::f7, &x, 1, 2, 3, 4, 5, 6, 7).join();
+ boost::thread( &X::f7, boost::ref(x), 1, 2, 3, 4, 5, 6, 7).join();
- thread( &X::g7, &x, 1, 2, 3, 4, 5, 6, 7).join();
- thread( &X::g7, x, 1, 2, 3, 4, 5, 6, 7).join();
- thread( &X::g7, ref(x), 1, 2, 3, 4, 5, 6, 7).join();
+ boost::thread( &X::g7, &x, 1, 2, 3, 4, 5, 6, 7).join();
+ boost::thread( &X::g7, x, 1, 2, 3, 4, 5, 6, 7).join();
+ boost::thread( &X::g7, boost::ref(x), 1, 2, 3, 4, 5, 6, 7).join();
// 8
- thread( &X::f8, &x, 1, 2, 3, 4, 5, 6, 7, 8 ).join();
- thread( &X::f8, ref(x), 1, 2, 3, 4, 5, 6, 7, 8 ).join();
+ boost::thread( &X::f8, &x, 1, 2, 3, 4, 5, 6, 7, 8 ).join();
+ boost::thread( &X::f8, boost::ref(x), 1, 2, 3, 4, 5, 6, 7, 8 ).join();
- thread( &X::g8, &x, 1, 2, 3, 4, 5, 6, 7, 8 ).join();
- thread( &X::g8, x, 1, 2, 3, 4, 5, 6, 7, 8 ).join();
- thread( &X::g8, ref(x), 1, 2, 3, 4, 5, 6, 7, 8 ).join();
+ boost::thread( &X::g8, &x, 1, 2, 3, 4, 5, 6, 7, 8 ).join();
+ boost::thread( &X::g8, x, 1, 2, 3, 4, 5, 6, 7, 8 ).join();
+ boost::thread( &X::g8, boost::ref(x), 1, 2, 3, 4, 5, 6, 7, 8 ).join();
BOOST_TEST( x.hash == 23558 );
- return report_errors();
+ return boost::report_errors();
}
Modified: branches/release/libs/thread/test/test_xtime.cpp
==============================================================================
--- branches/release/libs/thread/test/test_xtime.cpp (original)
+++ branches/release/libs/thread/test/test_xtime.cpp 2008-07-08 03:44:55 EDT (Tue, 08 Jul 2008)
@@ -1,5 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
+// Copyright (C) 2008 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -9,6 +10,8 @@
#include <boost/thread/xtime.hpp>
#include <boost/test/unit_test.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
void test_xtime_cmp()
{
@@ -53,6 +56,45 @@
}
}
+void test_xtime_mutex_backwards_compatibility()
+{
+ boost::timed_mutex m;
+ BOOST_CHECK(m.timed_lock(boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10))));
+ m.unlock();
+ boost::timed_mutex::scoped_timed_lock lk(m,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)));
+ BOOST_CHECK(lk.owns_lock());
+ if(lk.owns_lock())
+ {
+ lk.unlock();
+ }
+ BOOST_CHECK(lk.timed_lock(boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10))));
+ if(lk.owns_lock())
+ {
+ lk.unlock();
+ }
+}
+
+bool predicate()
+{
+ return false;
+}
+
+
+void test_xtime_condvar_backwards_compatibility()
+{
+ boost::condition_variable cond;
+ boost::condition_variable_any cond_any;
+ boost::mutex m;
+
+ boost::mutex::scoped_lock lk(m);
+ cond.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)));
+ cond.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)),predicate);
+ cond_any.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)));
+ cond_any.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)),predicate);
+}
+
+
+
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test =
@@ -60,6 +102,8 @@
test->add(BOOST_TEST_CASE(&test_xtime_cmp));
test->add(BOOST_TEST_CASE(&test_xtime_get));
+ test->add(BOOST_TEST_CASE(&test_xtime_mutex_backwards_compatibility));
+ test->add(BOOST_TEST_CASE(&test_xtime_condvar_backwards_compatibility));
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