|
Boost-Commit : |
From: anthony_at_[hidden]
Date: 2007-12-21 06:51:07
Author: anthonyw
Date: 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
New Revision: 42230
URL: http://svn.boost.org/trac/boost/changeset/42230
Log:
Merged latest changes to boost.thread over from trunk
Added:
branches/release/libs/thread/test/condition_test_common.hpp
- copied unchanged from r42229, /trunk/libs/thread/test/condition_test_common.hpp
branches/release/libs/thread/test/shared_mutex_locking_thread.hpp
- copied unchanged from r42229, /trunk/libs/thread/test/shared_mutex_locking_thread.hpp
branches/release/libs/thread/test/test_condition_notify_all.cpp
- copied unchanged from r42229, /trunk/libs/thread/test/test_condition_notify_all.cpp
branches/release/libs/thread/test/test_condition_notify_one.cpp
- copied unchanged from r42229, /trunk/libs/thread/test/test_condition_notify_one.cpp
branches/release/libs/thread/test/test_condition_timed_wait_times_out.cpp
- copied unchanged from r42229, /trunk/libs/thread/test/test_condition_timed_wait_times_out.cpp
branches/release/libs/thread/test/test_hardware_concurrency.cpp
- copied unchanged from r42229, /trunk/libs/thread/test/test_hardware_concurrency.cpp
branches/release/libs/thread/test/test_move_function.cpp
- copied unchanged from r42229, /trunk/libs/thread/test/test_move_function.cpp
branches/release/libs/thread/test/test_shared_mutex_part_2.cpp
- copied unchanged from r42229, /trunk/libs/thread/test/test_shared_mutex_part_2.cpp
branches/release/libs/thread/test/test_thread_id.cpp
- copied unchanged from r42229, /trunk/libs/thread/test/test_thread_id.cpp
branches/release/libs/thread/test/test_thread_move.cpp
- copied unchanged from r42229, /trunk/libs/thread/test/test_thread_move.cpp
Text files modified:
branches/release/boost/thread/detail/config.hpp | 5
branches/release/boost/thread/detail/move.hpp | 28 +-
branches/release/boost/thread/locks.hpp | 114 ++++++++++++--
branches/release/boost/thread/pthread/condition_variable.hpp | 16 +
branches/release/boost/thread/pthread/condition_variable_fwd.hpp | 16 +
branches/release/boost/thread/pthread/once.hpp | 18 +-
branches/release/boost/thread/pthread/thread.hpp | 86 +++++++---
branches/release/boost/thread/pthread/thread_data.hpp | 9
branches/release/boost/thread/pthread/tss.hpp | 1
branches/release/boost/thread/win32/condition_variable.hpp | 157 +++++++++++++------
branches/release/boost/thread/win32/shared_mutex.hpp | 8
branches/release/boost/thread/win32/thread.hpp | 110 +++++++++++++-
branches/release/boost/thread/win32/thread_primitives.hpp | 3
branches/release/libs/thread/build/Jamfile.v2 | 5
branches/release/libs/thread/src/pthread/once.cpp | 10
branches/release/libs/thread/src/pthread/thread.cpp | 76 ++++++++-
branches/release/libs/thread/src/win32/thread.cpp | 155 ++++++++++++++++---
branches/release/libs/thread/src/win32/tss_pe.cpp | 3
branches/release/libs/thread/test/Jamfile.v2 | 9 +
branches/release/libs/thread/test/test_barrier.cpp | 2
branches/release/libs/thread/test/test_condition.cpp | 84 ++--------
branches/release/libs/thread/test/test_mutex.cpp | 14 +
branches/release/libs/thread/test/test_once.cpp | 1
branches/release/libs/thread/test/test_shared_mutex.cpp | 310 ---------------------------------------
branches/release/libs/thread/test/test_tss.cpp | 14 -
branches/release/libs/thread/test/util.inl | 21 ++
26 files changed, 697 insertions(+), 578 deletions(-)
Modified: branches/release/boost/thread/detail/config.hpp
==============================================================================
--- branches/release/boost/thread/detail/config.hpp (original)
+++ branches/release/boost/thread/detail/config.hpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -17,8 +17,7 @@
# pragma warn -8066 // Unreachable code
#endif
-// insist on threading support being available:
-#include <boost/config/requires_threads.hpp>
+#include "platform.hpp"
// compatibility with the rest of Boost's auto-linking code:
#if defined(BOOST_THREAD_DYN_DLL) || defined(BOOST_ALL_DYN_LINK)
@@ -31,7 +30,7 @@
#elif defined(BOOST_THREAD_USE_DLL) //Use dll
#elif defined(BOOST_THREAD_USE_LIB) //Use lib
#else //Use default
-# if defined(BOOST_HAS_WINTHREADS)
+# if defined(BOOST_THREAD_PLATFORM_WIN32)
# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
//For compilers supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads lib
Modified: branches/release/boost/thread/detail/move.hpp
==============================================================================
--- branches/release/boost/thread/detail/move.hpp (original)
+++ branches/release/boost/thread/detail/move.hpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -8,25 +8,23 @@
namespace boost
{
- template<typename T>
- struct move_t
+ namespace detail
{
- T& t;
- move_t(T& t_):
- t(t_)
- {}
-
- T* operator->() const
+ template<typename T>
+ struct thread_move_t
{
- return &t;
- }
- };
+ T& t;
+ thread_move_t(T& t_):
+ t(t_)
+ {}
- template<typename T>
- move_t<T> move(T& t)
- {
- return move_t<T>(t);
+ T* operator->() const
+ {
+ return &t;
+ }
+ };
}
+
}
Modified: branches/release/boost/thread/locks.hpp
==============================================================================
--- branches/release/boost/thread/locks.hpp (original)
+++ branches/release/boost/thread/locks.hpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -86,21 +86,32 @@
{
timed_lock(target_time);
}
- unique_lock(boost::move_t<unique_lock<Mutex> > other):
+ unique_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
+ other->m=0;
}
- unique_lock(boost::move_t<upgrade_lock<Mutex> > other);
+ unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other);
- unique_lock& operator=(boost::move_t<unique_lock<Mutex> > other)
+ operator detail::thread_move_t<unique_lock<Mutex> >()
+ {
+ return move();
+ }
+
+ detail::thread_move_t<unique_lock<Mutex> > move()
+ {
+ return detail::thread_move_t<unique_lock<Mutex> >(*this);
+ }
+
+ unique_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
{
unique_lock temp(other);
swap(temp);
return *this;
}
- unique_lock& operator=(boost::move_t<upgrade_lock<Mutex> > other)
+ unique_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
{
unique_lock temp(other);
swap(temp);
@@ -112,7 +123,7 @@
std::swap(m,other.m);
std::swap(is_locked,other.is_locked);
}
- void swap(boost::move_t<unique_lock<Mutex> > other)
+ void swap(detail::thread_move_t<unique_lock<Mutex> > other)
{
std::swap(m,other->m);
std::swap(is_locked,other->is_locked);
@@ -197,6 +208,18 @@
};
template<typename Mutex>
+ inline detail::thread_move_t<unique_lock<Mutex> > move(unique_lock<Mutex> & x)
+ {
+ return x.move();
+ }
+
+ template<typename Mutex>
+ inline detail::thread_move_t<unique_lock<Mutex> > move(detail::thread_move_t<unique_lock<Mutex> > x)
+ {
+ return x;
+ }
+
+ template<typename Mutex>
class shared_lock
{
protected:
@@ -228,13 +251,13 @@
timed_lock(target_time);
}
- shared_lock(boost::move_t<shared_lock<Mutex> > other):
+ shared_lock(detail::thread_move_t<shared_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
}
- shared_lock(boost::move_t<unique_lock<Mutex> > other):
+ shared_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
@@ -244,7 +267,7 @@
}
}
- shared_lock(boost::move_t<upgrade_lock<Mutex> > other):
+ shared_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
@@ -254,21 +277,32 @@
}
}
- shared_lock& operator=(boost::move_t<shared_lock<Mutex> > other)
+ operator detail::thread_move_t<shared_lock<Mutex> >()
+ {
+ return move();
+ }
+
+ detail::thread_move_t<shared_lock<Mutex> > move()
+ {
+ return detail::thread_move_t<shared_lock<Mutex> >(*this);
+ }
+
+
+ shared_lock& operator=(detail::thread_move_t<shared_lock<Mutex> > other)
{
shared_lock temp(other);
swap(temp);
return *this;
}
- shared_lock& operator=(boost::move_t<unique_lock<Mutex> > other)
+ shared_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
{
shared_lock temp(other);
swap(temp);
return *this;
}
- shared_lock& operator=(boost::move_t<upgrade_lock<Mutex> > other)
+ shared_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
{
shared_lock temp(other);
swap(temp);
@@ -342,6 +376,19 @@
};
template<typename Mutex>
+ inline detail::thread_move_t<shared_lock<Mutex> > move(shared_lock<Mutex> & x)
+ {
+ return x.move();
+ }
+
+ template<typename Mutex>
+ inline detail::thread_move_t<shared_lock<Mutex> > move(detail::thread_move_t<shared_lock<Mutex> > x)
+ {
+ return x;
+ }
+
+
+ template<typename Mutex>
class upgrade_lock
{
protected:
@@ -364,13 +411,13 @@
lock();
}
}
- upgrade_lock(boost::move_t<upgrade_lock<Mutex> > other):
+ upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
}
- upgrade_lock(boost::move_t<unique_lock<Mutex> > other):
+ upgrade_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
@@ -380,14 +427,25 @@
}
}
- upgrade_lock& operator=(boost::move_t<upgrade_lock<Mutex> > other)
+ operator detail::thread_move_t<upgrade_lock<Mutex> >()
+ {
+ return move();
+ }
+
+ detail::thread_move_t<upgrade_lock<Mutex> > move()
+ {
+ return detail::thread_move_t<upgrade_lock<Mutex> >(*this);
+ }
+
+
+ upgrade_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
{
upgrade_lock temp(other);
swap(temp);
return *this;
}
- upgrade_lock& operator=(boost::move_t<unique_lock<Mutex> > other)
+ upgrade_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
{
upgrade_lock temp(other);
swap(temp);
@@ -452,8 +510,21 @@
friend class unique_lock<Mutex>;
};
+
+ template<typename Mutex>
+ inline detail::thread_move_t<upgrade_lock<Mutex> > move(upgrade_lock<Mutex> & x)
+ {
+ return x.move();
+ }
+
template<typename Mutex>
- unique_lock<Mutex>::unique_lock(boost::move_t<upgrade_lock<Mutex> > other):
+ inline detail::thread_move_t<upgrade_lock<Mutex> > move(detail::thread_move_t<upgrade_lock<Mutex> > x)
+ {
+ return x;
+ }
+
+ template<typename Mutex>
+ unique_lock<Mutex>::unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
@@ -474,23 +545,23 @@
upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&);
public:
explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_):
- source(&m_),exclusive(boost::move(*source))
+ source(&m_),exclusive(move(*source))
{}
~upgrade_to_unique_lock()
{
if(source)
{
- *source=boost::move(exclusive);
+ *source=move(exclusive);
}
}
- upgrade_to_unique_lock(boost::move_t<upgrade_to_unique_lock<Mutex> > other):
- source(other->source),exclusive(boost::move(other->exclusive))
+ upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other):
+ source(other->source),exclusive(move(other->exclusive))
{
other->source=0;
}
- upgrade_to_unique_lock& operator=(boost::move_t<upgrade_to_unique_lock<Mutex> > other)
+ upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other)
{
upgrade_to_unique_lock temp(other);
swap(temp);
@@ -515,6 +586,7 @@
return exclusive.owns_lock();
}
};
+
}
#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 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -5,11 +5,9 @@
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007 Anthony Williams
-#include <boost/thread/mutex.hpp>
#include <limits.h>
#include <boost/assert.hpp>
#include <algorithm>
-#include <boost/thread/thread_time.hpp>
#include <pthread.h>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
@@ -145,11 +143,23 @@
while (!pred())
{
if(!timed_wait(m, wait_until))
- return false;
+ return pred();
}
return true;
}
+ template<typename lock_type,typename predicate_type>
+ bool timed_wait(lock_type& m,xtime const& wait_until,predicate_type pred)
+ {
+ return timed_wait(m,system_time(wait_until),pred);
+ }
+
+ template<typename lock_type,typename duration_type,typename predicate_type>
+ bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
+ {
+ return timed_wait(m,get_system_time()+wait_duration,pred);
+ }
+
void notify_one()
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
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 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -6,8 +6,10 @@
// (C) Copyright 2007 Anthony Williams
#include <pthread.h>
+#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
+#include <boost/thread/xtime.hpp>
namespace boost
{
@@ -39,11 +41,23 @@
while (!pred())
{
if(!timed_wait(m, wait_until))
- return false;
+ return pred();
}
return true;
}
+ template<typename predicate_type>
+ bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until,predicate_type pred)
+ {
+ return timed_wait(m,system_time(wait_until),pred);
+ }
+
+ template<typename duration_type,typename predicate_type>
+ bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
+ {
+ return timed_wait(m,get_system_time()+wait_duration,pred);
+ }
+
void notify_one();
void notify_all();
};
Modified: branches/release/boost/thread/pthread/once.hpp
==============================================================================
--- branches/release/boost/thread/pthread/once.hpp (original)
+++ branches/release/boost/thread/pthread/once.hpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -14,8 +14,8 @@
#include <pthread.h>
#include <boost/assert.hpp>
#include "pthread_mutex_scoped_lock.hpp"
-#include <boost/cstdint.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
+#include <boost/cstdint.hpp>
namespace boost {
@@ -27,12 +27,12 @@
namespace detail
{
BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
- extern BOOST_THREAD_DECL boost::uintmax_t once_global_epoch;
- extern BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex;
- extern BOOST_THREAD_DECL pthread_cond_t once_epoch_cv;
+ BOOST_THREAD_DECL extern boost::uintmax_t once_global_epoch;
+ BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
+ BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
}
-#define BOOST_ONCE_INITIAL_FLAG_VALUE -1
+#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
@@ -42,15 +42,15 @@
void call_once(once_flag& flag,Function f)
{
static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
- static boost::uintmax_t const being_initialized=uninitialized_flag-1;
+ static boost::uintmax_t const being_initialized=uninitialized_flag+1;
boost::uintmax_t const epoch=flag.epoch;
boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
- if(epoch>this_thread_epoch)
+ if(epoch<this_thread_epoch)
{
pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
- while(flag.epoch>=being_initialized)
+ while(flag.epoch<=being_initialized)
{
if(flag.epoch==uninitialized_flag)
{
@@ -66,7 +66,7 @@
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
throw;
}
- flag.epoch=++detail::once_global_epoch;
+ flag.epoch=--detail::once_global_epoch;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
}
else
Modified: branches/release/boost/thread/pthread/thread.hpp
==============================================================================
--- branches/release/boost/thread/pthread/thread.hpp (original)
+++ branches/release/boost/thread/pthread/thread.hpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -40,44 +40,62 @@
{
class thread_id
{
- boost::optional<pthread_t> id;
-
+ private:
+ detail::thread_data_ptr thread_data;
+
+ thread_id(detail::thread_data_ptr thread_data_):
+ thread_data(thread_data_)
+ {}
friend class boost::thread;
-
friend thread_id this_thread::get_id();
-
- thread_id(pthread_t id_):
- id(id_)
- {}
-
public:
- thread_id()
+ thread_id():
+ thread_data()
{}
-
+
bool operator==(const thread_id& y) const
{
- return (id && y.id) && (pthread_equal(*id,*y.id)!=0);
+ return thread_data==y.thread_data;
}
bool operator!=(const thread_id& y) const
{
- return !(*this==y);
+ return thread_data!=y.thread_data;
+ }
+
+ bool operator<(const thread_id& y) const
+ {
+ return thread_data<y.thread_data;
+ }
+
+ bool operator>(const thread_id& y) const
+ {
+ return y.thread_data<thread_data;
+ }
+
+ bool operator<=(const thread_id& y) const
+ {
+ return !(y.thread_data<thread_data);
+ }
+
+ bool operator>=(const thread_id& y) const
+ {
+ return !(thread_data<y.thread_data);
}
template<class charT, class traits>
friend std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const thread_id& x)
{
- if(x.id)
+ if(x.thread_data)
{
- return os<<*x.id;
+ return os<<x.thread_data;
}
else
{
return os<<"{Not-any-thread}";
}
}
-
};
}
@@ -97,7 +115,7 @@
thread_data(F f_):
f(f_)
{}
- thread_data(boost::move_t<F> f_):
+ thread_data(detail::thread_move_t<F> f_):
f(f_)
{}
@@ -108,13 +126,13 @@
};
mutable boost::mutex thread_info_mutex;
- boost::shared_ptr<detail::thread_data_base> thread_info;
+ detail::thread_data_ptr thread_info;
void start_thread();
- explicit thread(boost::shared_ptr<detail::thread_data_base> data);
+ explicit thread(detail::thread_data_ptr data);
- boost::shared_ptr<detail::thread_data_base> get_thread_info() const;
+ detail::thread_data_ptr get_thread_info() const;
public:
thread();
@@ -127,16 +145,16 @@
start_thread();
}
template <class F>
- thread(boost::move_t<F> f):
+ thread(detail::thread_move_t<F> f):
thread_info(new thread_data<F>(f))
{
start_thread();
}
- explicit thread(boost::move_t<thread> x);
- thread& operator=(boost::move_t<thread> x);
- operator boost::move_t<thread>();
- boost::move_t<thread> move();
+ thread(detail::thread_move_t<thread> x);
+ thread& operator=(detail::thread_move_t<thread> x);
+ operator detail::thread_move_t<thread>();
+ detail::thread_move_t<thread> move();
void swap(thread& x);
@@ -169,6 +187,17 @@
bool interruption_requested() const;
};
+ inline detail::thread_move_t<thread> move(thread& x)
+ {
+ return x.move();
+ }
+
+ inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> x)
+ {
+ return x;
+ }
+
+
template<typename F>
struct thread::thread_data<boost::reference_wrapper<F> >:
detail::thread_data_base
@@ -208,22 +237,19 @@
~restore_interruption();
};
- BOOST_THREAD_DECL inline thread::id get_id()
- {
- return thread::id(pthread_self());
- }
+ BOOST_THREAD_DECL thread::id get_id();
BOOST_THREAD_DECL void interruption_point();
BOOST_THREAD_DECL bool interruption_enabled();
BOOST_THREAD_DECL bool interruption_requested();
- BOOST_THREAD_DECL inline void yield()
+ inline void yield()
{
thread::yield();
}
template<typename TimeDuration>
- BOOST_THREAD_DECL inline void sleep(TimeDuration const& rel_time)
+ inline void sleep(TimeDuration const& rel_time)
{
thread::sleep(get_system_time()+rel_time);
}
Modified: branches/release/boost/thread/pthread/thread_data.hpp
==============================================================================
--- branches/release/boost/thread/pthread/thread_data.hpp (original)
+++ branches/release/boost/thread/pthread/thread_data.hpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -7,6 +7,7 @@
#include <boost/thread/detail/config.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/optional.hpp>
#include <pthread.h>
@@ -21,10 +22,14 @@
{
struct thread_exit_callback_node;
struct tss_data_node;
+
+ struct thread_data_base;
+ typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
- struct thread_data_base
+ struct thread_data_base:
+ enable_shared_from_this<thread_data_base>
{
- boost::shared_ptr<thread_data_base> self;
+ thread_data_ptr self;
pthread_t thread_handle;
boost::mutex data_mutex;
boost::condition_variable done_condition;
Modified: branches/release/boost/thread/pthread/tss.hpp
==============================================================================
--- branches/release/boost/thread/pthread/tss.hpp (original)
+++ branches/release/boost/thread/pthread/tss.hpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -6,6 +6,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007 Anthony Williams
+#include <boost/thread/detail/config.hpp>
#include <boost/shared_ptr.hpp>
namespace boost
Modified: branches/release/boost/thread/win32/condition_variable.hpp
==============================================================================
--- branches/release/boost/thread/win32/condition_variable.hpp (original)
+++ branches/release/boost/thread/win32/condition_variable.hpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -13,6 +13,7 @@
#include <boost/thread/thread.hpp>
#include <boost/thread/thread_time.hpp>
#include "interlocked_read.hpp"
+#include <boost/thread/xtime.hpp>
namespace boost
{
@@ -110,54 +111,65 @@
};
+ template<typename lock_type>
+ void start_wait_loop_first_time(relocker<lock_type>& locker,
+ detail::win32::handle_manager& local_wake_sem)
+ {
+ locker.unlock();
+ if(!wake_sem)
+ {
+ wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
+ BOOST_ASSERT(wake_sem);
+ }
+ local_wake_sem=detail::win32::duplicate_handle(wake_sem);
+
+ if(generations[0].notified)
+ {
+ shift_generations_down();
+ }
+ else if(!active_generation_count)
+ {
+ active_generation_count=1;
+ }
+ }
+
+ template<typename lock_type>
+ void start_wait_loop(relocker<lock_type>& locker,
+ detail::win32::handle_manager& local_wake_sem,
+ detail::win32::handle_manager& sem)
+ {
+ boost::mutex::scoped_lock internal_lock(internal_mutex);
+ detail::interlocked_write_release(&total_count,total_count+1);
+ if(!local_wake_sem)
+ {
+ start_wait_loop_first_time(locker,local_wake_sem);
+ }
+ if(!generations[0].semaphore)
+ {
+ generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
+ BOOST_ASSERT(generations[0].semaphore);
+ }
+ ++generations[0].count;
+ sem=detail::win32::duplicate_handle(generations[0].semaphore);
+ }
+
protected:
template<typename lock_type>
- bool do_wait(lock_type& lock,::boost::system_time const& wait_until)
+ bool do_wait(lock_type& lock,timeout wait_until)
{
detail::win32::handle_manager local_wake_sem;
detail::win32::handle_manager sem;
- bool first_loop=true;
bool woken=false;
relocker<lock_type> locker(lock);
while(!woken)
{
+ start_wait_loop(locker,local_wake_sem,sem);
+
+ if(!this_thread::interruptible_wait(sem,wait_until))
{
- boost::mutex::scoped_lock internal_lock(internal_mutex);
- detail::interlocked_write_release(&total_count,total_count+1);
- if(first_loop)
- {
- locker.unlock();
- if(!wake_sem)
- {
- wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
- BOOST_ASSERT(wake_sem);
- }
- local_wake_sem=detail::win32::duplicate_handle(wake_sem);
-
- if(generations[0].notified)
- {
- shift_generations_down();
- }
- else if(!active_generation_count)
- {
- active_generation_count=1;
- }
-
- first_loop=false;
- }
- if(!generations[0].semaphore)
- {
- generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
- BOOST_ASSERT(generations[0].semaphore);
- }
- ++generations[0].count;
- sem=detail::win32::duplicate_handle(generations[0].semaphore);
- }
- if(!this_thread::interruptible_wait(sem,::boost::detail::get_milliseconds_until(wait_until)))
- {
- break;
+ return false;
}
unsigned long const woken_result=detail::win32::WaitForSingleObject(local_wake_sem,0);
@@ -167,6 +179,17 @@
}
return woken;
}
+
+ template<typename lock_type,typename predicate_type>
+ bool do_wait(lock_type& m,timeout const& wait_until,predicate_type pred)
+ {
+ while (!pred())
+ {
+ if(!do_wait(m, wait_until))
+ return pred();
+ }
+ return true;
+ }
basic_condition_variable(const basic_condition_variable& other);
basic_condition_variable& operator=(const basic_condition_variable& other);
@@ -238,7 +261,7 @@
public:
void wait(unique_lock<mutex>& m)
{
- do_wait(m,::boost::detail::get_system_time_sentinel());
+ do_wait(m,detail::timeout::sentinel());
}
template<typename predicate_type>
@@ -253,15 +276,30 @@
return do_wait(m,wait_until);
}
+ bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until)
+ {
+ return do_wait(m,system_time(wait_until));
+ }
+ template<typename duration_type>
+ bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
+ {
+ return do_wait(m,wait_duration.total_milliseconds());
+ }
+
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
{
- while (!pred())
- {
- if(!timed_wait(m, wait_until))
- return false;
- }
- return true;
+ return do_wait(m,wait_until,pred);
+ }
+ template<typename predicate_type>
+ bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until,predicate_type pred)
+ {
+ return do_wait(m,system_time(wait_until),pred);
+ }
+ template<typename duration_type,typename predicate_type>
+ bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
+ {
+ return do_wait(m,wait_duration.total_milliseconds(),pred);
}
};
@@ -272,7 +310,7 @@
template<typename lock_type>
void wait(lock_type& m)
{
- do_wait(m,::boost::detail::get_system_time_sentinel());
+ do_wait(m,detail::timeout::sentinel());
}
template<typename lock_type,typename predicate_type>
@@ -287,15 +325,34 @@
return do_wait(m,wait_until);
}
+ template<typename lock_type>
+ bool timed_wait(lock_type& m,boost::xtime const& wait_until)
+ {
+ return do_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 do_wait(m,wait_duration.total_milliseconds());
+ }
+
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
{
- while (!pred())
- {
- if(!timed_wait(m, wait_until))
- return false;
- }
- return true;
+ return do_wait(m,wait_until,pred);
+ }
+
+ template<typename lock_type,typename predicate_type>
+ bool timed_wait(lock_type& m,boost::xtime const& wait_until,predicate_type pred)
+ {
+ return do_wait(m,system_time(wait_until),pred);
+ }
+
+ template<typename lock_type,typename duration_type,typename predicate_type>
+ bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
+ {
+ return do_wait(m,wait_duration.total_milliseconds(),pred);
}
};
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 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -48,10 +48,10 @@
}
state_data state;
- void* semaphores[2];
- void* &unlock_sem;
- void* &exclusive_sem;
- void* upgrade_sem;
+ detail::win32::handle semaphores[2];
+ detail::win32::handle &unlock_sem;
+ detail::win32::handle &exclusive_sem;
+ detail::win32::handle upgrade_sem;
void release_waiters(state_data old_state)
{
Modified: branches/release/boost/thread/win32/thread.hpp
==============================================================================
--- branches/release/boost/thread/win32/thread.hpp (original)
+++ branches/release/boost/thread/win32/thread.hpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -19,6 +19,7 @@
#include <list>
#include <algorithm>
#include <boost/ref.hpp>
+#include <boost/cstdint.hpp>
namespace boost
{
@@ -73,6 +74,82 @@
};
typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
+
+ struct timeout
+ {
+ unsigned long start;
+ uintmax_t milliseconds;
+ bool relative;
+ boost::system_time abs_time;
+
+ static unsigned long const max_non_infinite_wait=0xfffffffe;
+
+ timeout(uintmax_t milliseconds_):
+ start(win32::GetTickCount()),
+ milliseconds(milliseconds_),
+ relative(true),
+ abs_time(boost::get_system_time())
+ {}
+
+ timeout(boost::system_time const& abs_time_):
+ start(win32::GetTickCount()),
+ milliseconds(0),
+ relative(false),
+ abs_time(abs_time_)
+ {}
+
+ struct remaining_time
+ {
+ bool more;
+ unsigned long milliseconds;
+
+ remaining_time(uintmax_t remaining):
+ more(remaining>max_non_infinite_wait),
+ milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
+ {}
+ };
+
+ remaining_time remaining_milliseconds() const
+ {
+ if(is_sentinel())
+ {
+ return remaining_time(win32::infinite);
+ }
+ else if(relative)
+ {
+ unsigned long const now=win32::GetTickCount();
+ unsigned long const elapsed=now-start;
+ return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
+ }
+ else
+ {
+ system_time const now=get_system_time();
+ if(abs_time<=now)
+ {
+ return remaining_time(0);
+ }
+ return remaining_time((abs_time-now).total_milliseconds()+1);
+ }
+ }
+
+ bool is_sentinel() const
+ {
+ return milliseconds==~uintmax_t(0);
+ }
+
+
+ static timeout sentinel()
+ {
+ return timeout(sentinel_type());
+ }
+ private:
+ struct sentinel_type
+ {};
+
+ explicit timeout(sentinel_type):
+ start(0),milliseconds(~uintmax_t(0)),relative(true)
+ {}
+ };
}
class BOOST_THREAD_DECL thread
@@ -92,7 +169,7 @@
thread_data(F f_):
f(f_)
{}
- thread_data(boost::move_t<F> f_):
+ thread_data(detail::thread_move_t<F> f_):
f(f_)
{}
@@ -123,16 +200,16 @@
start_thread();
}
template <class F>
- explicit thread(boost::move_t<F> f):
+ thread(detail::thread_move_t<F> f):
thread_info(detail::heap_new<thread_data<F> >(f))
{
start_thread();
}
- thread(boost::move_t<thread> x);
- thread& operator=(boost::move_t<thread> x);
- operator boost::move_t<thread>();
- boost::move_t<thread> move();
+ thread(detail::thread_move_t<thread> x);
+ thread& operator=(detail::thread_move_t<thread> x);
+ operator detail::thread_move_t<thread>();
+ detail::thread_move_t<thread> move();
void swap(thread& x);
@@ -168,6 +245,16 @@
bool interruption_requested() const;
};
+ inline detail::thread_move_t<thread> move(thread& x)
+ {
+ return x.move();
+ }
+
+ inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> x)
+ {
+ return x;
+ }
+
template<typename F>
struct thread::thread_data<boost::reference_wrapper<F> >:
detail::thread_data_base
@@ -210,7 +297,7 @@
thread::id BOOST_THREAD_DECL get_id();
- bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,unsigned long milliseconds);
+ bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
inline bool interruptible_wait(unsigned long milliseconds)
{
return interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
@@ -277,7 +364,14 @@
friend std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
{
- return os<<x.thread_data;
+ if(x.thread_data)
+ {
+ return os<<x.thread_data;
+ }
+ else
+ {
+ return os<<"{Not-any-thread}";
+ }
}
void interrupt()
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 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -53,6 +53,7 @@
using ::SleepEx;
using ::Sleep;
using ::QueueUserAPC;
+ using ::GetTickCount;
}
}
}
@@ -120,6 +121,8 @@
typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
__declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
+ __declspec(dllimport) unsigned long __stdcall GetTickCount();
+
# ifndef UNDER_CE
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
Modified: branches/release/libs/thread/build/Jamfile.v2
==============================================================================
--- branches/release/libs/thread/build/Jamfile.v2 (original)
+++ branches/release/libs/thread/build/Jamfile.v2 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -157,6 +157,7 @@
rule requirements ( properties * )
{
local result ;
+
if <threadapi>pthread in $(properties)
{
result += <define>BOOST_THREAD_POSIX ;
@@ -201,5 +202,7 @@
: thread_sources
: <conditional>@requirements
:
- : <conditional>@usage-requirements
+ : <link>shared:<define>BOOST_THREAD_USE_DLL=1
+ <link>static:<define>BOOST_THREAD_USE_LIB=1
+ <conditional>@usage-requirements
;
Modified: branches/release/libs/thread/src/pthread/once.cpp
==============================================================================
--- branches/release/libs/thread/src/pthread/once.cpp (original)
+++ branches/release/libs/thread/src/pthread/once.cpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -3,6 +3,7 @@
// 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)
+#define __STDC_CONSTANT_MACROS
#include <boost/thread/once.hpp>
#include <boost/assert.hpp>
#include <pthread.h>
@@ -12,9 +13,9 @@
{
namespace detail
{
- boost::uintmax_t once_global_epoch=0;
- pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER;
- pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER;
+ BOOST_THREAD_DECL boost::uintmax_t once_global_epoch=UINTMAX_C(~0);
+ BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER;
+ BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER;
namespace
{
@@ -41,11 +42,10 @@
{
data=malloc(sizeof(boost::uintmax_t));
BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data));
- *static_cast<boost::uintmax_t*>(data)=0;
+ *static_cast<boost::uintmax_t*>(data)=UINTMAX_C(~0);
}
return *static_cast<boost::uintmax_t*>(data);
}
-
}
}
Modified: branches/release/libs/thread/src/pthread/thread.cpp
==============================================================================
--- branches/release/libs/thread/src/pthread/thread.cpp (original)
+++ branches/release/libs/thread/src/pthread/thread.cpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -13,6 +13,14 @@
#include <boost/thread/locks.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/tss.hpp>
+#ifdef __linux__
+#include <sys/sysinfo.h>
+#elif defined(__APPLE__) || defined(__FreeBSD__)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#elif defined(__sun)
+#include <unistd.h>
+#endif
#include "timeconv.inl"
@@ -188,6 +196,37 @@
detach();
}
+ thread::thread(detail::thread_move_t<thread> x)
+ {
+ lock_guard<mutex> lock(x->thread_info_mutex);
+ thread_info=x->thread_info;
+ x->thread_info.reset();
+ }
+
+ thread& thread::operator=(detail::thread_move_t<thread> x)
+ {
+ thread new_thread(x);
+ swap(new_thread);
+ return *this;
+ }
+
+ thread::operator detail::thread_move_t<thread>()
+ {
+ return move();
+ }
+
+ detail::thread_move_t<thread> thread::move()
+ {
+ detail::thread_move_t<thread> x(*this);
+ return x;
+ }
+
+ void thread::swap(thread& x)
+ {
+ thread_info.swap(x.thread_info);
+ }
+
+
bool thread::operator==(const thread& other) const
{
return get_id()==other.get_id();
@@ -198,7 +237,7 @@
return !operator==(other);
}
- boost::shared_ptr<detail::thread_data_base> thread::get_thread_info() const
+ detail::thread_data_ptr thread::get_thread_info() const
{
lock_guard<mutex> l(thread_info_mutex);
return thread_info;
@@ -206,7 +245,7 @@
void thread::join()
{
- boost::shared_ptr<detail::thread_data_base> const local_thread_info=get_thread_info();
+ detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
bool do_join=false;
@@ -250,7 +289,7 @@
bool thread::timed_join(system_time const& wait_until)
{
- boost::shared_ptr<detail::thread_data_base> const local_thread_info=get_thread_info();
+ detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
bool do_join=false;
@@ -304,7 +343,7 @@
void thread::detach()
{
- boost::shared_ptr<detail::thread_data_base> local_thread_info;
+ detail::thread_data_ptr local_thread_info;
{
lock_guard<mutex> l1(thread_info_mutex);
thread_info.swap(local_thread_info);
@@ -377,15 +416,28 @@
unsigned thread::hardware_concurrency()
{
- return 1;
+#if defined(PTW32_VERSION) || defined(__hpux)
+ return pthread_num_processors_np();
+#elif defined(__linux__)
+ return get_nprocs();
+#elif defined(__APPLE__) || defined(__FreeBSD__)
+ int count;
+ size_t size=sizeof(count);
+ return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count;
+#elif defined(__sun)
+ int const count=sysconf(_SC_NPROCESSORS_ONLN);
+ return (count>0)?count:0;
+#else
+ return 0;
+#endif
}
thread::id thread::get_id() const
{
- boost::shared_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+ detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
- return id(local_thread_info->thread_handle);
+ return id(local_thread_info);
}
else
{
@@ -395,7 +447,7 @@
void thread::interrupt()
{
- boost::shared_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+ detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
lock_guard<mutex> lk(local_thread_info->data_mutex);
@@ -409,7 +461,7 @@
bool thread::interruption_requested() const
{
- boost::shared_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+ detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
lock_guard<mutex> lk(local_thread_info->data_mutex);
@@ -424,6 +476,12 @@
namespace this_thread
{
+ thread::id get_id()
+ {
+ boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
+ return thread::id(thread_info?thread_info->shared_from_this():detail::thread_data_ptr());
+ }
+
void interruption_point()
{
boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
Modified: branches/release/libs/thread/src/win32/thread.cpp
==============================================================================
--- branches/release/libs/thread/src/win32/thread.cpp (original)
+++ branches/release/libs/thread/src/win32/thread.cpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -4,6 +4,9 @@
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2007 David Deakins
+#define _WIN32_WINNT 0x400
+#define WINVER 0x400
+
#include <boost/thread/thread.hpp>
#include <algorithm>
#include <windows.h>
@@ -15,6 +18,7 @@
#include <boost/thread/tss.hpp>
#include <boost/assert.hpp>
#include <boost/thread/detail/tss_hooks.hpp>
+#include <boost/date_time/posix_time/conversion.hpp>
namespace boost
{
@@ -63,11 +67,11 @@
typedef void* uintptr_t;
inline uintptr_t const _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
- void* arglist, unsigned initflag, unsigned* thrdaddr)
+ void* arglist, unsigned initflag, unsigned* thrdaddr)
{
DWORD threadID;
HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy,
- new ThreadProxyData(start_address,arglist),initflag,&threadID);
+ new ThreadProxyData(start_address,arglist),initflag,&threadID);
if (hthread!=0)
*thrdaddr=threadID;
return reinterpret_cast<uintptr_t const>(hthread);
@@ -240,30 +244,28 @@
detach();
}
- thread::thread(boost::move_t<thread> x)
+ thread::thread(detail::thread_move_t<thread> x)
{
- {
- boost::mutex::scoped_lock l(x->thread_info_mutex);
- thread_info=x->thread_info;
- }
- x->release_handle();
+ lock_guard<mutex> lock(x->thread_info_mutex);
+ thread_info=x->thread_info;
+ x->thread_info=0;
}
- thread& thread::operator=(boost::move_t<thread> x)
+ thread& thread::operator=(detail::thread_move_t<thread> x)
{
thread new_thread(x);
swap(new_thread);
return *this;
}
- thread::operator boost::move_t<thread>()
+ thread::operator detail::thread_move_t<thread>()
{
return move();
}
- boost::move_t<thread> thread::move()
+ detail::thread_move_t<thread> thread::move()
{
- boost::move_t<thread> x(*this);
+ detail::thread_move_t<thread> x(*this);
return x;
}
@@ -287,7 +289,7 @@
detail::thread_data_ptr local_thread_info=get_thread_info();
if(local_thread_info)
{
- this_thread::interruptible_wait(local_thread_info->thread_handle,detail::win32::infinite);
+ this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel());
release_handle();
}
}
@@ -313,7 +315,7 @@
void thread::release_handle()
{
- boost::mutex::scoped_lock l1(thread_info_mutex);
+ lock_guard<mutex> l1(thread_info_mutex);
thread_info=0;
}
@@ -353,13 +355,57 @@
namespace this_thread
{
- bool interruptible_wait(detail::win32::handle handle_to_wait_for,unsigned long milliseconds)
+ namespace
+ {
+ LARGE_INTEGER get_due_time(detail::timeout const& target_time)
+ {
+ LARGE_INTEGER due_time={0};
+ if(target_time.relative)
+ {
+ unsigned long const elapsed_milliseconds=GetTickCount()-target_time.start;
+ LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds);
+ LONGLONG const hundred_nanoseconds_in_one_millisecond=10000;
+
+ if(remaining_milliseconds>0)
+ {
+ due_time.QuadPart=-(remaining_milliseconds*hundred_nanoseconds_in_one_millisecond);
+ }
+ }
+ else
+ {
+ SYSTEMTIME target_system_time={0};
+ target_system_time.wYear=target_time.abs_time.date().year();
+ target_system_time.wMonth=target_time.abs_time.date().month();
+ target_system_time.wDay=target_time.abs_time.date().day();
+ target_system_time.wHour=(WORD)target_time.abs_time.time_of_day().hours();
+ target_system_time.wMinute=(WORD)target_time.abs_time.time_of_day().minutes();
+ target_system_time.wSecond=(WORD)target_time.abs_time.time_of_day().seconds();
+
+ if(!SystemTimeToFileTime(&target_system_time,((FILETIME*)&due_time)))
+ {
+ due_time.QuadPart=0;
+ }
+ else
+ {
+ long const hundred_nanoseconds_in_one_second=10000000;
+ due_time.QuadPart+=target_time.abs_time.time_of_day().fractional_seconds()*(hundred_nanoseconds_in_one_second/target_time.abs_time.time_of_day().ticks_per_second());
+ }
+ }
+ return due_time;
+ }
+ }
+
+
+ bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
{
- detail::win32::handle handles[2]={0};
+ detail::win32::handle handles[3]={0};
unsigned handle_count=0;
+ unsigned wait_handle_index=~0U;
unsigned interruption_index=~0U;
+ unsigned timeout_index=~0U;
if(handle_to_wait_for!=detail::win32::invalid_handle_value)
{
+ wait_handle_index=handle_count;
handles[handle_count++]=handle_to_wait_for;
}
if(get_current_thread_data() && get_current_thread_data()->interruption_enabled)
@@ -367,24 +413,79 @@
interruption_index=handle_count;
handles[handle_count++]=get_current_thread_data()->interruption_handle;
}
-
- if(handle_count)
+
+ detail::win32::handle_manager timer_handle;
+
+#ifndef UNDER_CE
+ unsigned const min_timer_wait_period=20;
+
+ if(!target_time.is_sentinel())
{
- unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,milliseconds);
- if((handle_to_wait_for!=detail::win32::invalid_handle_value) && !notified_index)
+ detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
+ if(time_left.milliseconds > min_timer_wait_period)
{
- return true;
+ // for a long-enough timeout, use a waitable timer (which tracks clock changes)
+ timer_handle=CreateWaitableTimer(NULL,false,NULL);
+ if(timer_handle!=0)
+ {
+ LARGE_INTEGER due_time=get_due_time(target_time);
+
+ bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
+ if(set_time_succeeded)
+ {
+ timeout_index=handle_count;
+ handles[handle_count++]=timer_handle;
+ }
+ }
}
- else if(notified_index==interruption_index)
+ else if(!target_time.relative)
{
- detail::win32::ResetEvent(get_current_thread_data()->interruption_handle);
- throw thread_interrupted();
+ // convert short absolute-time timeouts into relative ones, so we don't race against clock changes
+ target_time=detail::timeout(time_left.milliseconds);
}
}
- else
+#endif
+
+ bool const using_timer=timeout_index!=~0u;
+ detail::timeout::remaining_time time_left(0);
+
+ do
{
- detail::win32::Sleep(milliseconds);
+ if(!using_timer)
+ {
+ time_left=target_time.remaining_milliseconds();
+ }
+
+ if(handle_count)
+ {
+ unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds);
+ if(notified_index<handle_count)
+ {
+ if(notified_index==wait_handle_index)
+ {
+ return true;
+ }
+ else if(notified_index==interruption_index)
+ {
+ detail::win32::ResetEvent(get_current_thread_data()->interruption_handle);
+ throw thread_interrupted();
+ }
+ else if(notified_index==timeout_index)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ detail::win32::Sleep(time_left.milliseconds);
+ }
+ if(target_time.relative)
+ {
+ target_time.milliseconds-=detail::timeout::max_non_infinite_wait;
+ }
}
+ while(time_left.more);
return false;
}
@@ -494,7 +595,7 @@
tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in
if(tss_data_node* const current_node=find_tss_data(key))
{
- if(cleanup_existing && current_node->func)
+ if(cleanup_existing && current_node->func.get())
{
(*current_node->func)(current_node->value);
}
Modified: branches/release/libs/thread/src/win32/tss_pe.cpp
==============================================================================
--- branches/release/libs/thread/src/win32/tss_pe.cpp (original)
+++ branches/release/libs/thread/src/win32/tss_pe.cpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -230,13 +230,10 @@
void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv)
{
- OutputDebugString("on_tls_callback\n");
-
switch (dwReason)
{
case DLL_THREAD_DETACH:
{
- OutputDebugString("on_tls_callback: thread_exit\n");
on_thread_exit();
break;
}
Modified: branches/release/libs/thread/test/Jamfile.v2
==============================================================================
--- branches/release/libs/thread/test/Jamfile.v2 (original)
+++ branches/release/libs/thread/test/Jamfile.v2 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -1,4 +1,5 @@
# (C) Copyright William E. Kempf 2001.
+# (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)
#
@@ -34,13 +35,21 @@
{
test-suite "threads"
: [ thread-run test_thread.cpp ]
+ [ thread-run test_thread_id.cpp ]
+ [ thread-run test_hardware_concurrency.cpp ]
+ [ thread-run test_thread_move.cpp ]
+ [ thread-run test_move_function.cpp ]
[ thread-run test_mutex.cpp ]
+ [ thread-run test_condition_notify_one.cpp ]
+ [ thread-run test_condition_timed_wait_times_out.cpp ]
+ [ thread-run test_condition_notify_all.cpp ]
[ thread-run test_condition.cpp ]
[ thread-run test_tss.cpp ]
[ thread-run test_once.cpp ]
[ thread-run test_xtime.cpp ]
[ thread-run test_barrier.cpp ]
[ thread-run test_shared_mutex.cpp ]
+ [ thread-run test_shared_mutex_part_2.cpp ]
[ thread-run test_lock_concept.cpp ]
;
}
Modified: branches/release/libs/thread/test/test_barrier.cpp
==============================================================================
--- branches/release/libs/thread/test/test_barrier.cpp (original)
+++ branches/release/libs/thread/test/test_barrier.cpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -52,7 +52,7 @@
throw;
}
- BOOST_CHECK(global_parameter == 5);
+ BOOST_CHECK_EQUAL(global_parameter,5);
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
Modified: branches/release/libs/thread/test/test_condition.cpp
==============================================================================
--- branches/release/libs/thread/test/test_condition.cpp (original)
+++ branches/release/libs/thread/test/test_condition.cpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -1,5 +1,6 @@
// 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)
@@ -19,7 +20,7 @@
condition_test_data() : notified(0), awoken(0) { }
boost::mutex mutex;
- boost::condition condition;
+ boost::condition_variable condition;
int notified;
int awoken;
};
@@ -82,66 +83,15 @@
BOOST_CHECK_EQUAL(data->notified, 4);
data->awoken++;
data->condition.notify_one();
-}
-
-void do_test_condition_notify_one()
-{
- condition_test_data data;
-
- boost::thread thread(bind(&condition_test_thread, &data));
-
- {
- boost::mutex::scoped_lock lock(data.mutex);
- BOOST_CHECK(lock ? true : false);
- data.notified++;
- data.condition.notify_one();
- }
-
- thread.join();
- BOOST_CHECK_EQUAL(data.awoken, 1);
-}
-
-void test_condition_notify_one()
-{
- timed_test(&do_test_condition_notify_one, 100, execution_monitor::use_mutex);
-}
-
-void do_test_condition_notify_all()
-{
- const int NUMTHREADS = 5;
- boost::thread_group threads;
- condition_test_data data;
-
- try
- {
- for (int i = 0; i < NUMTHREADS; ++i)
- threads.create_thread(bind(&condition_test_thread, &data));
-
- {
- boost::mutex::scoped_lock lock(data.mutex);
- BOOST_CHECK(lock ? true : false);
- data.notified++;
- data.condition.notify_all();
- }
-
- threads.join_all();
- }
- catch(...)
- {
- threads.interrupt_all();
- threads.join_all();
- throw;
- }
- BOOST_CHECK_EQUAL(data.awoken, NUMTHREADS);
-}
-
-void test_condition_notify_all()
-{
- // We should have already tested notify_one here, so
- // a timed test with the default execution_monitor::use_condition
- // should be OK, and gives the fastest performance
- timed_test(&do_test_condition_notify_all, 100);
+ // Test predicate timed_wait with relative timeout
+ cond_predicate pred_rel(data->notified, 5);
+ BOOST_CHECK(data->condition.timed_wait(lock, boost::posix_time::seconds(10), pred_rel));
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK(pred_rel());
+ BOOST_CHECK_EQUAL(data->notified, 5);
+ data->awoken++;
+ data->condition.notify_one();
}
void do_test_condition_waits()
@@ -185,10 +135,19 @@
data.condition.wait(lock);
BOOST_CHECK(lock ? true : false);
BOOST_CHECK_EQUAL(data.awoken, 4);
+
+
+ boost::thread::sleep(delay(1));
+ data.notified++;
+ data.condition.notify_one();
+ while (data.awoken != 5)
+ data.condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data.awoken, 5);
}
thread.join();
- BOOST_CHECK_EQUAL(data.awoken, 4);
+ BOOST_CHECK_EQUAL(data.awoken, 5);
}
void test_condition_waits()
@@ -216,14 +175,11 @@
timed_test(&do_test_condition_wait_is_a_interruption_point, 1);
}
-
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: condition test suite");
- test->add(BOOST_TEST_CASE(&test_condition_notify_one));
- test->add(BOOST_TEST_CASE(&test_condition_notify_all));
test->add(BOOST_TEST_CASE(&test_condition_waits));
test->add(BOOST_TEST_CASE(&test_condition_wait_is_a_interruption_point));
Modified: branches/release/libs/thread/test/test_mutex.cpp
==============================================================================
--- branches/release/libs/thread/test/test_mutex.cpp (original)
+++ branches/release/libs/thread/test/test_mutex.cpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -102,6 +102,11 @@
typedef M mutex_type;
typedef typename M::scoped_timed_lock timed_lock_type;
+ static bool fake_predicate()
+ {
+ return false;
+ }
+
void operator()()
{
mutex_type mutex;
@@ -123,14 +128,17 @@
BOOST_CHECK(lock ? true : false);
// Construct and initialize an xtime for a fast time out.
- boost::xtime xt = delay(0, 100);
+ boost::system_time timeout = boost::get_system_time()+boost::posix_time::milliseconds(100);
// Test the lock and the mutex with condition variables.
// No one is going to notify this condition variable. We expect to
// time out.
- BOOST_CHECK(!condition.timed_wait(lock, xt));
+ BOOST_CHECK(!condition.timed_wait(lock, timeout, fake_predicate));
BOOST_CHECK(lock ? true : false);
- BOOST_CHECK(in_range(xt));
+
+ boost::system_time now=boost::get_system_time();
+ boost::posix_time::milliseconds const timeout_resolution(20);
+ BOOST_CHECK((timeout-timeout_resolution)<now);
// Test the lock, unlock and timedlock methods.
lock.unlock();
Modified: branches/release/libs/thread/test/test_once.cpp
==============================================================================
--- branches/release/libs/thread/test/test_once.cpp (original)
+++ branches/release/libs/thread/test/test_once.cpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -19,6 +19,7 @@
++var_to_init;
}
+
void call_once_thread()
{
unsigned const loop_count=100;
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 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -5,13 +5,9 @@
#include <boost/test/unit_test.hpp>
#include <boost/thread/thread.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/condition_variable.hpp>
-#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/xtime.hpp>
#include "util.inl"
-#include <iostream>
-#include <boost/date_time/posix_time/posix_time_io.hpp>
+#include "shared_mutex_locking_thread.hpp"
#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
{ \
@@ -19,65 +15,6 @@
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::condition_variable& unblocked_condition;
- boost::mutex& finish_mutex;
- public:
- locking_thread(boost::shared_mutex& rw_mutex_,
- unsigned& unblocked_count_,
- boost::mutex& unblocked_count_mutex_,
- boost::condition_variable& unblocked_condition_,
- boost::mutex& finish_mutex_,
- unsigned& simultaneous_running_count_,
- unsigned& max_simultaneous_running_):
- rw_mutex(rw_mutex_),
- unblocked_count(unblocked_count_),
- unblocked_condition(unblocked_condition_),
- simultaneous_running_count(simultaneous_running_count_),
- max_simultaneous_running(max_simultaneous_running_),
- unblocked_count_mutex(unblocked_count_mutex_),
- finish_mutex(finish_mutex_)
- {}
-
- 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;
- unblocked_condition.notify_one();
- ++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;
@@ -328,250 +265,11 @@
throw;
}
-
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,1u);
}
-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::condition_variable unblocked_condition;
- boost::mutex finish_mutex;
- boost::mutex::scoped_lock finish_lock(finish_mutex);
-
- try
- {
- 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,unblocked_condition,
- 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();
- }
- catch(...)
- {
- pool.interrupt_all();
- pool.join_all();
- throw;
- }
-
- CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
- CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
-}
-
-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::condition_variable unblocked_condition;
- boost::mutex finish_mutex;
- boost::mutex::scoped_lock finish_lock(finish_mutex);
-
- unsigned const reader_count=100;
-
- try
- {
- 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,unblocked_condition,
- finish_mutex,simultaneous_running_count,max_simultaneous_running));
- }
- boost::thread::sleep(delay(1));
- pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
- finish_mutex,simultaneous_running_count,max_simultaneous_running));
- {
- boost::mutex::scoped_lock lk(unblocked_count_mutex);
- while(unblocked_count<(reader_count+1))
- {
- unblocked_condition.wait(lk);
- }
- }
- CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
-
- finish_lock.unlock();
- pool.join_all();
- }
- catch(...)
- {
- pool.interrupt_all();
- pool.join_all();
- throw;
- }
-
-
- 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,1u);
-
- 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,1u);
-
- 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,1u);
-
- boost::system_time const start=boost::get_system_time();
- boost::system_time const timeout=start+boost::posix_time::milliseconds(2000);
- bool const timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout);
- BOOST_CHECK(in_range(boost::get_xtime(timeout),1));
- 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 =
@@ -582,12 +280,6 @@
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;
}
Modified: branches/release/libs/thread/test/test_tss.cpp
==============================================================================
--- branches/release/libs/thread/test/test_tss.cpp (original)
+++ branches/release/libs/thread/test/test_tss.cpp 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -1,5 +1,6 @@
// 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)
@@ -73,7 +74,7 @@
native_thread_t create_native_thread(void)
{
- return CreateThread(
+ native_thread_t const res=CreateThread(
0, //security attributes (0 = not inheritable)
0, //stack size (0 = default)
&test_tss_thread_native, //function to execute
@@ -81,6 +82,8 @@
0, //creation flags (0 = run immediately)
0 //thread id (0 = thread id not returned)
);
+ BOOST_CHECK(res!=0);
+ return res;
}
void join_native_thread(native_thread_t thread)
@@ -154,19 +157,10 @@
tss_total = 0;
native_thread_t thread1 = create_native_thread();
- BOOST_CHECK(thread1 != 0);
-
native_thread_t thread2 = create_native_thread();
- BOOST_CHECK(thread2 != 0);
-
native_thread_t thread3 = create_native_thread();
- BOOST_CHECK(thread3 != 0);
-
native_thread_t thread4 = create_native_thread();
- BOOST_CHECK(thread3 != 0);
-
native_thread_t thread5 = create_native_thread();
- BOOST_CHECK(thread3 != 0);
join_native_thread(thread5);
join_native_thread(thread4);
Modified: branches/release/libs/thread/test/util.inl
==============================================================================
--- branches/release/libs/thread/test/util.inl (original)
+++ branches/release/libs/thread/test/util.inl 2007-12-21 06:51:05 EST (Fri, 21 Dec 2007)
@@ -1,5 +1,6 @@
// 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)
@@ -154,6 +155,26 @@
{
return thread_binder<F, T>(func, param);
}
+
+template <typename R, typename T>
+class thread_member_binder
+{
+public:
+ thread_member_binder(R (T::*func)(), T& param)
+ : func(func), param(param) { }
+ void operator()() const { (param.*func)(); }
+
+private:
+ R (T::*func)();
+ T& param;
+};
+
+
+template <typename R, typename T>
+thread_member_binder<R, T> bind(R (T::*func)(), T& param)
+{
+ return thread_member_binder<R, T>(func, param);
+}
} // namespace
#endif
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