2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-03 09:42:16 +00:00

Compare commits

...

7 Commits

Author SHA1 Message Date
Beman Dawes
cf4dd909d5 Release 1.49.0
[SVN r77094]
2012-02-22 22:08:43 +00:00
Vicente J. Botet Escriba
09362f0eac Thread: merge from trunk to fix #6141, #5594, #5040 and #5502.
[SVN r76346]
2012-01-07 20:52:57 +00:00
Vicente J. Botet Escriba
32b3f3f569 Thread: Fix typo on auto_ptr
[SVN r76345]
2012-01-07 20:15:14 +00:00
Vicente J. Botet Escriba
8affa33718 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]
2012-01-03 17:31:50 +00:00
Anthony Williams
b991c9a8a0 Merged thread changes from trunk
[SVN r72431]
2011-06-06 08:28:31 +00:00
Marshall Clow
ab665c8c56 Merge fixes to release; Fixes #1988
[SVN r71676]
2011-05-02 20:56:53 +00:00
Anthony Williams
7ec9804540 Merged Boost.Thread changes from trunk
[SVN r70382]
2011-03-21 22:59:40 +00:00
71 changed files with 1451 additions and 521 deletions

View File

@@ -5,7 +5,45 @@
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/5040 #5040] future.hpp in boost::thread does not compile with /clr.
* [@http://svn.boost.org/trac/boost/ticket/5423 #5423] thread issues with C++0x.
* [@http://svn.boost.org/trac/boost/ticket/5502 #5502] race condition between shared_mutex timed_lock and lock_shared.
* [@http://svn.boost.org/trac/boost/ticket/5594 #5594] boost::shared_mutex not fully compatible with Windows CE.
* [@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/6141 #6141] Compilation error when boost.thread and boost.move are used together.
* [@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 +123,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]

100
doc/compliance.qbk Normal file
View File

@@ -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<thread::id>] [#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]

View File

@@ -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

View File

@@ -310,6 +310,25 @@ without blocking.]]
[section:locks Lock Types]
[section:lock_tags Lock option tags]
#include <boost/thread/locks.hpp>
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 <boost/thread/locks.hpp>

View File

@@ -166,3 +166,5 @@
[include time.qbk]
[include acknowledgements.qbk]
[include compliance.qbk]

View File

@@ -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 <boost/thread/thread.hpp>
@@ -675,7 +713,7 @@ execution.]]
[endsect]
[section:less_than_or_equal `operator>=`]
[section:less_than_or_equal `operator<=`]
bool operator<=(const id& y) const;

View File

