|
Boost-Commit : |
From: anthony_at_[hidden]
Date: 2007-10-10 11:33:51
Author: anthonyw
Date: 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
New Revision: 39891
URL: http://svn.boost.org/trac/boost/changeset/39891
Log:
read_write_mutex makes a comeback --- as shared_mutex
Added:
trunk/boost/thread/pthread/shared_mutex.hpp (contents, props changed)
trunk/boost/thread/shared_mutex.hpp (contents, props changed)
trunk/boost/thread/win32/shared_mutex.hpp (contents, props changed)
trunk/libs/thread/test/test_lock_concept.cpp (contents, props changed)
trunk/libs/thread/test/test_shared_mutex.cpp (contents, props changed)
Removed:
trunk/libs/thread/src/mutex.cpp
trunk/libs/thread/src/mutex.inl
trunk/libs/thread/src/once.cpp
trunk/libs/thread/src/recursive_mutex.cpp
Text files modified:
trunk/boost/thread/locks.hpp | 162 ++++++++++++++++++++++++---------------
trunk/boost/thread/thread_time.hpp | 2
trunk/boost/thread/win32/thread_primitives.hpp | 3
trunk/boost/thread/xtime.hpp | 12 ++
trunk/libs/thread/test/Jamfile.v2 | 3
5 files changed, 115 insertions(+), 67 deletions(-)
Modified: trunk/boost/thread/locks.hpp
==============================================================================
--- trunk/boost/thread/locks.hpp (original)
+++ trunk/boost/thread/locks.hpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
@@ -24,13 +24,13 @@
const adopt_lock_t adopt_lock={};
template<typename Mutex>
- class shareable_lock;
+ class shared_lock;
template<typename Mutex>
class exclusive_lock;
template<typename Mutex>
- class upgradeable_lock;
+ class upgrade_lock;
template<typename Mutex>
class lock_guard
@@ -86,21 +86,21 @@
{
timed_lock(target_time);
}
- unique_lock(boost::move_t<unique_lock> other):
+ unique_lock(boost::move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
}
- unique_lock(boost::move_t<upgradeable_lock<Mutex> > other);
+ unique_lock(boost::move_t<upgrade_lock<Mutex> > other);
- unique_lock& operator=(boost::move_t<unique_lock> other)
+ unique_lock& operator=(boost::move_t<unique_lock<Mutex> > other)
{
unique_lock temp(other);
swap(temp);
return *this;
}
- unique_lock& operator=(boost::move_t<upgradeable_lock<Mutex> > other)
+ unique_lock& operator=(boost::move_t<upgrade_lock<Mutex> > other)
{
unique_lock temp(other);
swap(temp);
@@ -112,7 +112,7 @@
std::swap(m,other.m);
std::swap(is_locked,other.is_locked);
}
- void swap(boost::move_t<unique_lock> other)
+ void swap(boost::move_t<unique_lock<Mutex> > other)
{
std::swap(m,other->m);
std::swap(is_locked,other->is_locked);
@@ -170,6 +170,10 @@
{
return is_locked?&unique_lock::lock:0;
}
+ bool operator!() const
+ {
+ return !owns_lock();
+ }
bool owns_lock() const
{
return is_locked;
@@ -188,91 +192,100 @@
return res;
}
- friend class shareable_lock<Mutex>;
- friend class upgradeable_lock<Mutex>;
+ friend class shared_lock<Mutex>;
+ friend class upgrade_lock<Mutex>;
};
template<typename Mutex>
- class shareable_lock
+ class shared_lock
{
protected:
Mutex* m;
bool is_locked;
private:
- explicit shareable_lock(shareable_lock&);
- shareable_lock& operator=(shareable_lock&);
+ explicit shared_lock(shared_lock&);
+ shared_lock& operator=(shared_lock&);
public:
- explicit shareable_lock(Mutex& m_):
+ explicit shared_lock(Mutex& m_):
m(&m_),is_locked(false)
{
lock();
}
- shareable_lock(Mutex& m_,bool do_lock):
+ shared_lock(Mutex& m_,adopt_lock_t):
+ m(&m_),is_locked(true)
+ {}
+ shared_lock(Mutex& m_,defer_lock_t):
+ m(&m_),is_locked(false)
+ {}
+ shared_lock(Mutex& m_,try_to_lock_t):
m(&m_),is_locked(false)
{
- if(do_lock)
- {
- lock();
- }
+ try_lock();
+ }
+ shared_lock(Mutex& m_,system_time const& target_time):
+ m(&m_),is_locked(false)
+ {
+ timed_lock(target_time);
}
- shareable_lock(boost::move_t<shareable_lock> other):
+
+ shared_lock(boost::move_t<shared_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
}
- shareable_lock(boost::move_t<unique_lock<Mutex> > other):
+ shared_lock(boost::move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
if(is_locked)
{
- m->unlock_and_lock_shareable();
+ m->unlock_and_lock_shared();
}
}
- shareable_lock(boost::move_t<upgradeable_lock<Mutex> > other):
+ shared_lock(boost::move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
if(is_locked)
{
- m->unlock_upgradeable_and_lock_shareable();
+ m->unlock_upgrade_and_lock_shared();
}
}
- shareable_lock& operator=(boost::move_t<shareable_lock> other)
+ shared_lock& operator=(boost::move_t<shared_lock<Mutex> > other)
{
- shareable_lock temp(other);
+ shared_lock temp(other);
swap(temp);
return *this;
}
- shareable_lock& operator=(boost::move_t<unique_lock<Mutex> > other)
+ shared_lock& operator=(boost::move_t<unique_lock<Mutex> > other)
{
- shareable_lock temp(other);
+ shared_lock temp(other);
swap(temp);
return *this;
}
- shareable_lock& operator=(boost::move_t<upgradeable_lock<Mutex> > other)
+ shared_lock& operator=(boost::move_t<upgrade_lock<Mutex> > other)
{
- shareable_lock temp(other);
+ shared_lock temp(other);
swap(temp);
return *this;
}
- void swap(shareable_lock& other)
+ void swap(shared_lock& other)
{
std::swap(m,other.m);
std::swap(is_locked,other.is_locked);
}
- ~shareable_lock()
+ ~shared_lock()
{
if(owns_lock())
{
- m->unlock_shareable();
+ m->unlock_shared();
}
}
void lock()
@@ -281,7 +294,7 @@
{
throw boost::lock_error();
}
- m->lock_shareable();
+ m->lock_shared();
is_locked=true;
}
bool try_lock()
@@ -290,7 +303,16 @@
{
throw boost::lock_error();
}
- is_locked=m->try_lock_shareable();
+ is_locked=m->try_lock_shared();
+ return is_locked;
+ }
+ bool timed_lock(boost::system_time const& target_time)
+ {
+ if(owns_lock())
+ {
+ throw boost::lock_error();
+ }
+ is_locked=m->timed_lock_shared(target_time);
return is_locked;
}
void unlock()
@@ -299,14 +321,18 @@
{
throw boost::lock_error();
}
- m->unlock_shareable();
+ m->unlock_shared();
is_locked=false;
}
- typedef void (shareable_lock::*bool_type)();
+ typedef void (shared_lock::*bool_type)();
operator bool_type() const
{
- return is_locked?&shareable_lock::lock:0;
+ return is_locked?&shared_lock::lock:0;
+ }
+ bool operator!() const
+ {
+ return !owns_lock();
}
bool owns_lock() const
{
@@ -316,21 +342,21 @@
};
template<typename Mutex>
- class upgradeable_lock
+ class upgrade_lock
{
protected:
Mutex* m;
bool is_locked;
private:
- explicit upgradeable_lock(upgradeable_lock&);
- upgradeable_lock& operator=(upgradeable_lock&);
+ explicit upgrade_lock(upgrade_lock&);
+ upgrade_lock& operator=(upgrade_lock&);
public:
- explicit upgradeable_lock(Mutex& m_):
+ explicit upgrade_lock(Mutex& m_):
m(&m_),is_locked(false)
{
lock();
}
- upgradeable_lock(Mutex& m_,bool do_lock):
+ upgrade_lock(Mutex& m_,bool do_lock):
m(&m_),is_locked(false)
{
if(do_lock)
@@ -338,47 +364,47 @@
lock();
}
}
- upgradeable_lock(boost::move_t<upgradeable_lock> other):
+ upgrade_lock(boost::move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
}
- upgradeable_lock(boost::move_t<unique_lock<Mutex> > other):
+ upgrade_lock(boost::move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
if(is_locked)
{
- m->unlock_and_lock_upgradeable();
+ m->unlock_and_lock_upgrade();
}
}
- upgradeable_lock& operator=(boost::move_t<upgradeable_lock> other)
+ upgrade_lock& operator=(boost::move_t<upgrade_lock<Mutex> > other)
{
- upgradeable_lock temp(other);
+ upgrade_lock temp(other);
swap(temp);
return *this;
}
- upgradeable_lock& operator=(boost::move_t<unique_lock<Mutex> > other)
+ upgrade_lock& operator=(boost::move_t<unique_lock<Mutex> > other)
{
- upgradeable_lock temp(other);
+ upgrade_lock temp(other);
swap(temp);
return *this;
}
- void swap(upgradeable_lock& other)
+ void swap(upgrade_lock& other)
{
std::swap(m,other.m);
std::swap(is_locked,other.is_locked);
}
- ~upgradeable_lock()
+ ~upgrade_lock()
{
if(owns_lock())
{
- m->unlock_upgradeable();
+ m->unlock_upgrade();
}
}
void lock()
@@ -387,7 +413,7 @@
{
throw boost::lock_error();
}
- m->lock_upgradeable();
+ m->lock_upgrade();
is_locked=true;
}
bool try_lock()
@@ -396,7 +422,7 @@
{
throw boost::lock_error();
}
- is_locked=m->try_lock_upgradeable();
+ is_locked=m->try_lock_upgrade();
return is_locked;
}
void unlock()
@@ -405,31 +431,35 @@
{
throw boost::lock_error();
}
- m->unlock_upgradeable();
+ m->unlock_upgrade();
is_locked=false;
}
- typedef void (upgradeable_lock::*bool_type)();
+ typedef void (upgrade_lock::*bool_type)();
operator bool_type() const
{
- return is_locked?&upgradeable_lock::lock:0;
+ return is_locked?&upgrade_lock::lock:0;
+ }
+ bool operator!() const
+ {
+ return !owns_lock();
}
bool owns_lock() const
{
return is_locked;
}
- friend class shareable_lock<Mutex>;
+ friend class shared_lock<Mutex>;
friend class unique_lock<Mutex>;
};
template<typename Mutex>
- unique_lock<Mutex>::unique_lock(boost::move_t<upgradeable_lock<Mutex> > other):
+ unique_lock<Mutex>::unique_lock(boost::move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
if(is_locked)
{
- m->unlock_upgradeable_and_lock();
+ m->unlock_upgrade_and_lock();
}
}
@@ -437,13 +467,13 @@
class upgrade_to_unique_lock
{
private:
- upgradeable_lock<Mutex>* source;
+ upgrade_lock<Mutex>* source;
unique_lock<Mutex> exclusive;
explicit upgrade_to_unique_lock(upgrade_to_unique_lock&);
upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&);
public:
- explicit upgrade_to_unique_lock(upgradeable_lock<Mutex>& m_):
+ explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_):
source(&m_),exclusive(boost::move(*source))
{}
~upgrade_to_unique_lock()
@@ -454,13 +484,13 @@
}
}
- upgrade_to_unique_lock(boost::move_t<upgrade_to_unique_lock> other):
+ upgrade_to_unique_lock(boost::move_t<upgrade_to_unique_lock<Mutex> > other):
source(other->source),exclusive(boost::move(other->exclusive))
{
other->source=0;
}
- upgrade_to_unique_lock& operator=(boost::move_t<upgrade_to_unique_lock> other)
+ upgrade_to_unique_lock& operator=(boost::move_t<upgrade_to_unique_lock<Mutex> > other)
{
upgrade_to_unique_lock temp(other);
swap(temp);
@@ -476,6 +506,10 @@
{
return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0;
}
+ bool operator!() const
+ {
+ return !owns_lock();
+ }
bool owns_lock() const
{
return exclusive.owns_lock();
Added: trunk/boost/thread/pthread/shared_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/pthread/shared_mutex.hpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
@@ -0,0 +1,300 @@
+#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
+#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
+
+// (C) Copyright 2006-7 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)
+
+#include <boost/assert.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/xtime.hpp>
+
+namespace boost
+{
+ class shared_mutex
+ {
+ private:
+ struct state_data
+ {
+ unsigned shared_count;
+ bool exclusive;
+ bool upgrade;
+ bool exclusive_waiting_blocked;
+ };
+
+
+
+ state_data state;
+ boost::mutex state_change;
+ boost::condition shared_cond;
+ boost::condition exclusive_cond;
+ boost::condition upgrade_cond;
+
+ void release_waiters()
+ {
+ exclusive_cond.notify_one();
+ shared_cond.notify_all();
+ }
+
+
+ public:
+ shared_mutex()
+ {
+ state_data state_={0};
+ state=state_;
+ }
+
+ ~shared_mutex()
+ {
+ }
+
+ void lock_shared()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+
+ while(true)
+ {
+ if(!state.exclusive && !state.exclusive_waiting_blocked)
+ {
+ ++state.shared_count;
+ return;
+ }
+
+ shared_cond.wait(lock);
+ }
+ }
+
+ bool try_lock_shared()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+
+ if(state.exclusive || state.exclusive_waiting_blocked)
+ {
+ return false;
+ }
+ else
+ {
+ ++state.shared_count;
+ return true;
+ }
+ }
+
+ bool timed_lock_shared(system_time const& timeout)
+ {
+ boost::mutex::scoped_lock lock(state_change);
+
+ while(true)
+ {
+ if(!state.exclusive && !state.exclusive_waiting_blocked)
+ {
+ ++state.shared_count;
+ return true;
+ }
+
+ if(!shared_cond.timed_wait(lock,get_xtime(timeout)))
+ {
+ return false;
+ }
+ }
+ }
+
+ void unlock_shared()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+ bool const last_reader=!--state.shared_count;
+
+ if(last_reader)
+ {
+ if(state.upgrade)
+ {
+ state.upgrade=false;
+ state.exclusive=true;
+ upgrade_cond.notify_one();
+ }
+ else
+ {
+ state.exclusive_waiting_blocked=false;
+ }
+ release_waiters();
+ }
+ }
+
+ void lock()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+
+ while(true)
+ {
+ if(state.shared_count || state.exclusive)
+ {
+ state.exclusive_waiting_blocked=true;
+ }
+ else
+ {
+ state.exclusive=true;
+ return;
+ }
+ exclusive_cond.wait(lock);
+ }
+ }
+
+ bool timed_lock(system_time const& timeout)
+ {
+ boost::mutex::scoped_lock lock(state_change);
+
+ while(true)
+ {
+ if(state.shared_count || state.exclusive)
+ {
+ state.exclusive_waiting_blocked=true;
+ }
+ else
+ {
+ state.exclusive=true;
+ return true;
+ }
+ if(!exclusive_cond.timed_wait(lock,get_xtime(timeout)))
+ {
+ return false;
+ }
+ }
+ }
+
+ bool try_lock()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+
+ if(state.shared_count || state.exclusive)
+ {
+ return false;
+ }
+ else
+ {
+ state.exclusive=true;
+ return true;
+ }
+
+ }
+
+ void unlock()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+ state.exclusive=false;
+ state.exclusive_waiting_blocked=false;
+ release_waiters();
+ }
+
+ void lock_upgrade()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+ while(true)
+ {
+ if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade)
+ {
+ ++state.shared_count;
+ state.upgrade=true;
+ return;
+ }
+
+ shared_cond.wait(lock);
+ }
+ }
+
+ bool timed_lock_upgrade(system_time const& timeout)
+ {
+ boost::mutex::scoped_lock lock(state_change);
+ while(true)
+ {
+ if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade)
+ {
+ ++state.shared_count;
+ state.upgrade=true;
+ return true;
+ }
+
+ if(!shared_cond.timed_wait(lock,get_xtime(timeout)))
+ {
+ return false;
+ }
+ }
+ }
+
+ bool try_lock_upgrade()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+ if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
+ {
+ return false;
+ }
+ else
+ {
+ ++state.shared_count;
+ state.upgrade=true;
+ return true;
+ }
+ }
+
+ void unlock_upgrade()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+ state.upgrade=false;
+ bool const last_reader=!--state.shared_count;
+
+ if(last_reader)
+ {
+ state.exclusive_waiting_blocked=false;
+ release_waiters();
+ }
+ }
+
+ void unlock_upgrade_and_lock()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+ --state.shared_count;
+ while(true)
+ {
+ if(!state.shared_count)
+ {
+ state.upgrade=false;
+ state.exclusive=true;
+ break;
+ }
+ upgrade_cond.wait(lock);
+ }
+ }
+
+ void unlock_and_lock_upgrade()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+ state.exclusive=false;
+ state.upgrade=true;
+ ++state.shared_count;
+ state.exclusive_waiting_blocked=false;
+ release_waiters();
+ }
+
+ void unlock_and_lock_shared()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+ state.exclusive=false;
+ ++state.shared_count;
+ state.exclusive_waiting_blocked=false;
+ release_waiters();
+ }
+
+ void unlock_upgrade_and_lock_shared()
+ {
+ boost::mutex::scoped_lock lock(state_change);
+ state.upgrade=false;
+ state.exclusive_waiting_blocked=false;
+ release_waiters();
+ }
+ };
+}
+
+
+#endif
Added: trunk/boost/thread/shared_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/shared_mutex.hpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
@@ -0,0 +1,15 @@
+#ifndef BOOST_THREAD_SHARED_MUTEX_HPP
+#define BOOST_THREAD_SHARED_MUTEX_HPP
+
+// shared_mutex.hpp
+//
+// (C) Copyright 2007 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)
+
+#include <boost/thread/detail/platform.hpp>
+#include BOOST_THREAD_PLATFORM(shared_mutex.hpp)
+
+#endif
Modified: trunk/boost/thread/thread_time.hpp
==============================================================================
--- trunk/boost/thread/thread_time.hpp (original)
+++ trunk/boost/thread/thread_time.hpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
@@ -30,7 +30,7 @@
{
return 0;
}
- return (target_time-now).total_milliseconds();
+ return (target_time-now).total_milliseconds()+1;
}
}
Added: trunk/boost/thread/win32/shared_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/win32/shared_mutex.hpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
@@ -0,0 +1,516 @@
+#ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
+#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
+
+// (C) Copyright 2006-7 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)
+
+#include <boost/assert.hpp>
+#include <boost/detail/interlocked.hpp>
+#include <boost/thread/win32/thread_primitives.hpp>
+#include <boost/static_assert.hpp>
+#include <limits.h>
+#include <boost/utility.hpp>
+#include <boost/thread/thread_time.hpp>
+
+namespace boost
+{
+ class shared_mutex:
+ private boost::noncopyable
+ {
+ private:
+ struct state_data
+ {
+ unsigned shared_count:11;
+ unsigned shared_waiting:11;
+ unsigned exclusive:1;
+ unsigned upgrade:1;
+ unsigned exclusive_waiting:7;
+ unsigned exclusive_waiting_blocked:1;
+
+ friend bool operator==(state_data const& lhs,state_data const& rhs)
+ {
+ return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
+ }
+ };
+
+
+ template<typename T>
+ T interlocked_compare_exchange(T* target,T new_value,T comparand)
+ {
+ BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
+ long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
+ *reinterpret_cast<long*>(&new_value),
+ *reinterpret_cast<long*>(&comparand));
+ return *reinterpret_cast<T const*>(&res);
+ }
+
+ state_data state;
+ void* semaphores[2];
+ void* &unlock_sem;
+ void* &exclusive_sem;
+ void* upgrade_sem;
+
+ void release_waiters(state_data old_state)
+ {
+ if(old_state.exclusive_waiting)
+ {
+ bool const success=detail::win32::ReleaseSemaphore(exclusive_sem,1,NULL)!=0;
+ BOOST_ASSERT(success);
+ }
+
+ if(old_state.shared_waiting || old_state.exclusive_waiting)
+ {
+ bool const success=detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),NULL)!=0;
+ BOOST_ASSERT(success);
+ }
+ }
+
+
+ public:
+ shared_mutex():
+ unlock_sem(semaphores[0]),
+ exclusive_sem(semaphores[1])
+ {
+ unlock_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
+ exclusive_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
+ upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
+ state_data state_={0};
+ state=state_;
+ }
+
+ ~shared_mutex()
+ {
+ detail::win32::CloseHandle(upgrade_sem);
+ detail::win32::CloseHandle(unlock_sem);
+ detail::win32::CloseHandle(exclusive_sem);
+ }
+
+ bool try_lock_shared()
+ {
+ state_data old_state=state;
+ do
+ {
+ state_data new_state=old_state;
+ if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
+ {
+ ++new_state.shared_count;
+ }
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ break;
+ }
+ old_state=current_state;
+ }
+ while(true);
+ return !(old_state.exclusive| old_state.exclusive_waiting_blocked);
+ }
+
+ void lock_shared()
+ {
+ bool const success=timed_lock_shared(::boost::detail::get_system_time_sentinel());
+ BOOST_ASSERT(success);
+ }
+
+ bool timed_lock_shared(boost::system_time const& wait_until)
+ {
+ while(true)
+ {
+ state_data old_state=state;
+ do
+ {
+ state_data new_state=old_state;
+ if(new_state.exclusive || new_state.exclusive_waiting_blocked)
+ {
+ ++new_state.shared_waiting;
+ }
+ else
+ {
+ ++new_state.shared_count;
+ }
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ break;
+ }
+ old_state=current_state;
+ }
+ while(true);
+
+ if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
+ {
+ return true;
+ }
+
+ unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,::boost::detail::get_milliseconds_until(wait_until));
+ if(res==detail::win32::timeout)
+ {
+ do
+ {
+ state_data new_state=old_state;
+ if(new_state.exclusive || new_state.exclusive_waiting_blocked)
+ {
+ if(new_state.shared_waiting)
+ {
+ --new_state.shared_waiting;
+ }
+ }
+ else
+ {
+ ++new_state.shared_count;
+ }
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ break;
+ }
+ old_state=current_state;
+ }
+ while(true);
+
+ if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ BOOST_ASSERT(res==0);
+ }
+ }
+
+ void unlock_shared()
+ {
+ state_data old_state=state;
+ do
+ {
+ state_data new_state=old_state;
+ bool const last_reader=!--new_state.shared_count;
+
+ if(last_reader)
+ {
+ if(new_state.upgrade)
+ {
+ new_state.upgrade=false;
+ new_state.exclusive=true;
+ }
+ else
+ {
+ if(new_state.exclusive_waiting)
+ {
+ --new_state.exclusive_waiting;
+ new_state.exclusive_waiting_blocked=false;
+ }
+ new_state.shared_waiting=0;
+ }
+ }
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ if(last_reader)
+ {
+ if(old_state.upgrade)
+ {
+ bool const success=detail::win32::ReleaseSemaphore(upgrade_sem,1,NULL)!=0;
+ BOOST_ASSERT(success);
+ }
+ else
+ {
+ release_waiters(old_state);
+ }
+ }
+ break;
+ }
+ old_state=current_state;
+ }
+ while(true);
+ }
+
+ void lock()
+ {
+ bool const success=timed_lock(::boost::detail::get_system_time_sentinel());
+ BOOST_ASSERT(success);
+ }
+
+ bool timed_lock(boost::system_time const& wait_until)
+ {
+ while(true)
+ {
+ state_data old_state=state;
+
+ do
+ {
+ state_data new_state=old_state;
+ if(new_state.shared_count || new_state.exclusive)
+ {
+ ++new_state.exclusive_waiting;
+ new_state.exclusive_waiting_blocked=true;
+ }
+ 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;
+ }
+ while(true);
+
+ if(!old_state.shared_count && !old_state.exclusive)
+ {
+ return true;
+ }
+ 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
+ {
+ state_data new_state=old_state;
+ if(new_state.shared_count || new_state.exclusive)
+ {
+ if(new_state.exclusive_waiting)
+ {
+ --new_state.exclusive_waiting;
+ }
+ }
+ 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;
+ }
+ while(true);
+ if(!old_state.shared_count && !old_state.exclusive)
+ {
+ return true;
+ }
+ return false;
+ }
+ BOOST_ASSERT(wait_res<2);
+ }
+ }
+
+ void unlock()
+ {
+ state_data old_state=state;
+ do
+ {
+ state_data new_state=old_state;
+ new_state.exclusive=false;
+ if(new_state.exclusive_waiting)
+ {
+ --new_state.exclusive_waiting;
+ new_state.exclusive_waiting_blocked=false;
+ }
+ new_state.shared_waiting=0;
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ break;
+ }
+ old_state=current_state;
+ }
+ while(true);
+ release_waiters(old_state);
+ }
+
+ void lock_upgrade()
+ {
+ while(true)
+ {
+ state_data old_state=state;
+ do
+ {
+ state_data new_state=old_state;
+ if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
+ {
+ ++new_state.shared_waiting;
+ }
+ 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;
+ }
+ while(true);
+
+ if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade))
+ {
+ return;
+ }
+
+ unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite);
+ BOOST_ASSERT(res==0);
+ }
+ }
+
+ void unlock_upgrade()
+ {
+ state_data old_state=state;
+ do
+ {
+ state_data new_state=old_state;
+ new_state.upgrade=false;
+ bool const last_reader=!--new_state.shared_count;
+
+ if(last_reader)
+ {
+ if(new_state.exclusive_waiting)
+ {
+ --new_state.exclusive_waiting;
+ new_state.exclusive_waiting_blocked=false;
+ }
+ new_state.shared_waiting=0;
+ }
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ if(last_reader)
+ {
+ release_waiters(old_state);
+ }
+ break;
+ }
+ old_state=current_state;
+ }
+ while(true);
+ }
+
+ void unlock_upgrade_and_lock()
+ {
+ state_data old_state=state;
+ do
+ {
+ state_data new_state=old_state;
+ bool const last_reader=!--new_state.shared_count;
+
+ if(last_reader)
+ {
+ new_state.upgrade=false;
+ new_state.exclusive=true;
+ }
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ if(!last_reader)
+ {
+ unsigned long const res=detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite);
+ BOOST_ASSERT(res==0);
+ }
+ break;
+ }
+ old_state=current_state;
+ }
+ while(true);
+ }
+
+ void unlock_and_lock_upgrade()
+ {
+ state_data old_state=state;
+ do
+ {
+ state_data new_state=old_state;
+ new_state.exclusive=false;
+ new_state.upgrade=true;
+ ++new_state.shared_count;
+ if(new_state.exclusive_waiting)
+ {
+ --new_state.exclusive_waiting;
+ new_state.exclusive_waiting_blocked=false;
+ }
+ new_state.shared_waiting=0;
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ break;
+ }
+ old_state=current_state;
+ }
+ while(true);
+ release_waiters(old_state);
+ }
+
+ void unlock_and_lock_shared()
+ {
+ state_data old_state=state;
+ do
+ {
+ state_data new_state=old_state;
+ new_state.exclusive=false;
+ ++new_state.shared_count;
+ if(new_state.exclusive_waiting)
+ {
+ --new_state.exclusive_waiting;
+ new_state.exclusive_waiting_blocked=false;
+ }
+ new_state.shared_waiting=0;
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ break;
+ }
+ old_state=current_state;
+ }
+ while(true);
+ release_waiters(old_state);
+ }
+
+ void unlock_upgrade_and_lock_shared()
+ {
+ state_data old_state=state;
+ do
+ {
+ state_data new_state=old_state;
+ new_state.upgrade=false;
+ if(new_state.exclusive_waiting)
+ {
+ --new_state.exclusive_waiting;
+ new_state.exclusive_waiting_blocked=false;
+ }
+ new_state.shared_waiting=0;
+
+ state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if(current_state==old_state)
+ {
+ break;
+ }
+ old_state=current_state;
+ }
+ while(true);
+ release_waiters(old_state);
+ }
+
+ };
+}
+
+
+#endif
Modified: trunk/boost/thread/win32/thread_primitives.hpp
==============================================================================
--- trunk/boost/thread/win32/thread_primitives.hpp (original)
+++ trunk/boost/thread/win32/thread_primitives.hpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
@@ -112,7 +112,7 @@
inline handle create_anonymous_event(event_type type,initial_event_state state)
{
- handle const res=CreateEventA(0,type,state,0);
+ handle const res=win32::CreateEventA(0,type,state,0);
if(!res)
{
throw thread_resource_error();
@@ -177,6 +177,7 @@
{
cleanup();
handle_to_manage=new_handle;
+ return *this;
}
operator handle() const
Modified: trunk/boost/thread/xtime.hpp
==============================================================================
--- trunk/boost/thread/xtime.hpp (original)
+++ trunk/boost/thread/xtime.hpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
@@ -10,6 +10,8 @@
#include <boost/thread/detail/config.hpp>
#include <boost/cstdint.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/date_time/posix_time/conversion.hpp>
namespace boost {
@@ -49,6 +51,16 @@
return (xt1.sec > xt2.sec) ? 1 : -1;
}
+inline xtime get_xtime(boost::system_time const& abs_time)
+{
+ xtime res={0};
+ boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
+
+ res.sec=time_since_epoch.total_seconds();
+ res.nsec=time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second());
+ return res;
+}
+
} // namespace boost
#endif //BOOST_XTIME_WEK070601_HPP
Deleted: trunk/libs/thread/src/mutex.cpp
==============================================================================
--- trunk/libs/thread/src/mutex.cpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
+++ (empty file)
@@ -1,561 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-//
-// 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)
-
-#include <boost/thread/detail/config.hpp>
-
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/xtime.hpp>
-#include <boost/thread/thread.hpp>
-#include <boost/thread/exceptions.hpp>
-#include <boost/limits.hpp>
-#include <string>
-#include <stdexcept>
-#include <cassert>
-#include "timeconv.inl"
-
-#if defined(BOOST_HAS_WINTHREADS)
-# include <new>
-# include <boost/thread/once.hpp>
-# include <windows.h>
-# include <time.h>
-# include "mutex.inl"
-#elif defined(BOOST_HAS_PTHREADS)
-# include <errno.h>
-#elif defined(BOOST_HAS_MPTASKS)
-# include <MacErrors.h>
-# include "mac/init.hpp"
-# include "mac/safe.hpp"
-#endif
-
-namespace boost {
-
-#if defined(BOOST_HAS_WINTHREADS)
-
-mutex::mutex()
- : m_mutex(0)
- , m_critical_section(false)
-{
- m_critical_section = true;
- if (m_critical_section)
- m_mutex = new_critical_section();
- else
- m_mutex = new_mutex(0);
-}
-
-mutex::~mutex()
-{
- if (m_critical_section)
- delete_critical_section(m_mutex);
- else
- delete_mutex(m_mutex);
-}
-
-void mutex::do_lock()
-{
- if (m_critical_section)
- wait_critical_section_infinite(m_mutex);
- else
- wait_mutex(m_mutex, INFINITE);
-}
-
-void mutex::do_unlock()
-{
- if (m_critical_section)
- release_critical_section(m_mutex);
- else
- release_mutex(m_mutex);
-}
-
-void mutex::do_lock(cv_state&)
-{
- do_lock();
-}
-
-void mutex::do_unlock(cv_state&)
-{
- do_unlock();
-}
-
-try_mutex::try_mutex()
- : m_mutex(0)
- , m_critical_section(false)
-{
- m_critical_section = has_TryEnterCriticalSection();
- if (m_critical_section)
- m_mutex = new_critical_section();
- else
- m_mutex = new_mutex(0);
-}
-
-try_mutex::~try_mutex()
-{
- if (m_critical_section)
- delete_critical_section(m_mutex);
- else
- delete_mutex(m_mutex);
-}
-
-void try_mutex::do_lock()
-{
- if (m_critical_section)
- wait_critical_section_infinite(m_mutex);
- else
- wait_mutex(m_mutex, INFINITE);
-}
-
-bool try_mutex::do_trylock()
-{
- if (m_critical_section)
- return wait_critical_section_try(m_mutex);
- else
- return wait_mutex(m_mutex, 0) == WAIT_OBJECT_0;
-}
-
-void try_mutex::do_unlock()
-{
- if (m_critical_section)
- release_critical_section(m_mutex);
- else
- release_mutex(m_mutex);
-}
-
-void try_mutex::do_lock(cv_state&)
-{
- do_lock();
-}
-
-void try_mutex::do_unlock(cv_state&)
-{
- do_unlock();
-}
-
-timed_mutex::timed_mutex()
- : m_mutex(0)
-{
- m_mutex = new_mutex(0);
-}
-
-timed_mutex::~timed_mutex()
-{
- delete_mutex(m_mutex);
-}
-
-void timed_mutex::do_lock()
-{
- wait_mutex(m_mutex, INFINITE);
-}
-
-bool timed_mutex::do_trylock()
-{
- return wait_mutex(m_mutex, 0) == WAIT_OBJECT_0;
-}
-
-bool timed_mutex::do_timedlock(const xtime& xt)
-{
- for (;;)
- {
- int milliseconds;
- to_duration(xt, milliseconds);
-
- int res = wait_mutex(m_mutex, milliseconds);
-
- if (res == WAIT_TIMEOUT)
- {
- boost::xtime cur;
- boost::xtime_get(&cur, boost::TIME_UTC);
- if (boost::xtime_cmp(xt, cur) > 0)
- continue;
- }
-
- return res == WAIT_OBJECT_0;
- }
-}
-
-void timed_mutex::do_unlock()
-{
- release_mutex(m_mutex);
-}
-
-void timed_mutex::do_lock(cv_state&)
-{
- do_lock();
-}
-
-void timed_mutex::do_unlock(cv_state&)
-{
- do_unlock();
-}
-
-#elif defined(BOOST_HAS_PTHREADS)
-
-mutex::mutex()
-{
- int res = 0;
- res = pthread_mutex_init(&m_mutex, 0);
- if (res != 0)
- throw thread_resource_error();
-}
-
-mutex::~mutex()
-{
- int res = 0;
- res = pthread_mutex_destroy(&m_mutex);
- assert(res == 0);
-}
-
-void mutex::do_lock()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- if (res == EDEADLK) throw lock_error();
- assert(res == 0);
-}
-
-void mutex::do_unlock()
-{
- int res = 0;
- res = pthread_mutex_unlock(&m_mutex);
- if (res == EPERM) throw lock_error();
- assert(res == 0);
-}
-
-void mutex::do_lock(cv_state&)
-{
-}
-
-void mutex::do_unlock(cv_state& state)
-{
- state.pmutex = &m_mutex;
-}
-
-try_mutex::try_mutex()
-{
- int res = 0;
- res = pthread_mutex_init(&m_mutex, 0);
- if (res != 0)
- throw thread_resource_error();
-}
-
-try_mutex::~try_mutex()
-{
- int res = 0;
- res = pthread_mutex_destroy(&m_mutex);
- assert(res == 0);
-}
-
-void try_mutex::do_lock()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- if (res == EDEADLK) throw lock_error();
- assert(res == 0);
-}
-
-bool try_mutex::do_trylock()
-{
- int res = 0;
- res = pthread_mutex_trylock(&m_mutex);
- if (res == EDEADLK) throw lock_error();
- assert(res == 0 || res == EBUSY);
- return res == 0;
-}
-
-void try_mutex::do_unlock()
-{
- int res = 0;
- res = pthread_mutex_unlock(&m_mutex);
- if (res == EPERM) throw lock_error();
- assert(res == 0);
-}
-
-void try_mutex::do_lock(cv_state&)
-{
-}
-
-void try_mutex::do_unlock(cv_state& state)
-{
- state.pmutex = &m_mutex;
-}
-
-timed_mutex::timed_mutex()
- : m_locked(false)
-{
- int res = 0;
- res = pthread_mutex_init(&m_mutex, 0);
- if (res != 0)
- throw thread_resource_error();
-
- res = pthread_cond_init(&m_condition, 0);
- if (res != 0)
- {
- pthread_mutex_destroy(&m_mutex);
- throw thread_resource_error();
- }
-}
-
-timed_mutex::~timed_mutex()
-{
- assert(!m_locked);
- int res = 0;
- res = pthread_mutex_destroy(&m_mutex);
- assert(res == 0);
-
- res = pthread_cond_destroy(&m_condition);
- assert(res == 0);
-}
-
-void timed_mutex::do_lock()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- while (m_locked)
- {
- res = pthread_cond_wait(&m_condition, &m_mutex);
- assert(res == 0);
- }
-
- assert(!m_locked);
- m_locked = true;
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-}
-
-bool timed_mutex::do_trylock()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- bool ret = false;
- if (!m_locked)
- {
- m_locked = true;
- ret = true;
- }
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- return ret;
-}
-
-bool timed_mutex::do_timedlock(const xtime& xt)
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- timespec ts;
- to_timespec(xt, ts);
-
- while (m_locked)
- {
- res = pthread_cond_timedwait(&m_condition, &m_mutex, &ts);
- assert(res == 0 || res == ETIMEDOUT);
-
- if (res == ETIMEDOUT)
- break;
- }
-
- bool ret = false;
- if (!m_locked)
- {
- m_locked = true;
- ret = true;
- }
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- return ret;
-}
-
-void timed_mutex::do_unlock()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- assert(m_locked);
- m_locked = false;
-
- res = pthread_cond_signal(&m_condition);
- assert(res == 0);
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-}
-
-void timed_mutex::do_lock(cv_state&)
-{
- int res = 0;
- while (m_locked)
- {
- res = pthread_cond_wait(&m_condition, &m_mutex);
- assert(res == 0);
- }
-
- assert(!m_locked);
- m_locked = true;
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-}
-
-void timed_mutex::do_unlock(cv_state& state)
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- assert(m_locked);
- m_locked = false;
-
- res = pthread_cond_signal(&m_condition);
- assert(res == 0);
-
- state.pmutex = &m_mutex;
-}
-
-#elif defined(BOOST_HAS_MPTASKS)
-
-using threads::mac::detail::safe_enter_critical_region;
-
-mutex::mutex()
-{
-}
-
-mutex::~mutex()
-{
-}
-
-void mutex::do_lock()
-{
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
-}
-
-void mutex::do_unlock()
-{
- OSStatus lStatus = noErr;
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
-}
-
-void mutex::do_lock(cv_state& /*state*/)
-{
- do_lock();
-}
-
-void mutex::do_unlock(cv_state& /*state*/)
-{
- do_unlock();
-}
-
-try_mutex::try_mutex()
-{
-}
-
-try_mutex::~try_mutex()
-{
-}
-
-void try_mutex::do_lock()
-{
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
-}
-
-bool try_mutex::do_trylock()
-{
- OSStatus lStatus = noErr;
- lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
- assert(lStatus == noErr || lStatus == kMPTimeoutErr);
- return lStatus == noErr;
-}
-
-void try_mutex::do_unlock()
-{
- OSStatus lStatus = noErr;
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
-}
-
-void try_mutex::do_lock(cv_state& /*state*/)
-{
- do_lock();
-}
-
-void try_mutex::do_unlock(cv_state& /*state*/)
-{
- do_unlock();
-}
-
-timed_mutex::timed_mutex()
-{
-}
-
-timed_mutex::~timed_mutex()
-{
-}
-
-void timed_mutex::do_lock()
-{
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
-}
-
-bool timed_mutex::do_trylock()
-{
- OSStatus lStatus = noErr;
- lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
- assert(lStatus == noErr || lStatus == kMPTimeoutErr);
- return(lStatus == noErr);
-}
-
-bool timed_mutex::do_timedlock(const xtime& xt)
-{
- int microseconds;
- to_microduration(xt, microseconds);
- Duration lDuration = kDurationMicrosecond * microseconds;
-
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, lDuration, m_mutex_mutex);
- assert(lStatus == noErr || lStatus == kMPTimeoutErr);
-
- return(lStatus == noErr);
-}
-
-void timed_mutex::do_unlock()
-{
- OSStatus lStatus = noErr;
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
-}
-
-void timed_mutex::do_lock(cv_state& /*state*/)
-{
- do_lock();
-}
-
-void timed_mutex::do_unlock(cv_state& /*state*/)
-{
- do_unlock();
-}
-
-#endif
-
-} // namespace boost
-
-// Change Log:
-// 8 Feb 01 WEKEMPF Initial version.
Deleted: trunk/libs/thread/src/mutex.inl
==============================================================================
--- trunk/libs/thread/src/mutex.inl 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
+++ (empty file)
@@ -1,132 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-//
-// 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)
-// boostinspect:nounnamed
-
-namespace {
-
-#if defined(BOOST_HAS_WINTHREADS)
-//:PREVENT THIS FROM BEING DUPLICATED
-typedef BOOL (WINAPI* TryEnterCriticalSection_type)(LPCRITICAL_SECTION lpCriticalSection);
-TryEnterCriticalSection_type g_TryEnterCriticalSection = 0;
-boost::once_flag once_init_TryEnterCriticalSection = BOOST_ONCE_INIT;
-
-void init_TryEnterCriticalSection()
-{
- //TryEnterCriticalSection is only available on WinNT 4.0 or later;
- //it is not available on Win9x.
-
- OSVERSIONINFO version_info = {sizeof(OSVERSIONINFO)};
- ::GetVersionEx(&version_info);
- if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT &&
- version_info.dwMajorVersion >= 4)
- {
- if (HMODULE kernel_module = GetModuleHandle(TEXT("KERNEL32.DLL")))
- {
- g_TryEnterCriticalSection = reinterpret_cast<TryEnterCriticalSection_type>(
-#if defined(BOOST_NO_ANSI_APIS)
- GetProcAddressW(kernel_module, L"TryEnterCriticalSection")
-#else
- GetProcAddress(kernel_module, "TryEnterCriticalSection")
-#endif
- );
- }
- }
-}
-
-inline bool has_TryEnterCriticalSection()
-{
- boost::call_once(once_init_TryEnterCriticalSection, init_TryEnterCriticalSection);
- return g_TryEnterCriticalSection != 0;
-}
-
-inline HANDLE mutex_cast(void* p)
-{
- return reinterpret_cast<HANDLE>(p);
-}
-
-inline LPCRITICAL_SECTION critical_section_cast(void* p)
-{
- return reinterpret_cast<LPCRITICAL_SECTION>(p);
-}
-
-inline void* new_critical_section()
-{
- try
- {
- LPCRITICAL_SECTION critical_section = new CRITICAL_SECTION;
- if (critical_section == 0) throw boost::thread_resource_error();
- InitializeCriticalSection(critical_section);
- return critical_section;
- }
- catch(...)
- {
- throw boost::thread_resource_error();
- }
-}
-
-inline void* new_mutex(const char* name)
-{
-#if defined(BOOST_NO_ANSI_APIS)
- int const num_wide_chars = ::MultiByteToWideChar(CP_ACP, 0, name, -1, 0, 0);
- LPWSTR const wide_name = (LPWSTR)_alloca( (num_wide_chars+1) * 2 );
- int const res=::MultiByteToWideChar(CP_ACP, 0, name, -1, wide_name, num_wide_chars);
- if(!res)
- throw boost::thread_resource_error();
- HANDLE mutex = CreateMutexW(0, 0, wide_name);
-#else
- HANDLE mutex = CreateMutexA(0, 0, name);
-#endif
- if (mutex == 0 || mutex == INVALID_HANDLE_VALUE) //:xxx (check for both values?)
- throw boost::thread_resource_error();
- return reinterpret_cast<void*>(mutex);
-}
-
-inline void delete_critical_section(void* mutex)
-{
- DeleteCriticalSection(critical_section_cast(mutex));
- delete critical_section_cast(mutex);
-}
-
-inline void delete_mutex(void* mutex)
-{
- int res = 0;
- res = CloseHandle(mutex_cast(mutex));
- assert(res);
-}
-
-inline void wait_critical_section_infinite(void* mutex)
-{
- EnterCriticalSection(critical_section_cast(mutex)); //:xxx Can throw an exception under low memory conditions
-}
-
-inline bool wait_critical_section_try(void* mutex)
-{
- BOOL res = g_TryEnterCriticalSection(critical_section_cast(mutex));
- return res != 0;
-}
-
-inline int wait_mutex(void* mutex, int time)
-{
- unsigned int res = 0;
- res = WaitForSingleObject(mutex_cast(mutex), time);
-//:xxx assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
- return res;
-}
-
-inline void release_critical_section(void* mutex)
-{
- LeaveCriticalSection(critical_section_cast(mutex));
-}
-
-inline void release_mutex(void* mutex)
-{
- BOOL res = FALSE;
- res = ReleaseMutex(mutex_cast(mutex));
- assert(res);
-}
-#endif
-
-}
Deleted: trunk/libs/thread/src/once.cpp
==============================================================================
--- trunk/libs/thread/src/once.cpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
+++ (empty file)
@@ -1,50 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-// Copyright (C) 2007 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)
-
-#include <boost/thread/detail/config.hpp>
-#ifdef BOOST_HAS_MPTASKS
-
-#include <boost/detail/workaround.hpp>
-
-#include <boost/thread/once.hpp>
-#include <cstdio>
-#include <cassert>
-
-#include <Multiprocessing.h>
-
-namespace {
-void *remote_call_proxy(void *pData)
-{
- std::pair<void (*)(), boost::once_flag *> &rData(
- *reinterpret_cast<std::pair<void (*)(), boost::once_flag *> *>(pData));
-
- if(*rData.second == false)
- {
- rData.first();
- *rData.second = true;
- }
-
- return(NULL);
-}
-}
-
-namespace boost {
-
- void call_once(once_flag& flag, void (*func)())
-{
- if(flag == false)
- {
- // all we do here is make a remote call to blue, as blue is not
- // reentrant.
- std::pair<void (*)(), once_flag *> sData(func, &flag);
- MPRemoteCall(remote_call_proxy, &sData, kMPOwningProcessRemoteContext);
- assert(flag == true);
- }
-}
-
-}
-#endif
Deleted: trunk/libs/thread/src/recursive_mutex.cpp
==============================================================================
--- trunk/libs/thread/src/recursive_mutex.cpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
+++ (empty file)
@@ -1,1040 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-//
-// 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)
-
-#include <boost/thread/detail/config.hpp>
-
-#include <boost/thread/recursive_mutex.hpp>
-#include <boost/thread/xtime.hpp>
-#include <boost/thread/thread.hpp>
-#include <boost/limits.hpp>
-#include <string>
-#include <stdexcept>
-#include <cassert>
-#include "timeconv.inl"
-
-#if defined(BOOST_HAS_WINTHREADS)
-# include <new>
-# include <boost/thread/once.hpp>
-# include <windows.h>
-# include <time.h>
-# include "mutex.inl"
-#elif defined(BOOST_HAS_PTHREADS)
-# include <errno.h>
-#elif defined(BOOST_HAS_MPTASKS)
-# include <MacErrors.h>
-# include "safe.hpp"
-#endif
-
-namespace boost {
-
-#if defined(BOOST_HAS_WINTHREADS)
-
-recursive_mutex::recursive_mutex()
- : m_mutex(0)
- , m_critical_section(false)
- , m_count(0)
-{
- m_critical_section = true;
- if (m_critical_section)
- m_mutex = new_critical_section();
- else
- m_mutex = new_mutex(0);
-}
-
-recursive_mutex::~recursive_mutex()
-{
- if (m_critical_section)
- delete_critical_section(m_mutex);
- else
- delete_mutex(m_mutex);
-}
-
-void recursive_mutex::do_lock()
-{
- if (m_critical_section)
- wait_critical_section_infinite(m_mutex);
- else
- wait_mutex(m_mutex, INFINITE);
-
- if (++m_count > 1)
- {
- if (m_critical_section)
- release_critical_section(m_mutex);
- else
- release_mutex(m_mutex);
- }
-}
-
-void recursive_mutex::do_unlock()
-{
- if (--m_count == 0)
- {
- if (m_critical_section)
- release_critical_section(m_mutex);
- else
- release_mutex(m_mutex);
- }
-}
-
-void recursive_mutex::do_lock(cv_state& state)
-{
- if (m_critical_section)
- wait_critical_section_infinite(m_mutex);
- else
- wait_mutex(m_mutex, INFINITE);
-
- m_count = state;
-}
-
-void recursive_mutex::do_unlock(cv_state& state)
-{
- state = m_count;
- m_count = 0;
-
- if (m_critical_section)
- release_critical_section(m_mutex);
- else
- release_mutex(m_mutex);
-}
-
-recursive_try_mutex::recursive_try_mutex()
- : m_mutex(0)
- , m_critical_section(false)
- , m_count(0)
-{
- m_critical_section = has_TryEnterCriticalSection();
- if (m_critical_section)
- m_mutex = new_critical_section();
- else
- m_mutex = new_mutex(0);
-}
-
-recursive_try_mutex::~recursive_try_mutex()
-{
- if (m_critical_section)
- delete_critical_section(m_mutex);
- else
- delete_mutex(m_mutex);
-}
-
-void recursive_try_mutex::do_lock()
-{
- if (m_critical_section)
- wait_critical_section_infinite(m_mutex);
- else
- wait_mutex(m_mutex, INFINITE);
-
- if (++m_count > 1)
- {
- if (m_critical_section)
- release_critical_section(m_mutex);
- else
- release_mutex(m_mutex);
- }
-}
-
-bool recursive_try_mutex::do_trylock()
-{
- bool res = false;
- if (m_critical_section)
- res = wait_critical_section_try(m_mutex);
- else
- res = wait_mutex(m_mutex, 0) == WAIT_OBJECT_0;
-
- if (res)
- {
- if (++m_count > 1)
- {
- if (m_critical_section)
- release_critical_section(m_mutex);
- else
- release_mutex(m_mutex);
- }
- return true;
- }
- return false;
-}
-
-void recursive_try_mutex::do_unlock()
-{
- if (--m_count == 0)
- {
- if (m_critical_section)
- release_critical_section(m_mutex);
- else
- release_mutex(m_mutex);
- }
-}
-
-void recursive_try_mutex::do_lock(cv_state& state)
-{
- if (m_critical_section)
- wait_critical_section_infinite(m_mutex);
- else
- wait_mutex(m_mutex, INFINITE);
-
- m_count = state;
-}
-
-void recursive_try_mutex::do_unlock(cv_state& state)
-{
- state = m_count;
- m_count = 0;
-
- if (m_critical_section)
- release_critical_section(m_mutex);
- else
- release_mutex(m_mutex);
-}
-
-recursive_timed_mutex::recursive_timed_mutex()
- : m_mutex(0)
- , m_count(0)
-{
- m_mutex = new_mutex(0);
-}
-
-recursive_timed_mutex::~recursive_timed_mutex()
-{
- delete_mutex(m_mutex);
-}
-
-void recursive_timed_mutex::do_lock()
-{
- wait_mutex(m_mutex, INFINITE);
-
- if (++m_count > 1)
- release_mutex(m_mutex);
-}
-
-bool recursive_timed_mutex::do_trylock()
-{
- bool res = wait_mutex(m_mutex, 0) == WAIT_OBJECT_0;
-
- if (res)
- {
- if (++m_count > 1)
- release_mutex(m_mutex);
- return true;
- }
- return false;
-}
-
-bool recursive_timed_mutex::do_timedlock(const xtime& xt)
-{
- for (;;)
- {
- int milliseconds;
- to_duration(xt, milliseconds);
-
- unsigned int res = wait_mutex(m_mutex, milliseconds);
-
- if (res == WAIT_TIMEOUT)
- {
- xtime cur;
- xtime_get(&cur, TIME_UTC);
- if (xtime_cmp(xt, cur) > 0)
- continue;
- }
-
- if (res == WAIT_OBJECT_0)
- {
- if (++m_count > 1)
- release_mutex(m_mutex);
- return true;
- }
-
- return false;
- }
-}
-
-void recursive_timed_mutex::do_unlock()
-{
- if (--m_count == 0)
- release_mutex(m_mutex);
-}
-
-void recursive_timed_mutex::do_lock(cv_state& state)
-{
- wait_mutex(m_mutex, INFINITE);
-
- m_count = state;
-}
-
-void recursive_timed_mutex::do_unlock(cv_state& state)
-{
- state = m_count;
- m_count = 0;
-
- release_mutex(m_mutex);
-}
-
-#elif defined(BOOST_HAS_PTHREADS)
-
-recursive_mutex::recursive_mutex()
- : m_count(0)
-# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- , m_valid_id(false)
-# endif
-{
- pthread_mutexattr_t attr;
- int res = pthread_mutexattr_init(&attr);
- assert(res == 0);
-
-# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- assert(res == 0);
-# endif
-
- res = pthread_mutex_init(&m_mutex, &attr);
- {
- int res = 0;
- res = pthread_mutexattr_destroy(&attr);
- assert(res == 0);
- }
- if (res != 0)
- throw thread_resource_error();
-
-# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- res = pthread_cond_init(&m_unlocked, 0);
- if (res != 0)
- {
- pthread_mutex_destroy(&m_mutex);
- throw thread_resource_error();
- }
-# endif
-}
-
-recursive_mutex::~recursive_mutex()
-{
- int res = 0;
- res = pthread_mutex_destroy(&m_mutex);
- assert(res == 0);
-
-# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- res = pthread_cond_destroy(&m_unlocked);
- assert(res == 0);
-# endif
-}
-
-void recursive_mutex::do_lock()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
-# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- if (++m_count > 1)
- {
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- }
-# else
- pthread_t tid = pthread_self();
- if (m_valid_id && pthread_equal(m_thread_id, tid))
- ++m_count;
- else
- {
- while (m_valid_id)
- {
- res = pthread_cond_wait(&m_unlocked, &m_mutex);
- assert(res == 0);
- }
-
- m_thread_id = tid;
- m_valid_id = true;
- m_count = 1;
- }
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-# endif
-}
-
-void recursive_mutex::do_unlock()
-{
-# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- if (--m_count == 0)
- {
- int res = 0;
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- }
-# else
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- pthread_t tid = pthread_self();
- if (m_valid_id && !pthread_equal(m_thread_id, tid))
- {
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- throw lock_error();
- }
-
- if (--m_count == 0)
- {
- assert(m_valid_id);
- m_valid_id = false;
-
- res = pthread_cond_signal(&m_unlocked);
- assert(res == 0);
- }
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-# endif
-}
-
-void recursive_mutex::do_lock(cv_state& state)
-{
-# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- m_count = state.count;
-# else
- int res = 0;
-
- while (m_valid_id)
- {
- res = pthread_cond_wait(&m_unlocked, &m_mutex);
- assert(res == 0);
- }
-
- m_thread_id = pthread_self();
- m_valid_id = true;
- m_count = state.count;
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-# endif
-}
-
-void recursive_mutex::do_unlock(cv_state& state)
-{
-# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- assert(m_valid_id);
- m_valid_id = false;
-
- res = pthread_cond_signal(&m_unlocked);
- assert(res == 0);
-# endif
-
- state.pmutex = &m_mutex;
- state.count = m_count;
- m_count = 0;
-}
-
-recursive_try_mutex::recursive_try_mutex()
- : m_count(0)
-# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- , m_valid_id(false)
-# endif
-{
- pthread_mutexattr_t attr;
- int res = pthread_mutexattr_init(&attr);
- assert(res == 0);
-
-# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- assert(res == 0);
-# endif
-
- res = pthread_mutex_init(&m_mutex, &attr);
- {
- int res = 0;
- res = pthread_mutexattr_destroy(&attr);
- assert(res == 0);
- }
- if (res != 0)
- throw thread_resource_error();
-
-# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- res = pthread_cond_init(&m_unlocked, 0);
- if (res != 0)
- {
- pthread_mutex_destroy(&m_mutex);
- throw thread_resource_error();
- }
-# endif
-}
-
-recursive_try_mutex::~recursive_try_mutex()
-{
- int res = 0;
- res = pthread_mutex_destroy(&m_mutex);
- assert(res == 0);
-
-# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- res = pthread_cond_destroy(&m_unlocked);
- assert(res == 0);
-# endif
-}
-
-void recursive_try_mutex::do_lock()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
-# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- if (++m_count > 1)
- {
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- }
-# else
- pthread_t tid = pthread_self();
- if (m_valid_id && pthread_equal(m_thread_id, tid))
- ++m_count;
- else
- {
- while (m_valid_id)
- {
- res = pthread_cond_wait(&m_unlocked, &m_mutex);
- assert(res == 0);
- }
-
- m_thread_id = tid;
- m_valid_id = true;
- m_count = 1;
- }
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-# endif
-}
-
-bool recursive_try_mutex::do_trylock()
-{
-# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- int res = 0;
- res = pthread_mutex_trylock(&m_mutex);
- assert(res == 0 || res == EBUSY);
-
- if (res == 0)
- {
- if (++m_count > 1)
- {
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- }
- return true;
- }
-
- return false;
-# else
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- bool ret = false;
- pthread_t tid = pthread_self();
- if (m_valid_id && pthread_equal(m_thread_id, tid))
- {
- ++m_count;
- ret = true;
- }
- else if (!m_valid_id)
- {
- m_thread_id = tid;
- m_valid_id = true;
- m_count = 1;
- ret = true;
- }
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- return ret;
-# endif
-}
-
-void recursive_try_mutex::do_unlock()
-{
-# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- if (--m_count == 0)
- {
- int res = 0;
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- }
-# else
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- pthread_t tid = pthread_self();
- if (m_valid_id && !pthread_equal(m_thread_id, tid))
- {
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- throw lock_error();
- }
-
- if (--m_count == 0)
- {
- assert(m_valid_id);
- m_valid_id = false;
-
- res = pthread_cond_signal(&m_unlocked);
- assert(res == 0);
- }
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-# endif
-}
-
-void recursive_try_mutex::do_lock(cv_state& state)
-{
-# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- m_count = state.count;
-# else
- int res = 0;
-
- while (m_valid_id)
- {
- res = pthread_cond_wait(&m_unlocked, &m_mutex);
- assert(res == 0);
- }
-
- m_thread_id = pthread_self();
- m_valid_id = true;
- m_count = state.count;
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-# endif
-}
-
-void recursive_try_mutex::do_unlock(cv_state& state)
-{
-# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- assert(m_valid_id);
- m_valid_id = false;
-
- res = pthread_cond_signal(&m_unlocked);
- assert(res == 0);
-# endif
-
- state.pmutex = &m_mutex;
- state.count = m_count;
- m_count = 0;
-}
-
-recursive_timed_mutex::recursive_timed_mutex()
- : m_valid_id(false), m_count(0)
-{
- int res = 0;
- res = pthread_mutex_init(&m_mutex, 0);
- if (res != 0)
- throw thread_resource_error();
-
- res = pthread_cond_init(&m_unlocked, 0);
- if (res != 0)
- {
- pthread_mutex_destroy(&m_mutex);
- throw thread_resource_error();
- }
-}
-
-recursive_timed_mutex::~recursive_timed_mutex()
-{
- int res = 0;
- res = pthread_mutex_destroy(&m_mutex);
- assert(res == 0);
-
- res = pthread_cond_destroy(&m_unlocked);
- assert(res == 0);
-}
-
-void recursive_timed_mutex::do_lock()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- pthread_t tid = pthread_self();
- if (m_valid_id && pthread_equal(m_thread_id, tid))
- ++m_count;
- else
- {
- while (m_valid_id)
- {
- res = pthread_cond_wait(&m_unlocked, &m_mutex);
- assert(res == 0);
- }
-
- m_thread_id = tid;
- m_valid_id = true;
- m_count = 1;
- }
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-}
-
-bool recursive_timed_mutex::do_trylock()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- bool ret = false;
- pthread_t tid = pthread_self();
- if (m_valid_id && pthread_equal(m_thread_id, tid))
- {
- ++m_count;
- ret = true;
- }
- else if (!m_valid_id)
- {
- m_thread_id = tid;
- m_valid_id = true;
- m_count = 1;
- ret = true;
- }
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- return ret;
-}
-
-bool recursive_timed_mutex::do_timedlock(const xtime& xt)
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- bool ret = false;
- pthread_t tid = pthread_self();
- if (m_valid_id && pthread_equal(m_thread_id, tid))
- {
- ++m_count;
- ret = true;
- }
- else
- {
- timespec ts;
- to_timespec(xt, ts);
-
- while (m_valid_id)
- {
- res = pthread_cond_timedwait(&m_unlocked, &m_mutex, &ts);
- if (res == ETIMEDOUT)
- break;
- assert(res == 0);
- }
-
- if (!m_valid_id)
- {
- m_thread_id = tid;
- m_valid_id = true;
- m_count = 1;
- ret = true;
- }
- }
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- return ret;
-}
-
-void recursive_timed_mutex::do_unlock()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- pthread_t tid = pthread_self();
- if (m_valid_id && !pthread_equal(m_thread_id, tid))
- {
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
- throw lock_error();
- }
-
- if (--m_count == 0)
- {
- assert(m_valid_id);
- m_valid_id = false;
-
- res = pthread_cond_signal(&m_unlocked);
- assert(res == 0);
- }
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-}
-
-void recursive_timed_mutex::do_lock(cv_state& state)
-{
- int res = 0;
-
- while (m_valid_id)
- {
- res = pthread_cond_wait(&m_unlocked, &m_mutex);
- assert(res == 0);
- }
-
- m_thread_id = pthread_self();
- m_valid_id = true;
- m_count = state.count;
-
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-}
-
-void recursive_timed_mutex::do_unlock(cv_state& state)
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
-
- assert(m_valid_id);
- m_valid_id = false;
-
- res = pthread_cond_signal(&m_unlocked);
- assert(res == 0);
-
- state.pmutex = &m_mutex;
- state.count = m_count;
- m_count = 0;
-}
-#elif defined(BOOST_HAS_MPTASKS)
-
-using threads::mac::detail::safe_enter_critical_region;
-
-
-recursive_mutex::recursive_mutex()
- : m_count(0)
-{
-}
-
-recursive_mutex::~recursive_mutex()
-{
-}
-
-void recursive_mutex::do_lock()
-{
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
-
- if (++m_count > 1)
- {
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
- }
-}
-
-void recursive_mutex::do_unlock()
-{
- if (--m_count == 0)
- {
- OSStatus lStatus = noErr;
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
- }
-}
-
-void recursive_mutex::do_lock(cv_state& state)
-{
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
-
- m_count = state;
-}
-
-void recursive_mutex::do_unlock(cv_state& state)
-{
- state = m_count;
- m_count = 0;
-
- OSStatus lStatus = noErr;
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
-}
-
-recursive_try_mutex::recursive_try_mutex()
- : m_count(0)
-{
-}
-
-recursive_try_mutex::~recursive_try_mutex()
-{
-}
-
-void recursive_try_mutex::do_lock()
-{
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
-
- if (++m_count > 1)
- {
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
- }
-}
-
-bool recursive_try_mutex::do_trylock()
-{
- OSStatus lStatus = noErr;
- lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
- assert(lStatus == noErr || lStatus == kMPTimeoutErr);
-
- if (lStatus == noErr)
- {
- if (++m_count > 1)
- {
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
- }
- return true;
- }
- return false;
-}
-
-void recursive_try_mutex::do_unlock()
-{
- if (--m_count == 0)
- {
- OSStatus lStatus = noErr;
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
- }
-}
-
-void recursive_try_mutex::do_lock(cv_state& state)
-{
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
-
- m_count = state;
-}
-
-void recursive_try_mutex::do_unlock(cv_state& state)
-{
- state = m_count;
- m_count = 0;
-
- OSStatus lStatus = noErr;
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
-}
-
-recursive_timed_mutex::recursive_timed_mutex()
- : m_count(0)
-{
-}
-
-recursive_timed_mutex::~recursive_timed_mutex()
-{
-}
-
-void recursive_timed_mutex::do_lock()
-{
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
-
- if (++m_count > 1)
- {
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
- }
-}
-
-bool recursive_timed_mutex::do_trylock()
-{
- OSStatus lStatus = noErr;
- lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
- assert(lStatus == noErr || lStatus == kMPTimeoutErr);
-
- if (lStatus == noErr)
- {
- if (++m_count > 1)
- {
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
- }
- return true;
- }
- return false;
-}
-
-bool recursive_timed_mutex::do_timedlock(const xtime& xt)
-{
- int microseconds;
- to_microduration(xt, microseconds);
- Duration lDuration = kDurationMicrosecond * microseconds;
-
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, lDuration, m_mutex_mutex);
- assert(lStatus == noErr || lStatus == kMPTimeoutErr);
-
- if (lStatus == noErr)
- {
- if (++m_count > 1)
- {
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
- }
- return true;
- }
- return false;
-}
-
-void recursive_timed_mutex::do_unlock()
-{
- if (--m_count == 0)
- {
- OSStatus lStatus = noErr;
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
- }
-}
-
-void recursive_timed_mutex::do_lock(cv_state& state)
-{
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
-
- m_count = state;
-}
-
-void recursive_timed_mutex::do_unlock(cv_state& state)
-{
- state = m_count;
- m_count = 0;
-
- OSStatus lStatus = noErr;
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
-}
-#endif
-
-} // namespace boost
-
-// Change Log:
-// 8 Feb 01 WEKEMPF Initial version.
Modified: trunk/libs/thread/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2 (original)
+++ trunk/libs/thread/test/Jamfile.v2 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
@@ -40,6 +40,7 @@
[ thread-run test_once.cpp ]
[ thread-run test_xtime.cpp ]
[ thread-run test_barrier.cpp ]
-# [ thread-run test_read_write_mutex.cpp ]
+ [ thread-run test_shared_mutex.cpp ]
+ [ thread-run test_lock_concept.cpp ]
;
}
Added: trunk/libs/thread/test/test_lock_concept.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/test_lock_concept.cpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
@@ -0,0 +1,173 @@
+// (C) Copyright 2006-7 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)
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/test_case_template.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+
+template<typename Mutex,typename Lock>
+struct test_initially_locked
+{
+ void operator()() const
+ {
+ Mutex m;
+ Lock lock(m);
+
+ BOOST_CHECK(lock);
+ BOOST_CHECK(lock.owns_lock());
+ }
+};
+
+template<typename Mutex,typename Lock>
+struct test_initially_unlocked_with_defer_lock_parameter
+{
+ void operator()() const
+ {
+ Mutex m;
+ Lock lock(m,boost::defer_lock);
+
+ BOOST_CHECK(!lock);
+ BOOST_CHECK(!lock.owns_lock());
+ }
+};
+
+template<typename Mutex,typename Lock>
+struct test_initially_locked_with_adopt_lock_parameter
+{
+ void operator()() const
+ {
+ Mutex m;
+ m.lock();
+ Lock lock(m,boost::adopt_lock);
+
+ BOOST_CHECK(lock);
+ BOOST_CHECK(lock.owns_lock());
+ }
+};
+
+
+template<typename Mutex,typename Lock>
+struct test_unlocked_after_unlock_called
+{
+ void operator()() const
+ {
+ Mutex m;
+ Lock lock(m);
+ lock.unlock();
+ BOOST_CHECK(!lock);
+ BOOST_CHECK(!lock.owns_lock());
+ }
+};
+
+template<typename Mutex,typename Lock>
+struct test_locked_after_lock_called
+{
+ void operator()() const
+ {
+ Mutex m;
+ Lock lock(m,boost::defer_lock);
+ lock.lock();
+ BOOST_CHECK(lock);
+ BOOST_CHECK(lock.owns_lock());
+ }
+};
+
+template<typename Mutex,typename Lock>
+struct test_locked_after_try_lock_called
+{
+ void operator()() const
+ {
+ Mutex m;
+ Lock lock(m,boost::defer_lock);
+ lock.try_lock();
+ BOOST_CHECK(lock);
+ BOOST_CHECK(lock.owns_lock());
+ }
+};
+
+template<typename Mutex,typename Lock>
+struct test_throws_if_lock_called_when_already_locked
+{
+ void operator()() const
+ {
+ Mutex m;
+ Lock lock(m);
+
+ BOOST_CHECK_THROW( lock.lock(), boost::lock_error );
+ }
+};
+
+template<typename Mutex,typename Lock>
+struct test_throws_if_try_lock_called_when_already_locked
+{
+ void operator()() const
+ {
+ Mutex m;
+ Lock lock(m);
+
+ BOOST_CHECK_THROW( lock.try_lock(), boost::lock_error );
+ }
+};
+
+template<typename Mutex,typename Lock>
+struct test_throws_if_unlock_called_when_already_unlocked
+{
+ void operator()() const
+ {
+ Mutex m;
+ Lock lock(m);
+ lock.unlock();
+
+ BOOST_CHECK_THROW( lock.unlock(), boost::lock_error );
+ }
+};
+
+BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_lock_concept,Mutex)
+{
+ typedef typename Mutex::scoped_lock 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>()();
+}
+
+BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_try_lock_concept,Mutex)
+{
+ typedef typename Mutex::scoped_try_lock 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_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>()();
+}
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
+{
+ boost::unit_test_framework::test_suite* test =
+ 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;
+
+ test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types));
+
+ typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
+ boost::recursive_try_mutex,boost::recursive_timed_mutex> try_mutex_types;
+
+ test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,try_mutex_types));
+
+ return test;
+}
Added: trunk/libs/thread/test/test_shared_mutex.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/test_shared_mutex.cpp 2007-10-10 11:33:49 EDT (Wed, 10 Oct 2007)
@@ -0,0 +1,460 @@
+// (C) Copyright 2006-7 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)
+
+#include <boost/test/unit_test.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/xtime.hpp>
+#include "util.inl"
+
+#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
+ { \
+ boost::mutex::scoped_lock lock(mutex_name); \
+ BOOST_CHECK_EQUAL(value,expected_value); \
+ }
+
+
+namespace
+{
+ template<typename lock_type>
+ class locking_thread
+ {
+ boost::shared_mutex& rw_mutex;
+ unsigned& unblocked_count;
+ unsigned& simultaneous_running_count;
+ unsigned& max_simultaneous_running;
+ boost::mutex& unblocked_count_mutex;
+ boost::mutex& finish_mutex;
+ public:
+ locking_thread(boost::shared_mutex& rw_mutex_,
+ unsigned& unblocked_count_,
+ boost::mutex& unblocked_count_mutex_,
+ boost::mutex& finish_mutex_,
+ unsigned& simultaneous_running_count_,
+ unsigned& max_simultaneous_running_):
+ rw_mutex(rw_mutex_),
+ unblocked_count(unblocked_count_),
+ unblocked_count_mutex(unblocked_count_mutex_),
+ finish_mutex(finish_mutex_),
+ simultaneous_running_count(simultaneous_running_count_),
+ max_simultaneous_running(max_simultaneous_running_)
+ {}
+
+ void operator()()
+ {
+ // acquire lock
+ lock_type lock(rw_mutex);
+
+ // increment count to show we're unblocked
+ {
+ boost::mutex::scoped_lock ublock(unblocked_count_mutex);
+ ++unblocked_count;
+ ++simultaneous_running_count;
+ if(simultaneous_running_count>max_simultaneous_running)
+ {
+ max_simultaneous_running=simultaneous_running_count;
+ }
+ }
+
+ // wait to finish
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+ {
+ boost::mutex::scoped_lock ublock(unblocked_count_mutex);
+ --simultaneous_running_count;
+ }
+ }
+ };
+
+}
+
+
+void test_multiple_readers()
+{
+ unsigned const number_of_threads=100;
+
+ boost::thread_group pool;
+
+ boost::shared_mutex rw_mutex;
+ unsigned unblocked_count=0;
+ unsigned simultaneous_running_count=0;
+ unsigned max_simultaneous_running=0;
+ boost::mutex unblocked_count_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+
+ for(unsigned i=0;i<number_of_threads;++i)
+ {
+ pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,finish_mutex,simultaneous_running_count,max_simultaneous_running));
+ }
+
+ boost::thread::sleep(delay(1));
+
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
+
+ finish_lock.unlock();
+
+ pool.join_all();
+
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,number_of_threads);
+}
+
+void test_only_one_writer_permitted()
+{
+ unsigned const number_of_threads=100;
+
+ boost::thread_group pool;
+
+ boost::shared_mutex rw_mutex;
+ unsigned unblocked_count=0;
+ unsigned simultaneous_running_count=0;
+ unsigned max_simultaneous_running=0;
+ boost::mutex unblocked_count_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+
+ for(unsigned i=0;i<number_of_threads;++i)
+ {
+ pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,finish_mutex,simultaneous_running_count,max_simultaneous_running));
+ }
+
+ boost::thread::sleep(delay(1));
+
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
+
+ finish_lock.unlock();
+
+ pool.join_all();
+
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1);
+}
+
+void test_reader_blocks_writer()
+{
+ boost::thread_group pool;
+
+ boost::shared_mutex rw_mutex;
+ unsigned unblocked_count=0;
+ unsigned simultaneous_running_count=0;
+ unsigned max_simultaneous_running=0;
+ boost::mutex unblocked_count_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+
+ pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,finish_mutex,simultaneous_running_count,max_simultaneous_running));
+ boost::thread::sleep(delay(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
+ pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,finish_mutex,simultaneous_running_count,max_simultaneous_running));
+ boost::thread::sleep(delay(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
+
+ finish_lock.unlock();
+
+ pool.join_all();
+
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,2U);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1);
+}
+
+void test_unlocking_writer_unblocks_all_readers()
+{
+ boost::thread_group pool;
+
+ boost::shared_mutex rw_mutex;
+ boost::unique_lock<boost::shared_mutex> write_lock(rw_mutex);
+ unsigned unblocked_count=0;
+ unsigned simultaneous_running_count=0;
+ unsigned max_simultaneous_running=0;
+ boost::mutex unblocked_count_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+
+ unsigned const reader_count=100;
+
+ for(unsigned i=0;i<reader_count;++i)
+ {
+ pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,finish_mutex,simultaneous_running_count,max_simultaneous_running));
+ }
+ boost::thread::sleep(delay(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,0U);
+
+ write_lock.unlock();
+
+ boost::thread::sleep(delay(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count);
+
+ finish_lock.unlock();
+ pool.join_all();
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count);
+}
+
+void test_unlocking_last_reader_only_unblocks_one_writer()
+{
+ boost::thread_group pool;
+
+ boost::shared_mutex rw_mutex;
+ unsigned unblocked_count=0;
+ unsigned simultaneous_running_readers=0;
+ unsigned max_simultaneous_readers=0;
+ unsigned simultaneous_running_writers=0;
+ unsigned max_simultaneous_writers=0;
+ boost::mutex unblocked_count_mutex;
+ boost::mutex finish_reading_mutex;
+ boost::mutex::scoped_lock finish_reading_lock(finish_reading_mutex);
+ 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;
+
+ for(unsigned i=0;i<reader_count;++i)
+ {
+ pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,finish_reading_mutex,simultaneous_running_readers,max_simultaneous_readers));
+ }
+ for(unsigned i=0;i<writer_count;++i)
+ {
+ pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,finish_writing_mutex,simultaneous_running_writers,max_simultaneous_writers));
+ }
+ boost::thread::sleep(delay(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count);
+
+ finish_reading_lock.unlock();
+
+ boost::thread::sleep(delay(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
+
+ finish_writing_lock.unlock();
+ pool.join_all();
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+writer_count);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_readers,reader_count);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_writers,1);
+}
+
+void test_only_one_upgrade_lock_permitted()
+{
+ unsigned const number_of_threads=100;
+
+ boost::thread_group pool;
+
+ boost::shared_mutex rw_mutex;
+ unsigned unblocked_count=0;
+ unsigned simultaneous_running_count=0;
+ unsigned max_simultaneous_running=0;
+ boost::mutex unblocked_count_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+
+ for(unsigned i=0;i<number_of_threads;++i)
+ {
+ pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,finish_mutex,simultaneous_running_count,max_simultaneous_running));
+ }
+
+ boost::thread::sleep(delay(1));
+
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
+
+ finish_lock.unlock();
+
+ pool.join_all();
+
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1);
+}
+
+void test_can_lock_upgrade_if_currently_locked_shared()
+{
+ boost::thread_group pool;
+
+ boost::shared_mutex rw_mutex;
+ unsigned unblocked_count=0;
+ unsigned simultaneous_running_count=0;
+ unsigned max_simultaneous_running=0;
+ boost::mutex unblocked_count_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+
+ unsigned const reader_count=100;
+
+ for(unsigned i=0;i<reader_count;++i)
+ {
+ pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,finish_mutex,simultaneous_running_count,max_simultaneous_running));
+ }
+ pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,finish_mutex,simultaneous_running_count,max_simultaneous_running));
+ boost::thread::sleep(delay(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
+
+ finish_lock.unlock();
+ pool.join_all();
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count+1);
+}
+
+namespace
+{
+ class simple_writing_thread
+ {
+ boost::shared_mutex& rwm;
+ boost::mutex& finish_mutex;
+ boost::mutex& unblocked_mutex;
+ unsigned& unblocked_count;
+
+ public:
+ simple_writing_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::unique_lock<boost::shared_mutex> lk(rwm);
+
+ {
+ boost::mutex::scoped_lock ulk(unblocked_mutex);
+ ++unblocked_count;
+ }
+
+ boost::mutex::scoped_lock flk(finish_mutex);
+ }
+ };
+}
+
+void test_if_other_thread_has_write_lock_try_lock_shared_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::thread::sleep(delay(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1);
+
+ bool const try_succeeded=rw_mutex.try_lock_shared();
+ BOOST_CHECK(!try_succeeded);
+ if(try_succeeded)
+ {
+ rw_mutex.unlock_shared();
+ }
+
+ finish_lock.unlock();
+ writer.join();
+}
+
+void test_if_no_thread_has_lock_try_lock_shared_returns_true()
+{
+ boost::shared_mutex rw_mutex;
+ bool const try_succeeded=rw_mutex.try_lock_shared();
+ BOOST_CHECK(try_succeeded);
+ if(try_succeeded)
+ {
+ rw_mutex.unlock_shared();
+ }
+}
+
+namespace
+{
+ class simple_reading_thread
+ {
+ boost::shared_mutex& rwm;
+ boost::mutex& finish_mutex;
+ boost::mutex& unblocked_mutex;
+ unsigned& unblocked_count;
+
+ public:
+ simple_reading_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::shared_lock<boost::shared_mutex> lk(rwm);
+
+ {
+ boost::mutex::scoped_lock ulk(unblocked_mutex);
+ ++unblocked_count;
+ }
+
+ boost::mutex::scoped_lock flk(finish_mutex);
+ }
+ };
+}
+
+void test_if_other_thread_has_shared_lock_try_lock_shared_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,1);
+
+ bool const try_succeeded=rw_mutex.try_lock_shared();
+ BOOST_CHECK(try_succeeded);
+ if(try_succeeded)
+ {
+ rw_mutex.unlock_shared();
+ }
+
+ finish_lock.unlock();
+ writer.join();
+}
+
+void test_timed_lock_shared_times_out_if_write_lock_held()
+{
+ 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::thread::sleep(delay(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1);
+
+ boost::system_time const start=boost::get_system_time();
+ boost::system_time const timeout=start+boost::posix_time::milliseconds(100);
+ bool const timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout);
+ BOOST_CHECK(timeout<=boost::get_system_time());
+ BOOST_CHECK(!timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock_shared();
+ }
+
+ finish_lock.unlock();
+ writer.join();
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
+{
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite");
+
+ test->add(BOOST_TEST_CASE(&test_multiple_readers));
+ test->add(BOOST_TEST_CASE(&test_only_one_writer_permitted));
+ test->add(BOOST_TEST_CASE(&test_reader_blocks_writer));
+ test->add(BOOST_TEST_CASE(&test_unlocking_writer_unblocks_all_readers));
+ test->add(BOOST_TEST_CASE(&test_unlocking_last_reader_only_unblocks_one_writer));
+ test->add(BOOST_TEST_CASE(&test_only_one_upgrade_lock_permitted));
+ test->add(BOOST_TEST_CASE(&test_can_lock_upgrade_if_currently_locked_shared));
+ test->add(BOOST_TEST_CASE(&test_if_other_thread_has_write_lock_try_lock_shared_returns_false));
+ test->add(BOOST_TEST_CASE(&test_if_no_thread_has_lock_try_lock_shared_returns_true));
+ test->add(BOOST_TEST_CASE(&test_if_other_thread_has_shared_lock_try_lock_shared_returns_true));
+ test->add(BOOST_TEST_CASE(&test_timed_lock_shared_times_out_if_write_lock_held));
+
+ 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