From 8affa3371829824bf0d1fbdd3eacf2179934f43a Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Tue, 3 Jan 2012 17:31:50 +0000 Subject: [PATCH] Thread fixed Bugs: * [@http://svn.boost.org/trac/boost/ticket/2309 #2309] Lack of g++ symbol visibility support in Boost.Thread. * [@http://svn.boost.org/trac/boost/ticket/2639 #2639] documentation should be extended(defer_lock, try_to_lock, ...). * [@http://svn.boost.org/trac/boost/ticket/3639 #3639] Boost.Thread doesn't build with Sun-5.9 on Linux. * [@http://svn.boost.org/trac/boost/ticket/3762 #3762] Thread can't be compiled with winscw (Codewarrior by Nokia). * [@http://svn.boost.org/trac/boost/ticket/3885 #3885] document about mix usage of boost.thread and native thread api. * [@http://svn.boost.org/trac/boost/ticket/3975 #3975] Incorrect precondition for promise::set_wait_callback(). * [@http://svn.boost.org/trac/boost/ticket/4048 #4048] thread::id formatting involves locale * [@http://svn.boost.org/trac/boost/ticket/4315 #4315] gcc 4.4 Warning: inline ... declared as dllimport: attribute ignored. * [@http://svn.boost.org/trac/boost/ticket/4480 #4480] OpenVMS patches for compiler issues workarounds. * [@http://svn.boost.org/trac/boost/ticket/4819 #4819] boost.thread's documentation misprints. * [@http://svn.boost.org/trac/boost/ticket/5423 #5423] thread issues with C++0x. * [@http://svn.boost.org/trac/boost/ticket/5617 #5617] boost::thread::id copy ctor. * [@http://svn.boost.org/trac/boost/ticket/5739 #5739] set-but-not-used warnings with gcc-4.6. * [@http://svn.boost.org/trac/boost/ticket/5826 #5826] threads.cpp: resource leak on threads creation failure. * [@http://svn.boost.org/trac/boost/ticket/5839 #5839] thread.cpp: ThreadProxy leaks on exceptions. * [@http://svn.boost.org/trac/boost/ticket/5859 #5859] win32 shared_mutex constructor leaks on exceptions. * [@http://svn.boost.org/trac/boost/ticket/6100 #6100] Compute hardware_concurrency() using get_nprocs() on GLIBC systems. * [@http://svn.boost.org/trac/boost/ticket/6168 #6168] recursive_mutex is using wrong config symbol (possible typo). * [@http://svn.boost.org/trac/boost/ticket/6175 #6175] Compile error with SunStudio. * [@http://svn.boost.org/trac/boost/ticket/6200 #6200] patch to have condition_variable and mutex error better handle EINTR. * [@http://svn.boost.org/trac/boost/ticket/6207 #6207] shared_lock swap compiler error on clang 3.0 c++11. * [@http://svn.boost.org/trac/boost/ticket/6208 #6208] try_lock_wrapper swap compiler error on clang 3.0 c++11. [SVN r76291] --- doc/changes.qbk | 55 ++++++- doc/compliance.qbk | 100 ++++++++++++ doc/future_ref.qbk | 2 +- doc/mutex_concepts.qbk | 19 +++ doc/thread.qbk | 2 + doc/thread_ref.qbk | 40 ++++- include/boost/thread/detail/config.hpp | 14 +- include/boost/thread/detail/thread.hpp | 93 ++++++----- include/boost/thread/exceptions.hpp | 16 +- include/boost/thread/future.hpp | 151 +++++++++--------- include/boost/thread/locks.hpp | 126 ++++++++------- .../thread/pthread/condition_variable.hpp | 28 ++-- .../thread/pthread/condition_variable_fwd.hpp | 8 +- include/boost/thread/pthread/mutex.hpp | 45 ++++-- include/boost/thread/pthread/once.hpp | 7 +- .../boost/thread/pthread/recursive_mutex.hpp | 38 ++--- include/boost/thread/pthread/thread_data.hpp | 26 ++- .../thread/win32/basic_recursive_mutex.hpp | 14 +- .../boost/thread/win32/basic_timed_mutex.hpp | 22 +-- .../boost/thread/win32/condition_variable.hpp | 54 +++---- include/boost/thread/win32/mutex.hpp | 2 +- .../boost/thread/win32/recursive_mutex.hpp | 8 +- include/boost/thread/win32/shared_mutex.hpp | 55 ++++--- include/boost/thread/win32/thread_data.hpp | 28 ++-- .../boost/thread/win32/thread_heap_alloc.hpp | 14 +- .../boost/thread/win32/thread_primitives.hpp | 43 +++-- src/pthread/thread.cpp | 54 ++++--- src/pthread/timeconv.inl | 9 +- src/win32/thread.cpp | 64 ++++---- test/test_barrier.cpp | 4 +- test/test_condition.cpp | 4 +- test/test_condition_notify_all.cpp | 4 +- test/test_condition_notify_one.cpp | 4 +- test/test_condition_timed_wait_times_out.cpp | 4 +- test/test_futures.cpp | 4 +- test/test_generic_locks.cpp | 4 +- test/test_hardware_concurrency.cpp | 4 +- test/test_lock_concept.cpp | 5 +- test/test_move_function.cpp | 4 +- test/test_mutex.cpp | 4 +- test/test_once.cpp | 4 +- test/test_shared_mutex.cpp | 4 +- test/test_shared_mutex_part_2.cpp | 4 +- test/test_shared_mutex_timed_locks.cpp | 4 +- test/test_thread.cpp | 4 +- test/test_thread_exit.cpp | 4 +- test/test_thread_id.cpp | 4 +- test/test_thread_launching.cpp | 4 +- test/test_thread_move.cpp | 4 +- test/test_thread_move_return.cpp | 4 +- test/test_thread_return_local.cpp | 4 +- test/test_tss.cpp | 4 +- test/test_xtime.cpp | 4 +- 53 files changed, 768 insertions(+), 466 deletions(-) create mode 100644 doc/compliance.qbk diff --git a/doc/changes.qbk b/doc/changes.qbk index fcb110f9..4b6e5e83 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -5,7 +5,41 @@ http://www.boost.org/LICENSE_1_0.txt). ] -[section:changes Changes since boost 1.40] +[section:changes Changes since] + +[heading Changes since boost 1.41] + +Fixed Bugs: + +* [@http://svn.boost.org/trac/boost/ticket/2309 #2309] Lack of g++ symbol visibility support in Boost.Thread. +* [@http://svn.boost.org/trac/boost/ticket/2639 #2639] documentation should be extended(defer_lock, try_to_lock, ...). + +* [@http://svn.boost.org/trac/boost/ticket/3639 #3639] Boost.Thread doesn't build with Sun-5.9 on Linux. +* [@http://svn.boost.org/trac/boost/ticket/3762 #3762] Thread can't be compiled with winscw (Codewarrior by Nokia). +* [@http://svn.boost.org/trac/boost/ticket/3885 #3885] document about mix usage of boost.thread and native thread api. +* [@http://svn.boost.org/trac/boost/ticket/3975 #3975] Incorrect precondition for promise::set_wait_callback(). + +* [@http://svn.boost.org/trac/boost/ticket/4048 #4048] thread::id formatting involves locale +* [@http://svn.boost.org/trac/boost/ticket/4315 #4315] gcc 4.4 Warning: inline ... declared as dllimport: attribute ignored. +* [@http://svn.boost.org/trac/boost/ticket/4480 #4480] OpenVMS patches for compiler issues workarounds. +* [@http://svn.boost.org/trac/boost/ticket/4819 #4819] boost.thread's documentation misprints. + +* [@http://svn.boost.org/trac/boost/ticket/5423 #5423] thread issues with C++0x. +* [@http://svn.boost.org/trac/boost/ticket/5617 #5617] boost::thread::id copy ctor. +* [@http://svn.boost.org/trac/boost/ticket/5739 #5739] set-but-not-used warnings with gcc-4.6. +* [@http://svn.boost.org/trac/boost/ticket/5826 #5826] threads.cpp: resource leak on threads creation failure. +* [@http://svn.boost.org/trac/boost/ticket/5839 #5839] thread.cpp: ThreadProxy leaks on exceptions. +* [@http://svn.boost.org/trac/boost/ticket/5859 #5859] win32 shared_mutex constructor leaks on exceptions. + +* [@http://svn.boost.org/trac/boost/ticket/6100 #6100] Compute hardware_concurrency() using get_nprocs() on GLIBC systems. +* [@http://svn.boost.org/trac/boost/ticket/6168 #6168] recursive_mutex is using wrong config symbol (possible typo). +* [@http://svn.boost.org/trac/boost/ticket/6175 #6175] Compile error with SunStudio. +* [@http://svn.boost.org/trac/boost/ticket/6200 #6200] patch to have condition_variable and mutex error better handle EINTR. +* [@http://svn.boost.org/trac/boost/ticket/6207 #6207] shared_lock swap compiler error on clang 3.0 c++11. +* [@http://svn.boost.org/trac/boost/ticket/6208 #6208] try_lock_wrapper swap compiler error on clang 3.0 c++11. + + +[heading Changes since boost 1.40] The 1.41.0 release of Boost adds futures to the thread library. There are also a few minor changes. @@ -85,3 +119,22 @@ been moved to __thread_id__. unlocked one level, and not completely. This prior behaviour was not guaranteed and did not feature in the tests. [endsect] + +[section:future Future] + +The following features will be included in next releases. By order of priority: + +* [@http://svn.boost.org/trac/boost/ticket/6194 #6194] Adapt to Boost.Move. +* [@http://svn.boost.org/trac/boost/ticket/4710 #4710] Missing async(). +* [@http://svn.boost.org/trac/boost/ticket/6195 #6195] Provide the standard time related interface using Boost.Chrono. + * [@http://svn.boost.org/trac/boost/ticket/2637 #2637] shared mutex lock +* Lock guards + * [@http://svn.boost.org/trac/boost/ticket/1850 #1850] request for unlock_guard (and/or unique_unlock) to compliment lock_guard/unique_lock + * [@http://svn.boost.org/trac/boost/ticket/3567 #3567] Request for shared_lock_guard +* [@http://svn.boost.org/trac/boost/ticket/2741 #2741] Proposal to manage portable and non portable thread attributes. + * #2880 Request for Thread scheduler support for boost .. + * #3696 Boost Thread library lacks any way to set priority of threads + * #5956 Add optional stack_size argument to thread::start_thread() + +[endsect] + diff --git a/doc/compliance.qbk b/doc/compliance.qbk new file mode 100644 index 00000000..2bf923eb --- /dev/null +++ b/doc/compliance.qbk @@ -0,0 +1,100 @@ +[/ + (C) Copyright 2011 Vicente J. Botet Escriba. + 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). +] + +[section:compliance Compliance with standard] + +[section:cpp11 C++11 standard Thread library] + + +[table Compliance C++11 standard + [[Section] [Description] [Status] [Comments] [Ticket]] + [[30] [Thread support library] [Partial] [-] [-]] + [[30.1] [General] [-] [-] [-]] + [[30.2] [Requirements] [-] [-] [-]] + [[30.2.1] [Template parameter names] [-] [-] [-]] + [[30.2.2] [Exceptions] [No] [-] [#12]] + [[30.2.3] [Native handles] [Yes] [-] [-]] + [[30.2.4] [Timing specifications] [No] [-] [#6195]] + [[30.2.5] [Requirements for Lockable types] [Partial] [-] [-]] + [[30.2.5.1] [In general] [-] [-] [-]] + [[30.2.5.2] [BasicLockable requirements] [No] [-] [#13]] + [[30.2.5.3] [Lockable requirements] [yes] [-] [-]] + [[30.2.5.4] [TimedLockable requirements] [Partial] [chrono] [#6195]] + [[30.2.6] [decay_copy] [-] [-] [-]] + [[30.3] [Threads] [Partial] [-] [-]] + [[30.3.1] [Class thread] [Partial] [-] [-]] + [[30.3.1.1] [Class thread::id] [Partial] [Missing noexcept, template <> struct hash] [#3,#4]] + [[30.3.1.2] [thread constructors] [Partial] [Missing noexcept and move semantics] [#3,#6194]] + [[30.3.1.3] [thread destructor] [Yes] [-] [-]] + [[30.3.1.4] [thread assignment] [Partial] [move semantics] [-]] + [[30.3.1.5] [thread members] [Partial] [Missing noexcept, chrono] [#3,#6195]] + [[30.3.1.6] [thread static members] [Partial] [Missing noexcept] [#3,#6195]] + [[30.3.1.7] [thread specialized algorithms] [Yes] [-] [-]] + [[30.3.2] [Namespace this_thread] [Partial] [chrono] [#6195]] + [[30.4] [Mutual exclusion] [Partial] [-] [-]] + [[30.4.1] [Mutex requirements] [Partial] [-] [-]] + [[30.4.1.1] [In general] [Partial] [-] [-]] + [[30.4.1.2] [Mutex types] [Partial] [noexcept,delete] [#3,#5]] + [[30.4.1.2.1] [Class mutex] [Partial] [noexcept,delete] [#3,#5]] + [[30.4.1.2.2] [Class recursive_mutex] [Partial] [noexcept,delete] [#3,#5]] + [[30.4.1.3] [Timed mutex types] [Partial] [noexcept,chrono,delete] [#3,#6195,#5]] + [[30.4.1.3.1] [Class timed_mutex] [Partial] [noexcept,chrono,delete] [#3,#6195,#5]] + [[30.4.1.3.1] [Class recursive_timed_mutex] [Partial] [noexcept,chrono,delete] [#3,#6195,#5]] + [[30.4.2] [Locks] [Partial] [noexcept,chrono,move,delete,bool] [#3,#6195,#5,#6]] + [[30.4.2.1] [Class template lock_guard] [Partial] [cons/dest delete] [#5]] + [[30.4.2.2] [Class template unique_lock] [Partial] [noexcept, chrono, move, delete] [#3,#6195,#5,#6]] + [[30.4.2.2.1] [unique_lock constructors, destructor, and assignment] [Partial] [noexcept, chrono, move, delete] [#3,#6195,#5,#6]] + [[30.4.2.2.2] [unique_lock locking] [Partial] [chrono] [,#6195,]] + [[30.4.2.2.3] [unique_lock modifiers] [Yes] [-] [-]] + [[30.4.2.2.4] [unique_lock observers] [Partial] [explicit operator bool] [#6]] + [[30.4.3] [Generic locking algorithms] [Partial] [Variadic,] [#7]] + [[30.4.4] [Call once] [Partial] [move,variadic] [#6194,#7]] + [[30.4.4.1] [Struct once_flag] [Yes] [-] [-]] + [[30.4.4.2] [Function call_once] [Yes] [-] [-]] + [[30.5] [Condition variables] [Partial] [chrono,cv_status,notify_all_at_thread_exit] [#6195,#8,#9]] + [[30.5 6-10] [Function notify_all_at_thread_exit] [No] [-] [#9]] + [[30.5.1] [Class condition_variable] [Partial] [chrono,cv_status] [#6195,#8]] + [[30.5.2] [Class condition_variable_any] [Partial] [chrono,cv_status] [#6195,#8]] + [[30.6] [Futures] [Partial] [-] [-]] + [[30.6.1] [Overview] [Partial] [-] [-]] + [[30.6.2] [Error handling] [No] [-] [-]] + [[30.6.3] [Class future_error] [No] [-] [-]] + [[30.6.4] [Shared state] [No] [-] [-]] + [[30.6.5] [Class template promise] [Partial] [allocator,move,delete] [#10,#6194,#5]] + [[30.6.6] [Class template future] [No] [unique_future is the closest to future] [#11]] + [[30.6.7] [Class template shared_future] [Partial] [allocator,move,delete] [#10,#6194,#5]] + [[30.6.8] [Function template async] [No] [async] [#4710]] + [[30.6.8] [Class template packaged_task] [Partial] [-] [-]] +] + + +[table Extension + [[Section] [Description] [Comments]] + [[30.3.1.5.x] [interrupt] [-]] + [[30.3.1.5.y] [operator==,operator!=] [-]] + [[30.3.2.x] [Interruprion] [-]] + [[30.3.2.y] [at_thread_exit] [-]] + [[30.4.3.x] [Generic locking algorithms begin/end] [-]] + [[30.x] [Barriers] [-]] + [[30.y] [Thread Local Storage] [-]] + [[30.z] [Class thread_group] [-]] +] + +[endsect] + +[section:shared Shared Mutex library extension] + +[table Clock Requirements + [[Section] [Description] [Status] [Comments]] + [[XXXX] [DDDD] [SSSS] [CCCC]] + [[XXXX] [DDDD] [SSSS] [CCCC]] +] + +[endsect] + + +[endsect] diff --git a/doc/future_ref.qbk b/doc/future_ref.qbk index f80bf22f..219619ca 100644 --- a/doc/future_ref.qbk +++ b/doc/future_ref.qbk @@ -701,7 +701,7 @@ required for storage of the result cannot be allocated.]] [variablelist -[[Preconditions:] [The expression `f(t)` where `t` is a lvalue of type __packaged_task__ shall be well-formed. Invoking a copy of +[[Preconditions:] [The expression `f(t)` where `t` is a lvalue of type __promise__ shall be well-formed. Invoking a copy of `f` shall have the same effect as invoking `f`]] [[Effects:] [Store a copy of `f` with the asynchronous result associated with `*this` as a ['wait callback]. This will replace any diff --git a/doc/mutex_concepts.qbk b/doc/mutex_concepts.qbk index 1affa78c..dd3aba79 100644 --- a/doc/mutex_concepts.qbk +++ b/doc/mutex_concepts.qbk @@ -310,6 +310,25 @@ without blocking.]] [section:locks Lock Types] +[section:lock_tags Lock option tags] + + #include + + struct defer_lock_t {}; + struct try_to_lock_t {}; + struct adopt_lock_t {}; + const defer_lock_t defer_lock; + const try_to_lock_t try_to_lock; + const adopt_lock_t adopt_lock; + +These tags are used in scoped locks constructors to specify a specific behavior. + +*`defer_lock_t`: is used to construct the scoped lock without locking it. +*`try_to_lock_t`: is used to construct the scoped lock trying to lock it. +*`adopt_lock_t`: is used to construct the scoped lock without locking it but adopting ownership. + +[endsect] + [section:lock_guard Class template `lock_guard`] #include diff --git a/doc/thread.qbk b/doc/thread.qbk index eca953ec..c1a236c6 100644 --- a/doc/thread.qbk +++ b/doc/thread.qbk @@ -166,3 +166,5 @@ [include time.qbk] [include acknowledgements.qbk] + +[include compliance.qbk] diff --git a/doc/thread_ref.qbk b/doc/thread_ref.qbk index 9a3b5640..aa0d5e94 100644 --- a/doc/thread_ref.qbk +++ b/doc/thread_ref.qbk @@ -163,6 +163,44 @@ Each instance of __thread_id__ either refers to some thread, or __not_a_thread__ compare equal to each other, but not equal to any instances that refer to an actual thread of execution. The comparison operators on __thread_id__ yield a total order for every non-equal thread ID. +[heading Using native interfaces with Boost.Thread resources] + + +__thread__ class has members `native_handle_type` and `native_handle` providing access to the underlying native handle. + +This native handle can be used to change for example the scheduling. + + +In general, it is not safe to use this handle with operations that can conflict with the ones provided by Boost.Thread. An example of bad usage could be detaching a thread directly as it will not change the internals of the __thread__ instance, so for example the joinable function will continue to return true, while the native thread is no more joinable. + + thread t(fct); + thread::native_handle_type hnd=t.native_handle(); + pthread_detach(hnd); + assert(t.joinable()); + +[heading Using Boost.Thread interfaces in a native thread] + + +Any thread of execution created using the native interface is called a native thread in this documentation. + +The first example of a native thread of execution is the main thread. + +The user can access to some synchronization functions related to the native current thread using the `boost::this_thread` `yield`, `sleep`, functions. + + + int main() { + // ... + boost::this_thread::sleep(); + // ... + } + + +Of course all the synchronization facilities provided by Boost.Thread are also available on native threads. + +The `boost::this_thread` interrupt related functions behave in a degraded mode when called from a thread created using the native interface, i.e. `boost::this_thread::interruption_enabled()` returns false. As consequence the use of `boost::this_thread::disable_interruption` and `boost::this_thread::restore_interruption` will do nothing and calls to `boost::this_thread::interrupt_point()` will be just ignored. + +As the single way to interrupt a thread is through a __thread__ instance, `interruption_request()` wiil returns false for the native threads. + [section:thread Class `thread`] #include @@ -675,7 +713,7 @@ execution.]] [endsect] -[section:less_than_or_equal `operator>=`] +[section:less_than_or_equal `operator<=`] bool operator<=(const id& y) const; diff --git a/include/boost/thread/detail/config.hpp b/include/boost/thread/detail/config.hpp index 4015a6c7..da4e288d 100644 --- a/include/boost/thread/detail/config.hpp +++ b/include/boost/thread/detail/config.hpp @@ -1,7 +1,7 @@ // Copyright (C) 2001-2003 // William E. Kempf // -// Distributed under the Boost Software License, Version 1.0. (See accompanying +// 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) #ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP @@ -53,12 +53,18 @@ #if defined(BOOST_HAS_DECLSPEC) # if defined(BOOST_THREAD_BUILD_DLL) //Build dll -# define BOOST_THREAD_DECL __declspec(dllexport) +# define BOOST_THREAD_DECL BOOST_SYMBOL_EXPORT +//# define BOOST_THREAD_DECL __declspec(dllexport) + # elif defined(BOOST_THREAD_USE_DLL) //Use dll -# define BOOST_THREAD_DECL __declspec(dllimport) +# define BOOST_THREAD_DECL BOOST_SYMBOL_IMPORT +//# define BOOST_THREAD_DECL __declspec(dllimport) # else # define BOOST_THREAD_DECL # endif +#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# define BOOST_THREAD_DECL BOOST_SYMBOL_VISIBLE + #else # define BOOST_THREAD_DECL #endif // BOOST_HAS_DECLSPEC @@ -69,7 +75,7 @@ #if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB) // // Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp -// once it's done with it: +// once it's done with it: // #if defined(BOOST_THREAD_USE_DLL) # define BOOST_DYN_LINK diff --git a/include/boost/thread/detail/thread.hpp b/include/boost/thread/detail/thread.hpp index 005555e6..7863c2f9 100644 --- a/include/boost/thread/detail/thread.hpp +++ b/include/boost/thread/detail/thread.hpp @@ -4,7 +4,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007-10 Anthony Williams - + #include #ifndef BOOST_NO_IOSTREAM #include @@ -55,7 +55,7 @@ namespace boost thread_data(detail::thread_move_t f_): f(f_) {} -#endif +#endif void run() { f(); @@ -80,7 +80,7 @@ namespace boost thread_data(boost::reference_wrapper f_): f(f_) {} - + void run() { f(); @@ -99,14 +99,14 @@ namespace boost thread_data(const boost::reference_wrapper f_): f(f_) {} - + void run() { f(); } }; } - + class BOOST_THREAD_DECL thread { private: @@ -114,11 +114,11 @@ namespace boost thread& operator=(thread&); void release_handle(); - + detail::thread_data_ptr thread_info; void start_thread(); - + explicit thread(detail::thread_data_ptr data); detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const; @@ -149,8 +149,8 @@ namespace boost struct dummy; public: #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) - thread(const volatile thread&); -#endif + thread(const volatile thread&); +#endif thread(); ~thread(); @@ -175,7 +175,7 @@ namespace boost { thread_info.swap(other.thread_info); } - + thread& operator=(thread&& other) { thread_info=other.thread_info; @@ -187,7 +187,7 @@ namespace boost { return static_cast(*this); } - + #else #ifdef BOOST_NO_SFINAE template @@ -204,7 +204,7 @@ namespace boost start_thread(); } #endif - + template explicit thread(detail::thread_move_t f): thread_info(make_thread_info(f)) @@ -217,13 +217,13 @@ namespace boost thread_info=x->thread_info; x->thread_info.reset(); } - + #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) - thread& operator=(thread x) - { - swap(x); - return *this; - } + thread& operator=(thread x) + { + swap(x); + return *this; + } #else thread& operator=(detail::thread_move_t x) { @@ -231,12 +231,12 @@ namespace boost swap(new_thread); return *this; } -#endif +#endif operator detail::thread_move_t() { return move(); } - + detail::thread_move_t move() { detail::thread_move_t x(*this); @@ -312,7 +312,7 @@ namespace boost thread_info.swap(x.thread_info); } - class id; + class BOOST_SYMBOL_VISIBLE id; id get_id() const; @@ -340,7 +340,7 @@ namespace boost { this_thread::yield(); } - + static inline void sleep(const system_time& xt) { this_thread::sleep(xt); @@ -355,7 +355,7 @@ namespace boost { return lhs.swap(rhs); } - + #ifndef BOOST_NO_RVALUE_REFERENCES inline thread&& move(thread& t) { @@ -380,17 +380,17 @@ namespace boost bool BOOST_THREAD_DECL interruption_enabled(); bool BOOST_THREAD_DECL interruption_requested(); - inline void sleep(xtime const& abs_time) + inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time) { sleep(system_time(abs_time)); } } - class thread::id + class BOOST_SYMBOL_VISIBLE thread::id { private: detail::thread_data_ptr thread_data; - + id(detail::thread_data_ptr thread_data_): thread_data(thread_data_) {} @@ -400,32 +400,36 @@ namespace boost id(): thread_data() {} - + + id(const id& other): + thread_data(other.thread_data) + {} + bool operator==(const id& y) const { return thread_data==y.thread_data; } - + bool operator!=(const id& y) const { return thread_data!=y.thread_data; } - + bool operator<(const id& y) const { return thread_data(const id& y) const { return y.thread_data=(const id& y) const { return !(thread_data - friend std::basic_ostream& + friend BOOST_SYMBOL_VISIBLE + std::basic_ostream& operator<<(std::basic_ostream& os, const id& x) { if(x.thread_data) { - return os< - std::basic_ostream& + BOOST_SYMBOL_VISIBLE + std::basic_ostream& print(std::basic_ostream& os) const { if(thread_data) @@ -467,7 +473,8 @@ namespace boost #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template - std::basic_ostream& + BOOST_SYMBOL_VISIBLE + std::basic_ostream& operator<<(std::basic_ostream& os, const thread::id& x) { return x.print(os); @@ -478,12 +485,12 @@ namespace boost { return get_id()==other.get_id(); } - + inline bool thread::operator!=(const thread& other) const { return get_id()!=other.get_id(); } - + namespace detail { struct thread_exit_function_base @@ -492,26 +499,26 @@ namespace boost {} virtual void operator()()=0; }; - + template struct thread_exit_function: thread_exit_function_base { F f; - + thread_exit_function(F f_): f(f_) {} - + void operator()() { f(); } }; - + void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*); } - + namespace this_thread { template diff --git a/include/boost/thread/exceptions.hpp b/include/boost/thread/exceptions.hpp index 2a05b506..06ce04e0 100644 --- a/include/boost/thread/exceptions.hpp +++ b/include/boost/thread/exceptions.hpp @@ -24,10 +24,10 @@ namespace boost { - class thread_interrupted + class BOOST_SYMBOL_VISIBLE thread_interrupted {}; - class thread_exception: + class BOOST_SYMBOL_VISIBLE thread_exception: public std::exception { protected: @@ -55,7 +55,7 @@ namespace boost int m_sys_err; }; - class condition_error: + class BOOST_SYMBOL_VISIBLE condition_error: public std::exception { public: @@ -66,7 +66,7 @@ namespace boost }; - class lock_error: + class BOOST_SYMBOL_VISIBLE lock_error: public thread_exception { public: @@ -87,7 +87,7 @@ namespace boost } }; - class thread_resource_error: + class BOOST_SYMBOL_VISIBLE thread_resource_error: public thread_exception { public: @@ -109,7 +109,7 @@ namespace boost }; - class unsupported_thread_option: + class BOOST_SYMBOL_VISIBLE unsupported_thread_option: public thread_exception { public: @@ -131,7 +131,7 @@ namespace boost }; - class invalid_thread_argument: + class BOOST_SYMBOL_VISIBLE invalid_thread_argument: public thread_exception { public: @@ -153,7 +153,7 @@ namespace boost }; - class thread_permission_error: + class BOOST_SYMBOL_VISIBLE thread_permission_error: public thread_exception { public: diff --git a/include/boost/thread/future.hpp b/include/boost/thread/future.hpp index a4b43432..5ea12026 100644 --- a/include/boost/thread/future.hpp +++ b/include/boost/thread/future.hpp @@ -1,4 +1,4 @@ -// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2008-10 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -111,7 +111,7 @@ namespace boost do_callback(lock); return external_waiters.insert(external_waiters.end(),&cv); } - + void remove_external_waiter(waiter_list::iterator it) { boost::lock_guard lock(mutex); @@ -132,7 +132,7 @@ namespace boost struct relocker { boost::unique_lock& lock; - + relocker(boost::unique_lock& lock_): lock(lock_) { @@ -155,7 +155,7 @@ namespace boost local_callback(); } } - + void wait(bool rethrow=true) { @@ -185,7 +185,7 @@ namespace boost } return true; } - + void mark_exceptional_finish_internal(boost::exception_ptr const& e) { exception=e; @@ -213,7 +213,7 @@ namespace boost { callback=boost::bind(f,boost::ref(*u)); } - + private: future_object_base(future_object_base const&); future_object_base& operator=(future_object_base const&); @@ -238,7 +238,7 @@ namespace boost { storage.reset(new T(t)); } - + static void init(storage_type& storage,rvalue_source_type t) { storage.reset(new T(static_cast(t))); @@ -249,7 +249,7 @@ namespace boost storage.reset(); } }; - + template struct future_traits { @@ -296,7 +296,7 @@ namespace boost typedef typename future_traits::source_reference_type source_reference_type; typedef typename future_traits::rvalue_source_type rvalue_source_type; typedef typename future_traits::move_dest_type move_dest_type; - + storage_type result; future_object(): @@ -353,6 +353,8 @@ namespace boost struct future_object: detail::future_object_base { + typedef void move_dest_type; + future_object() {} @@ -371,7 +373,7 @@ namespace boost { wait(); } - + future_state::state get_state() { boost::lock_guard guard(mutex); @@ -394,7 +396,7 @@ namespace boost { struct registered_waiter; typedef std::vector::size_type count_type; - + struct registered_waiter { boost::shared_ptr future; @@ -408,26 +410,30 @@ namespace boost {} }; - + struct all_futures_lock { count_type count; boost::scoped_array > locks; - + all_futures_lock(std::vector& futures): count(futures.size()),locks(new boost::unique_lock[count]) { for(count_type i=0;i(futures[i].future->mutex).move(); +#else locks[i]=boost::unique_lock(futures[i].future->mutex); +#endif } } - + void lock() { boost::lock(locks.get(),locks.get()+count); } - + void unlock() { for(count_type i=0;i futures; count_type future_count; - + public: future_waiter(): future_count(0) {} - + template void add(F& f) { @@ -471,7 +477,7 @@ namespace boost cv.wait(lk); } } - + ~future_waiter() { for(count_type i=0;iremove_external_waiter(futures[i].wait_iterator); } } - + }; - + } template @@ -495,13 +501,13 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value=false); }; - + template struct is_future_type > { BOOST_STATIC_CONSTANT(bool, value=true); }; - + template struct is_future_type > { @@ -531,7 +537,7 @@ namespace boost f2.wait(); f3.wait(); } - + template void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4) { @@ -556,7 +562,7 @@ namespace boost { if(begin==end) return end; - + detail::future_waiter waiter; for(Iterator current=begin;current!=end;++current) { @@ -583,7 +589,7 @@ namespace boost waiter.add(f3); return waiter.wait(); } - + template unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4) { @@ -606,7 +612,7 @@ namespace boost waiter.add(f5); return waiter.wait(); } - + template class promise; @@ -620,7 +626,7 @@ namespace boost unique_future& operator=(unique_future& rhs);// = delete; typedef boost::shared_ptr > future_ptr; - + future_ptr future; friend class shared_future; @@ -639,7 +645,7 @@ namespace boost unique_future() {} - + ~unique_future() {} @@ -689,7 +695,7 @@ namespace boost return future->get(); } - + // functions to check state, and wait for ready state get_state() const { @@ -699,23 +705,23 @@ namespace boost } return future->get_state(); } - + bool is_ready() const { return get_state()==future_state::ready; } - + bool has_exception() const { return future && future->has_exception(); } - + bool has_value() const { return future && future->has_value(); } - + void wait() const { if(!future) @@ -724,13 +730,13 @@ namespace boost } future->wait(false); } - + template bool timed_wait(Duration const& rel_time) const { return timed_wait_until(boost::get_system_time()+rel_time); } - + bool timed_wait_until(boost::system_time const& abs_time) const { if(!future) @@ -739,14 +745,14 @@ namespace boost } return future->timed_wait_until(abs_time); } - + }; template class shared_future { typedef boost::shared_ptr > future_ptr; - + future_ptr future; // shared_future(const unique_future& other); @@ -755,7 +761,7 @@ namespace boost friend class detail::future_waiter; friend class promise; friend class packaged_task; - + shared_future(future_ptr future_): future(future_) {} @@ -799,7 +805,7 @@ namespace boost other.future.reset(); return *this; } -#else +#else shared_future(boost::detail::thread_move_t other): future(other->future) { @@ -837,6 +843,7 @@ namespace boost } // retrieving the value + //typename detail::future_object::move_dest_type get() R get() { if(!future) @@ -846,7 +853,7 @@ namespace boost return future->get(); } - + // functions to check state, and wait for ready state get_state() const { @@ -856,18 +863,18 @@ namespace boost } return future->get_state(); } - + bool is_ready() const { return get_state()==future_state::ready; } - + bool has_exception() const { return future && future->has_exception(); } - + bool has_value() const { return future && future->has_value(); @@ -881,13 +888,13 @@ namespace boost } future->wait(false); } - + template bool timed_wait(Duration const& rel_time) const { return timed_wait_until(boost::get_system_time()+rel_time); } - + bool timed_wait_until(boost::system_time const& abs_time) const { if(!future) @@ -896,17 +903,17 @@ namespace boost } return future->timed_wait_until(abs_time); } - + }; template class promise { typedef boost::shared_ptr > future_ptr; - + future_ptr future; bool future_obtained; - + promise(promise & rhs);// = delete; promise & operator=(promise & rhs);// = delete; @@ -918,14 +925,14 @@ namespace boost atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object)); } } - + public: // template explicit promise(Allocator a); promise(): future(),future_obtained(false) {} - + ~promise() { if(future) @@ -975,8 +982,8 @@ namespace boost { return boost::detail::thread_move_t(*this); } -#endif - +#endif + void swap(promise& other) { future.swap(other.future); @@ -1035,17 +1042,17 @@ namespace boost lazy_init(); future->set_wait_callback(f,this); } - + }; template <> class promise { typedef boost::shared_ptr > future_ptr; - + future_ptr future; bool future_obtained; - + promise(promise & rhs);// = delete; promise & operator=(promise & rhs);// = delete; @@ -1063,7 +1070,7 @@ namespace boost promise(): future(),future_obtained(false) {} - + ~promise() { if(future) @@ -1114,7 +1121,7 @@ namespace boost return boost::detail::thread_move_t(*this); } #endif - + void swap(promise& other) { future.swap(other.future); @@ -1125,7 +1132,7 @@ namespace boost unique_future get_future() { lazy_init(); - + if(future_obtained) { boost::throw_exception(future_already_retrieved()); @@ -1162,7 +1169,7 @@ namespace boost lazy_init(); future->set_wait_callback(f,this); } - + }; namespace detail @@ -1199,12 +1206,12 @@ namespace boost this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise())); } } - - + + virtual void do_run()=0; }; - - + + template struct task_object: task_base @@ -1216,7 +1223,7 @@ namespace boost task_object(boost::detail::thread_move_t f_): f(f_) {} - + void do_run() { try @@ -1241,7 +1248,7 @@ namespace boost task_object(boost::detail::thread_move_t f_): f(f_) {} - + void do_run() { try @@ -1257,7 +1264,7 @@ namespace boost }; } - + template class packaged_task @@ -1267,12 +1274,12 @@ namespace boost packaged_task(packaged_task&);// = delete; packaged_task& operator=(packaged_task&);// = delete; - + public: packaged_task(): future_obtained(false) {} - + // construction and destruction template explicit packaged_task(F const& f): @@ -1281,7 +1288,7 @@ namespace boost explicit packaged_task(R(*f)()): task(new detail::task_object(f)),future_obtained(false) {} - + template explicit packaged_task(boost::detail::thread_move_t f): task(new detail::task_object(f)),future_obtained(false) @@ -1357,7 +1364,7 @@ namespace boost boost::throw_exception(future_already_retrieved()); } } - + // execution void operator()() @@ -1374,7 +1381,7 @@ namespace boost { task->set_wait_callback(f,this); } - + }; } diff --git a/include/boost/thread/locks.hpp b/include/boost/thread/locks.hpp index d23e6194..f159b7f9 100644 --- a/include/boost/thread/locks.hpp +++ b/include/boost/thread/locks.hpp @@ -71,7 +71,7 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value=false); }; - + template struct has_member_lock { @@ -80,22 +80,22 @@ namespace boost { true_type dummy[2]; }; - + template static true_type has_member(V (U::*)()); template static false_type has_member(U); - + BOOST_STATIC_CONSTANT( bool,value=sizeof(has_member_lock::has_member(&T::lock))==sizeof(true_type)); }; - + template::value > struct has_member_unlock { BOOST_STATIC_CONSTANT(bool, value=false); }; - + template struct has_member_unlock { @@ -104,22 +104,22 @@ namespace boost { true_type dummy[2]; }; - + template static true_type has_member(V (U::*)()); template static false_type has_member(U); - + BOOST_STATIC_CONSTANT( bool,value=sizeof(has_member_unlock::has_member(&T::unlock))==sizeof(true_type)); }; - + template::value > struct has_member_try_lock { BOOST_STATIC_CONSTANT(bool, value=false); }; - + template struct has_member_try_lock { @@ -128,18 +128,18 @@ namespace boost { true_type dummy[2]; }; - + template static true_type has_member(bool (U::*)()); template static false_type has_member(U); - + BOOST_STATIC_CONSTANT( bool,value=sizeof(has_member_try_lock::has_member(&T::try_lock))==sizeof(true_type)); }; } - + template struct is_mutex_type @@ -147,7 +147,7 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock::value && detail::has_member_unlock::value && detail::has_member_try_lock::value); - + }; #else template @@ -155,7 +155,7 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value = false); }; -#endif +#endif struct defer_lock_t {}; @@ -163,7 +163,7 @@ namespace boost {}; struct adopt_lock_t {}; - + const defer_lock_t defer_lock={}; const try_to_lock_t try_to_lock={}; const adopt_lock_t adopt_lock={}; @@ -182,7 +182,7 @@ namespace boost template class try_lock_wrapper; } - + #ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES template struct is_mutex_type > @@ -201,7 +201,7 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value = true); }; - + template struct is_mutex_type > { @@ -213,7 +213,7 @@ namespace boost class recursive_mutex; class recursive_timed_mutex; class shared_mutex; - + template<> struct is_mutex_type { @@ -277,13 +277,13 @@ namespace boost unique_lock& operator=(unique_lock&); unique_lock& operator=(upgrade_lock& other); public: -#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) - unique_lock(const volatile unique_lock&); +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) + unique_lock(const volatile unique_lock&); #endif unique_lock(): m(0),is_locked(false) {} - + explicit unique_lock(Mutex& m_): m(&m_),is_locked(false) { @@ -363,12 +363,12 @@ namespace boost return detail::thread_move_t >(*this); } -#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) - unique_lock& operator=(unique_lock other) - { - swap(other); - return *this; - } +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) + unique_lock& operator=(unique_lock other) + { + swap(other); + return *this; + } #else unique_lock& operator=(detail::thread_move_t > other) { @@ -395,7 +395,7 @@ namespace boost std::swap(m,other.m); std::swap(is_locked,other.is_locked); } - + ~unique_lock() { if(owns_lock()) @@ -427,7 +427,7 @@ namespace boost is_locked=m->timed_lock(relative_time); return is_locked; } - + bool timed_lock(::boost::system_time const& absolute_time) { is_locked=m->timed_lock(absolute_time); @@ -447,7 +447,7 @@ namespace boost m->unlock(); is_locked=false; } - + typedef void (unique_lock::*bool_type)(); operator bool_type() const { @@ -531,7 +531,7 @@ namespace boost shared_lock(): m(0),is_locked(false) {} - + explicit shared_lock(Mutex& m_): m(&m_),is_locked(false) { @@ -638,7 +638,7 @@ namespace boost { return m; } - + ~shared_lock() { if(owns_lock()) @@ -692,7 +692,7 @@ namespace boost m->unlock_shared(); is_locked=false; } - + typedef void (shared_lock::*bool_type)(); operator bool_type() const { @@ -715,6 +715,11 @@ namespace boost { lhs.swap(rhs); } + template + void swap(shared_lock& lhs,shared_lock& rhs) + { + lhs.swap(rhs); + } #else template void swap(shared_lock& lhs,shared_lock& rhs) @@ -736,7 +741,7 @@ namespace boost upgrade_lock(): m(0),is_locked(false) {} - + explicit upgrade_lock(Mutex& m_): m(&m_),is_locked(false) { @@ -835,7 +840,7 @@ namespace boost std::swap(m,other.m); std::swap(is_locked,other.is_locked); } - + ~upgrade_lock() { if(owns_lock()) @@ -870,7 +875,7 @@ namespace boost m->unlock_upgrade(); is_locked=false; } - + typedef void (upgrade_lock::*bool_type)(); operator bool_type() const { @@ -939,7 +944,7 @@ namespace boost { other.source=0; } - + upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&& other) { upgrade_to_unique_lock temp(other); @@ -952,7 +957,7 @@ namespace boost { other->source=0; } - + upgrade_to_unique_lock& operator=(detail::thread_move_t > other) { upgrade_to_unique_lock temp(other); @@ -990,7 +995,7 @@ namespace boost public: try_lock_wrapper() {} - + explicit try_lock_wrapper(Mutex& m): base(m,try_to_lock) {} @@ -1098,6 +1103,11 @@ namespace boost { lhs.swap(rhs); } + template + void swap(try_lock_wrapper& lhs,try_lock_wrapper& rhs) + { + lhs.swap(rhs); + } #else template void swap(try_lock_wrapper& lhs,try_lock_wrapper& rhs) @@ -1105,7 +1115,7 @@ namespace boost lhs.swap(rhs); } #endif - + template unsigned try_lock_internal(MutexType1& m1,MutexType2& m2) { @@ -1234,7 +1244,7 @@ namespace boost template struct is_mutex_type_wrapper {}; - + template void lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper) { @@ -1262,7 +1272,7 @@ namespace boost template void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper); } - + template void lock(MutexType1& m1,MutexType2& m2) @@ -1407,7 +1417,7 @@ namespace boost { typedef int type; }; - + template struct try_lock_impl_return { @@ -1423,7 +1433,7 @@ namespace boost template Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper); } - + template typename detail::try_lock_impl_return::type try_lock(MutexType1& m1,MutexType2& m2) { @@ -1465,7 +1475,7 @@ namespace boost { return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1; } - + namespace detail { @@ -1474,13 +1484,13 @@ namespace boost { Iterator begin; Iterator end; - + range_lock_guard(Iterator begin_,Iterator end_): begin(begin_),end(end_) { - lock(begin,end); + boost::lock(begin,end); } - + void release() { begin=end; @@ -1505,21 +1515,21 @@ namespace boost } 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); + Iterator const failed=boost::try_lock(++begin,end); if(failed==end) { guard.release(); } - + return failed; } } - + namespace detail { @@ -1527,7 +1537,7 @@ namespace boost void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper) { typedef typename std::iterator_traits::value_type lock_type; - + if(begin==end) { return; @@ -1536,14 +1546,14 @@ namespace boost 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); + Iterator const failed_lock=boost::try_lock(next,end); if(failed_lock==end) { begin_lock.release(); @@ -1557,7 +1567,7 @@ namespace boost detail::range_lock_guard guard(next,end); if(begin_lock.try_lock()) { - Iterator const failed_lock=try_lock(second,next); + Iterator const failed_lock=boost::try_lock(second,next); if(failed_lock==next) { begin_lock.release(); @@ -1575,9 +1585,9 @@ namespace boost } } } - + } - + } #include diff --git a/include/boost/thread/pthread/condition_variable.hpp b/include/boost/thread/pthread/condition_variable.hpp index 160c7072..48ed8ff7 100644 --- a/include/boost/thread/pthread/condition_variable.hpp +++ b/include/boost/thread/pthread/condition_variable.hpp @@ -5,10 +5,10 @@ // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007-10 Anthony Williams -#include "timespec.hpp" -#include "pthread_mutex_scoped_lock.hpp" -#include "thread_data.hpp" -#include "condition_variable_fwd.hpp" +#include +#include +#include +#include #include @@ -18,14 +18,14 @@ namespace boost { void BOOST_THREAD_DECL interruption_point(); } - + namespace thread_cv_detail { template struct lock_on_exit { MutexType* m; - + lock_on_exit(): m(0) {} @@ -44,7 +44,7 @@ namespace boost } }; } - + inline void condition_variable::wait(unique_lock& m) { int res=0; @@ -52,7 +52,9 @@ namespace boost thread_cv_detail::lock_on_exit > guard; detail::interruption_checker check_for_interruption(&internal_mutex,&cond); guard.activate(m); - res=pthread_cond_wait(&cond,&internal_mutex); + do { + res = pthread_cond_wait(&cond,&internal_mutex); + } while (res == EINTR); } this_thread::interruption_point(); if(res) @@ -88,13 +90,13 @@ namespace boost boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); BOOST_VERIFY(!pthread_cond_signal(&cond)); } - + inline void condition_variable::notify_all() { boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); BOOST_VERIFY(!pthread_cond_broadcast(&cond)); } - + class condition_variable_any { pthread_mutex_t internal_mutex; @@ -123,7 +125,7 @@ namespace boost BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); BOOST_VERIFY(!pthread_cond_destroy(&cond)); } - + template void wait(lock_type& m) { @@ -146,7 +148,7 @@ namespace boost { while(!pred()) wait(m); } - + template bool timed_wait(lock_type& m,boost::system_time const& wait_until) { @@ -209,7 +211,7 @@ namespace boost boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); BOOST_VERIFY(!pthread_cond_signal(&cond)); } - + void notify_all() { boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); diff --git a/include/boost/thread/pthread/condition_variable_fwd.hpp b/include/boost/thread/pthread/condition_variable_fwd.hpp index 365f511c..f56bee47 100644 --- a/include/boost/thread/pthread/condition_variable_fwd.hpp +++ b/include/boost/thread/pthread/condition_variable_fwd.hpp @@ -22,7 +22,7 @@ namespace boost private: pthread_mutex_t internal_mutex; pthread_cond_t cond; - + condition_variable(condition_variable&); condition_variable& operator=(condition_variable&); @@ -44,7 +44,11 @@ namespace boost ~condition_variable() { BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); - BOOST_VERIFY(!pthread_cond_destroy(&cond)); + int ret; + do { + ret = pthread_cond_destroy(&cond); + } while (ret == EINTR); + BOOST_VERIFY(!ret); } void wait(unique_lock& m); diff --git a/include/boost/thread/pthread/mutex.hpp b/include/boost/thread/pthread/mutex.hpp index 2a326d76..fc7c9cdf 100644 --- a/include/boost/thread/pthread/mutex.hpp +++ b/include/boost/thread/pthread/mutex.hpp @@ -14,11 +14,11 @@ #include #include #include -#include "timespec.hpp" -#include "pthread_mutex_scoped_lock.hpp" +#include +#include #ifdef _POSIX_TIMEOUTS -#if _POSIX_TIMEOUTS >= 0 +#if _POSIX_TIMEOUTS >= 0 && _POSIX_C_SOURCE>=200112L #define BOOST_PTHREAD_HAS_TIMEDLOCK #endif #endif @@ -31,7 +31,7 @@ namespace boost { private: mutex(mutex const&); - mutex& operator=(mutex const&); + mutex& operator=(mutex const&); pthread_mutex_t m; public: mutex() @@ -44,12 +44,20 @@ namespace boost } ~mutex() { - BOOST_VERIFY(!pthread_mutex_destroy(&m)); + int ret; + do + { + ret = pthread_mutex_destroy(&m); + } while (ret == EINTR); } - + void lock() { - int const res=pthread_mutex_lock(&m); + int res; + do + { + res = pthread_mutex_lock(&m); + } while (res == EINTR); if(res) { boost::throw_exception(lock_error(res)); @@ -58,17 +66,26 @@ namespace boost void unlock() { - BOOST_VERIFY(!pthread_mutex_unlock(&m)); + int ret; + do + { + ret = pthread_mutex_unlock(&m); + } while (ret == EINTR); + BOOST_VERIFY(!ret); } - + bool try_lock() { - int const res=pthread_mutex_trylock(&m); + int res; + do + { + res = pthread_mutex_trylock(&m); + } while (res == EINTR); if(res && (res!=EBUSY)) { boost::throw_exception(lock_error(res)); } - + return !res; } @@ -88,7 +105,7 @@ namespace boost { private: timed_mutex(timed_mutex const&); - timed_mutex& operator=(timed_mutex const&); + timed_mutex& operator=(timed_mutex const&); private: pthread_mutex_t m; #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK @@ -141,7 +158,7 @@ namespace boost { BOOST_VERIFY(!pthread_mutex_unlock(&m)); } - + bool try_lock() { int const res=pthread_mutex_trylock(&m); @@ -179,7 +196,7 @@ namespace boost is_locked=false; BOOST_VERIFY(!pthread_cond_signal(&cond)); } - + bool try_lock() { boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); diff --git a/include/boost/thread/pthread/once.hpp b/include/boost/thread/pthread/once.hpp index 6321aa2f..81e744e6 100644 --- a/include/boost/thread/pthread/once.hpp +++ b/include/boost/thread/pthread/once.hpp @@ -3,7 +3,7 @@ // once.hpp // -// (C) Copyright 2007-8 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 @@ -14,7 +14,6 @@ #include #include -#include "pthread_mutex_scoped_lock.hpp" #include #include @@ -35,7 +34,7 @@ namespace boost 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 0 #define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE} @@ -49,7 +48,7 @@ namespace boost 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 #include -#include "timespec.hpp" -#include "pthread_mutex_scoped_lock.hpp" +#include +#include #ifdef _POSIX_TIMEOUTS #if _POSIX_TIMEOUTS >= 0 @@ -26,7 +26,7 @@ #endif #endif -#if defined(BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK) +#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK) #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK #endif @@ -38,9 +38,9 @@ namespace boost { private: recursive_mutex(recursive_mutex const&); - recursive_mutex& operator=(recursive_mutex const&); + recursive_mutex& operator=(recursive_mutex const&); pthread_mutex_t m; -#ifndef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE +#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE pthread_cond_t cond; bool is_locked; pthread_t owner; @@ -49,9 +49,9 @@ namespace boost public: recursive_mutex() { -#ifdef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE +#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE pthread_mutexattr_t attr; - + int const init_attr_res=pthread_mutexattr_init(&attr); if(init_attr_res) { @@ -63,7 +63,7 @@ namespace boost BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); boost::throw_exception(thread_resource_error()); } - + int const res=pthread_mutex_init(&m,&attr); if(res) { @@ -90,12 +90,12 @@ namespace boost ~recursive_mutex() { BOOST_VERIFY(!pthread_mutex_destroy(&m)); -#ifndef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE +#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE BOOST_VERIFY(!pthread_cond_destroy(&cond)); #endif } -#ifdef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE +#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE void lock() { BOOST_VERIFY(!pthread_mutex_lock(&m)); @@ -105,7 +105,7 @@ namespace boost { BOOST_VERIFY(!pthread_mutex_unlock(&m)); } - + bool try_lock() { int const res=pthread_mutex_trylock(&m); @@ -127,7 +127,7 @@ namespace boost ++count; return; } - + while(is_locked) { BOOST_VERIFY(!pthread_cond_wait(&cond,&m)); @@ -146,7 +146,7 @@ namespace boost } BOOST_VERIFY(!pthread_cond_signal(&cond)); } - + bool try_lock() { boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); @@ -172,7 +172,7 @@ namespace boost { private: recursive_timed_mutex(recursive_timed_mutex const&); - recursive_timed_mutex& operator=(recursive_timed_mutex const&); + recursive_timed_mutex& operator=(recursive_timed_mutex const&); private: pthread_mutex_t m; #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK @@ -186,7 +186,7 @@ namespace boost { #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK pthread_mutexattr_t attr; - + int const init_attr_res=pthread_mutexattr_init(&attr); if(init_attr_res) { @@ -197,7 +197,7 @@ namespace boost { boost::throw_exception(thread_resource_error()); } - + int const res=pthread_mutex_init(&m,&attr); if(res) { @@ -245,7 +245,7 @@ namespace boost { BOOST_VERIFY(!pthread_mutex_unlock(&m)); } - + bool try_lock() { int const res=pthread_mutex_trylock(&m); @@ -275,7 +275,7 @@ namespace boost ++count; return; } - + while(is_locked) { BOOST_VERIFY(!pthread_cond_wait(&cond,&m)); @@ -294,7 +294,7 @@ namespace boost } BOOST_VERIFY(!pthread_cond_signal(&cond)); } - + bool try_lock() { boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); diff --git a/include/boost/thread/pthread/thread_data.hpp b/include/boost/thread/pthread/thread_data.hpp index 1bee28b6..3de9b41b 100644 --- a/include/boost/thread/pthread/thread_data.hpp +++ b/include/boost/thread/pthread/thread_data.hpp @@ -13,7 +13,7 @@ #include #include #include -#include "condition_variable_fwd.hpp" +#include #include #include @@ -21,7 +21,7 @@ namespace boost { class thread; - + namespace detail { struct tss_cleanup_function; @@ -39,7 +39,7 @@ namespace boost struct thread_data_base; typedef boost::shared_ptr thread_data_ptr; - + struct BOOST_THREAD_DECL thread_data_base: enable_shared_from_this { @@ -89,7 +89,7 @@ namespace boost throw thread_interrupted(); } } - + void operator=(interruption_checker&); public: explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond): @@ -129,14 +129,26 @@ namespace boost namespace this_thread { void BOOST_THREAD_DECL yield(); - - void BOOST_THREAD_DECL sleep(system_time const& abs_time); - + +#ifdef __DECXXX + /// Workaround of DECCXX issue of incorrect template substitution template inline void sleep(TimeDuration const& rel_time) { this_thread::sleep(get_system_time()+rel_time); } + + template<> + void BOOST_THREAD_DECL sleep(system_time const& abs_time); +#else + void BOOST_THREAD_DECL sleep(system_time const& abs_time); + + template + inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) + { + this_thread::sleep(get_system_time()+rel_time); + } +#endif } } diff --git a/include/boost/thread/win32/basic_recursive_mutex.hpp b/include/boost/thread/win32/basic_recursive_mutex.hpp index 05eb8d76..e748aa72 100644 --- a/include/boost/thread/win32/basic_recursive_mutex.hpp +++ b/include/boost/thread/win32/basic_recursive_mutex.hpp @@ -3,14 +3,14 @@ // basic_recursive_mutex.hpp // -// (C) Copyright 2006-8 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 // http://www.boost.org/LICENSE_1_0.txt) -#include "thread_primitives.hpp" -#include "basic_timed_mutex.hpp" +#include +#include #include @@ -42,7 +42,7 @@ namespace boost long const current_thread_id=win32::GetCurrentThreadId(); return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id); } - + void lock() { long const current_thread_id=win32::GetCurrentThreadId(); @@ -83,7 +83,7 @@ namespace boost } return false; } - + bool try_basic_lock(long current_thread_id) { if(mutex.try_lock()) @@ -94,7 +94,7 @@ namespace boost } return false; } - + bool try_timed_lock(long current_thread_id,::boost::system_time const& target) { if(mutex.timed_lock(target)) @@ -105,7 +105,7 @@ namespace boost } return false; } - + }; typedef basic_recursive_mutex_impl basic_recursive_mutex; diff --git a/include/boost/thread/win32/basic_timed_mutex.hpp b/include/boost/thread/win32/basic_timed_mutex.hpp index 7c6797d1..a88c2a0f 100644 --- a/include/boost/thread/win32/basic_timed_mutex.hpp +++ b/include/boost/thread/win32/basic_timed_mutex.hpp @@ -3,15 +3,15 @@ // basic_timed_mutex_win32.hpp // -// (C) Copyright 2006-8 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 // http://www.boost.org/LICENSE_1_0.txt) #include -#include "thread_primitives.hpp" -#include "interlocked_read.hpp" +#include +#include #include #include #include @@ -52,13 +52,13 @@ namespace boost win32::CloseHandle(old_event); } } - - + + bool try_lock() { return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit); } - + void lock() { if(try_lock()) @@ -112,8 +112,8 @@ namespace boost old_count=current; } } - - + + bool timed_lock(::boost::system_time const& wait_until) { if(try_lock()) @@ -171,7 +171,7 @@ namespace boost void* get_event() { void* current_event=::boost::detail::interlocked_read_acquire(&event); - + if(!current_event) { void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset); @@ -196,9 +196,9 @@ namespace boost } return current_event; } - + }; - + } } diff --git a/include/boost/thread/win32/condition_variable.hpp b/include/boost/thread/win32/condition_variable.hpp index 6e676b49..056bda80 100644 --- a/include/boost/thread/win32/condition_variable.hpp +++ b/include/boost/thread/win32/condition_variable.hpp @@ -6,13 +6,13 @@ // (C) Copyright 2007-8 Anthony Williams #include -#include "thread_primitives.hpp" +#include #include #include #include #include #include -#include "interlocked_read.hpp" +#include #include #include #include @@ -26,7 +26,7 @@ namespace boost class basic_cv_list_entry; void intrusive_ptr_add_ref(basic_cv_list_entry * p); void intrusive_ptr_release(basic_cv_list_entry * p); - + class basic_cv_list_entry { private: @@ -38,7 +38,7 @@ namespace boost basic_cv_list_entry(basic_cv_list_entry&); void operator=(basic_cv_list_entry&); - + public: explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_): semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)), @@ -55,7 +55,7 @@ namespace boost { BOOST_INTERLOCKED_INCREMENT(&waiters); } - + void remove_waiter() { BOOST_INTERLOCKED_DECREMENT(&waiters); @@ -97,7 +97,7 @@ namespace boost { BOOST_INTERLOCKED_INCREMENT(&p->references); } - + inline void intrusive_ptr_release(basic_cv_list_entry * p) { if(!BOOST_INTERLOCKED_DECREMENT(&p->references)) @@ -125,13 +125,13 @@ namespace boost detail::interlocked_write_release(&total_count,total_count-count_to_wake); detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0); } - + template struct relocker { lock_type& lock; bool unlocked; - + relocker(lock_type& lock_): lock(lock_),unlocked(false) {} @@ -146,13 +146,13 @@ namespace boost { lock.lock(); } - + } private: relocker(relocker&); void operator=(relocker&); }; - + entry_ptr get_wait_entry() { @@ -177,15 +177,15 @@ namespace boost return generations.back(); } } - + struct entry_manager { entry_ptr const entry; - + entry_manager(entry_ptr const& entry_): entry(entry_) {} - + ~entry_manager() { entry->remove_waiter(); @@ -200,14 +200,14 @@ namespace boost void operator=(entry_manager&); entry_manager(entry_manager&); }; - + protected: template bool do_wait(lock_type& lock,timeout wait_until) { relocker locker(lock); - + entry_manager entry(get_wait_entry()); locker.unlock(); @@ -219,7 +219,7 @@ namespace boost { return false; } - + woken=entry->woken(); } return woken; @@ -235,7 +235,7 @@ namespace boost } return true; } - + basic_condition_variable(const basic_condition_variable& other); basic_condition_variable& operator=(const basic_condition_variable& other); @@ -243,7 +243,7 @@ namespace boost basic_condition_variable(): total_count(0),active_generation_count(0),wake_sem(0) {} - + ~basic_condition_variable() {} @@ -267,7 +267,7 @@ namespace boost generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end()); } } - + void notify_all() { if(detail::interlocked_read_acquire(&total_count)) @@ -288,7 +288,7 @@ namespace boost wake_sem=detail::win32::handle(0); } } - + }; } @@ -301,10 +301,10 @@ namespace boost public: condition_variable() {} - + using detail::basic_condition_variable::notify_one; using detail::basic_condition_variable::notify_all; - + void wait(unique_lock& m) { do_wait(m,detail::timeout::sentinel()); @@ -315,7 +315,7 @@ namespace boost { while(!pred()) wait(m); } - + bool timed_wait(unique_lock& m,boost::system_time const& wait_until) { @@ -348,7 +348,7 @@ namespace boost return do_wait(m,wait_duration.total_milliseconds(),pred); } }; - + class condition_variable_any: private detail::basic_condition_variable { @@ -358,10 +358,10 @@ namespace boost public: condition_variable_any() {} - + using detail::basic_condition_variable::notify_one; using detail::basic_condition_variable::notify_all; - + template void wait(lock_type& m) { @@ -373,7 +373,7 @@ namespace boost { while(!pred()) wait(m); } - + template bool timed_wait(lock_type& m,boost::system_time const& wait_until) { diff --git a/include/boost/thread/win32/mutex.hpp b/include/boost/thread/win32/mutex.hpp index d59fbfa3..92b2669e 100644 --- a/include/boost/thread/win32/mutex.hpp +++ b/include/boost/thread/win32/mutex.hpp @@ -5,7 +5,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include "basic_timed_mutex.hpp" +#include #include #include #include diff --git a/include/boost/thread/win32/recursive_mutex.hpp b/include/boost/thread/win32/recursive_mutex.hpp index e83d3bc0..7832bf27 100644 --- a/include/boost/thread/win32/recursive_mutex.hpp +++ b/include/boost/thread/win32/recursive_mutex.hpp @@ -3,7 +3,7 @@ // recursive_mutex.hpp // -// (C) Copyright 2006-7 Anthony Williams +// (C) Copyright 2006-7 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -11,7 +11,7 @@ #include -#include "basic_recursive_mutex.hpp" +#include #include #include @@ -24,7 +24,7 @@ namespace boost { private: recursive_mutex(recursive_mutex const&); - recursive_mutex& operator=(recursive_mutex const&); + recursive_mutex& operator=(recursive_mutex const&); public: recursive_mutex() { @@ -46,7 +46,7 @@ namespace boost { private: recursive_timed_mutex(recursive_timed_mutex const&); - recursive_timed_mutex& operator=(recursive_timed_mutex const&); + recursive_timed_mutex& operator=(recursive_timed_mutex const&); public: recursive_timed_mutex() { diff --git a/include/boost/thread/win32/shared_mutex.hpp b/include/boost/thread/win32/shared_mutex.hpp index 58fc6224..06675139 100644 --- a/include/boost/thread/win32/shared_mutex.hpp +++ b/include/boost/thread/win32/shared_mutex.hpp @@ -23,7 +23,7 @@ namespace boost { private: shared_mutex(shared_mutex const&); - shared_mutex& operator=(shared_mutex const&); + shared_mutex& operator=(shared_mutex const&); private: struct state_data { @@ -39,7 +39,7 @@ namespace boost return *reinterpret_cast(&lhs)==*reinterpret_cast(&rhs); } }; - + template T interlocked_compare_exchange(T* target,T new_value,T comparand) @@ -67,20 +67,31 @@ namespace boost { BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0); } - + if(old_state.shared_waiting || old_state.exclusive_waiting) { BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0); } } - + public: shared_mutex() { semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); - semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); - upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + if (!semaphores[exclusive_sem]) + { + detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); + boost::throw_exception(thread_resource_error()); + } + upgrade_sem=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + if (!upgrade_sem) + { + detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); + detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX); + boost::throw_exception(thread_resource_error()); + } state_data state_={0}; state=state_; } @@ -106,7 +117,7 @@ namespace boost return false; } } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -165,7 +176,7 @@ namespace boost { return true; } - + unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until)); if(res==detail::win32::timeout) { @@ -202,7 +213,7 @@ namespace boost } return false; } - + BOOST_ASSERT(res==0); } } @@ -214,7 +225,7 @@ namespace boost { state_data new_state=old_state; bool const last_reader=!--new_state.shared_count; - + if(last_reader) { if(new_state.upgrade) @@ -232,7 +243,7 @@ namespace boost new_state.shared_waiting=0; } } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -278,7 +289,7 @@ namespace boost { new_state.exclusive=true; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -306,7 +317,7 @@ namespace boost { boost::throw_exception(boost::lock_error()); } - + new_state.exclusive_waiting_blocked=true; } else @@ -426,7 +437,7 @@ namespace boost { return; } - + BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite)); } } @@ -450,7 +461,7 @@ namespace boost } new_state.upgrade=true; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -469,7 +480,7 @@ namespace boost state_data new_state=old_state; new_state.upgrade=false; bool const last_reader=!--new_state.shared_count; - + if(last_reader) { if(new_state.exclusive_waiting) @@ -479,7 +490,7 @@ namespace boost } new_state.shared_waiting=0; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -500,13 +511,13 @@ namespace boost { state_data new_state=old_state; bool const last_reader=!--new_state.shared_count; - + if(last_reader) { new_state.upgrade=false; new_state.exclusive=true; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -545,7 +556,7 @@ namespace boost } release_waiters(old_state); } - + void unlock_and_lock_shared() { state_data old_state=state; @@ -570,7 +581,7 @@ namespace boost } release_waiters(old_state); } - + void unlock_upgrade_and_lock_shared() { state_data old_state=state; @@ -594,7 +605,7 @@ namespace boost } release_waiters(old_state); } - + }; } diff --git a/include/boost/thread/win32/thread_data.hpp b/include/boost/thread/win32/thread_data.hpp index 1f69aa00..d5303d89 100644 --- a/include/boost/thread/win32/thread_data.hpp +++ b/include/boost/thread/win32/thread_data.hpp @@ -8,8 +8,8 @@ #include #include #include -#include "thread_primitives.hpp" -#include "thread_heap_alloc.hpp" +#include +#include #include @@ -23,8 +23,8 @@ namespace boost struct thread_data_base; void intrusive_ptr_add_ref(thread_data_base * p); void intrusive_ptr_release(thread_data_base * p); - - struct thread_data_base + + struct BOOST_SYMBOL_VISIBLE thread_data_base { long count; detail::win32::handle_manager thread_handle; @@ -48,7 +48,7 @@ namespace boost { BOOST_INTERLOCKED_INCREMENT(&p->count); } - + friend void intrusive_ptr_release(thread_data_base * p) { if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) @@ -61,7 +61,7 @@ namespace boost { BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0); } - + typedef detail::win32::handle native_handle_type; virtual void run()=0; @@ -69,7 +69,7 @@ namespace boost typedef boost::intrusive_ptr thread_data_ptr; - struct timeout + struct BOOST_SYMBOL_VISIBLE timeout { unsigned long start; uintmax_t milliseconds; @@ -92,7 +92,7 @@ namespace boost abs_time(abs_time_) {} - struct remaining_time + struct BOOST_SYMBOL_VISIBLE remaining_time { bool more; unsigned long milliseconds; @@ -130,7 +130,7 @@ namespace boost { return milliseconds==~uintmax_t(0); } - + static timeout sentinel() { @@ -139,7 +139,7 @@ namespace boost private: struct sentinel_type {}; - + explicit timeout(sentinel_type): start(0),milliseconds(~uintmax_t(0)),relative(true) {} @@ -160,22 +160,22 @@ namespace boost { interruptible_wait(detail::win32::invalid_handle_value,milliseconds); } - inline void interruptible_wait(system_time const& abs_time) + inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time) { interruptible_wait(detail::win32::invalid_handle_value,abs_time); } template - inline void sleep(TimeDuration const& rel_time) + inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); } - inline void sleep(system_time const& abs_time) + inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) { interruptible_wait(abs_time); } } - + } #include diff --git a/include/boost/thread/win32/thread_heap_alloc.hpp b/include/boost/thread/win32/thread_heap_alloc.hpp index b70623aa..b7d329f3 100644 --- a/include/boost/thread/win32/thread_heap_alloc.hpp +++ b/include/boost/thread/win32/thread_heap_alloc.hpp @@ -5,7 +5,7 @@ #ifndef THREAD_HEAP_ALLOC_HPP #define THREAD_HEAP_ALLOC_HPP #include -#include "thread_primitives.hpp" +#include #include #include #include @@ -56,7 +56,7 @@ namespace boost { namespace detail { - inline BOOST_THREAD_DECL void* allocate_raw_heap_memory(unsigned size) + inline void* allocate_raw_heap_memory(unsigned size) { void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size); if(!heap_memory) @@ -66,11 +66,11 @@ namespace boost return heap_memory; } - inline BOOST_THREAD_DECL void free_raw_heap_memory(void* heap_memory) + inline void free_raw_heap_memory(void* heap_memory) { BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0); } - + template inline T* heap_new() { @@ -226,7 +226,7 @@ namespace boost { return heap_new_impl(a1); } - + template inline T* heap_new(A1 const& a1,A2 const& a2) { @@ -372,8 +372,8 @@ namespace boost { return heap_new_impl(a1,a2,a3,a4); } - -#endif + +#endif template inline void heap_delete(T* data) { diff --git a/include/boost/thread/win32/thread_primitives.hpp b/include/boost/thread/win32/thread_primitives.hpp index 9b20e860..0166f37d 100644 --- a/include/boost/thread/win32/thread_primitives.hpp +++ b/include/boost/thread/win32/thread_primitives.hpp @@ -3,8 +3,8 @@ // win32_thread_primitives.hpp // -// (C) Copyright 2005-7 Anthony Williams -// (C) Copyright 2007 David Deakins +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2007 David Deakins // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -94,7 +94,7 @@ namespace boost { namespace win32 { - + # ifdef _WIN64 typedef unsigned __int64 ulong_ptr; # else @@ -170,20 +170,20 @@ namespace boost auto_reset_event=false, manual_reset_event=true }; - + enum initial_event_state { event_initially_reset=false, event_initially_set=true }; - + inline handle create_anonymous_event(event_type type,initial_event_state state) { -#if !defined(BOOST_NO_ANSI_APIS) +#if !defined(BOOST_NO_ANSI_APIS) handle const res=win32::CreateEventA(0,type,state,0); #else handle const res=win32::CreateEventW(0,type,state,0); -#endif +#endif if(!res) { boost::throw_exception(thread_resource_error()); @@ -193,17 +193,26 @@ namespace boost inline handle create_anonymous_semaphore(long initial_count,long max_count) { -#if !defined(BOOST_NO_ANSI_APIS) +#if !defined(BOOST_NO_ANSI_APIS) handle const res=CreateSemaphoreA(0,initial_count,max_count,0); #else handle const res=CreateSemaphoreW(0,initial_count,max_count,0); -#endif +#endif if(!res) { boost::throw_exception(thread_resource_error()); } return res; } + inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count) + { +#if !defined(BOOST_NO_ANSI_APIS) + handle const res=CreateSemaphoreA(0,initial_count,max_count,0); +#else + handle const res=CreateSemaphoreW(0,initial_count,max_count,0); +#endif + return res; + } inline handle duplicate_handle(handle source) { @@ -237,7 +246,7 @@ namespace boost BOOST_VERIFY(CloseHandle(handle_to_manage)); } } - + public: explicit handle_manager(handle handle_to_manage_): handle_to_manage(handle_to_manage_) @@ -245,7 +254,7 @@ namespace boost handle_manager(): handle_to_manage(0) {} - + handle_manager& operator=(handle new_handle) { cleanup(); @@ -279,13 +288,13 @@ namespace boost { return !handle_to_manage; } - + ~handle_manager() { cleanup(); } }; - + } } } @@ -318,7 +327,7 @@ namespace boost { return _interlockedbittestandreset(x,bit)!=0; } - + } } } @@ -337,7 +346,7 @@ namespace boost mov edx,x; lock bts [edx],eax; setc al; - }; + }; } inline bool interlocked_bit_test_and_reset(long* x,long bit) @@ -347,9 +356,9 @@ namespace boost mov edx,x; lock btr [edx],eax; setc al; - }; + }; } - + } } } diff --git a/src/pthread/thread.cpp b/src/pthread/thread.cpp index ecff395d..07b8458b 100644 --- a/src/pthread/thread.cpp +++ b/src/pthread/thread.cpp @@ -2,7 +2,7 @@ // William E. Kempf // Copyright (C) 2007-8 Anthony Williams // -// Distributed under the Boost Software License, Version 1.0. (See accompanying +// 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 @@ -14,7 +14,7 @@ #include #include #include -#ifdef __linux__ +#ifdef __GLIBC__ #include #elif defined(__APPLE__) || defined(__FreeBSD__) #include @@ -86,14 +86,14 @@ namespace boost } } } - + void create_current_thread_tls_key() { BOOST_VERIFY(!pthread_key_create(¤t_thread_tls_key,&tls_destructor)); } } - + boost::detail::thread_data_base* get_current_thread_data() { boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); @@ -106,7 +106,7 @@ namespace boost BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data)); } } - + namespace { extern "C" @@ -146,7 +146,7 @@ namespace boost { interrupt_enabled=false; } - + void run() {} @@ -207,7 +207,7 @@ namespace boost if(local_thread_info) { bool do_join=false; - + { unique_lock lock(local_thread_info->data_mutex); while(!local_thread_info->done) @@ -215,7 +215,7 @@ namespace boost local_thread_info->done_condition.wait(lock); } do_join=!local_thread_info->join_started; - + if(do_join) { local_thread_info->join_started=true; @@ -236,7 +236,7 @@ namespace boost local_thread_info->joined=true; local_thread_info->done_condition.notify_all(); } - + if(thread_info==local_thread_info) { thread_info.reset(); @@ -250,7 +250,7 @@ namespace boost if(local_thread_info) { bool do_join=false; - + { unique_lock lock(local_thread_info->data_mutex); while(!local_thread_info->done) @@ -261,7 +261,7 @@ namespace boost } } do_join=!local_thread_info->join_started; - + if(do_join) { local_thread_info->join_started=true; @@ -282,7 +282,7 @@ namespace boost local_thread_info->joined=true; local_thread_info->done_condition.notify_all(); } - + if(thread_info==local_thread_info) { thread_info.reset(); @@ -301,7 +301,7 @@ namespace boost { detail::thread_data_ptr local_thread_info; thread_info.swap(local_thread_info); - + if(local_thread_info) { lock_guard lock(local_thread_info->data_mutex); @@ -316,11 +316,15 @@ namespace boost namespace this_thread { - + +#ifdef __DECXXX + /// Workaround of DECCXX issue of incorrect template substitution + template<> +#endif void sleep(const system_time& st) { detail::thread_data_base* const thread_info=detail::get_current_thread_data(); - + if(thread_info) { unique_lock lk(thread_info->sleep_mutex); @@ -329,7 +333,7 @@ namespace boost else { xtime const xt=get_xtime(st); - + for (int foo=0; foo < 5; ++foo) { # if defined(BOOST_HAS_PTHREAD_DELAY_NP) @@ -339,7 +343,7 @@ namespace boost # elif defined(BOOST_HAS_NANOSLEEP) timespec ts; to_timespec_duration(xt, ts); - + // nanosleep takes a timespec that is an offset, not // an absolute time. nanosleep(&ts, 0); @@ -382,7 +386,7 @@ namespace boost #elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN) int const count=sysconf(_SC_NPROCESSORS_ONLN); return (count>0)?count:0; -#elif defined(_GNU_SOURCE) +#elif defined(__GLIBC__) return get_nprocs(); #else return 0; @@ -444,8 +448,8 @@ namespace boost return pthread_t(); } } - - + + namespace this_thread { @@ -468,13 +472,13 @@ namespace boost } } } - + bool interruption_enabled() { boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); return thread_info && thread_info->interrupt_enabled; } - + bool interruption_requested() { boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); @@ -497,7 +501,7 @@ namespace boost detail::get_current_thread_data()->interrupt_enabled=false; } } - + disable_interruption::~disable_interruption() { if(detail::get_current_thread_data()) @@ -513,7 +517,7 @@ namespace boost detail::get_current_thread_data()->interrupt_enabled=true; } } - + restore_interruption::~restore_interruption() { if(detail::get_current_thread_data()) @@ -570,7 +574,7 @@ namespace boost detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); current_thread_data->tss_data.erase(key); } - + void set_tss_data(void const* key, boost::shared_ptr func, void* tss_data,bool cleanup_existing) diff --git a/src/pthread/timeconv.inl b/src/pthread/timeconv.inl index b75a1353..1c0a0cdc 100644 --- a/src/pthread/timeconv.inl +++ b/src/pthread/timeconv.inl @@ -21,7 +21,7 @@ inline void to_time(int milliseconds, boost::xtime& xt) { int res = 0; res = boost::xtime_get(&xt, boost::TIME_UTC); - BOOST_ASSERT(res == boost::TIME_UTC); + BOOST_ASSERT(res == boost::TIME_UTC); (void)res; xt.sec += (milliseconds / MILLISECONDS_PER_SECOND); xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) * @@ -33,7 +33,6 @@ inline void to_time(int milliseconds, boost::xtime& xt) xt.nsec -= NANOSECONDS_PER_SECOND; } } - #if defined(BOOST_HAS_PTHREADS) inline void to_timespec(const boost::xtime& xt, timespec& ts) { @@ -58,7 +57,7 @@ inline void to_timespec_duration(const boost::xtime& xt, timespec& ts) boost::xtime cur; int res = 0; res = boost::xtime_get(&cur, boost::TIME_UTC); - BOOST_ASSERT(res == boost::TIME_UTC); + BOOST_ASSERT(res == boost::TIME_UTC); (void)res; if (boost::xtime_cmp(xt, cur) <= 0) { @@ -89,7 +88,7 @@ inline void to_duration(boost::xtime xt, int& milliseconds) boost::xtime cur; int res = 0; res = boost::xtime_get(&cur, boost::TIME_UTC); - BOOST_ASSERT(res == boost::TIME_UTC); + BOOST_ASSERT(res == boost::TIME_UTC); (void)res; if (boost::xtime_cmp(xt, cur) <= 0) milliseconds = 0; @@ -111,7 +110,7 @@ inline void to_microduration(boost::xtime xt, int& microseconds) boost::xtime cur; int res = 0; res = boost::xtime_get(&cur, boost::TIME_UTC); - BOOST_ASSERT(res == boost::TIME_UTC); + BOOST_ASSERT(res == boost::TIME_UTC); (void)res; if (boost::xtime_cmp(xt, cur) <= 0) microseconds = 0; diff --git a/src/win32/thread.cpp b/src/win32/thread.cpp index b9434621..bc6e56fb 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace boost { @@ -80,22 +81,25 @@ namespace boost DWORD WINAPI ThreadProxy(LPVOID args) { - ThreadProxyData* data=reinterpret_cast(args); + autp_ptr data=reinterpret_cast(args); DWORD ret=data->start_address_(data->arglist_); - delete data; return ret; } - + 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) { DWORD threadID; + ThreadProxyData* data = new ThreadProxyData(start_address,arglist); HANDLE hthread=CreateThread(static_cast(security),stack_size,ThreadProxy, - new ThreadProxyData(start_address,arglist),initflag,&threadID); - if (hthread!=0) - *thrdaddr=threadID; + data,initflag,&threadID); + if (hthread==0) { + delete data; + return 0; + } + *thrdaddr=threadID; return reinterpret_cast(hthread); } @@ -162,11 +166,11 @@ namespace boost boost::detail::heap_delete(current_node); } } - + set_current_thread_data(0); } } - + unsigned __stdcall thread_start_function(void* param) { detail::thread_data_base* const thread_info(reinterpret_cast(param)); @@ -218,7 +222,7 @@ namespace boost ++count; interruption_enabled=false; } - + void run() {} private: @@ -250,14 +254,14 @@ namespace boost } return current_thread_data; } - + } thread::~thread() { detach(); } - + thread::id thread::get_id() const { return thread::id((get_thread_info)()); @@ -291,7 +295,7 @@ namespace boost } return true; } - + void thread::detach() { release_handle(); @@ -301,7 +305,7 @@ namespace boost { thread_info=0; } - + void thread::interrupt() { detail::thread_data_ptr local_thread_info=(get_thread_info)(); @@ -310,20 +314,20 @@ namespace boost local_thread_info->interrupt(); } } - + bool thread::interruption_requested() const { detail::thread_data_ptr local_thread_info=(get_thread_info)(); return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0); } - + unsigned thread::hardware_concurrency() { SYSTEM_INFO info={{0}}; GetSystemInfo(&info); return info.dwNumberOfProcessors; } - + thread::native_handle_type thread::native_handle() { detail::thread_data_ptr local_thread_info=(get_thread_info)(); @@ -374,7 +378,7 @@ namespace boost target_time.abs_time.time_of_day().ticks_per_second(); if(ticks_per_second>hundred_nanoseconds_in_one_second) { - posix_time::time_duration::tick_type const + posix_time::time_duration::tick_type const ticks_per_hundred_nanoseconds= ticks_per_second/hundred_nanoseconds_in_one_second; due_time.QuadPart+= @@ -392,7 +396,7 @@ namespace boost return due_time; } } - + bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time) { @@ -413,10 +417,10 @@ namespace boost } detail::win32::handle_manager timer_handle; - + #ifndef UNDER_CE unsigned const min_timer_wait_period=20; - + if(!target_time.is_sentinel()) { detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds(); @@ -427,7 +431,7 @@ namespace boost 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) { @@ -443,17 +447,17 @@ namespace boost } } #endif - + bool const using_timer=timeout_index!=~0u; detail::timeout::remaining_time time_left(0); - + do { 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); @@ -500,12 +504,12 @@ namespace boost throw thread_interrupted(); } } - + bool interruption_enabled() { return get_current_thread_data() && get_current_thread_data()->interruption_enabled; } - + bool interruption_requested() { return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0); @@ -515,7 +519,7 @@ namespace boost { detail::win32::Sleep(0); } - + disable_interruption::disable_interruption(): interruption_was_enabled(interruption_enabled()) { @@ -524,7 +528,7 @@ namespace boost get_current_thread_data()->interruption_enabled=false; } } - + disable_interruption::~disable_interruption() { if(get_current_thread_data()) @@ -540,7 +544,7 @@ namespace boost get_current_thread_data()->interruption_enabled=true; } } - + restore_interruption::~restore_interruption() { if(get_current_thread_data()) @@ -587,7 +591,7 @@ namespace boost } return NULL; } - + void set_tss_data(void const* key,boost::shared_ptr func,void* tss_data,bool cleanup_existing) { if(tss_data_node* const current_node=find_tss_data(key)) diff --git a/test/test_barrier.cpp b/test/test_barrier.cpp index e4879704..cd350ba2 100644 --- a/test/test_barrier.cpp +++ b/test/test_barrier.cpp @@ -55,9 +55,9 @@ void test_barrier() BOOST_CHECK_EQUAL(global_parameter,5); } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: barrier test suite"); test->add(BOOST_TEST_CASE(&test_barrier)); diff --git a/test/test_condition.cpp b/test/test_condition.cpp index ea008bfe..f33b7a2b 100644 --- a/test/test_condition.cpp +++ b/test/test_condition.cpp @@ -178,9 +178,9 @@ void test_condition_wait_is_a_interruption_point() 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::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: condition test suite"); test->add(BOOST_TEST_CASE(&test_condition_waits)); diff --git a/test/test_condition_notify_all.cpp b/test/test_condition_notify_all.cpp index 11a983eb..83165c99 100644 --- a/test/test_condition_notify_all.cpp +++ b/test/test_condition_notify_all.cpp @@ -211,9 +211,9 @@ void test_condition_notify_all() } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: condition test suite"); test->add(BOOST_TEST_CASE(&test_condition_notify_all)); diff --git a/test/test_condition_notify_one.cpp b/test/test_condition_notify_one.cpp index a5d82bec..1e489da6 100644 --- a/test/test_condition_notify_one.cpp +++ b/test/test_condition_notify_one.cpp @@ -144,9 +144,9 @@ void test_condition_notify_one() } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: condition test suite"); test->add(BOOST_TEST_CASE(&test_condition_notify_one)); diff --git a/test/test_condition_timed_wait_times_out.cpp b/test/test_condition_timed_wait_times_out.cpp index 9e17003f..c731b5b6 100644 --- a/test/test_condition_timed_wait_times_out.cpp +++ b/test/test_condition_timed_wait_times_out.cpp @@ -162,9 +162,9 @@ void test_timed_wait_times_out() timed_test(&do_test_cv_any_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: condition test suite"); test->add(BOOST_TEST_CASE(&test_timed_wait_times_out)); diff --git a/test/test_futures.cpp b/test/test_futures.cpp index 4fdc7593..4d89e5a9 100644 --- a/test/test_futures.cpp +++ b/test/test_futures.cpp @@ -1157,9 +1157,9 @@ void test_wait_for_all_five_futures() } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: futures test suite"); test->add(BOOST_TEST_CASE(test_initial_state)); diff --git a/test/test_generic_locks.cpp b/test/test_generic_locks.cpp index c1dd85de..8e66fad4 100644 --- a/test/test_generic_locks.cpp +++ b/test/test_generic_locks.cpp @@ -568,9 +568,9 @@ void test_try_lock_five() -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: generic locks test suite"); test->add(BOOST_TEST_CASE(&test_lock_two_uncontended)); diff --git a/test/test_hardware_concurrency.cpp b/test/test_hardware_concurrency.cpp index 7c1c148b..39f2fd6a 100644 --- a/test/test_hardware_concurrency.cpp +++ b/test/test_hardware_concurrency.cpp @@ -11,9 +11,9 @@ void test_hardware_concurrency_is_non_zero() BOOST_CHECK(boost::thread::hardware_concurrency()!=0); } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: hardware concurrency test suite"); test->add(BOOST_TEST_CASE(test_hardware_concurrency_is_non_zero)); diff --git a/test/test_lock_concept.cpp b/test/test_lock_concept.cpp index 06367d5b..bd0a22ad 100644 --- a/test/test_lock_concept.cpp +++ b/test/test_lock_concept.cpp @@ -4,7 +4,6 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include #include #include #include @@ -546,9 +545,9 @@ void test_shared_lock() BOOST_CHECK(dummy.shared_timed_locked_absolute); } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: lock concept test suite"); typedef boost::mpl::vectoradd(BOOST_TEST_CASE(test_thread_move_from_lvalue_on_construction)); diff --git a/test/test_mutex.cpp b/test/test_mutex.cpp index 8725a8fd..0350898e 100644 --- a/test/test_mutex.cpp +++ b/test/test_mutex.cpp @@ -331,9 +331,9 @@ void test_recursive_timed_mutex() timed_test(&do_test_recursive_timed_mutex, 3); } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: mutex test suite"); test->add(BOOST_TEST_CASE(&test_mutex)); diff --git a/test/test_once.cpp b/test/test_once.cpp index f0e2c1e5..340bef7e 100644 --- a/test/test_once.cpp +++ b/test/test_once.cpp @@ -178,9 +178,9 @@ void test_call_once_retried_on_exception() } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: call_once test suite"); test->add(BOOST_TEST_CASE(test_call_once)); diff --git a/test/test_shared_mutex.cpp b/test/test_shared_mutex.cpp index 2cd4502b..6085bd12 100644 --- a/test/test_shared_mutex.cpp +++ b/test/test_shared_mutex.cpp @@ -270,9 +270,9 @@ void test_unlocking_last_reader_only_unblocks_one_writer() CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_writers,1u); } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite"); test->add(BOOST_TEST_CASE(&test_multiple_readers)); diff --git a/test/test_shared_mutex_part_2.cpp b/test/test_shared_mutex_part_2.cpp index bd5d1b9b..eb9c05ee 100644 --- a/test/test_shared_mutex_part_2.cpp +++ b/test/test_shared_mutex_part_2.cpp @@ -283,9 +283,9 @@ void test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false() writer.join(); } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite"); test->add(BOOST_TEST_CASE(&test_only_one_upgrade_lock_permitted)); diff --git a/test/test_shared_mutex_timed_locks.cpp b/test/test_shared_mutex_timed_locks.cpp index 04efbc9b..2e39cc06 100644 --- a/test/test_shared_mutex_timed_locks.cpp +++ b/test/test_shared_mutex_timed_locks.cpp @@ -251,9 +251,9 @@ void test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held() } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite"); test->add(BOOST_TEST_CASE(&test_timed_lock_shared_times_out_if_write_lock_held)); diff --git a/test/test_thread.cpp b/test/test_thread.cpp index 480e258a..fe6ffa36 100644 --- a/test/test_thread.cpp +++ b/test/test_thread.cpp @@ -216,9 +216,9 @@ void test_swap() } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: thread test suite"); test->add(BOOST_TEST_CASE(test_sleep)); diff --git a/test/test_thread_exit.cpp b/test/test_thread_exit.cpp index b9e0c10c..a706cb33 100644 --- a/test/test_thread_exit.cpp +++ b/test/test_thread_exit.cpp @@ -61,9 +61,9 @@ void test_can_use_function_object_for_exit_func() } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: futures test suite"); test->add(BOOST_TEST_CASE(test_thread_exit_func_runs_when_thread_exits)); diff --git a/test/test_thread_id.cpp b/test/test_thread_id.cpp index 777bc718..a20805d8 100644 --- a/test/test_thread_id.cpp +++ b/test/test_thread_id.cpp @@ -135,9 +135,9 @@ void test_thread_id_of_running_thread_returned_by_this_thread_get_id() BOOST_CHECK(id==t_id); } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: thread move test suite"); test->add(BOOST_TEST_CASE(test_thread_id_for_default_constructed_thread_is_default_constructed_id)); diff --git a/test/test_thread_launching.cpp b/test/test_thread_launching.cpp index 4582e657..714f33bf 100644 --- a/test/test_thread_launching.cpp +++ b/test/test_thread_launching.cpp @@ -209,9 +209,9 @@ void test_thread_member_function_one_argument() } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: thread launching test suite"); test->add(BOOST_TEST_CASE(test_thread_function_no_arguments)); diff --git a/test/test_thread_move.cpp b/test/test_thread_move.cpp index b0acc3ac..f644e1eb 100644 --- a/test/test_thread_move.cpp +++ b/test/test_thread_move.cpp @@ -44,9 +44,9 @@ void test_move_assign() BOOST_CHECK_EQUAL(the_id,y_id); } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: thread move test suite"); test->add(BOOST_TEST_CASE(test_move_on_construction)); diff --git a/test/test_thread_move_return.cpp b/test/test_thread_move_return.cpp index 1146df59..51f0b3fa 100644 --- a/test/test_thread_move_return.cpp +++ b/test/test_thread_move_return.cpp @@ -25,9 +25,9 @@ void test_move_from_function_move_return() BOOST_CHECK_EQUAL(the_id,x_id); } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: thread move test suite"); test->add(BOOST_TEST_CASE(test_move_from_function_move_return)); diff --git a/test/test_thread_return_local.cpp b/test/test_thread_return_local.cpp index f2f9c078..be2aec51 100644 --- a/test/test_thread_return_local.cpp +++ b/test/test_thread_return_local.cpp @@ -25,9 +25,9 @@ void test_move_from_function_return_local() BOOST_CHECK_EQUAL(the_id,x_id); } -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: thread move test suite"); test->add(BOOST_TEST_CASE(test_move_from_function_return_local)); diff --git a/test/test_tss.cpp b/test/test_tss.cpp index 1423d7f1..894875fe 100644 --- a/test/test_tss.cpp +++ b/test/test_tss.cpp @@ -343,9 +343,9 @@ void test_tss_cleanup_not_called_for_null_pointer() -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: tss test suite"); test->add(BOOST_TEST_CASE(test_tss)); diff --git a/test/test_xtime.cpp b/test/test_xtime.cpp index efdfd3c7..0dff6200 100644 --- a/test/test_xtime.cpp +++ b/test/test_xtime.cpp @@ -95,9 +95,9 @@ void test_xtime_condvar_backwards_compatibility() -boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) { - boost::unit_test_framework::test_suite* test = + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: xtime test suite"); test->add(BOOST_TEST_CASE(&test_xtime_cmp));