@@ -41,6 +41,11 @@ order. If a cleanup routine sets the value of associated with an instance of `bo
cleaned up, that value is added to the cleanup list. Cleanup finishes when there are no outstanding instances of
`boost::thread_specific_ptr` with values.
Note: on some platforms, cleanup of thread-specific data is not
performed for threads created with the platform's native API. On those
platforms such cleanup is only done for threads that are started with
`boost::thread` unless `boost::on_thread_exit()` is called manually
from that thread.
[section:thread_specific_ptr Class `thread_specific_ptr`]

View File

@@ -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
@@ -10,6 +10,15 @@
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#if !defined BOOST_THREAD_VERSION
#define BOOST_THREAD_VERSION 1
#else
#if BOOST_THREAD_VERSION!=1 && BOOST_THREAD_VERSION!=2
#error "BOOST_THREAD_VERSION must be 1 or 2"
#endif
#endif
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
# pragma warn -8008 // Condition always true/false
# pragma warn -8080 // Identifier declared but never used
@@ -53,12 +62,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 +84,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

View File

@@ -6,15 +6,20 @@
#ifndef BOOST_THREAD_MOVE_HPP
#define BOOST_THREAD_MOVE_HPP
#include <boost/thread/detail/config.hpp>
#ifndef BOOST_NO_SFINAE
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/remove_reference.hpp>
#endif
#include <boost/move/move.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
template<typename T>
@@ -41,18 +46,19 @@ namespace boost
#ifndef BOOST_NO_SFINAE
template<typename T>
typename enable_if<boost::is_convertible<T&,detail::thread_move_t<T> >, detail::thread_move_t<T> >::type move(T& t)
typename enable_if<boost::is_convertible<T&,boost::detail::thread_move_t<T> >, boost::detail::thread_move_t<T> >::type move(T& t)
{
return detail::thread_move_t<T>(t);
return boost::detail::thread_move_t<T>(t);
}
#endif
template<typename T>
detail::thread_move_t<T> move(detail::thread_move_t<T> t)
boost::detail::thread_move_t<T> move(boost::detail::thread_move_t<T> t)
{
return t;
}
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -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 <boost/thread/exceptions.hpp>
#ifndef BOOST_NO_IOSTREAM
#include <ostream>
@@ -24,6 +24,7 @@
#include <memory>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/io/ios_state.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -55,7 +56,7 @@ namespace boost
thread_data(detail::thread_move_t<F> f_):
f(f_)
{}
#endif
#endif
void run()
{
f();
@@ -80,7 +81,7 @@ namespace boost
thread_data(boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
@@ -99,14 +100,14 @@ namespace boost
thread_data(const boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
}
};
}
class BOOST_THREAD_DECL thread
{
private:
@@ -114,11 +115,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 +150,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 +176,7 @@ namespace boost
{
thread_info.swap(other.thread_info);
}
thread& operator=(thread&& other)
{
thread_info=other.thread_info;
@@ -187,7 +188,7 @@ namespace boost
{
return static_cast<thread&&>(*this);
}
#else
#ifdef BOOST_NO_SFINAE
template <class F>
@@ -204,7 +205,7 @@ namespace boost
start_thread();
}
#endif
template <class F>
explicit thread(detail::thread_move_t<F> f):
thread_info(make_thread_info(f))
@@ -217,13 +218,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<thread> x)
{
@@ -231,12 +232,12 @@ namespace boost
swap(new_thread);
return *this;
}
#endif
#endif
operator detail::thread_move_t<thread>()
{
return move();
}
detail::thread_move_t<thread> move()
{
detail::thread_move_t<thread> x(*this);
@@ -312,7 +313,7 @@ namespace boost
thread_info.swap(x.thread_info);
}
class id;
class BOOST_SYMBOL_VISIBLE id;
id get_id() const;
@@ -340,7 +341,7 @@ namespace boost
{
this_thread::yield();
}
static inline void sleep(const system_time& xt)
{
this_thread::sleep(xt);
@@ -355,7 +356,7 @@ namespace boost
{
return lhs.swap(rhs);
}
#ifndef BOOST_NO_RVALUE_REFERENCES
inline thread&& move(thread& t)
{
@@ -380,17 +381,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 +401,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<y.thread_data;
}
bool operator>(const id& y) const
{
return y.thread_data<thread_data;
}
bool operator<=(const id& y) const
{
return !(y.thread_data<thread_data);
}
bool operator>=(const id& y) const
{
return !(thread_data<y.thread_data);
@@ -434,12 +439,14 @@ namespace boost
#ifndef BOOST_NO_IOSTREAM
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
template<class charT, class traits>
friend std::basic_ostream<charT, traits>&
friend BOOST_SYMBOL_VISIBLE
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
{
if(x.thread_data)
{
return os<<x.thread_data;
io::ios_flags_saver ifs( os );
return os<< std::hex << x.thread_data;
}
else
{
@@ -448,7 +455,8 @@ namespace boost
}
#else
template<class charT, class traits>
std::basic_ostream<charT, traits>&
BOOST_SYMBOL_VISIBLE
std::basic_ostream<charT, traits>&
print(std::basic_ostream<charT, traits>& os) const
{
if(thread_data)
@@ -467,7 +475,8 @@ namespace boost
#if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<class charT, class traits>
std::basic_ostream<charT, traits>&
BOOST_SYMBOL_VISIBLE
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x)
{
return x.print(os);
@@ -478,12 +487,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 +501,33 @@ namespace boost
{}
virtual void operator()()=0;
};
template<typename F>
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*);
}
#ifdef BOOST_NO_RVALUE_REFERENCES
template <>
struct has_move_emulation_enabled_aux<thread>
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
#endif
namespace this_thread
{
template<typename F>

View File

@@ -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:

View File

@@ -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<boost::mutex> lock(mutex);
@@ -132,7 +132,7 @@ namespace boost
struct relocker
{
boost::unique_lock<boost::mutex>& lock;
relocker(boost::unique_lock<boost::mutex>& 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<rvalue_source_type>(t)));
@@ -249,7 +249,7 @@ namespace boost
storage.reset();
}
};
template<typename T>
struct future_traits<T&>
{
@@ -296,7 +296,7 @@ namespace boost
typedef typename future_traits<T>::source_reference_type source_reference_type;
typedef typename future_traits<T>::rvalue_source_type rvalue_source_type;
typedef typename future_traits<T>::move_dest_type move_dest_type;
storage_type result;
future_object():
@@ -353,6 +353,8 @@ namespace boost
struct future_object<void>:
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<boost::mutex> guard(mutex);
@@ -394,7 +396,7 @@ namespace boost
{
struct registered_waiter;
typedef std::vector<registered_waiter>::size_type count_type;
struct registered_waiter
{
boost::shared_ptr<detail::future_object_base> future;
@@ -408,44 +410,54 @@ namespace boost
{}
};
struct all_futures_lock
{
count_type count;
#ifdef _MANAGED
typedef std::ptrdiff_t count_type_portable;
#else
typedef count_type count_type_portable;
#endif
count_type_portable count;
boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
all_futures_lock(std::vector<registered_waiter>& futures):
count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
{
for(count_type i=0;i<count;++i)
for(count_type_portable i=0;i<count;++i)
{
#if defined __DECCXX || defined __SUNPRO_CC
locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex).move();
#else
locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex);
#endif
}
}
void lock()
{
boost::lock(locks.get(),locks.get()+count);
}
void unlock()
{
for(count_type i=0;i<count;++i)
for(count_type_portable i=0;i<count;++i)
{
locks[i].unlock();
}
}
};
boost::condition_variable_any cv;
std::vector<registered_waiter> futures;
count_type future_count;
public:
future_waiter():
future_count(0)
{}
template<typename F>
void add(F& f)
{
@@ -471,7 +483,7 @@ namespace boost
cv.wait(lk);
}
}
~future_waiter()
{
for(count_type i=0;i<futures.size();++i)
@@ -479,9 +491,9 @@ namespace boost
futures[i].future->remove_external_waiter(futures[i].wait_iterator);
}
}
};
}
template <typename R>
@@ -495,13 +507,13 @@ namespace boost
{
BOOST_STATIC_CONSTANT(bool, value=false);
};
template<typename T>
struct is_future_type<unique_future<T> >
{
BOOST_STATIC_CONSTANT(bool, value=true);
};
template<typename T>
struct is_future_type<shared_future<T> >
{
@@ -531,7 +543,7 @@ namespace boost
f2.wait();
f3.wait();
}
template<typename F1,typename F2,typename F3,typename F4>
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4)
{
@@ -556,7 +568,7 @@ namespace boost
{
if(begin==end)
return end;
detail::future_waiter waiter;
for(Iterator current=begin;current!=end;++current)
{
@@ -583,7 +595,7 @@ namespace boost
waiter.add(f3);
return waiter.wait();
}
template<typename F1,typename F2,typename F3,typename F4>
unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
{
@@ -606,7 +618,7 @@ namespace boost
waiter.add(f5);
return waiter.wait();
}
template <typename R>
class promise;
@@ -620,7 +632,7 @@ namespace boost
unique_future& operator=(unique_future& rhs);// = delete;
typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
future_ptr future;
friend class shared_future<R>;
@@ -639,7 +651,7 @@ namespace boost
unique_future()
{}
~unique_future()
{}
@@ -689,7 +701,7 @@ namespace boost
return future->get();
}
// functions to check state, and wait for ready
state get_state() const
{
@@ -699,23 +711,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 +736,13 @@ namespace boost
}
future->wait(false);
}
template<typename Duration>
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 +751,21 @@ namespace boost
}
return future->timed_wait_until(abs_time);
}
};
#ifdef BOOST_NO_RVALUE_REFERENCES
template <typename T>
struct has_move_emulation_enabled_aux<unique_future<T> >
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
#endif
template <typename R>
class shared_future
{
typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
future_ptr future;
// shared_future(const unique_future<R>& other);
@@ -755,7 +774,7 @@ namespace boost
friend class detail::future_waiter;
friend class promise<R>;
friend class packaged_task<R>;
shared_future(future_ptr future_):
future(future_)
{}
@@ -799,7 +818,7 @@ namespace boost
other.future.reset();
return *this;
}
#else
#else
shared_future(boost::detail::thread_move_t<shared_future> other):
future(other->future)
{
@@ -837,6 +856,7 @@ namespace boost
}
// retrieving the value
//typename detail::future_object<R>::move_dest_type get()
R get()
{
if(!future)
@@ -846,7 +866,7 @@ namespace boost
return future->get();
}
// functions to check state, and wait for ready
state get_state() const
{
@@ -856,18 +876,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 +901,13 @@ namespace boost
}
future->wait(false);
}
template<typename Duration>
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 +916,24 @@ namespace boost
}
return future->timed_wait_until(abs_time);
}
};
#ifdef BOOST_NO_RVALUE_REFERENCES
template <typename T>
struct has_move_emulation_enabled_aux<shared_future<T> >
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
#endif
template <typename R>
class promise
{
typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
future_ptr future;
bool future_obtained;
promise(promise & rhs);// = delete;
promise & operator=(promise & rhs);// = delete;
@@ -918,14 +945,14 @@ namespace boost
atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<R>));
}
}
public:
// template <class Allocator> explicit promise(Allocator a);
promise():
future(),future_obtained(false)
{}
~promise()
{
if(future)
@@ -975,8 +1002,8 @@ namespace boost
{
return boost::detail::thread_move_t<promise>(*this);
}
#endif
#endif
void swap(promise& other)
{
future.swap(other.future);
@@ -1035,17 +1062,17 @@ namespace boost
lazy_init();
future->set_wait_callback(f,this);
}
};
template <>
class promise<void>
{
typedef boost::shared_ptr<detail::future_object<void> > future_ptr;
future_ptr future;
bool future_obtained;
promise(promise & rhs);// = delete;
promise & operator=(promise & rhs);// = delete;
@@ -1063,7 +1090,7 @@ namespace boost
promise():
future(),future_obtained(false)
{}
~promise()
{
if(future)
@@ -1114,7 +1141,7 @@ namespace boost
return boost::detail::thread_move_t<promise>(*this);
}
#endif
void swap(promise& other)
{
future.swap(other.future);
@@ -1125,7 +1152,7 @@ namespace boost
unique_future<void> get_future()
{
lazy_init();
if(future_obtained)
{
boost::throw_exception(future_already_retrieved());
@@ -1162,9 +1189,16 @@ namespace boost
lazy_init();
future->set_wait_callback(f,this);
}
};
#ifdef BOOST_NO_RVALUE_REFERENCES
template <typename T>
struct has_move_emulation_enabled_aux<promise<T> >
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
#endif
namespace detail
{
template<typename R>
@@ -1199,12 +1233,12 @@ namespace boost
this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()));
}
}
virtual void do_run()=0;
};
template<typename R,typename F>
struct task_object:
task_base<R>
@@ -1213,10 +1247,16 @@ namespace boost
task_object(F const& f_):
f(f_)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
task_object(F&& f_):
f(f_)
{}
#else
task_object(boost::detail::thread_move_t<F> f_):
f(f_)
{}
#endif
void do_run()
{
try
@@ -1238,10 +1278,16 @@ namespace boost
task_object(F const& f_):
f(f_)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
task_object(F&& f_):
f(f_)
{}
#else
task_object(boost::detail::thread_move_t<F> f_):
f(f_)
{}
#endif
void do_run()
{
try
@@ -1257,7 +1303,7 @@ namespace boost
};
}
template<typename R>
class packaged_task
@@ -1267,12 +1313,12 @@ namespace boost
packaged_task(packaged_task&);// = delete;
packaged_task& operator=(packaged_task&);// = delete;
public:
packaged_task():
future_obtained(false)
{}
// construction and destruction
template <class F>
explicit packaged_task(F const& f):
@@ -1281,11 +1327,18 @@ namespace boost
explicit packaged_task(R(*f)()):
task(new detail::task_object<R,R(*)()>(f)),future_obtained(false)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
template <class F>
explicit packaged_task(F&& f):
task(new detail::task_object<R,F>(f)),future_obtained(false)
{}
#else
template <class F>
explicit packaged_task(boost::detail::thread_move_t<F> f):
task(new detail::task_object<R,F>(f)),future_obtained(false)
{}
#endif
// template <class F, class Allocator>
// explicit packaged_task(F const& f, Allocator a);
@@ -1334,7 +1387,7 @@ namespace boost
}
#endif
void swap(packaged_task& other)
void swap(packaged_task& other)
{
task.swap(other.task);
std::swap(future_obtained,other.future_obtained);
@@ -1357,7 +1410,7 @@ namespace boost
boost::throw_exception(future_already_retrieved());
}
}
// execution
void operator()()
@@ -1374,9 +1427,16 @@ namespace boost
{
task->set_wait_callback(f,this);
}
};
#ifdef BOOST_NO_RVALUE_REFERENCES
template <typename T>
struct has_move_emulation_enabled_aux<packaged_task<T> >
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
#endif
}

View File

@@ -71,7 +71,7 @@ namespace boost
{
BOOST_STATIC_CONSTANT(bool, value=false);
};
template<typename T>
struct has_member_lock<T,true>
{
@@ -80,22 +80,22 @@ namespace boost
{
true_type dummy[2];
};
template<typename U,typename V>
static true_type has_member(V (U::*)());
template<typename U>
static false_type has_member(U);
BOOST_STATIC_CONSTANT(
bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type));
};
template<typename T,bool=has_member_called_unlock<T>::value >
struct has_member_unlock
{
BOOST_STATIC_CONSTANT(bool, value=false);
};
template<typename T>
struct has_member_unlock<T,true>
{
@@ -104,22 +104,22 @@ namespace boost
{
true_type dummy[2];
};
template<typename U,typename V>
static true_type has_member(V (U::*)());
template<typename U>
static false_type has_member(U);
BOOST_STATIC_CONSTANT(
bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type));
};
template<typename T,bool=has_member_called_try_lock<T>::value >
struct has_member_try_lock
{
BOOST_STATIC_CONSTANT(bool, value=false);
};
template<typename T>
struct has_member_try_lock<T,true>
{
@@ -128,18 +128,18 @@ namespace boost
{
true_type dummy[2];
};
template<typename U>
static true_type has_member(bool (U::*)());
template<typename U>
static false_type has_member(U);
BOOST_STATIC_CONSTANT(
bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
};
}
template<typename T>
struct is_mutex_type
@@ -147,7 +147,7 @@ namespace boost
BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value &&
detail::has_member_unlock<T>::value &&
detail::has_member_try_lock<T>::value);
};
#else
template<typename T>
@@ -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<typename Mutex>
class try_lock_wrapper;
}
#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
template<typename T>
struct is_mutex_type<unique_lock<T> >
@@ -201,7 +201,7 @@ namespace boost
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template<typename T>
struct is_mutex_type<detail::try_lock_wrapper<T> >
{
@@ -213,7 +213,7 @@ namespace boost
class recursive_mutex;
class recursive_timed_mutex;
class shared_mutex;
template<>
struct is_mutex_type<mutex>
{
@@ -277,13 +277,13 @@ namespace boost
unique_lock& operator=(unique_lock&);
unique_lock& operator=(upgrade_lock<Mutex>& 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<unique_lock<Mutex> >(*this);
}
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
unique_lock& operator=(unique_lock<Mutex> other)
{
swap(other);
return *this;
}
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
unique_lock& operator=(unique_lock<Mutex> other)
{
swap(other);
return *this;
}
#else
unique_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > 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
{
@@ -518,6 +518,13 @@ namespace boost
}
#endif
#ifdef BOOST_NO_RVALUE_REFERENCES
template <typename Mutex>
struct has_move_emulation_enabled_aux<unique_lock<Mutex> >
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
#endif
template<typename Mutex>
class shared_lock
{
@@ -531,7 +538,7 @@ namespace boost
shared_lock():
m(0),is_locked(false)
{}
explicit shared_lock(Mutex& m_):
m(&m_),is_locked(false)
{
@@ -553,7 +560,9 @@ namespace boost
{
timed_lock(target_time);
}
#ifndef BOOST_NO_RVALUE_REFERENCES
#else
shared_lock(detail::thread_move_t<shared_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
@@ -614,6 +623,7 @@ namespace boost
swap(temp);
return *this;
}
#endif
#ifndef BOOST_NO_RVALUE_REFERENCES
void swap(shared_lock&& other)
@@ -638,7 +648,7 @@ namespace boost
{
return m;
}
~shared_lock()
{
if(owns_lock())
@@ -692,7 +702,7 @@ namespace boost
m->unlock_shared();
is_locked=false;
}
typedef void (shared_lock<Mutex>::*bool_type)();
operator bool_type() const
{
@@ -709,12 +719,25 @@ namespace boost
};
#ifdef BOOST_NO_RVALUE_REFERENCES
template <typename Mutex>
struct has_move_emulation_enabled_aux<shared_lock<Mutex> >
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
#endif
#ifndef BOOST_NO_RVALUE_REFERENCES
template<typename Mutex>
void swap(shared_lock<Mutex>&& lhs,shared_lock<Mutex>&& rhs)
{
lhs.swap(rhs);
}
template<typename Mutex>
void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs)
{
lhs.swap(rhs);
}
#else
template<typename Mutex>
void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs)
@@ -736,7 +759,7 @@ namespace boost
upgrade_lock():
m(0),is_locked(false)
{}
explicit upgrade_lock(Mutex& m_):
m(&m_),is_locked(false)
{
@@ -753,7 +776,7 @@ namespace boost
{
try_lock();
}
#ifdef BOOST_HAS_RVALUE_REFS
#ifndef BOOST_NO_RVALUE_REFERENCES
upgrade_lock(upgrade_lock<Mutex>&& other):
m(other.m),is_locked(other.is_locked)
{
@@ -835,7 +858,7 @@ namespace boost
std::swap(m,other.m);
std::swap(is_locked,other.is_locked);
}
~upgrade_lock()
{
if(owns_lock())
@@ -870,7 +893,7 @@ namespace boost
m->unlock_upgrade();
is_locked=false;
}
typedef void (upgrade_lock::*bool_type)();
operator bool_type() const
{
@@ -888,6 +911,12 @@ namespace boost
friend class unique_lock<Mutex>;
};
#ifdef BOOST_NO_RVALUE_REFERENCES
template <typename Mutex>
struct has_move_emulation_enabled_aux<upgrade_lock<Mutex> >
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
#endif
#ifndef BOOST_NO_RVALUE_REFERENCES
template<typename Mutex>
@@ -933,13 +962,13 @@ namespace boost
}
}
#ifdef BOOST_HAS_RVALUE_REFS
#ifndef BOOST_NO_RVALUE_REFERENCES
upgrade_to_unique_lock(upgrade_to_unique_lock<Mutex>&& other):
source(other.source),exclusive(move(other.exclusive))
{
other.source=0;
}
upgrade_to_unique_lock& operator=(upgrade_to_unique_lock<Mutex>&& other)
{
upgrade_to_unique_lock temp(other);
@@ -952,7 +981,7 @@ namespace boost
{
other->source=0;
}
upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other)
{
upgrade_to_unique_lock temp(other);
@@ -980,6 +1009,13 @@ namespace boost
}
};
#ifdef BOOST_NO_RVALUE_REFERENCES
template <typename Mutex>
struct has_move_emulation_enabled_aux<upgrade_to_unique_lock<Mutex> >
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
#endif
namespace detail
{
template<typename Mutex>
@@ -990,7 +1026,7 @@ namespace boost
public:
try_lock_wrapper()
{}
explicit try_lock_wrapper(Mutex& m):
base(m,try_to_lock)
{}
@@ -1098,6 +1134,11 @@ namespace boost
{
lhs.swap(rhs);
}
template<typename Mutex>
void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs)
{
lhs.swap(rhs);
}
#else
template<typename Mutex>
void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs)
@@ -1105,7 +1146,7 @@ namespace boost
lhs.swap(rhs);
}
#endif
template<typename MutexType1,typename MutexType2>
unsigned try_lock_internal(MutexType1& m1,MutexType2& m2)
{
@@ -1234,7 +1275,7 @@ namespace boost
template<bool x>
struct is_mutex_type_wrapper
{};
template<typename MutexType1,typename MutexType2>
void lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper<true>)
{
@@ -1262,7 +1303,7 @@ namespace boost
template<typename Iterator>
void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>);
}
template<typename MutexType1,typename MutexType2>
void lock(MutexType1& m1,MutexType2& m2)
@@ -1407,7 +1448,7 @@ namespace boost
{
typedef int type;
};
template<typename Iterator>
struct try_lock_impl_return<Iterator,false>
{
@@ -1423,7 +1464,7 @@ namespace boost
template<typename Iterator>
Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>);
}
template<typename MutexType1,typename MutexType2>
typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1,MutexType2& m2)
{
@@ -1465,7 +1506,7 @@ namespace boost
{
return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1;
}
namespace detail
{
@@ -1474,13 +1515,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 +1546,21 @@ namespace boost
}
typedef typename std::iterator_traits<Iterator>::value_type lock_type;
unique_lock<lock_type> 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 +1568,7 @@ namespace boost
void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>)
{
typedef typename std::iterator_traits<Iterator>::value_type lock_type;
if(begin==end)
{
return;
@@ -1536,14 +1577,14 @@ namespace boost
Iterator second=begin;
++second;
Iterator next=second;
for(;;)
{
unique_lock<lock_type> 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 +1598,7 @@ namespace boost
detail::range_lock_guard<Iterator> 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 +1616,9 @@ namespace boost
}
}
}
}
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -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 <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/thread/pthread/thread_data.hpp>
#include <boost/thread/pthread/condition_variable_fwd.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -18,14 +18,14 @@ namespace boost
{
void BOOST_THREAD_DECL interruption_point();
}
namespace thread_cv_detail
{
template<typename MutexType>
struct lock_on_exit
{
MutexType* m;
lock_on_exit():
m(0)
{}
@@ -44,30 +44,44 @@ namespace boost
}
};
}
inline void condition_variable::wait(unique_lock<mutex>& m)
{
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
int const res=pthread_cond_wait(&cond,&internal_mutex);
BOOST_ASSERT(!res);
int res=0;
{
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
do {
res = pthread_cond_wait(&cond,&internal_mutex);
} while (res == EINTR);
}
this_thread::interruption_point();
if(res)
{
boost::throw_exception(condition_error());
}
}
inline bool condition_variable::timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
{
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
struct timespec const timeout=detail::get_timespec(wait_until);
int const cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
int cond_res;
{
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
struct timespec const timeout=detail::get_timespec(wait_until);
cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
}
this_thread::interruption_point();
if(cond_res==ETIMEDOUT)
{
return false;
}
BOOST_ASSERT(!cond_res);
if(cond_res)
{
boost::throw_exception(condition_error());
}
return true;
}
@@ -76,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;
@@ -111,7 +125,7 @@ namespace boost
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
BOOST_VERIFY(!pthread_cond_destroy(&cond));
}
template<typename lock_type>
void wait(lock_type& m)
{
@@ -121,8 +135,8 @@ namespace boost
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
res=pthread_cond_wait(&cond,&internal_mutex);
this_thread::interruption_point();
}
this_thread::interruption_point();
if(res)
{
boost::throw_exception(condition_error());
@@ -134,7 +148,7 @@ namespace boost
{
while(!pred()) wait(m);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{
@@ -145,8 +159,8 @@ namespace boost
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
this_thread::interruption_point();
}
this_thread::interruption_point();
if(res==ETIMEDOUT)
{
return false;
@@ -197,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);

View File

@@ -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<mutex>& m);

View File

@@ -14,11 +14,11 @@
#include <boost/thread/xtime.hpp>
#include <boost/assert.hpp>
#include <errno.h>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#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);

View File

@@ -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 <pthread.h>
#include <boost/assert.hpp>
#include "pthread_mutex_scoped_lock.hpp"
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/cstdint.hpp>
@@ -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<this_thread_epoch)
{
pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);

View File

@@ -17,8 +17,8 @@
#endif
#include <boost/date_time/posix_time/conversion.hpp>
#include <errno.h>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#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);

View File

@@ -27,7 +27,7 @@ namespace boost
bool upgrade;
bool exclusive_waiting_blocked;
};
state_data state;
@@ -41,7 +41,7 @@ namespace boost
exclusive_cond.notify_one();
shared_cond.notify_all();
}
public:
shared_mutex()
@@ -58,7 +58,7 @@ namespace boost
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
shared_cond.wait(lk);
@@ -69,7 +69,7 @@ namespace boost
bool try_lock_shared()
{
boost::mutex::scoped_lock lk(state_change);
if(state.exclusive || state.exclusive_waiting_blocked)
{
return false;
@@ -85,7 +85,7 @@ namespace boost
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
if(!shared_cond.timed_wait(lk,timeout))
@@ -107,7 +107,7 @@ namespace boost
{
boost::mutex::scoped_lock lk(state_change);
bool const last_reader=!--state.shared_count;
if(last_reader)
{
if(state.upgrade)
@@ -128,7 +128,7 @@ namespace boost
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
@@ -150,7 +150,7 @@ namespace boost
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=false;
exclusive_cond.notify_one();
release_waiters();
return false;
}
break;
@@ -169,7 +169,7 @@ namespace boost
bool try_lock()
{
boost::mutex::scoped_lock lk(state_change);
if(state.shared_count || state.exclusive)
{
return false;
@@ -179,7 +179,7 @@ namespace boost
state.exclusive=true;
return true;
}
}
void unlock()
@@ -248,7 +248,7 @@ namespace boost
boost::mutex::scoped_lock lk(state_change);
state.upgrade=false;
bool const last_reader=!--state.shared_count;
if(last_reader)
{
state.exclusive_waiting_blocked=false;
@@ -278,7 +278,7 @@ namespace boost
state.exclusive_waiting_blocked=false;
release_waiters();
}
void unlock_and_lock_shared()
{
boost::mutex::scoped_lock lk(state_change);
@@ -287,7 +287,7 @@ namespace boost
state.exclusive_waiting_blocked=false;
release_waiters();
}
void unlock_upgrade_and_lock_shared()
{
boost::mutex::scoped_lock lk(state_change);

View File

@@ -13,7 +13,7 @@
#include <boost/optional.hpp>
#include <pthread.h>
#include <boost/assert.hpp>
#include "condition_variable_fwd.hpp"
#include <boost/thread/pthread/condition_variable_fwd.hpp>
#include <map>
#include <boost/config/abi_prefix.hpp>
@@ -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_base> thread_data_ptr;
struct BOOST_THREAD_DECL thread_data_base:
enable_shared_from_this<thread_data_base>
{
@@ -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<typename TimeDuration>
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<typename TimeDuration>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
this_thread::sleep(get_system_time()+rel_time);
}
#endif
}
}

View File

@@ -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 <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/basic_timed_mutex.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -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_timed_mutex> basic_recursive_mutex;

View File

@@ -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 <boost/assert.hpp>
#include "thread_primitives.hpp"
#include "interlocked_read.hpp"
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/detail/interlocked.hpp>
@@ -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;
}
};
}
}

View File

@@ -6,13 +6,13 @@
// (C) Copyright 2007-8 Anthony Williams
#include <boost/thread/mutex.hpp>
#include "thread_primitives.hpp"
#include <boost/thread/win32/thread_primitives.hpp>
#include <limits.h>
#include <boost/assert.hpp>
#include <algorithm>
#include <boost/thread/thread.hpp>
#include <boost/thread/thread_time.hpp>
#include "interlocked_read.hpp"
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/thread/xtime.hpp>
#include <vector>
#include <boost/intrusive_ptr.hpp>
@@ -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<typename lock_type>
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<typename lock_type>
bool do_wait(lock_type& lock,timeout wait_until)
{
relocker<lock_type> 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<mutex>& m)
{
do_wait(m,detail::timeout::sentinel());
@@ -315,7 +315,7 @@ namespace boost
{
while(!pred()) wait(m);
}
bool timed_wait(unique_lock<mutex>& 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<typename lock_type>
void wait(lock_type& m)
{
@@ -373,7 +373,7 @@ namespace boost
{
while(!pred()) wait(m);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{

View File

@@ -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 <boost/thread/win32/basic_timed_mutex.hpp>
#include <boost/utility.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>

View File

@@ -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 <boost/utility.hpp>
#include "basic_recursive_mutex.hpp"
#include <boost/thread/win32/basic_recursive_mutex.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
@@ -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()
{

View File

@@ -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<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
}
};
template<typename T>
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
@@ -326,7 +337,12 @@ namespace boost
{
return true;
}
unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,true,::boost::detail::get_milliseconds_until(wait_until));
#ifndef UNDER_CE
const bool wait_all = true;
#else
const bool wait_all = false;
#endif
unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until));
if(wait_res==detail::win32::timeout)
{
for(;;)
@@ -426,7 +442,7 @@ namespace boost
{
return;
}
BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite));
}
}
@@ -450,7 +466,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 +485,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 +495,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 +516,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 +561,7 @@ namespace boost
}
release_waiters(old_state);
}
void unlock_and_lock_shared()
{
state_data old_state=state;
@@ -570,7 +586,7 @@ namespace boost
}
release_waiters(old_state);
}
void unlock_upgrade_and_lock_shared()
{
state_data old_state=state;
@@ -594,7 +610,7 @@ namespace boost
}
release_waiters(old_state);
}
};
}

View File

@@ -8,8 +8,8 @@
#include <boost/thread/detail/config.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/thread/thread_time.hpp>
#include "thread_primitives.hpp"
#include "thread_heap_alloc.hpp"
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/thread_heap_alloc.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -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<detail::thread_data_base> 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,15 +139,15 @@ namespace boost
private:
struct sentinel_type
{};
explicit timeout(sentinel_type):
start(0),milliseconds(~uintmax_t(0)),relative(true)
{}
};
inline unsigned long pin_to_zero(long value)
inline uintmax_t pin_to_zero(intmax_t value)
{
return (value<0)?0u:(unsigned long)value;
return (value<0)?0u:(uintmax_t)value;
}
}
@@ -156,26 +156,26 @@ namespace boost
void BOOST_THREAD_DECL yield();
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
inline void interruptible_wait(unsigned long milliseconds)
inline void interruptible_wait(uintmax_t milliseconds)
{
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<typename TimeDuration>
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 <boost/config/abi_suffix.hpp>

View File

@@ -5,7 +5,7 @@
#ifndef THREAD_HEAP_ALLOC_HPP
#define THREAD_HEAP_ALLOC_HPP
#include <new>
#include "thread_primitives.hpp"
#include <boost/thread/win32/thread_primitives.hpp>
#include <stdexcept>
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
@@ -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<typename T>
inline T* heap_new()
{
@@ -226,7 +226,7 @@ namespace boost
{
return heap_new_impl<T,A1&>(a1);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2 const& a2)
{
@@ -372,8 +372,8 @@ namespace boost
{
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
#endif
#endif
template<typename T>
inline void heap_delete(T* data)
{

View File

@@ -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;
};
};
}
}
}
}

16
src/pthread/once.cpp Executable file → Normal file
View File

@@ -22,16 +22,18 @@ namespace boost
pthread_key_t epoch_tss_key;
pthread_once_t epoch_tss_key_flag=PTHREAD_ONCE_INIT;
extern "C" void delete_epoch_tss_data(void* data)
extern "C"
{
free(data);
}
static void delete_epoch_tss_data(void* data)
{
free(data);
}
extern "C" void create_epoch_tss_key()
{
BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data));
static void create_epoch_tss_key()
{
BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data));
}
}
}
boost::uintmax_t& get_once_per_thread_epoch()

View File

@@ -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 <boost/thread/detail/config.hpp>
@@ -14,7 +14,7 @@
#include <boost/thread/once.hpp>
#include <boost/thread/tss.hpp>
#include <boost/throw_exception.hpp>
#ifdef __linux__
#ifdef __GLIBC__
#include <sys/sysinfo.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/types.h>
@@ -50,7 +50,7 @@ namespace boost
extern "C"
{
void tls_destructor(void* data)
static void tls_destructor(void* data)
{
boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
if(thread_info)
@@ -86,14 +86,14 @@ namespace boost
}
}
}
void create_current_thread_tls_key()
{
BOOST_VERIFY(!pthread_key_create(&current_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,12 +106,12 @@ namespace boost
BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data));
}
}
namespace
{
extern "C"
{
void* thread_proxy(void* param)
static void* thread_proxy(void* param)
{
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
thread_info->self.reset();
@@ -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<mutex> 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<mutex> 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<mutex> 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<mutex> 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<tss_cleanup_function> func,
void* tss_data,bool cleanup_existing)

View File

@@ -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;

View File

@@ -9,7 +9,6 @@
#include <boost/thread/thread.hpp>
#include <algorithm>
#include <windows.h>
#ifndef UNDER_CE
#include <process.h>
#endif
@@ -20,6 +19,8 @@
#include <boost/throw_exception.hpp>
#include <boost/thread/detail/tss_hooks.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
#include <windows.h>
#include <memory>
namespace boost
{
@@ -32,7 +33,12 @@ namespace boost
{
tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in
current_thread_tls_key=TlsAlloc();
BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES);
#if defined(UNDER_CE)
// Windows CE does not define the TLS_OUT_OF_INDEXES constant.
BOOST_ASSERT(current_thread_tls_key!=0xFFFFFFFF);
#else
BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES);
#endif
}
void cleanup_tls_key()
@@ -62,7 +68,7 @@ namespace boost
boost::throw_exception(thread_resource_error());
}
#ifdef BOOST_NO_THREADEX
#ifndef BOOST_HAS_THREADEX
// Windows CE doesn't define _beginthreadex
struct ThreadProxyData
@@ -75,22 +81,25 @@ namespace boost
DWORD WINAPI ThreadProxy(LPVOID args)
{
ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args);
std::auto_ptr<ThreadProxyData> data(reinterpret_cast<ThreadProxyData*>(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<LPSECURITY_ATTRIBUTES>(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<uintptr_t const>(hthread);
}
@@ -157,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<detail::thread_data_base*>(param));
@@ -213,7 +222,7 @@ namespace boost
++count;
interruption_enabled=false;
}
void run()
{}
private:
@@ -245,14 +254,14 @@ namespace boost
}
return current_thread_data;
}
}
thread::~thread()
{
detach();
}
thread::id thread::get_id() const
{
return thread::id((get_thread_info)());
@@ -286,7 +295,7 @@ namespace boost
}
return true;
}
void thread::detach()
{
release_handle();
@@ -296,7 +305,7 @@ namespace boost
{
thread_info=0;
}
void thread::interrupt()
{
detail::thread_data_ptr local_thread_info=(get_thread_info)();
@@ -305,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)();
@@ -369,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+=
@@ -387,7 +396,7 @@ namespace boost
return due_time;
}
}
bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
{
@@ -408,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();
@@ -422,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)
{
@@ -438,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);
@@ -495,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);
@@ -510,7 +519,7 @@ namespace boost
{
detail::win32::Sleep(0);
}
disable_interruption::disable_interruption():
interruption_was_enabled(interruption_enabled())
{
@@ -519,7 +528,7 @@ namespace boost
get_current_thread_data()->interruption_enabled=false;
}
}
disable_interruption::~disable_interruption()
{
if(get_current_thread_data())
@@ -535,7 +544,7 @@ namespace boost
get_current_thread_data()->interruption_enabled=true;
}
}
restore_interruption::~restore_interruption()
{
if(get_current_thread_data())
@@ -582,7 +591,7 @@ namespace boost
}
return NULL;
}
void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing)
{
if(tss_data_node* const current_node=find_tss_data(key))

View File

@@ -11,7 +11,7 @@
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
#if defined(__MINGW32__) && !defined(_WIN64)
#if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__)
#include <boost/thread/detail/tss_hooks.hpp>
@@ -38,7 +38,8 @@ namespace {
}
}
#if (__MINGW32_MAJOR_VERSION >3) || ((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18))
#if defined(__MINGW64__) || (__MINGW32_MAJOR_VERSION >3) || \
((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18))
extern "C"
{
PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback;

View File

@@ -62,4 +62,29 @@ rule thread-run ( sources )
[ compile-fail no_implicit_move_from_lvalue_thread.cpp ]
[ compile-fail no_implicit_assign_from_lvalue_thread.cpp ]
;
#explicit tickets ;
test-suite tickets
:
[ thread-run test_6170.cpp ]
;
explicit oth_tickets ;
test-suite oth_tickets
:
[ thread-run test_2501.cpp ]
[ thread-run test_4521.cpp ]
[ thread-run test_4648.cpp ]
[ thread-run test_4882.cpp ]
[ thread-run test_5351.cpp ]
[ thread-run test_5502.cpp ]
[ thread-run test_5542_1.cpp ]
[ thread-run test_5542_2.cpp ]
[ thread-run test_5542_3.cpp ]
[ thread-run test_6130.cpp ]
[ thread-run test_6174.cpp ]
;
}

10
test/test_2501.cpp Normal file
View File

@@ -0,0 +1,10 @@
#include <boost/thread/shared_mutex.hpp>
int main() {
boost::shared_mutex mtx; boost::upgrade_lock<boost::shared_mutex> lk(mtx);
boost::upgrade_to_unique_lock<boost::shared_mutex> lk2(lk);
return 0;
}

21
test/test_4521.cpp Normal file
View File

@@ -0,0 +1,21 @@
#include <boost/thread.hpp>
int calculate_the_answer_to_life_the_universe_and_everything()
{
return 42;
}
int main() {
boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything);
boost::unique_future<int> fi=pt.get_future();
boost::thread task(boost::move(pt)); // launch task on a thread
fi.wait(); // wait for it to finish
//assert(fi.is_ready());
//assert(fi.has_value());
//assert(!fi.has_exception());
//assert(fi.get_state()==boost::future_state::ready);
//assert(fi.get()==42);
}

42
test/test_4648.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include <iostream>
#include <boost/thread.hpp>
#include <boost/current_function.hpp>
class boostThreadLocksTest
{
public:
boost::shared_mutex myMutex;
//boost::upgrade_lock<boost::shared_mutex> myLock;
static int firstFunction(boostThreadLocksTest *pBoostThreadLocksTest);
static int secondFunction(boostThreadLocksTest *pBoostThreadLocksTest,
boost::upgrade_lock<boost::shared_mutex>& upgr);
boostThreadLocksTest()
:myMutex()
//, myLock(myMutex,boost::defer_lock_t())
{};
};
int boostThreadLocksTest::firstFunction(boostThreadLocksTest *pBoostThreadLocksTest)
{
std::cout<<"Entering "<<boost::this_thread::get_id()<<" "<<"firstFunction"<<std::endl;
boost::upgrade_lock<boost::shared_mutex> myLock(pBoostThreadLocksTest->myMutex);
pBoostThreadLocksTest->secondFunction(pBoostThreadLocksTest, myLock);
std::cout<<"Returned From Call "<<boost::this_thread::get_id()<<" "<<"firstFunction"<<std::endl;
std::cout<<"Returning from "<<boost::this_thread::get_id()<<" "<<"firstFunction"<<std::endl;
return(0);
}
int boostThreadLocksTest::secondFunction(boostThreadLocksTest *pBoostThreadLocksTest, boost::upgrade_lock<boost::shared_mutex>& upgr) {
std::cout<<"Before Exclusive Locking "<<boost::this_thread::get_id()<<" "<<"secondFunction"<<std::endl;
boost::upgrade_to_unique_lock<boost::shared_mutex> localUniqueLock(upgr);
std::cout<<"After Exclusive Locking "<<boost::this_thread::get_id()<<" "<<"secondFunction"<<std::endl;
return(0);
}
int main() {
boostThreadLocksTest myObject;
boost::thread_group myThreadGroup;
myThreadGroup.create_thread(boost::bind(boostThreadLocksTest::firstFunction,&myObject));
myThreadGroup.create_thread(boost::bind(boostThreadLocksTest::firstFunction,&myObject));
myThreadGroup.create_thread(boost::bind(boostThreadLocksTest::firstFunction,&myObject));
myThreadGroup.join_all();
return 0;
}

50
test/test_4882.cpp Normal file
View File

@@ -0,0 +1,50 @@
#include <boost/thread/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <iostream>
boost::shared_mutex mutex;
void thread()
{
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
try
{
for (int i =0; i<10; ++i)
{
boost::system_time timeout = boost::get_system_time() + boost::posix_time::milliseconds(50);
if (mutex.timed_lock(timeout))
{
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
boost::this_thread::sleep(boost::posix_time::milliseconds(10));
mutex.unlock();
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
}
}
}
catch (boost::lock_error& le)
{
std::cerr << "lock_error exception\n";
}
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
}
int main()
{
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
const int nrThreads = 20;
boost::thread* threads[nrThreads];
for (int i = 0; i < nrThreads; ++i)
threads[i] = new boost::thread(&thread);
for (int i = 0; i < nrThreads; ++i)
{
threads[i]->join();
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
delete threads[i];
}
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
return 0;
}

45
test/test_5351.cpp Normal file
View File

@@ -0,0 +1,45 @@
#include <iostream>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/thread/future.hpp>
using namespace boost::posix_time;
using namespace boost;
int foo()
{
this_thread::sleep(seconds(10));
return 0;
}
int main(int argc, char** argv)
{
boost::packaged_task<int> pt(&foo);
boost::unique_future<int> fi = pt.get_future();
boost::thread task(boost::move(pt)); // launch task on a thread
task.interrupt();
try
{
int v = fi.get();
}
catch (boost::thread_interrupted& exc)
{
std::cout << "OK: " << std::endl;
return 0;
}
catch (boost::exception& exc)
{
std::cout << __LINE__ << " ERROR: " << boost::diagnostic_information(exc) << std::endl;
return 1;
}
catch (...)
{
std::cout << __LINE__ << " ERROR: " << std::endl;
return 2;
}
std::cout << __LINE__ << " ERROR: " << std::endl;
return 3;
}

86
test/test_5502.cpp Normal file
View File

@@ -0,0 +1,86 @@
// bm.cpp
// g++ test.cpp -lboost_thread-mt && ./a.out
// the ration of XXX and YYY determines
// if this works or deadlocks
int XXX = 20;
int YYY = 10;
#include <boost/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <unistd.h>
#include <iostream>
#include <boost/detail/lightweight_test.hpp>
using namespace std;
void sleepmillis(useconds_t miliis)
{
usleep(miliis * 1000);
}
void worker1(boost::shared_mutex * lk, int * x)
{
(*x)++; // 1
cout << "lock b try " << *x << endl;
while (1)
{
if (lk->timed_lock(boost::posix_time::milliseconds(XXX))) break;
sleepmillis(YYY);
}
cout << "lock b got " << *x << endl;
(*x)++; // 2
lk->unlock();
}
void worker2(boost::shared_mutex * lk, int * x)
{
cout << "lock c try" << endl;
lk->lock_shared();
(*x)++;
cout << "lock c got" << endl;
lk->unlock_shared();
cout << "lock c unlocked" << endl;
(*x)++;
}
int main()
{
// create
boost::shared_mutex* lk = new boost::shared_mutex();
// read lock
cout << "lock a" << endl;
lk->lock_shared();
int x1 = 0;
boost::thread t1(boost::bind(worker1, lk, &x1));
while (!x1)
;
BOOST_TEST(x1 == 1);
sleepmillis(500);
BOOST_TEST(x1 == 1);
int x2 = 0;
boost::thread t2(boost::bind(worker2, lk, &x2));
t2.join();
BOOST_TEST(x2 == 2);
lk->unlock_shared();
cout << "unlock a" << endl;
for (int i = 0; i < 2000; i++)
{
if (x1 == 2) break;
sleepmillis(10);
}
BOOST_TEST(x1 == 2);
t1.join();
delete lk;
return 0;
}

62
test/test_5542_1.cpp Normal file
View File

@@ -0,0 +1,62 @@
#include <iostream>
#include <boost/thread.hpp>
class Worker
{
public:
Worker()
{
// the thread is not-a-thread until we call start()
}
void start(int N)
{
std::cout << "start\n";
m_Thread = boost::thread(&Worker::processQueue, this, N);
std::cout << "started\n";
}
void join()
{
m_Thread.join();
}
void processQueue(unsigned N)
{
float ms = N * 1e3;
boost::posix_time::milliseconds workTime(ms);
std::cout << "Worker: started, will work for "
<< ms << "ms"
<< std::endl;
// We're busy, honest!
boost::this_thread::sleep(workTime);
std::cout << "Worker: completed" << std::endl;
}
private:
boost::thread m_Thread;
};
int main(int argc, char* argv[])
{
std::cout << "main: startup" << std::endl;
Worker worker;
std::cout << "main: create worker" << std::endl;
worker.start(3);
std::cout << "main: waiting for thread" << std::endl;
worker.join();
std::cout << "main: done" << std::endl;
return 0;
}

11
test/test_5542_2.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include <boost/thread.hpp>
void run_thread() {
return;
}
int main() {
boost::thread t(run_thread);
return 0;
}

30
test/test_5542_3.cpp Normal file
View File

@@ -0,0 +1,30 @@
#include <iostream>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
void workerFunc()
{
boost::posix_time::seconds workTime(3);
std::cout << "Worker: running" << std::endl;
// Pretend to do something useful...
boost::this_thread::sleep(workTime);
std::cout << "Worker: finished" << std::endl;
}
int main(int argc, char* argv[])
{
std::cout << "main: startup" << std::endl;
boost::thread workerThread(workerFunc);
std::cout << "main: waiting for thread" << std::endl;
workerThread.join();
std::cout << "main: done" << std::endl;
return 0;
}

22
test/test_6130.cpp Normal file
View File

@@ -0,0 +1,22 @@
#include <boost/thread.hpp>
#include <assert.h>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
boost::mutex mtx;
boost::condition_variable cv;
int main()
{
for (int i=0; i<3; ++i) {
const time_t wait_time = ::time(0)+1;
boost::mutex::scoped_lock lk(mtx);
const bool res = cv.timed_wait(lk, boost::posix_time::from_time_t(wait_time));
const time_t end_time = ::time(0);
assert(end_time >= wait_time);
std::cerr << end_time - wait_time << " OK\n";
}
return 0;
}

26
test/test_6170.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/locks.hpp>
// Including this will cause ambiguous errors in boost::move
#include <boost/unordered_map.hpp>
using namespace boost;
typedef upgrade_lock<shared_mutex> auto_upgrade_lock;
typedef upgrade_to_unique_lock<shared_mutex> auto_upgrade_unique_lock;
void testUpgrade(void)
{
shared_mutex mtx;
auto_upgrade_lock lock(mtx);
// Do some read-only stuff
auto_upgrade_unique_lock writeLock(lock);
// Do some write-only stuff with the upgraded lock
}
int main()
{
testUpgrade();
return 0;
}

35
test/test_6174.cpp Normal file
View File

@@ -0,0 +1,35 @@
#include <boost/thread.hpp>
#include <boost/config.hpp>
#ifndef BOOST_NO_RVALUE_REFERENCES
struct MovableButNonCopyable {
#ifndef BOOST_NO_DEFAULTED_FUNCTIONS
MovableButNonCopyable() = default;
MovableButNonCopyable(MovableButNonCopyable const&) = delete;
MovableButNonCopyable& operator=(MovableButNonCopyable const&) = delete;
MovableButNonCopyable(MovableButNonCopyable&&) = default;
MovableButNonCopyable& operator=(MovableButNonCopyable&&) = default;
#else
MovableButNonCopyable() {};
MovableButNonCopyable(MovableButNonCopyable&&) {};
MovableButNonCopyable& operator=(MovableButNonCopyable&&) {
return *this;
};
private:
MovableButNonCopyable(MovableButNonCopyable const&);
MovableButNonCopyable& operator=(MovableButNonCopyable const&);
#endif
};
int main()
{
boost::packaged_task<MovableButNonCopyable>(MovableButNonCopyable());
return 0;
}
#else
int main()
{
return 0;
}
#endif

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -4,7 +4,6 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/shared_mutex.hpp>
@@ -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::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,

View File

@@ -1,6 +1,6 @@
// 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 <boost/thread/thread.hpp>
#include <boost/test/unit_test.hpp>
@@ -89,10 +89,17 @@ namespace user_test_ns
}
bool move_called=false;
struct nc:
public boost::shared_ptr<int>
{
#ifndef BOOST_NO_RVALUE_REFERENCES
nc() {}
nc(nc&&)
{
move_called=true;
}
#endif
nc move()
{
move_called=true;
@@ -101,16 +108,30 @@ namespace user_test_ns
};
}
#ifdef BOOST_NO_RVALUE_REFERENCES
namespace boost
{
template <>
struct has_move_emulation_enabled_aux<user_test_ns::nc>
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
}
#endif
void test_move_for_user_defined_type_unaffected()
{
user_test_ns::nc src;
#ifndef BOOST_NO_RVALUE_REFERENCES
user_test_ns::nc dest=boost::move(src);
#else
user_test_ns::nc dest=move(src);
#endif
BOOST_CHECK(user_test_ns::move_called);
}
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_move_from_lvalue_on_construction));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));