diff --git a/doc/thread.qbk b/doc/thread.qbk index aaf975fd..b2ea6e6b 100644 --- a/doc/thread.qbk +++ b/doc/thread.qbk @@ -147,4 +147,6 @@ [include tss.qbk] +[include time.qbk] + [include acknowledgements.qbk] diff --git a/doc/thread_ref.qbk b/doc/thread_ref.qbk index 849bc3c7..55ff306f 100644 --- a/doc/thread_ref.qbk +++ b/doc/thread_ref.qbk @@ -17,6 +17,13 @@ allows the details of thread creation to be wrapped in a function. some_thread.join(); } +[Note: On compilers that support rvalue references, __thread__ provides a proper move constructor and move-assignment operator, and +therefore meets the C++0x ['MoveConstructible] and ['MoveAssignable] concepts. With such compilers, __thread__ can therefore be used +with containers that support those concepts. + +For other compilers, move support is provided with a move emulation layer, so containers must explicitly detect that move emulation +layer. See for details.] + [heading Launching threads] A new thread is launched by passing an object of a callable type that can be invoked with no parameters to the constructor. The @@ -318,7 +325,7 @@ unchanged.]] [variablelist -[[Effects:] [If `*this` refers to a thread of execution, that thread of execution becomes detached, and longer has an associated __thread__ object.]] +[[Effects:] [If `*this` refers to a thread of execution, that thread of execution becomes detached, and no longer has an associated __thread__ object.]] [[Postconditions:] [`*this` no longer refers to any thread of execution.]] @@ -499,7 +506,7 @@ otherwise.]] [variablelist -[[Returns:] [`true` if `*this` and `y` represent the different threads of execution, or one represents a thread of execution, and +[[Returns:] [`true` if `*this` and `y` represent different threads of execution, or one represents a thread of execution, and the other represent __not_a_thread__, `false` otherwise.]] [[Throws:] [Nothing]] diff --git a/doc/time.qbk b/doc/time.qbk new file mode 100644 index 00000000..f817206c --- /dev/null +++ b/doc/time.qbk @@ -0,0 +1,64 @@ +[section:time Date and Time Requirements] + +As of Boost 1.35.0, the __boost_thread__ library uses the [link date_time Boost.Date_Time] library for all operations that require a +time out. These include (but are not limited to): + +* __sleep__ +* __timed_join__ +* __cond_timed_wait__ +* __timed_lock_ref__ + +For the overloads that accept an absolute time parameter, an object of type [link thread.time.system_time `boost::system_time`] is +required. Typically, this will be obtained by adding a duration to the current time, obtained with a call to [link +thread.time.get_system_time `boost::get_system_time()`]. e.g. + + boost::system_time const timeout=boost::get_system_time() + boost::posix_time::milliseconds(500); + + extern bool done; + extern boost::mutex m; + extern boost::condition_variable cond; + + boost::unique_lock lk(m); + while(!done) + { + if(!cond.timed_wait(lk,timeout)) + { + throw "timed out"; + } + } + +For the overloads that accept a ['TimeDuration] parameter, an object of any type that meets the [link +date_time.posix_time.time_duration Boost.Date_Time Time Duration requirements] can be used, e.g. + + boost::this_thread::sleep(boost::posix_time::milliseconds(25)); + + boost::mutex m; + if(m.timed_lock(boost::posix_time::nanoseconds(100))) + { + // ... + } + +[section:system_time Typedef `system_time`] + + typedef boost::posix_time::ptime system_time; + +See the documentation for [link date_time.posix_time.ptime_class `boost::posix_time::ptime`] in the Boost.Date_Time library. + +[endsect] + +[section:get_system_time Non-member function `get_system_time()`] + + system_time get_system_time(); + +[variablelist + +[[Returns:] [The current time.]] + +[[Throws:] [Nothing.]] + +] + +[endsect] + + +[endsect] \ No newline at end of file diff --git a/include/boost/thread/barrier.hpp b/include/boost/thread/barrier.hpp index 665e3b03..546f5e97 100644 --- a/include/boost/thread/barrier.hpp +++ b/include/boost/thread/barrier.hpp @@ -1,6 +1,6 @@ // Copyright (C) 2002-2003 // David Moore, William E. Kempf -// Copyright (C) 2007 Anthony Williams +// Copyright (C) 2007-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -15,6 +15,8 @@ #include #include +#include + namespace boost { @@ -56,4 +58,6 @@ namespace boost } // namespace boost +#include + #endif diff --git a/include/boost/thread/detail/move.hpp b/include/boost/thread/detail/move.hpp index 48744932..f8917758 100644 --- a/include/boost/thread/detail/move.hpp +++ b/include/boost/thread/detail/move.hpp @@ -1,7 +1,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) -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams #ifndef BOOST_THREAD_MOVE_HPP #define BOOST_THREAD_MOVE_HPP @@ -9,6 +9,8 @@ #include #include +#include + namespace boost { namespace detail @@ -49,5 +51,6 @@ namespace boost } +#include #endif diff --git a/include/boost/thread/detail/thread.hpp b/include/boost/thread/detail/thread.hpp index 10810ef0..1ada38f9 100644 --- a/include/boost/thread/detail/thread.hpp +++ b/include/boost/thread/detail/thread.hpp @@ -21,6 +21,8 @@ #include #include +#include + #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable:4251) @@ -28,20 +30,13 @@ namespace boost { - class BOOST_THREAD_DECL thread + namespace detail { - private: - thread(thread&); - thread& operator=(thread&); - - void release_handle(); - template - struct thread_data: - detail::thread_data_base + class thread_data: + public detail::thread_data_base { - F f; - + public: #ifdef BOOST_HAS_RVALUE_REFS thread_data(F&& f_): f(static_cast(f_)) @@ -59,9 +54,59 @@ namespace boost f(); } private: + F f; + void operator=(thread_data&); thread_data(thread_data&); }; + + template + class thread_data >: + public detail::thread_data_base + { + private: + F& f; + + void operator=(thread_data&); + thread_data(thread_data&); + public: + thread_data(boost::reference_wrapper f_): + f(f_) + {} + + void run() + { + f(); + } + }; + + template + class thread_data >: + public detail::thread_data_base + { + private: + F& f; + void operator=(thread_data&); + thread_data(thread_data&); + public: + thread_data(const boost::reference_wrapper f_): + f(f_) + {} + + void run() + { + f(); + } + }; + } + + class BOOST_THREAD_DECL thread + { + private: + thread(thread&); + thread& operator=(thread&); + + void release_handle(); mutable boost::mutex thread_info_mutex; detail::thread_data_ptr thread_info; @@ -76,18 +121,18 @@ namespace boost template static inline detail::thread_data_ptr make_thread_info(F&& f) { - return detail::thread_data_ptr(detail::heap_new >(static_cast(f))); + return detail::thread_data_ptr(detail::heap_new >(static_cast(f))); } #else template static inline detail::thread_data_ptr make_thread_info(F f) { - return detail::thread_data_ptr(detail::heap_new >(f)); + return detail::thread_data_ptr(detail::heap_new >(f)); } template static inline detail::thread_data_ptr make_thread_info(boost::detail::thread_move_t f) { - return detail::thread_data_ptr(detail::heap_new >(f)); + return detail::thread_data_ptr(detail::heap_new >(f)); } #endif public: @@ -278,39 +323,6 @@ namespace boost } #endif - template - struct thread::thread_data >: - detail::thread_data_base - { - F& f; - - thread_data(boost::reference_wrapper f_): - f(f_) - {} - - void run() - { - f(); - } - }; - - template - struct thread::thread_data >: - detail::thread_data_base - { - F& f; - - thread_data(const boost::reference_wrapper f_): - f(f_) - {} - - void run() - { - f(); - } - }; - - namespace this_thread { class BOOST_THREAD_DECL disable_interruption @@ -536,4 +548,6 @@ namespace boost #pragma warning(pop) #endif +#include + #endif diff --git a/include/boost/thread/detail/tss_hooks.hpp b/include/boost/thread/detail/tss_hooks.hpp index 99a976f9..c4968442 100644 --- a/include/boost/thread/detail/tss_hooks.hpp +++ b/include/boost/thread/detail/tss_hooks.hpp @@ -8,6 +8,8 @@ #include +#include + #if defined(BOOST_HAS_WINTHREADS) typedef void (__cdecl *thread_exit_handler)(void); @@ -75,4 +77,6 @@ #endif //defined(BOOST_HAS_WINTHREADS) +#include + #endif //!defined(BOOST_TLS_HOOKS_HPP) diff --git a/include/boost/thread/exceptions.hpp b/include/boost/thread/exceptions.hpp index e46b30d2..49e244fe 100644 --- a/include/boost/thread/exceptions.hpp +++ b/include/boost/thread/exceptions.hpp @@ -1,6 +1,6 @@ // Copyright (C) 2001-2003 // William E. Kempf -// Copyright (C) 2007 Anthony Williams +// Copyright (C) 2007-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,6 +19,8 @@ #include #include +#include + namespace boost { @@ -103,6 +105,8 @@ public: } // namespace boost +#include + #endif // BOOST_THREAD_CONFIG_PDM070801_H // Change log: diff --git a/include/boost/thread/locks.hpp b/include/boost/thread/locks.hpp index dee1bdf7..8b183d38 100644 --- a/include/boost/thread/locks.hpp +++ b/include/boost/thread/locks.hpp @@ -8,10 +8,77 @@ #include #include #include +#include #include +#include + +#include namespace boost { + namespace detail + { + template + struct has_member_lock + { + typedef char true_type; + struct false_type + { + true_type dummy[2]; + }; + + template + static true_type has_member(U*,void (U::*dummy)()=&U::lock); + static false_type has_member(void*); + + BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_lock::has_member((T*)NULL))==sizeof(true_type)); + }; + + template + struct has_member_unlock + { + typedef char true_type; + struct false_type + { + true_type dummy[2]; + }; + + template + static true_type has_member(U*,void (U::*dummy)()=&U::unlock); + static false_type has_member(void*); + + BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_unlock::has_member((T*)NULL))==sizeof(true_type)); + }; + + template + struct has_member_try_lock + { + typedef char true_type; + struct false_type + { + true_type dummy[2]; + }; + + template + static true_type has_member(U*,bool (U::*dummy)()=&U::try_lock); + static false_type has_member(void*); + + BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_try_lock::has_member((T*)NULL))==sizeof(true_type)); + }; + + } + + + template + struct is_mutex_type + { + BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock::value && + detail::has_member_unlock::value && + detail::has_member_try_lock::value); + + }; + + struct defer_lock_t {}; struct try_to_lock_t @@ -621,13 +688,30 @@ namespace boost base::swap(*other); } - using base::lock; - using base::try_lock; - using base::unlock; - using base::owns_lock; - using base::mutex; - using base::release; - + void lock() + { + base::lock(); + } + bool try_lock() + { + return base::try_lock(); + } + void unlock() + { + base::unlock(); + } + bool owns_lock() const + { + return base::owns_lock(); + } + Mutex* mutex() const + { + return base::mutex(); + } + Mutex* release() + { + return base::release(); + } bool operator!() const { return !this->owns_lock(); @@ -764,7 +848,7 @@ namespace boost } template - void lock(MutexType1& m1,MutexType2& m2) + typename enable_if, void>::type lock(MutexType1& m1,MutexType2& m2) { unsigned const lock_count=2; unsigned lock_first=0; @@ -898,6 +982,142 @@ namespace boost } } } + + template + typename enable_if, int>::type try_lock(MutexType1& m1,MutexType2& m2) + { + return ((int)detail::try_lock_internal(m1,m2))-1; + } + + template + int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3) + { + return ((int)detail::try_lock_internal(m1,m2,m3))-1; + } + + template + int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4) + { + return ((int)detail::try_lock_internal(m1,m2,m3,m4))-1; + } + + template + int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4,MutexType5& m5) + { + return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1; + } + + + template + typename disable_if, void>::type lock(Iterator begin,Iterator end); + + namespace detail + { + template + struct range_lock_guard + { + Iterator begin; + Iterator end; + + range_lock_guard(Iterator begin_,Iterator end_): + begin(begin_),end(end_) + { + lock(begin,end); + } + + void release() + { + begin=end; + } + + ~range_lock_guard() + { + for(;begin!=end;++begin) + { + begin->unlock(); + } + } + }; + } + + template + typename disable_if, Iterator>::type try_lock(Iterator begin,Iterator end) + { + if(begin==end) + { + return end; + } + typedef typename std::iterator_traits::value_type lock_type; + unique_lock guard(*begin,try_to_lock); + + if(!guard.owns_lock()) + { + return begin; + } + Iterator const failed=try_lock(++begin,end); + if(failed==end) + { + guard.release(); + } + + return failed; + } + + template + typename disable_if, void>::type lock(Iterator begin,Iterator end) + { + typedef typename std::iterator_traits::value_type lock_type; + + if(begin==end) + { + return; + } + bool start_with_begin=true; + Iterator second=begin; + ++second; + Iterator next=second; + + for(;;) + { + unique_lock begin_lock(*begin,defer_lock); + if(start_with_begin) + { + begin_lock.lock(); + Iterator const failed_lock=try_lock(next,end); + if(failed_lock==end) + { + begin_lock.release(); + return; + } + start_with_begin=false; + next=failed_lock; + } + else + { + detail::range_lock_guard guard(next,end); + if(begin_lock.try_lock()) + { + Iterator const failed_lock=try_lock(second,next); + if(failed_lock==next) + { + begin_lock.release(); + guard.release(); + return; + } + start_with_begin=false; + next=failed_lock; + } + else + { + start_with_begin=true; + next=second; + } + } + } + } + } +#include + #endif diff --git a/include/boost/thread/once.hpp b/include/boost/thread/once.hpp index 608b77d6..975304e1 100644 --- a/include/boost/thread/once.hpp +++ b/include/boost/thread/once.hpp @@ -18,6 +18,8 @@ #error "Boost threads unavailable on this platform" #endif +#include + namespace boost { inline void call_once(void (*func)(),once_flag& flag) @@ -26,4 +28,6 @@ namespace boost } } +#include + #endif diff --git a/include/boost/thread/pthread/condition_variable.hpp b/include/boost/thread/pthread/condition_variable.hpp index 52c156bc..2d130a63 100644 --- a/include/boost/thread/pthread/condition_variable.hpp +++ b/include/boost/thread/pthread/condition_variable.hpp @@ -3,32 +3,17 @@ // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams -#include -#include -#include -#include #include "timespec.hpp" #include "pthread_mutex_scoped_lock.hpp" #include "thread_data.hpp" #include "condition_variable_fwd.hpp" +#include + namespace boost { - inline condition_variable::condition_variable() - { - int const res=pthread_cond_init(&cond,NULL); - if(res) - { - throw thread_resource_error(); - } - } - inline condition_variable::~condition_variable() - { - BOOST_VERIFY(!pthread_cond_destroy(&cond)); - } - inline void condition_variable::wait(unique_lock& m) { detail::interruption_checker check_for_interruption(&cond); @@ -175,4 +160,6 @@ namespace boost } +#include + #endif diff --git a/include/boost/thread/pthread/condition_variable_fwd.hpp b/include/boost/thread/pthread/condition_variable_fwd.hpp index 37884dd9..c3941511 100644 --- a/include/boost/thread/pthread/condition_variable_fwd.hpp +++ b/include/boost/thread/pthread/condition_variable_fwd.hpp @@ -3,14 +3,17 @@ // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams +#include #include #include #include #include #include +#include + namespace boost { class condition_variable @@ -22,8 +25,18 @@ namespace boost condition_variable& operator=(condition_variable&); public: - condition_variable(); - ~condition_variable(); + condition_variable() + { + int const res=pthread_cond_init(&cond,NULL); + if(res) + { + throw thread_resource_error(); + } + } + ~condition_variable() + { + BOOST_VERIFY(!pthread_cond_destroy(&cond)); + } void wait(unique_lock& m); @@ -69,4 +82,6 @@ namespace boost }; } +#include + #endif diff --git a/include/boost/thread/pthread/mutex.hpp b/include/boost/thread/pthread/mutex.hpp index e1fa2593..4b33358e 100644 --- a/include/boost/thread/pthread/mutex.hpp +++ b/include/boost/thread/pthread/mutex.hpp @@ -1,6 +1,6 @@ #ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP #define BOOST_THREAD_PTHREAD_MUTEX_HPP -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -24,6 +24,8 @@ #endif #endif +#include + namespace boost { class mutex: @@ -200,5 +202,7 @@ namespace boost } +#include + #endif diff --git a/include/boost/thread/pthread/once.hpp b/include/boost/thread/pthread/once.hpp index f342ed1d..f278a578 100644 --- a/include/boost/thread/pthread/once.hpp +++ b/include/boost/thread/pthread/once.hpp @@ -3,7 +3,7 @@ // once.hpp // -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -17,7 +17,10 @@ #include #include -namespace boost { +#include + +namespace boost +{ struct once_flag { @@ -82,4 +85,6 @@ namespace boost { } } +#include + #endif diff --git a/include/boost/thread/pthread/pthread_mutex_scoped_lock.hpp b/include/boost/thread/pthread/pthread_mutex_scoped_lock.hpp index 6b474a95..2407f915 100644 --- a/include/boost/thread/pthread/pthread_mutex_scoped_lock.hpp +++ b/include/boost/thread/pthread/pthread_mutex_scoped_lock.hpp @@ -1,6 +1,6 @@ #ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP #define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -9,6 +9,8 @@ #include #include +#include + namespace boost { namespace pthread @@ -47,4 +49,6 @@ namespace boost } } +#include + #endif diff --git a/include/boost/thread/pthread/recursive_mutex.hpp b/include/boost/thread/pthread/recursive_mutex.hpp index d0ddcef8..30689460 100644 --- a/include/boost/thread/pthread/recursive_mutex.hpp +++ b/include/boost/thread/pthread/recursive_mutex.hpp @@ -1,6 +1,6 @@ #ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP #define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -25,6 +25,8 @@ #endif #endif +#include + namespace boost { class recursive_mutex: @@ -259,5 +261,6 @@ namespace boost } +#include #endif diff --git a/include/boost/thread/pthread/shared_mutex.hpp b/include/boost/thread/pthread/shared_mutex.hpp index d44b101c..74345d88 100644 --- a/include/boost/thread/pthread/shared_mutex.hpp +++ b/include/boost/thread/pthread/shared_mutex.hpp @@ -1,7 +1,7 @@ #ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP #define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP -// (C) Copyright 2006-7 Anthony Williams +// (C) Copyright 2006-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -13,6 +13,8 @@ #include #include +#include + namespace boost { class shared_mutex @@ -296,5 +298,6 @@ namespace boost }; } +#include #endif diff --git a/include/boost/thread/pthread/thread_data.hpp b/include/boost/thread/pthread/thread_data.hpp index 2532b854..244035b4 100644 --- a/include/boost/thread/pthread/thread_data.hpp +++ b/include/boost/thread/pthread/thread_data.hpp @@ -14,6 +14,8 @@ #include #include "condition_variable_fwd.hpp" +#include + namespace boost { class thread; @@ -111,5 +113,6 @@ namespace boost } } +#include #endif diff --git a/include/boost/thread/pthread/thread_heap_alloc.hpp b/include/boost/thread/pthread/thread_heap_alloc.hpp index 338092da..7cc0aa04 100644 --- a/include/boost/thread/pthread/thread_heap_alloc.hpp +++ b/include/boost/thread/pthread/thread_heap_alloc.hpp @@ -5,6 +5,8 @@ #ifndef THREAD_HEAP_ALLOC_PTHREAD_HPP #define THREAD_HEAP_ALLOC_PTHREAD_HPP +#include + namespace boost { namespace detail @@ -235,5 +237,6 @@ namespace boost } } +#include #endif diff --git a/include/boost/thread/pthread/timespec.hpp b/include/boost/thread/pthread/timespec.hpp index 0837e97e..105030ff 100644 --- a/include/boost/thread/pthread/timespec.hpp +++ b/include/boost/thread/pthread/timespec.hpp @@ -1,6 +1,6 @@ #ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP #define BOOST_THREAD_PTHREAD_TIMESPEC_HPP -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -8,6 +8,12 @@ #include #include +#include +#ifndef _WIN32 +#include +#endif + +#include namespace boost { @@ -25,4 +31,6 @@ namespace boost } } +#include + #endif diff --git a/include/boost/thread/pthread/tss.hpp b/include/boost/thread/pthread/tss.hpp index 8d3bfd36..1f3cb246 100644 --- a/include/boost/thread/pthread/tss.hpp +++ b/include/boost/thread/pthread/tss.hpp @@ -4,11 +4,13 @@ // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams #include #include +#include + namespace boost { namespace detail @@ -100,4 +102,6 @@ namespace boost }; } +#include + #endif diff --git a/include/boost/thread/thread_time.hpp b/include/boost/thread/thread_time.hpp index 5468961f..8b557d5c 100644 --- a/include/boost/thread/thread_time.hpp +++ b/include/boost/thread/thread_time.hpp @@ -9,6 +9,8 @@ #include #include +#include + namespace boost { typedef boost::posix_time::ptime system_time; @@ -43,4 +45,6 @@ namespace boost } +#include + #endif diff --git a/include/boost/thread/win32/basic_recursive_mutex.hpp b/include/boost/thread/win32/basic_recursive_mutex.hpp index d2b8e77d..89c5f1dc 100644 --- a/include/boost/thread/win32/basic_recursive_mutex.hpp +++ b/include/boost/thread/win32/basic_recursive_mutex.hpp @@ -3,7 +3,7 @@ // basic_recursive_mutex.hpp // -// (C) Copyright 2006-7 Anthony Williams +// (C) Copyright 2006-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -12,6 +12,8 @@ #include "thread_primitives.hpp" #include "basic_timed_mutex.hpp" +#include + namespace boost { namespace detail @@ -123,4 +125,6 @@ namespace boost #define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0} +#include + #endif diff --git a/include/boost/thread/win32/basic_timed_mutex.hpp b/include/boost/thread/win32/basic_timed_mutex.hpp index 77a9332f..a218233c 100644 --- a/include/boost/thread/win32/basic_timed_mutex.hpp +++ b/include/boost/thread/win32/basic_timed_mutex.hpp @@ -3,7 +3,7 @@ // basic_timed_mutex_win32.hpp // -// (C) Copyright 2006 Anthony Williams +// (C) Copyright 2006-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -15,6 +15,8 @@ #include #include +#include + namespace boost { namespace detail @@ -175,4 +177,6 @@ namespace boost #define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0} +#include + #endif diff --git a/include/boost/thread/win32/condition_variable.hpp b/include/boost/thread/win32/condition_variable.hpp index 0581f459..b7a38665 100644 --- a/include/boost/thread/win32/condition_variable.hpp +++ b/include/boost/thread/win32/condition_variable.hpp @@ -3,7 +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) -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams #include #include "thread_primitives.hpp" @@ -17,6 +17,8 @@ #include #include +#include + namespace boost { namespace detail @@ -372,4 +374,6 @@ namespace boost } +#include + #endif diff --git a/include/boost/thread/win32/interlocked_read.hpp b/include/boost/thread/win32/interlocked_read.hpp index 72315f60..133fb6f9 100644 --- a/include/boost/thread/win32/interlocked_read.hpp +++ b/include/boost/thread/win32/interlocked_read.hpp @@ -3,12 +3,16 @@ // interlocked_read_win32.hpp // -// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2005-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include + +#include + #ifdef BOOST_MSVC extern "C" void _ReadWriteBarrier(void); @@ -46,8 +50,6 @@ namespace boost #else -#include - namespace boost { namespace detail @@ -73,5 +75,6 @@ namespace boost #endif +#include #endif diff --git a/include/boost/thread/win32/mutex.hpp b/include/boost/thread/win32/mutex.hpp index 41787559..3fa11d9c 100644 --- a/include/boost/thread/win32/mutex.hpp +++ b/include/boost/thread/win32/mutex.hpp @@ -10,6 +10,8 @@ #include #include +#include + namespace boost { namespace detail @@ -58,4 +60,6 @@ namespace boost }; } +#include + #endif diff --git a/include/boost/thread/win32/once.hpp b/include/boost/thread/win32/once.hpp index 719eaea5..a6fcc94d 100644 --- a/include/boost/thread/win32/once.hpp +++ b/include/boost/thread/win32/once.hpp @@ -18,6 +18,8 @@ #include #include +#include + #ifdef BOOST_NO_STDC_NAMESPACE namespace std { @@ -129,4 +131,6 @@ namespace boost } } +#include + #endif diff --git a/include/boost/thread/win32/recursive_mutex.hpp b/include/boost/thread/win32/recursive_mutex.hpp index 7f7541a1..2360a92b 100644 --- a/include/boost/thread/win32/recursive_mutex.hpp +++ b/include/boost/thread/win32/recursive_mutex.hpp @@ -15,6 +15,8 @@ #include #include +#include + namespace boost { class recursive_mutex: @@ -57,5 +59,6 @@ namespace boost }; } +#include #endif diff --git a/include/boost/thread/win32/shared_mutex.hpp b/include/boost/thread/win32/shared_mutex.hpp index 0b7d6fae..9f3c489e 100644 --- a/include/boost/thread/win32/shared_mutex.hpp +++ b/include/boost/thread/win32/shared_mutex.hpp @@ -15,6 +15,8 @@ #include #include +#include + namespace boost { class shared_mutex: @@ -632,5 +634,6 @@ namespace boost }; } +#include #endif diff --git a/include/boost/thread/win32/thread_data.hpp b/include/boost/thread/win32/thread_data.hpp index 604569a5..1a6a1e03 100644 --- a/include/boost/thread/win32/thread_data.hpp +++ b/include/boost/thread/win32/thread_data.hpp @@ -11,6 +11,8 @@ #include "thread_primitives.hpp" #include "thread_heap_alloc.hpp" +#include + namespace boost { namespace detail @@ -171,5 +173,6 @@ namespace boost } +#include #endif diff --git a/include/boost/thread/win32/thread_heap_alloc.hpp b/include/boost/thread/win32/thread_heap_alloc.hpp index a669654d..9f8186f5 100644 --- a/include/boost/thread/win32/thread_heap_alloc.hpp +++ b/include/boost/thread/win32/thread_heap_alloc.hpp @@ -49,6 +49,8 @@ namespace boost #endif +#include + namespace boost { namespace detail @@ -389,5 +391,7 @@ namespace boost } } +#include + #endif diff --git a/include/boost/thread/win32/thread_primitives.hpp b/include/boost/thread/win32/thread_primitives.hpp index 372f262d..022dc9ee 100644 --- a/include/boost/thread/win32/thread_primitives.hpp +++ b/include/boost/thread/win32/thread_primitives.hpp @@ -18,6 +18,7 @@ #if defined( BOOST_USE_WINDOWS_H ) # include + namespace boost { namespace detail @@ -147,6 +148,8 @@ namespace boost # error "Win32 functions not available" #endif +#include + namespace boost { namespace detail @@ -391,5 +394,6 @@ namespace boost } #endif +#include #endif diff --git a/include/boost/thread/win32/tss.hpp b/include/boost/thread/win32/tss.hpp index c6ce5c12..a5f1c31c 100644 --- a/include/boost/thread/win32/tss.hpp +++ b/include/boost/thread/win32/tss.hpp @@ -3,11 +3,13 @@ // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams #include #include "thread_heap_alloc.hpp" +#include + namespace boost { namespace detail @@ -99,5 +101,6 @@ namespace boost }; } +#include #endif diff --git a/include/boost/thread/xtime.hpp b/include/boost/thread/xtime.hpp index e3970758..54f91720 100644 --- a/include/boost/thread/xtime.hpp +++ b/include/boost/thread/xtime.hpp @@ -1,6 +1,6 @@ // Copyright (C) 2001-2003 // William E. Kempf -// Copyright (C) 2007 Anthony Williams +// Copyright (C) 2007-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -14,6 +14,8 @@ #include #include +#include + namespace boost { enum xtime_clock_types @@ -85,4 +87,6 @@ inline int xtime_cmp(const xtime& xt1, const xtime& xt2) } // namespace boost +#include + #endif //BOOST_XTIME_WEK070601_HPP diff --git a/src/pthread/thread.cpp b/src/pthread/thread.cpp index 89fbf928..2ceb68af 100644 --- a/src/pthread/thread.cpp +++ b/src/pthread/thread.cpp @@ -1,6 +1,6 @@ // Copyright (C) 2001-2003 // William E. Kempf -// Copyright (C) 2007 Anthony Williams +// Copyright (C) 2007-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,7 +18,7 @@ #elif defined(__APPLE__) || defined(__FreeBSD__) #include #include -#elif defined(__sun) +#elif defined(__sun) || defined(__CYGWIN__) #include #endif @@ -394,7 +394,7 @@ namespace boost int count; size_t size=sizeof(count); return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count; -#elif defined(__sun) +#elif defined(__sun) || defined(__CYGWIN__) int const count=sysconf(_SC_NPROCESSORS_ONLN); return (count>0)?count:0; #else diff --git a/test/test_generic_locks.cpp b/test/test_generic_locks.cpp index b0023bab..a091976e 100644 --- a/test/test_generic_locks.cpp +++ b/test/test_generic_locks.cpp @@ -123,6 +123,370 @@ void test_lock_two_other_thread_locks_in_opposite_order() t.join(); } +void test_lock_five_uncontended() +{ + boost::mutex m1,m2,m3,m4,m5; + + boost::mutex::scoped_lock l1(m1,boost::defer_lock), + l2(m2,boost::defer_lock), + l3(m3,boost::defer_lock), + l4(m4,boost::defer_lock), + l5(m5,boost::defer_lock); + + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); + BOOST_CHECK(!l3.owns_lock()); + BOOST_CHECK(!l4.owns_lock()); + BOOST_CHECK(!l5.owns_lock()); + + boost::lock(l1,l2,l3,l4,l5); + + BOOST_CHECK(l1.owns_lock()); + BOOST_CHECK(l2.owns_lock()); + BOOST_CHECK(l3.owns_lock()); + BOOST_CHECK(l4.owns_lock()); + BOOST_CHECK(l5.owns_lock()); +} + +void lock_five_mutexes_slowly(boost::mutex* m1,boost::mutex* m2,boost::mutex* m3,boost::mutex* m4,boost::mutex* m5, + wait_data* locked,wait_data* quit) +{ + boost::lock_guard l1(*m1); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard l2(*m2); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard l3(*m3); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard l4(*m4); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard l5(*m5); + locked->signal(); + quit->wait(); +} + +void lock_five(boost::mutex* m1,boost::mutex* m2,boost::mutex* m3,boost::mutex* m4,boost::mutex* m5) +{ + boost::lock(*m1,*m2,*m3,*m4,*m5); + m1->unlock(); + m2->unlock(); + m3->unlock(); + m4->unlock(); + m5->unlock(); +} + +void test_lock_five_other_thread_locks_in_order() +{ + boost::mutex m1,m2,m3,m4,m5; + wait_data locked; + wait_data release; + + boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_five,&m1,&m2,&m3,&m4,&m5); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3))); + + t.join(); +} + +void test_lock_five_other_thread_locks_in_different_order() +{ + boost::mutex m1,m2,m3,m4,m5; + wait_data locked; + wait_data release; + + boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_five,&m5,&m1,&m4,&m2,&m3); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3))); + + t.join(); +} + +void lock_n(boost::mutex* mutexes,unsigned count) +{ + boost::lock(mutexes,mutexes+count); + for(unsigned i=0;i l1(m1,boost::defer_lock), + l2(m2,boost::defer_lock); + + int const res=boost::try_lock(l1,l2); + + BOOST_CHECK(res==0); + BOOST_CHECK(m1.is_locked); + BOOST_CHECK(!m2.is_locked); + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); +} +void test_try_lock_two_second_locked() +{ + dummy_mutex m1,m2; + m2.lock(); + + boost::unique_lock l1(m1,boost::defer_lock), + l2(m2,boost::defer_lock); + + int const res=boost::try_lock(l1,l2); + + BOOST_CHECK(res==1); + BOOST_CHECK(!m1.is_locked); + BOOST_CHECK(m2.is_locked); + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); +} + +void test_try_lock_three() +{ + int const num_mutexes=3; + + for(int i=-1;i=0) + { + mutexes[i].lock(); + } + boost::unique_lock l1(mutexes[0],boost::defer_lock), + l2(mutexes[1],boost::defer_lock), + l3(mutexes[2],boost::defer_lock); + + int const res=boost::try_lock(l1,l2,l3); + + BOOST_CHECK(res==i); + for(int j=0;j=0) + { + mutexes[i].lock(); + } + boost::unique_lock l1(mutexes[0],boost::defer_lock), + l2(mutexes[1],boost::defer_lock), + l3(mutexes[2],boost::defer_lock), + l4(mutexes[3],boost::defer_lock); + + int const res=boost::try_lock(l1,l2,l3,l4); + + BOOST_CHECK(res==i); + for(int j=0;j=0) + { + mutexes[i].lock(); + } + boost::unique_lock l1(mutexes[0],boost::defer_lock), + l2(mutexes[1],boost::defer_lock), + l3(mutexes[2],boost::defer_lock), + l4(mutexes[3],boost::defer_lock), + l5(mutexes[4],boost::defer_lock); + + int const res=boost::try_lock(l1,l2,l3,l4,l5); + + BOOST_CHECK(res==i); + for(int j=0;jadd(BOOST_TEST_CASE(&test_lock_two_uncontended)); test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_order)); test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_opposite_order)); + test->add(BOOST_TEST_CASE(&test_lock_five_uncontended)); + test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_order)); + test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_different_order)); + test->add(BOOST_TEST_CASE(&test_lock_five_in_range)); + test->add(BOOST_TEST_CASE(&test_lock_ten_in_range)); + test->add(BOOST_TEST_CASE(&test_lock_ten_other_thread_locks_in_different_order)); + test->add(BOOST_TEST_CASE(&test_try_lock_two_uncontended)); + test->add(BOOST_TEST_CASE(&test_try_lock_two_first_locked)); + test->add(BOOST_TEST_CASE(&test_try_lock_two_second_locked)); + test->add(BOOST_TEST_CASE(&test_try_lock_three)); + test->add(BOOST_TEST_CASE(&test_try_lock_four)); + test->add(BOOST_TEST_CASE(&test_try_lock_five)); return test; } diff --git a/test/test_thread_launching.cpp b/test/test_thread_launching.cpp index 24a646f0..4582e657 100644 --- a/test/test_thread_launching.cpp +++ b/test/test_thread_launching.cpp @@ -143,8 +143,10 @@ void test_thread_callable_object_multiple_arguments() { x.push_back(i*i); } + + callable_multiple_arg func; - boost::thread callable3(callable_multiple_arg(),"hello",x,1.2); + boost::thread callable3(func,"hello",x,1.2); callable3.join(); BOOST_CHECK(callable_multiple_arg::called_three); BOOST_CHECK_EQUAL(callable_multiple_arg::called_three_arg1,"hello"); @@ -158,7 +160,7 @@ void test_thread_callable_object_multiple_arguments() double const dbl=1.234; - boost::thread callable2(callable_multiple_arg(),19,dbl); + boost::thread callable2(func,19,dbl); callable2.join(); BOOST_CHECK(callable_multiple_arg::called_two); BOOST_CHECK_EQUAL(callable_multiple_arg::called_two_arg1,19);