2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-04 22:02:10 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Beman Dawes
ddb4981ce7 Release 1.43.0
[SVN r61817]
2010-05-06 13:21:09 +00:00
82 changed files with 779 additions and 2280 deletions

View File

@@ -43,7 +43,6 @@ project boost/thread
<link>shared:<define>BOOST_THREAD_BUILD_DLL=1
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@$(__name__).tag
<toolset>gcc:<cxxflags>-Wno-long-long
: default-build <threading>multi
;

View File

@@ -26,6 +26,11 @@ boostbook standalone
<xsl:param>generate.section.toc.level=10
# Path for links to Boost:
<xsl:param>boost.root=../../../..
# Path for libraries index:
<xsl:param>boost.libraries=../../../../libs/libraries.htm
# Use the main Boost stylesheet:
<xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
;

View File

@@ -5,45 +5,7 @@
http://www.boost.org/LICENSE_1_0.txt).
]
[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]
[section:changes 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.
@@ -123,22 +85,3 @@ 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]

View File

@@ -1,100 +0,0 @@
[/
(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 __promise__ shall be well-formed. Invoking a copy of
[[Preconditions:] [The expression `f(t)` where `t` is a lvalue of type __packaged_task__ 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,25 +310,6 @@ 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,5 +166,3 @@
[include time.qbk]
[include acknowledgements.qbk]
[include compliance.qbk]

View File

@@ -163,44 +163,6 @@ 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>
@@ -257,7 +219,6 @@ As the single way to interrupt a thread is through a __thread__ instance, `inter
};
void swap(thread& lhs,thread& rhs);
detail::thread_move_t<thread> move(detail::thread_move_t<thread> t);
[section:default_constructor Default Constructor]
@@ -273,40 +234,6 @@ As the single way to interrupt a thread is through a __thread__ instance, `inter
[endsect]
[section:move_constructor Move Constructor]
thread(detail::thread_move_t<thread> other);
[variablelist
[[Effects:] [Transfers ownership of the thread managed by `other` (if any) to the newly constructed __thread__ instance.]]
[[Postconditions:] [`other->get_id()==thread::id()`]]
[[Throws:] [Nothing]]
]
[endsect]
[section:move_assignment Move assignment operator]
thread& operator=(detail::thread_move_t<thread> other);
[variablelist
[[Effects:] [Transfers ownership of the thread managed by `other` (if
any) to `*this`. If there was a thread previously associated with
`*this` then that thread is detached.]]
[[Postconditions:] [`other->get_id()==thread::id()`]]
[[Throws:] [Nothing]]
]
[endsect]
[section:callable_constructor Thread Constructor]
template<typename Callable>
@@ -594,26 +521,6 @@ value as `this->get_id()` prior to the call.]]
[endsect]
[section:non_member_move Non-member function `move()`]
#include <boost/thread/thread.hpp>
detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
[variablelist
[[Returns:] [`t`.]]
]
Enables moving thread objects. e.g.
extern void some_func();
boost::thread t(some_func);
boost::thread t2(boost::move(t)); // transfer thread from t to t2
[endsect]
[section:id Class `boost::thread::id`]
@@ -713,7 +620,7 @@ execution.]]
[endsect]
[section:less_than_or_equal `operator<=`]
[section:less_than_or_equal `operator>=`]
bool operator<=(const id& y) const;
@@ -849,14 +756,11 @@ instances of __thread_id__ `a` and `b` is the same if `a==b`, and different if `
{
template<typename TimeDuration>
void sleep(TimeDuration const& rel_time);
void sleep(system_time const& abs_time)
}
[variablelist
[[Effects:] [Suspends the current thread until the time period
specified by `rel_time` has elapsed or the time point specified by
`abs_time` has been reached.]]
[[Effects:] [Suspends the current thread until the specified time has elapsed.]]
[[Throws:] [__thread_interrupted__ if the current thread of execution is interrupted.]]

View File

@@ -41,11 +41,6 @@ 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,15 +10,6 @@
#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
@@ -28,14 +19,8 @@
#include "platform.hpp"
// provided for backwards compatibility, since this
// macro was used for several releases by mistake.
#if defined(BOOST_THREAD_DYN_DLL)
# define BOOST_THREAD_DYN_LINK
#endif
// compatibility with the rest of Boost's auto-linking code:
#if defined(BOOST_THREAD_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
#if defined(BOOST_THREAD_DYN_DLL) || defined(BOOST_ALL_DYN_LINK)
# undef BOOST_THREAD_USE_LIB
# define BOOST_THREAD_USE_DLL
#endif
@@ -62,18 +47,12 @@
#if defined(BOOST_HAS_DECLSPEC)
# if defined(BOOST_THREAD_BUILD_DLL) //Build dll
# define BOOST_THREAD_DECL BOOST_SYMBOL_EXPORT
//# define BOOST_THREAD_DECL __declspec(dllexport)
# define BOOST_THREAD_DECL __declspec(dllexport)
# elif defined(BOOST_THREAD_USE_DLL) //Use dll
# define BOOST_THREAD_DECL BOOST_SYMBOL_IMPORT
//# define BOOST_THREAD_DECL __declspec(dllimport)
# 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
@@ -84,7 +63,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,20 +6,15 @@
#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>
@@ -46,19 +41,18 @@ namespace boost
#ifndef BOOST_NO_SFINAE
template<typename T>
typename enable_if<boost::is_convertible<T&,boost::detail::thread_move_t<T> >, boost::detail::thread_move_t<T> >::type move(T& t)
typename enable_if<boost::is_convertible<T&,detail::thread_move_t<T> >, detail::thread_move_t<T> >::type move(T& t)
{
return boost::detail::thread_move_t<T>(t);
return detail::thread_move_t<T>(t);
}
#endif
template<typename T>
boost::detail::thread_move_t<T> move(boost::detail::thread_move_t<T> t)
detail::thread_move_t<T> move(detail::thread_move_t<T> t)
{
return t;
}
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -29,7 +29,7 @@
# define BOOST_THREAD_HPUX
#elif defined(__CYGWIN__)
# define BOOST_THREAD_CYGWIN
#elif (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(BOOST_DISABLE_WIN32)
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
# define BOOST_THREAD_WIN32
#elif defined(__BEOS__)
# define BOOST_THREAD_BEOS

View File

@@ -3,12 +3,10 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-10 Anthony Williams
// (C) Copyright 2007-8 Anthony Williams
#include <boost/thread/exceptions.hpp>
#ifndef BOOST_NO_IOSTREAM
#include <ostream>
#endif
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/xtime.hpp>
@@ -24,7 +22,6 @@
#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>
@@ -56,7 +53,7 @@ namespace boost
thread_data(detail::thread_move_t<F> f_):
f(f_)
{}
#endif
#endif
void run()
{
f();
@@ -81,7 +78,7 @@ namespace boost
thread_data(boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
@@ -100,14 +97,14 @@ namespace boost
thread_data(const boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
}
};
}
class BOOST_THREAD_DECL thread
{
private:
@@ -115,14 +112,15 @@ namespace boost
thread& operator=(thread&);
void release_handle();
mutable boost::mutex thread_info_mutex;
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;
detail::thread_data_ptr get_thread_info() const;
#ifndef BOOST_NO_RVALUE_REFERENCES
template<typename F>
@@ -149,9 +147,9 @@ namespace boost
#endif
struct dummy;
public:
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
thread(const volatile thread&);
#endif
#ifdef __SUNPRO_CC
thread(const volatile thread&);
#endif
thread();
~thread();
@@ -159,7 +157,7 @@ namespace boost
#ifdef BOOST_MSVC
template <class F>
explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0):
thread_info(make_thread_info(static_cast<F&&>(f)))
thread_info(make_thread_info(f))
{
start_thread();
}
@@ -176,7 +174,7 @@ namespace boost
{
thread_info.swap(other.thread_info);
}
thread& operator=(thread&& other)
{
thread_info=other.thread_info;
@@ -188,7 +186,7 @@ namespace boost
{
return static_cast<thread&&>(*this);
}
#else
#ifdef BOOST_NO_SFINAE
template <class F>
@@ -205,7 +203,7 @@ namespace boost
start_thread();
}
#endif
template <class F>
explicit thread(detail::thread_move_t<F> f):
thread_info(make_thread_info(f))
@@ -218,13 +216,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;
}
#ifdef __SUNPRO_CC
thread& operator=(thread x)
{
swap(x);
return *this;
}
#else
thread& operator=(detail::thread_move_t<thread> x)
{
@@ -232,12 +230,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);
@@ -313,7 +311,7 @@ namespace boost
thread_info.swap(x.thread_info);
}
class BOOST_SYMBOL_VISIBLE id;
class id;
id get_id() const;
@@ -341,7 +339,7 @@ namespace boost
{
this_thread::yield();
}
static inline void sleep(const system_time& xt)
{
this_thread::sleep(xt);
@@ -356,7 +354,7 @@ namespace boost
{
return lhs.swap(rhs);
}
#ifndef BOOST_NO_RVALUE_REFERENCES
inline thread&& move(thread& t)
{
@@ -381,118 +379,82 @@ namespace boost
bool BOOST_THREAD_DECL interruption_enabled();
bool BOOST_THREAD_DECL interruption_requested();
inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time)
inline void sleep(xtime const& abs_time)
{
sleep(system_time(abs_time));
}
}
class BOOST_SYMBOL_VISIBLE thread::id
class thread::id
{
private:
detail::thread_data_ptr thread_data;
id(detail::thread_data_ptr thread_data_):
thread_data(thread_data_)
{}
friend class thread;
friend id BOOST_THREAD_DECL this_thread::get_id();
friend id this_thread::get_id();
public:
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);
}
#ifndef BOOST_NO_IOSTREAM
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
template<class charT, class traits>
friend BOOST_SYMBOL_VISIBLE
std::basic_ostream<charT, traits>&
friend std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
{
if(x.thread_data)
{
io::ios_flags_saver ifs( os );
return os<< std::hex << x.thread_data;
return os<<x.thread_data;
}
else
{
return os<<"{Not-any-thread}";
}
}
#else
template<class charT, class traits>
BOOST_SYMBOL_VISIBLE
std::basic_ostream<charT, traits>&
print(std::basic_ostream<charT, traits>& os) const
{
if(thread_data)
{
return os<<thread_data;
}
else
{
return os<<"{Not-any-thread}";
}
}
#endif
#endif
};
#if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<class charT, class traits>
BOOST_SYMBOL_VISIBLE
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x)
{
return x.print(os);
}
#endif
inline bool thread::operator==(const thread& other) const
{
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
@@ -501,33 +463,26 @@ 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

@@ -18,13 +18,10 @@
namespace boost
{
class thread_group
class thread_group:
private noncopyable
{
private:
thread_group(thread_group const&);
thread_group& operator=(thread_group const&);
public:
thread_group() {}
~thread_group()
{
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();

View File

@@ -12,9 +12,27 @@
#if defined(BOOST_HAS_WINTHREADS)
namespace boost
{
BOOST_THREAD_DECL void __cdecl on_process_enter(void);
typedef void (__cdecl *thread_exit_handler)(void);
extern "C" BOOST_THREAD_DECL int at_thread_exit(
thread_exit_handler exit_handler
);
//Add a function to the list of functions that will
//be called when a thread is about to exit.
//Currently only implemented for Win32, but should
//later be implemented for all platforms.
//Used by Win32 implementation of Boost.Threads
//tss to perform cleanup.
//Like the C runtime library atexit() function,
//which it mimics, at_thread_exit() returns
//zero if successful and a nonzero
//value if an error occurs.
#endif //defined(BOOST_HAS_WINTHREADS)
#if defined(BOOST_HAS_WINTHREADS)
extern "C" BOOST_THREAD_DECL void on_process_enter(void);
//Function to be called when the exe or dll
//that uses Boost.Threads first starts
//or is first loaded.
@@ -24,7 +42,7 @@ namespace boost
//a method for doing so has been discovered.
//May be omitted; may be called multiple times.
BOOST_THREAD_DECL void __cdecl on_process_exit(void);
extern "C" BOOST_THREAD_DECL void on_process_exit(void);
//Function to be called when the exe or dll
//that uses Boost.Threads first starts
//or is first loaded.
@@ -34,7 +52,7 @@ namespace boost
//a method for doing so has been discovered.
//Must not be omitted; may be called multiple times.
BOOST_THREAD_DECL void __cdecl on_thread_enter(void);
extern "C" BOOST_THREAD_DECL void on_thread_enter(void);
//Function to be called just after a thread starts
//in an exe or dll that uses Boost.Threads.
//Must be called in the context of the thread
@@ -43,7 +61,7 @@ namespace boost
//a method for doing so has been discovered.
//May be omitted; may be called multiple times.
BOOST_THREAD_DECL void __cdecl on_thread_exit(void);
extern "C" BOOST_THREAD_DECL void __cdecl on_thread_exit(void);
//Function to be called just be fore a thread ends
//in an exe or dll that uses Boost.Threads.
//Must be called in the context of the thread
@@ -52,11 +70,10 @@ namespace boost
//a method for doing so has been discovered.
//Must not be omitted; may be called multiple times.
void tss_cleanup_implemented();
extern "C" void tss_cleanup_implemented(void);
//Dummy function used both to detect whether tss cleanup
//cleanup has been implemented and to force
//it to be linked into the Boost.Threads library.
}
#endif //defined(BOOST_HAS_WINTHREADS)

View File

@@ -24,10 +24,10 @@
namespace boost
{
class BOOST_SYMBOL_VISIBLE thread_interrupted
class thread_interrupted
{};
class BOOST_SYMBOL_VISIBLE thread_exception:
class thread_exception:
public std::exception
{
protected:
@@ -55,7 +55,7 @@ namespace boost
int m_sys_err;
};
class BOOST_SYMBOL_VISIBLE condition_error:
class condition_error:
public std::exception
{
public:
@@ -66,7 +66,7 @@ namespace boost
};
class BOOST_SYMBOL_VISIBLE lock_error:
class lock_error:
public thread_exception
{
public:
@@ -87,7 +87,7 @@ namespace boost
}
};
class BOOST_SYMBOL_VISIBLE thread_resource_error:
class thread_resource_error:
public thread_exception
{
public:
@@ -109,7 +109,7 @@ namespace boost
};
class BOOST_SYMBOL_VISIBLE unsupported_thread_option:
class unsupported_thread_option:
public thread_exception
{
public:
@@ -131,7 +131,7 @@ namespace boost
};
class BOOST_SYMBOL_VISIBLE invalid_thread_argument:
class invalid_thread_argument:
public thread_exception
{
public:
@@ -153,7 +153,7 @@ namespace boost
};
class BOOST_SYMBOL_VISIBLE thread_permission_error:
class 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
@@ -9,8 +9,6 @@
#include <stdexcept>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
@@ -111,7 +109,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 +130,7 @@ namespace boost
struct relocker
{
boost::unique_lock<boost::mutex>& lock;
relocker(boost::unique_lock<boost::mutex>& lock_):
lock(lock_)
{
@@ -142,8 +140,6 @@ namespace boost
{
lock.lock();
}
private:
relocker& operator=(relocker const&);
};
void do_callback(boost::unique_lock<boost::mutex>& lock)
@@ -155,7 +151,7 @@ namespace boost
local_callback();
}
}
void wait(bool rethrow=true)
{
@@ -185,7 +181,7 @@ namespace boost
}
return true;
}
void mark_exceptional_finish_internal(boost::exception_ptr const& e)
{
exception=e;
@@ -213,7 +209,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 +234,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 +245,7 @@ namespace boost
storage.reset();
}
};
template<typename T>
struct future_traits<T&>
{
@@ -296,7 +292,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,8 +349,6 @@ namespace boost
struct future_object<void>:
detail::future_object_base
{
typedef void move_dest_type;
future_object()
{}
@@ -373,7 +367,7 @@ namespace boost
{
wait();
}
future_state::state get_state()
{
boost::lock_guard<boost::mutex> guard(mutex);
@@ -394,70 +388,58 @@ namespace boost
class future_waiter
{
struct registered_waiter;
typedef std::vector<registered_waiter>::size_type count_type;
struct registered_waiter
{
boost::shared_ptr<detail::future_object_base> future;
detail::future_object_base::waiter_list::iterator wait_iterator;
count_type index;
unsigned index;
registered_waiter(boost::shared_ptr<detail::future_object_base> const& future_,
detail::future_object_base::waiter_list::iterator wait_iterator_,
count_type index_):
unsigned index_):
future(future_),wait_iterator(wait_iterator_),index(index_)
{}
};
struct all_futures_lock
{
#ifdef _MANAGED
typedef std::ptrdiff_t count_type_portable;
#else
typedef count_type count_type_portable;
#endif
count_type_portable count;
typedef std::vector<registered_waiter>::size_type count_type;
count_type 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_portable i=0;i<count;++i)
for(count_type 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_portable i=0;i<count;++i)
for(unsigned i=0;i<count;++i)
{
locks[i].unlock();
}
}
};
boost::condition_variable_any cv;
std::vector<registered_waiter> futures;
count_type future_count;
unsigned future_count;
public:
future_waiter():
future_count(0)
{}
template<typename F>
void add(F& f)
{
@@ -468,12 +450,12 @@ namespace boost
++future_count;
}
count_type wait()
unsigned wait()
{
all_futures_lock lk(futures);
for(;;)
{
for(count_type i=0;i<futures.size();++i)
for(unsigned i=0;i<futures.size();++i)
{
if(futures[i].future->done)
{
@@ -483,17 +465,17 @@ namespace boost
cv.wait(lk);
}
}
~future_waiter()
{
for(count_type i=0;i<futures.size();++i)
for(unsigned i=0;i<futures.size();++i)
{
futures[i].future->remove_external_waiter(futures[i].wait_iterator);
}
}
};
}
template <typename R>
@@ -507,13 +489,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> >
{
@@ -543,7 +525,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)
{
@@ -566,9 +548,6 @@ namespace boost
template<typename Iterator>
typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
{
if(begin==end)
return end;
detail::future_waiter waiter;
for(Iterator current=begin;current!=end;++current)
{
@@ -595,7 +574,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)
{
@@ -618,7 +597,7 @@ namespace boost
waiter.add(f5);
return waiter.wait();
}
template <typename R>
class promise;
@@ -632,7 +611,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>;
@@ -651,7 +630,7 @@ namespace boost
unique_future()
{}
~unique_future()
{}
@@ -701,7 +680,7 @@ namespace boost
return future->get();
}
// functions to check state, and wait for ready
state get_state() const
{
@@ -711,23 +690,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)
@@ -736,13 +715,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)
@@ -751,21 +730,14 @@ 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);
@@ -774,7 +746,7 @@ namespace boost
friend class detail::future_waiter;
friend class promise<R>;
friend class packaged_task<R>;
shared_future(future_ptr future_):
future(future_)
{}
@@ -818,7 +790,7 @@ namespace boost
other.future.reset();
return *this;
}
#else
#else
shared_future(boost::detail::thread_move_t<shared_future> other):
future(other->future)
{
@@ -856,7 +828,6 @@ namespace boost
}
// retrieving the value
//typename detail::future_object<R>::move_dest_type get()
R get()
{
if(!future)
@@ -866,7 +837,7 @@ namespace boost
return future->get();
}
// functions to check state, and wait for ready
state get_state() const
{
@@ -876,18 +847,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();
@@ -901,13 +872,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)
@@ -916,43 +887,36 @@ 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;
void lazy_init()
{
if(!atomic_load(&future))
if(!future)
{
future_ptr blank;
atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<R>));
future_obtained=false;
future.reset(new detail::future_object<R>);
}
}
public:
// template <class Allocator> explicit promise(Allocator a);
promise():
future(),future_obtained(false)
{}
~promise()
{
if(future)
@@ -972,14 +936,12 @@ namespace boost
future_obtained(rhs.future_obtained)
{
future.swap(rhs.future);
rhs.future_obtained=false;
}
promise & operator=(promise&& rhs)
{
future.swap(rhs.future);
future_obtained=rhs.future_obtained;
rhs.future.reset();
rhs.future_obtained=false;
return *this;
}
#else
@@ -987,14 +949,12 @@ namespace boost
future(rhs->future),future_obtained(rhs->future_obtained)
{
rhs->future.reset();
rhs->future_obtained=false;
}
promise & operator=(boost::detail::thread_move_t<promise> rhs)
{
future=rhs->future;
future_obtained=rhs->future_obtained;
rhs->future.reset();
rhs->future_obtained=false;
return *this;
}
@@ -1002,8 +962,8 @@ namespace boost
{
return boost::detail::thread_move_t<promise>(*this);
}
#endif
#endif
void swap(promise& other)
{
future.swap(other.future);
@@ -1062,26 +1022,26 @@ 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;
void lazy_init()
{
if(!atomic_load(&future))
if(!future)
{
future_ptr blank;
atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<void>));
future_obtained=false;
future.reset(new detail::future_object<void>);
}
}
public:
@@ -1090,7 +1050,7 @@ namespace boost
promise():
future(),future_obtained(false)
{}
~promise()
{
if(future)
@@ -1110,14 +1070,12 @@ namespace boost
future_obtained(rhs.future_obtained)
{
future.swap(rhs.future);
rhs.future_obtained=false;
}
promise & operator=(promise&& rhs)
{
future.swap(rhs.future);
future_obtained=rhs.future_obtained;
rhs.future.reset();
rhs.future_obtained=false;
return *this;
}
#else
@@ -1125,14 +1083,12 @@ namespace boost
future(rhs->future),future_obtained(rhs->future_obtained)
{
rhs->future.reset();
rhs->future_obtained=false;
}
promise & operator=(boost::detail::thread_move_t<promise> rhs)
{
future=rhs->future;
future_obtained=rhs->future_obtained;
rhs->future.reset();
rhs->future_obtained=false;
return *this;
}
@@ -1141,7 +1097,7 @@ namespace boost
return boost::detail::thread_move_t<promise>(*this);
}
#endif
void swap(promise& other)
{
future.swap(other.future);
@@ -1152,7 +1108,7 @@ namespace boost
unique_future<void> get_future()
{
lazy_init();
if(future_obtained)
{
boost::throw_exception(future_already_retrieved());
@@ -1189,16 +1145,9 @@ 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>
@@ -1233,12 +1182,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>
@@ -1247,16 +1196,10 @@ 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
@@ -1278,16 +1221,10 @@ 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
@@ -1303,7 +1240,7 @@ namespace boost
};
}
template<typename R>
class packaged_task
@@ -1313,12 +1250,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):
@@ -1327,18 +1264,11 @@ 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);
@@ -1387,7 +1317,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);
@@ -1410,7 +1340,7 @@ namespace boost
boost::throw_exception(future_already_retrieved());
}
}
// execution
void operator()()
@@ -1427,16 +1357,9 @@ 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

@@ -11,7 +11,6 @@
#include <iterator>
#include <boost/thread/thread_time.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -28,118 +27,56 @@ namespace boost
#ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
namespace detail
{
#define BOOST_DEFINE_HAS_MEMBER_CALLED(member_name) \
template<typename T, bool=boost::is_class<T>::value> \
struct has_member_called_##member_name \
{ \
BOOST_STATIC_CONSTANT(bool, value=false); \
}; \
\
template<typename T> \
struct has_member_called_##member_name<T,true> \
{ \
typedef char true_type; \
struct false_type \
{ \
true_type dummy[2]; \
}; \
\
struct fallback { int member_name; }; \
struct derived: \
T, fallback \
{ \
derived(); \
}; \
\
template<int fallback::*> struct tester; \
\
template<typename U> \
static false_type has_member(tester<&U::member_name>*); \
template<typename U> \
static true_type has_member(...); \
\
BOOST_STATIC_CONSTANT( \
bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \
}
BOOST_DEFINE_HAS_MEMBER_CALLED(lock);
BOOST_DEFINE_HAS_MEMBER_CALLED(unlock);
BOOST_DEFINE_HAS_MEMBER_CALLED(try_lock);
template<typename T,bool=has_member_called_lock<T>::value >
template<typename T>
struct has_member_lock
{
BOOST_STATIC_CONSTANT(bool, value=false);
};
template<typename T>
struct has_member_lock<T,true>
{
typedef char true_type;
struct false_type
{
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));
static true_type has_member(U*,void (U::*dummy)()=&U::lock);
static false_type has_member(void*);
BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_lock<T>::has_member((T*)NULL))==sizeof(true_type));
};
template<typename T,bool=has_member_called_unlock<T>::value >
template<typename T>
struct has_member_unlock
{
BOOST_STATIC_CONSTANT(bool, value=false);
};
template<typename T>
struct has_member_unlock<T,true>
{
typedef char true_type;
struct false_type
{
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));
static true_type has_member(U*,void (U::*dummy)()=&U::unlock);
static false_type has_member(void*);
BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_unlock<T>::has_member((T*)NULL))==sizeof(true_type));
};
template<typename T,bool=has_member_called_try_lock<T>::value >
template<typename T>
struct has_member_try_lock
{
BOOST_STATIC_CONSTANT(bool, value=false);
};
template<typename T>
struct has_member_try_lock<T,true>
{
typedef char true_type;
struct false_type
{
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));
static true_type has_member(U*,bool (U::*dummy)()=&U::try_lock);
static false_type has_member(void*);
BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_try_lock<T>::has_member((T*)NULL))==sizeof(true_type));
};
}
template<typename T>
struct is_mutex_type
@@ -147,7 +84,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 +92,7 @@ namespace boost
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
#endif
#endif
struct defer_lock_t
{};
@@ -163,7 +100,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 +119,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 +138,7 @@ namespace boost
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template<typename T>
struct is_mutex_type<detail::try_lock_wrapper<T> >
{
@@ -213,7 +150,7 @@ namespace boost
class recursive_mutex;
class recursive_timed_mutex;
class shared_mutex;
template<>
struct is_mutex_type<mutex>
{
@@ -277,13 +214,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&);
#ifdef __SUNPRO_CC
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 +300,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;
}
#ifdef __SUNPRO_CC
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 +332,7 @@ namespace boost
std::swap(m,other.m);
std::swap(is_locked,other.is_locked);
}
~unique_lock()
{
if(owns_lock())
@@ -427,7 +364,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 +384,7 @@ namespace boost
m->unlock();
is_locked=false;
}
typedef void (unique_lock::*bool_type)();
operator bool_type() const
{
@@ -485,18 +422,6 @@ namespace boost
{
lhs.swap(rhs);
}
template<typename Mutex>
inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>&& ul)
{
return static_cast<upgrade_lock<Mutex>&&>(ul);
}
template<typename Mutex>
inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>& ul)
{
return static_cast<upgrade_lock<Mutex>&&>(ul);
}
#endif
template<typename Mutex>
void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs)
@@ -518,13 +443,6 @@ 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
{
@@ -538,7 +456,7 @@ namespace boost
shared_lock():
m(0),is_locked(false)
{}
explicit shared_lock(Mutex& m_):
m(&m_),is_locked(false)
{
@@ -560,9 +478,7 @@ 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)
{
@@ -623,7 +539,6 @@ namespace boost
swap(temp);
return *this;
}
#endif
#ifndef BOOST_NO_RVALUE_REFERENCES
void swap(shared_lock&& other)
@@ -648,7 +563,7 @@ namespace boost
{
return m;
}
~shared_lock()
{
if(owns_lock())
@@ -702,7 +617,7 @@ namespace boost
m->unlock_shared();
is_locked=false;
}
typedef void (shared_lock<Mutex>::*bool_type)();
operator bool_type() const
{
@@ -719,25 +634,12 @@ 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)
@@ -759,7 +661,7 @@ namespace boost
upgrade_lock():
m(0),is_locked(false)
{}
explicit upgrade_lock(Mutex& m_):
m(&m_),is_locked(false)
{
@@ -776,39 +678,6 @@ namespace boost
{
try_lock();
}
#ifndef BOOST_NO_RVALUE_REFERENCES
upgrade_lock(upgrade_lock<Mutex>&& other):
m(other.m),is_locked(other.is_locked)
{
other.is_locked=false;
other.m=0;
}
upgrade_lock(unique_lock<Mutex>&& other):
m(other.m),is_locked(other.is_locked)
{
if(is_locked)
{
m->unlock_and_lock_upgrade();
}
other.is_locked=false;
other.m=0;
}
upgrade_lock& operator=(upgrade_lock<Mutex>&& other)
{
upgrade_lock temp(static_cast<upgrade_lock<Mutex>&&>(other));
swap(temp);
return *this;
}
upgrade_lock& operator=(unique_lock<Mutex>&& other)
{
upgrade_lock temp(static_cast<unique_lock<Mutex>&&>(other));
swap(temp);
return *this;
}
#else
upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
@@ -851,14 +720,13 @@ namespace boost
swap(temp);
return *this;
}
#endif
void swap(upgrade_lock& other)
{
std::swap(m,other.m);
std::swap(is_locked,other.is_locked);
}
~upgrade_lock()
{
if(owns_lock())
@@ -893,7 +761,7 @@ namespace boost
m->unlock_upgrade();
is_locked=false;
}
typedef void (upgrade_lock::*bool_type)();
operator bool_type() const
{
@@ -911,12 +779,6 @@ 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>
@@ -962,33 +824,18 @@ namespace boost
}
}
#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);
swap(temp);
return *this;
}
#else
upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other):
source(other->source),exclusive(move(other->exclusive))
{
other->source=0;
}
upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other)
{
upgrade_to_unique_lock temp(other);
swap(temp);
return *this;
}
#endif
void swap(upgrade_to_unique_lock& other)
{
std::swap(source,other.source);
@@ -1009,13 +856,6 @@ 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>
@@ -1026,7 +866,7 @@ namespace boost
public:
try_lock_wrapper()
{}
explicit try_lock_wrapper(Mutex& m):
base(m,try_to_lock)
{}
@@ -1083,15 +923,15 @@ namespace boost
return *this;
}
void swap(try_lock_wrapper& other)
{
base::swap(other);
}
void swap(detail::thread_move_t<try_lock_wrapper<Mutex> > other)
{
base::swap(*other);
}
#endif
void swap(try_lock_wrapper& other)
{
base::swap(other);
}
void lock()
{
base::lock();
@@ -1134,11 +974,6 @@ 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)
@@ -1146,7 +981,7 @@ namespace boost
lhs.swap(rhs);
}
#endif
template<typename MutexType1,typename MutexType2>
unsigned try_lock_internal(MutexType1& m1,MutexType2& m2)
{
@@ -1275,13 +1110,13 @@ 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>)
{
unsigned const lock_count=2;
unsigned lock_first=0;
for(;;)
while(true)
{
switch(lock_first)
{
@@ -1303,7 +1138,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)
@@ -1334,7 +1169,7 @@ namespace boost
{
unsigned const lock_count=3;
unsigned lock_first=0;
for(;;)
while(true)
{
switch(lock_first)
{
@@ -1366,7 +1201,7 @@ namespace boost
{
unsigned const lock_count=4;
unsigned lock_first=0;
for(;;)
while(true)
{
switch(lock_first)
{
@@ -1404,7 +1239,7 @@ namespace boost
{
unsigned const lock_count=5;
unsigned lock_first=0;
for(;;)
while(true)
{
switch(lock_first)
{
@@ -1448,7 +1283,7 @@ namespace boost
{
typedef int type;
};
template<typename Iterator>
struct try_lock_impl_return<Iterator,false>
{
@@ -1464,7 +1299,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)
{
@@ -1506,7 +1341,7 @@ namespace boost
{
return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1;
}
namespace detail
{
@@ -1515,13 +1350,13 @@ namespace boost
{
Iterator begin;
Iterator end;
range_lock_guard(Iterator begin_,Iterator end_):
begin(begin_),end(end_)
{
boost::lock(begin,end);
lock(begin,end);
}
void release()
{
begin=end;
@@ -1546,21 +1381,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=boost::try_lock(++begin,end);
Iterator const failed=try_lock(++begin,end);
if(failed==end)
{
guard.release();
}
return failed;
}
}
namespace detail
{
@@ -1568,7 +1403,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;
@@ -1577,14 +1412,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=boost::try_lock(next,end);
Iterator const failed_lock=try_lock(next,end);
if(failed_lock==end)
{
begin_lock.release();
@@ -1598,7 +1433,7 @@ namespace boost
detail::range_lock_guard<Iterator> guard(next,end);
if(begin_lock.try_lock())
{
Iterator const failed_lock=boost::try_lock(second,next);
Iterator const failed_lock=try_lock(second,next);
if(failed_lock==next)
{
begin_lock.release();
@@ -1616,9 +1451,9 @@ namespace boost
}
}
}
}
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -3,107 +3,53 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-10 Anthony Williams
// (C) Copyright 2007-8 Anthony Williams
#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 "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#include "thread_data.hpp"
#include "condition_variable_fwd.hpp"
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace this_thread
{
void BOOST_THREAD_DECL interruption_point();
}
namespace thread_cv_detail
{
template<typename MutexType>
struct lock_on_exit
{
MutexType* m;
lock_on_exit():
m(0)
{}
void activate(MutexType& m_)
{
m_.unlock();
m=&m_;
}
~lock_on_exit()
{
if(m)
{
m->lock();
}
}
};
}
inline void condition_variable::wait(unique_lock<mutex>& m)
{
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());
}
detail::interruption_checker check_for_interruption(&cond);
BOOST_VERIFY(!pthread_cond_wait(&cond,m.mutex()->native_handle()));
}
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;
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();
detail::interruption_checker check_for_interruption(&cond);
struct timespec const timeout=detail::get_timespec(wait_until);
int const cond_res=pthread_cond_timedwait(&cond,m.mutex()->native_handle(),&timeout);
if(cond_res==ETIMEDOUT)
{
return false;
}
if(cond_res)
{
boost::throw_exception(condition_error());
}
BOOST_ASSERT(!cond_res);
return true;
}
inline void condition_variable::notify_one()
{
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;
pthread_cond_t cond;
condition_variable_any(condition_variable_any&);
condition_variable_any& operator=(condition_variable_any&);
condition_variable_any(condition_variable&);
condition_variable_any& operator=(condition_variable&);
public:
condition_variable_any()
@@ -125,18 +71,20 @@ namespace boost
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
BOOST_VERIFY(!pthread_cond_destroy(&cond));
}
template<typename lock_type>
void wait(lock_type& m)
{
int res=0;
{
thread_cv_detail::lock_on_exit<lock_type> guard;
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
res=pthread_cond_wait(&cond,&internal_mutex);
detail::interruption_checker check_for_interruption(&cond);
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
m.unlock();
res=pthread_cond_wait(&cond,&internal_mutex);
}
m.lock();
}
this_thread::interruption_point();
if(res)
{
boost::throw_exception(condition_error());
@@ -148,19 +96,21 @@ namespace boost
{
while(!pred()) wait(m);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{
struct timespec const timeout=detail::get_timespec(wait_until);
int res=0;
{
thread_cv_detail::lock_on_exit<lock_type> guard;
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
detail::interruption_checker check_for_interruption(&cond);
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
m.unlock();
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
}
m.lock();
}
this_thread::interruption_point();
if(res==ETIMEDOUT)
{
return false;
@@ -211,7 +161,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

@@ -20,35 +20,23 @@ namespace boost
class condition_variable
{
private:
pthread_mutex_t internal_mutex;
pthread_cond_t cond;
condition_variable(condition_variable&);
condition_variable& operator=(condition_variable&);
public:
condition_variable()
{
int const res=pthread_mutex_init(&internal_mutex,NULL);
int const res=pthread_cond_init(&cond,NULL);
if(res)
{
boost::throw_exception(thread_resource_error());
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
boost::throw_exception(thread_resource_error());
}
}
~condition_variable()
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
int ret;
do {
ret = pthread_cond_destroy(&cond);
} while (ret == EINTR);
BOOST_VERIFY(!ret);
BOOST_VERIFY(!pthread_cond_destroy(&cond));
}
void wait(unique_lock<mutex>& m);
@@ -59,8 +47,7 @@ namespace boost
while(!pred()) wait(m);
}
inline bool timed_wait(unique_lock<mutex>& m,
boost::system_time const& wait_until);
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until);
bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until)
{
return timed_wait(m,system_time(wait_until));

View File

@@ -14,11 +14,11 @@
#include <boost/thread/xtime.hpp>
#include <boost/assert.hpp>
#include <errno.h>
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0 && _POSIX_C_SOURCE>=200112L
#if _POSIX_TIMEOUTS >= 0
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
@@ -27,11 +27,10 @@
namespace boost
{
class mutex
class mutex:
boost::noncopyable
{
private:
mutex(mutex const&);
mutex& operator=(mutex const&);
pthread_mutex_t m;
public:
mutex()
@@ -44,48 +43,23 @@ namespace boost
}
~mutex()
{
int ret;
do
{
ret = pthread_mutex_destroy(&m);
} while (ret == EINTR);
BOOST_VERIFY(!pthread_mutex_destroy(&m));
}
void lock()
{
int res;
do
{
res = pthread_mutex_lock(&m);
} while (res == EINTR);
if(res)
{
boost::throw_exception(lock_error(res));
}
BOOST_VERIFY(!pthread_mutex_lock(&m));
}
void unlock()
{
int ret;
do
{
ret = pthread_mutex_unlock(&m);
} while (ret == EINTR);
BOOST_VERIFY(!ret);
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int res;
do
{
res = pthread_mutex_trylock(&m);
} while (res == EINTR);
if(res && (res!=EBUSY))
{
boost::throw_exception(lock_error(res));
}
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
@@ -101,11 +75,9 @@ namespace boost
typedef mutex try_mutex;
class timed_mutex
class timed_mutex:
boost::noncopyable
{
private:
timed_mutex(timed_mutex const&);
timed_mutex& operator=(timed_mutex const&);
private:
pthread_mutex_t m;
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
@@ -158,7 +130,7 @@ namespace boost
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
@@ -196,7 +168,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,6 +14,7 @@
#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>
@@ -34,7 +35,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}
@@ -48,7 +49,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

@@ -18,25 +18,15 @@ namespace boost
class pthread_mutex_scoped_lock
{
pthread_mutex_t* m;
bool locked;
public:
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
m(m_),locked(true)
m(m_)
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
void unlock()
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
locked=false;
}
~pthread_mutex_scoped_lock()
{
if(locked)
{
unlock();
}
BOOST_VERIFY(!pthread_mutex_unlock(m));
}
};

View File

@@ -17,8 +17,8 @@
#endif
#include <boost/date_time/posix_time/conversion.hpp>
#include <errno.h>
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0
@@ -26,32 +26,20 @@
#endif
#endif
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK)
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class recursive_mutex
class recursive_mutex:
boost::noncopyable
{
private:
recursive_mutex(recursive_mutex const&);
recursive_mutex& operator=(recursive_mutex const&);
pthread_mutex_t m;
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_cond_t cond;
bool is_locked;
pthread_t owner;
unsigned count;
#endif
public:
recursive_mutex()
{
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_mutexattr_t attr;
int const init_attr_res=pthread_mutexattr_init(&attr);
if(init_attr_res)
{
@@ -60,42 +48,21 @@ namespace boost
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
if(set_attr_res)
{
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
boost::throw_exception(thread_resource_error());
}
int const res=pthread_mutex_init(&m,&attr);
if(res)
{
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
boost::throw_exception(thread_resource_error());
}
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
#else
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
boost::throw_exception(thread_resource_error());
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
boost::throw_exception(thread_resource_error());
}
is_locked=false;
count=0;
#endif
}
~recursive_mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
@@ -105,77 +72,32 @@ namespace boost
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
#else
void lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && pthread_equal(owner,pthread_self()))
{
++count;
return;
}
while(is_locked)
{
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
}
is_locked=true;
++count;
owner=pthread_self();
}
void unlock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(!--count)
{
is_locked=false;
}
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
bool try_lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && !pthread_equal(owner,pthread_self()))
{
return false;
}
is_locked=true;
++count;
owner=pthread_self();
return true;
}
#endif
typedef unique_lock<recursive_mutex> scoped_lock;
typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
};
typedef recursive_mutex recursive_try_mutex;
class recursive_timed_mutex
class recursive_timed_mutex:
boost::noncopyable
{
private:
recursive_timed_mutex(recursive_timed_mutex const&);
recursive_timed_mutex& operator=(recursive_timed_mutex const&);
private:
pthread_mutex_t m;
#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
pthread_cond_t cond;
bool is_locked;
pthread_t owner;
@@ -184,9 +106,9 @@ namespace boost
public:
recursive_timed_mutex()
{
#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
pthread_mutexattr_t attr;
int const init_attr_res=pthread_mutexattr_init(&attr);
if(init_attr_res)
{
@@ -197,7 +119,7 @@ namespace boost
{
boost::throw_exception(thread_resource_error());
}
int const res=pthread_mutex_init(&m,&attr);
if(res)
{
@@ -224,7 +146,7 @@ namespace boost
~recursive_timed_mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
@@ -235,7 +157,7 @@ namespace boost
return timed_lock(get_system_time()+relative_time);
}
#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
@@ -245,7 +167,7 @@ namespace boost
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
@@ -275,7 +197,7 @@ namespace boost
++count;
return;
}
while(is_locked)
{
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
@@ -294,7 +216,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;
release_waiters();
exclusive_cond.notify_one();
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()
@@ -225,7 +225,7 @@ namespace boost
template<typename TimeDuration>
bool timed_lock_upgrade(TimeDuration const & relative_time)
{
return timed_lock_upgrade(get_system_time()+relative_time);
return timed_lock(get_system_time()+relative_time);
}
bool try_lock_upgrade()
@@ -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

@@ -12,8 +12,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/optional.hpp>
#include <pthread.h>
#include <boost/assert.hpp>
#include <boost/thread/pthread/condition_variable_fwd.hpp>
#include "condition_variable_fwd.hpp"
#include <map>
#include <boost/config/abi_prefix.hpp>
@@ -21,7 +20,7 @@
namespace boost
{
class thread;
namespace detail
{
struct tss_cleanup_function;
@@ -39,7 +38,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>
{
@@ -56,7 +55,6 @@ namespace boost
std::map<void const*,boost::detail::tss_data_node> tss_data;
bool interrupt_enabled;
bool interrupt_requested;
pthread_mutex_t* cond_mutex;
pthread_cond_t* current_cond;
thread_data_base():
@@ -78,8 +76,6 @@ namespace boost
class interruption_checker
{
thread_data_base* const thread_info;
pthread_mutex_t* m;
bool set;
void check_for_interruption()
{
@@ -89,38 +85,26 @@ namespace boost
throw thread_interrupted();
}
}
void operator=(interruption_checker&);
public:
explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond):
thread_info(detail::get_current_thread_data()),m(cond_mutex),
set(thread_info && thread_info->interrupt_enabled)
explicit interruption_checker(pthread_cond_t* cond):
thread_info(detail::get_current_thread_data())
{
if(set)
if(thread_info && thread_info->interrupt_enabled)
{
lock_guard<mutex> guard(thread_info->data_mutex);
check_for_interruption();
thread_info->cond_mutex=cond_mutex;
thread_info->current_cond=cond;
BOOST_VERIFY(!pthread_mutex_lock(m));
}
else
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
}
~interruption_checker()
{
if(set)
if(thread_info && thread_info->interrupt_enabled)
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
lock_guard<mutex> guard(thread_info->data_mutex);
thread_info->cond_mutex=NULL;
thread_info->current_cond=NULL;
}
else
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
check_for_interruption();
}
}
};
@@ -129,26 +113,14 @@ namespace boost
namespace this_thread
{
void BOOST_THREAD_DECL yield();
#ifdef __DECXXX
/// Workaround of DECCXX issue of incorrect template substitution
void BOOST_THREAD_DECL sleep(system_time const& abs_time);
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

@@ -6,7 +6,6 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/date_time/time_clock.hpp>
#include <boost/date_time/microsec_time_clock.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
@@ -18,11 +17,7 @@ namespace boost
inline system_time get_system_time()
{
#if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
return boost::date_time::microsec_clock<system_time>::universal_time();
#else // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
return boost::date_time::second_clock<system_time>::universal_time();
#endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
}
namespace detail

View File

@@ -62,8 +62,6 @@ namespace boost
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
public:
typedef T element_type;
thread_specific_ptr():
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
{}

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 <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/basic_timed_mutex.hpp>
#include "thread_primitives.hpp"
#include "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 <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include "thread_primitives.hpp"
#include "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 <boost/thread/win32/thread_primitives.hpp>
#include "thread_primitives.hpp"
#include <limits.h>
#include <boost/assert.hpp>
#include <algorithm>
#include <boost/thread/thread.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include "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 <boost/thread/win32/basic_timed_mutex.hpp>
#include "basic_timed_mutex.hpp"
#include <boost/utility.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
@@ -20,11 +20,9 @@ namespace boost
}
class mutex:
boost::noncopyable,
public ::boost::detail::underlying_mutex
{
private:
mutex(mutex const&);
mutex& operator=(mutex const&);
public:
mutex()
{
@@ -42,11 +40,9 @@ namespace boost
typedef mutex try_mutex;
class timed_mutex:
boost::noncopyable,
public ::boost::detail::basic_timed_mutex
{
private:
timed_mutex(timed_mutex const&);
timed_mutex& operator=(timed_mutex const&);
public:
timed_mutex()
{

View File

@@ -34,85 +34,42 @@ namespace boost
{
long status;
long count;
long throw_count;
void* event_handle;
~once_flag()
{
if(count)
{
BOOST_ASSERT(count==throw_count);
}
void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event_handle,0);
if(old_event)
{
::boost::detail::win32::CloseHandle(old_event);
}
}
};
#define BOOST_ONCE_INIT {0,0}
#define BOOST_ONCE_INIT {0,0,0,0}
namespace detail
{
#ifdef BOOST_NO_ANSI_APIS
typedef wchar_t once_char_type;
#else
typedef char once_char_type;
#endif
unsigned const once_mutex_name_fixed_length=54;
unsigned const once_mutex_name_length=once_mutex_name_fixed_length+
sizeof(void*)*2+sizeof(unsigned long)*2+1;
template <class I>
void int_to_string(I p, once_char_type* buf)
inline void* allocate_event_handle(void*& handle)
{
for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
{
#ifdef BOOST_NO_ANSI_APIS
once_char_type const a=L'A';
#else
once_char_type const a='A';
#endif
*buf = a + static_cast<once_char_type>((p >> (i*4)) & 0x0f);
}
*buf = 0;
}
inline void name_once_mutex(once_char_type* mutex_name,void* flag_address)
{
#ifdef BOOST_NO_ANSI_APIS
static const once_char_type fixed_mutex_name[]=L"Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
#else
static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
#endif
BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) ==
(sizeof(once_char_type)*(once_mutex_name_fixed_length+1)));
void* const new_handle=::boost::detail::win32::create_anonymous_event(
::boost::detail::win32::manual_reset_event,
::boost::detail::win32::event_initially_reset);
std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address),
mutex_name + once_mutex_name_fixed_length);
detail::int_to_string(win32::GetCurrentProcessId(),
mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
}
inline void* open_once_event(once_char_type* mutex_name,void* flag_address)
{
if(!*mutex_name)
void* event_handle=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&handle,
new_handle,0);
if(event_handle)
{
name_once_mutex(mutex_name,flag_address);
::boost::detail::win32::CloseHandle(new_handle);
return event_handle;
}
#ifdef BOOST_NO_ANSI_APIS
return ::boost::detail::win32::OpenEventW(
#else
return ::boost::detail::win32::OpenEventA(
#endif
::boost::detail::win32::synchronize |
::boost::detail::win32::event_modify_state,
false,
mutex_name);
}
inline void* create_once_event(once_char_type* mutex_name,void* flag_address)
{
if(!*mutex_name)
{
name_once_mutex(mutex_name,flag_address);
}
#ifdef BOOST_NO_ANSI_APIS
return ::boost::detail::win32::CreateEventW(
#else
return ::boost::detail::win32::CreateEventA(
#endif
0,::boost::detail::win32::manual_reset_event,
::boost::detail::win32::event_initially_reset,
mutex_name);
return new_handle;
}
}
@@ -126,9 +83,8 @@ namespace boost
long const running_value=0x7f0725e3;
long status;
bool counted=false;
detail::win32::handle_manager event_handle;
detail::once_char_type mutex_name[detail::once_mutex_name_length];
mutex_name[0]=0;
void* event_handle=0;
long throw_count=0;
while((status=::boost::detail::interlocked_read_acquire(&flag.status))
!=function_complete_flag_value)
@@ -140,7 +96,7 @@ namespace boost
{
if(!event_handle)
{
event_handle=detail::open_once_event(mutex_name,&flag);
event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
}
if(event_handle)
{
@@ -156,20 +112,25 @@ namespace boost
if(!event_handle &&
(::boost::detail::interlocked_read_acquire(&flag.count)>1))
{
event_handle=detail::create_once_event(mutex_name,&flag);
event_handle=::boost::detail::allocate_event_handle(flag.event_handle);
}
if(event_handle)
{
::boost::detail::win32::SetEvent(event_handle);
}
throw_count=::boost::detail::interlocked_read_acquire(&flag.throw_count);
break;
}
catch(...)
{
if(counted)
{
BOOST_INTERLOCKED_INCREMENT(&flag.throw_count);
}
BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
if(!event_handle)
{
event_handle=detail::open_once_event(mutex_name,&flag);
event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
}
if(event_handle)
{
@@ -188,15 +149,31 @@ namespace boost
{
break;
}
event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
if(!event_handle)
{
event_handle=detail::create_once_event(mutex_name,&flag);
event_handle=::boost::detail::allocate_event_handle(flag.event_handle);
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
event_handle,::boost::detail::win32::infinite));
}
if(counted || throw_count)
{
if(!BOOST_INTERLOCKED_EXCHANGE_ADD(&flag.count,(counted?-1:0)-throw_count))
{
if(!event_handle)
{
event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
}
if(event_handle)
{
BOOST_INTERLOCKED_EXCHANGE_POINTER(&flag.event_handle,0);
::boost::detail::win32::CloseHandle(event_handle);
}
}
}
}
}

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 <boost/thread/win32/basic_recursive_mutex.hpp>
#include "basic_recursive_mutex.hpp"
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
@@ -20,11 +20,9 @@
namespace boost
{
class recursive_mutex:
boost::noncopyable,
public ::boost::detail::basic_recursive_mutex
{
private:
recursive_mutex(recursive_mutex const&);
recursive_mutex& operator=(recursive_mutex const&);
public:
recursive_mutex()
{
@@ -42,11 +40,9 @@ namespace boost
typedef recursive_mutex recursive_try_mutex;
class recursive_timed_mutex:
boost::noncopyable,
public ::boost::detail::basic_recursive_timed_mutex
{
private:
recursive_timed_mutex(recursive_timed_mutex const&);
recursive_timed_mutex& operator=(recursive_timed_mutex const&);
public:
recursive_timed_mutex()
{

View File

@@ -19,11 +19,9 @@
namespace boost
{
class shared_mutex
class shared_mutex:
private boost::noncopyable
{
private:
shared_mutex(shared_mutex const&);
shared_mutex& operator=(shared_mutex const&);
private:
struct state_data
{
@@ -39,7 +37,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)
@@ -51,47 +49,34 @@ namespace boost
return *reinterpret_cast<T const*>(&res);
}
enum
{
unlock_sem = 0,
exclusive_sem = 1
};
state_data state;
detail::win32::handle semaphores[2];
detail::win32::handle &unlock_sem;
detail::win32::handle &exclusive_sem;
detail::win32::handle upgrade_sem;
void release_waiters(state_data old_state)
{
if(old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
BOOST_VERIFY(detail::win32::ReleaseSemaphore(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);
BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
}
}
public:
shared_mutex()
shared_mutex():
unlock_sem(semaphores[0]),
exclusive_sem(semaphores[1])
{
semaphores[unlock_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());
}
unlock_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
exclusive_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
state_data state_={0};
state=state_;
}
@@ -99,8 +84,8 @@ namespace boost
~shared_mutex()
{
detail::win32::CloseHandle(upgrade_sem);
detail::win32::CloseHandle(semaphores[unlock_sem]);
detail::win32::CloseHandle(semaphores[exclusive_sem]);
detail::win32::CloseHandle(unlock_sem);
detail::win32::CloseHandle(exclusive_sem);
}
bool try_lock_shared()
@@ -112,12 +97,8 @@ namespace boost
if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
@@ -150,18 +131,10 @@ namespace boost
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
++new_state.shared_waiting;
if(!new_state.shared_waiting)
{
boost::throw_exception(boost::lock_error());
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
boost::throw_exception(boost::lock_error());
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
@@ -176,8 +149,8 @@ namespace boost
{
return true;
}
unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until));
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,::boost::detail::get_milliseconds_until(wait_until));
if(res==detail::win32::timeout)
{
for(;;)
@@ -193,10 +166,6 @@ namespace boost
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
@@ -213,7 +182,7 @@ namespace boost
}
return false;
}
BOOST_ASSERT(res==0);
}
}
@@ -225,7 +194,7 @@ namespace boost
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
if(new_state.upgrade)
@@ -243,7 +212,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)
{
@@ -289,7 +258,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)
{
@@ -313,11 +282,6 @@ namespace boost
if(new_state.shared_count || new_state.exclusive)
{
++new_state.exclusive_waiting;
if(!new_state.exclusive_waiting)
{
boost::throw_exception(boost::lock_error());
}
new_state.exclusive_waiting_blocked=true;
}
else
@@ -337,12 +301,7 @@ namespace boost
{
return true;
}
#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));
unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,true,::boost::detail::get_milliseconds_until(wait_until));
if(wait_res==detail::win32::timeout)
{
for(;;)
@@ -415,18 +374,10 @@ namespace boost
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
{
++new_state.shared_waiting;
if(!new_state.shared_waiting)
{
boost::throw_exception(boost::lock_error());
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
boost::throw_exception(boost::lock_error());
}
new_state.upgrade=true;
}
@@ -442,8 +393,8 @@ namespace boost
{
return;
}
BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite));
BOOST_VERIFY(!detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite));
}
}
@@ -460,13 +411,9 @@ namespace boost
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
new_state.upgrade=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
@@ -485,7 +432,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)
@@ -495,7 +442,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)
{
@@ -516,13 +463,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)
{
@@ -561,7 +508,7 @@ namespace boost
}
release_waiters(old_state);
}
void unlock_and_lock_shared()
{
state_data old_state=state;
@@ -586,7 +533,7 @@ namespace boost
}
release_waiters(old_state);
}
void unlock_upgrade_and_lock_shared()
{
state_data old_state=state;
@@ -610,7 +557,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 <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/thread_heap_alloc.hpp>
#include "thread_primitives.hpp"
#include "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 BOOST_SYMBOL_VISIBLE thread_data_base
struct 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 BOOST_SYMBOL_VISIBLE timeout
struct timeout
{
unsigned long start;
uintmax_t milliseconds;
@@ -92,7 +92,7 @@ namespace boost
abs_time(abs_time_)
{}
struct BOOST_SYMBOL_VISIBLE remaining_time
struct remaining_time
{
bool more;
unsigned long milliseconds;
@@ -130,7 +130,7 @@ namespace boost
{
return milliseconds==~uintmax_t(0);
}
static timeout sentinel()
{
@@ -139,16 +139,11 @@ namespace boost
private:
struct sentinel_type
{};
explicit timeout(sentinel_type):
start(0),milliseconds(~uintmax_t(0)),relative(true)
{}
};
inline uintmax_t pin_to_zero(intmax_t value)
{
return (value<0)?0u:(uintmax_t)value;
}
}
namespace this_thread
@@ -156,26 +151,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(uintmax_t milliseconds)
inline void interruptible_wait(unsigned long milliseconds)
{
interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
}
inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time)
inline void interruptible_wait(system_time const& abs_time)
{
interruptible_wait(detail::win32::invalid_handle_value,abs_time);
}
template<typename TimeDuration>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
inline void sleep(TimeDuration const& rel_time)
{
interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
interruptible_wait(static_cast<unsigned long>(rel_time.total_milliseconds()));
}
inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
inline 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 <boost/thread/win32/thread_primitives.hpp>
#include "thread_primitives.hpp"
#include <stdexcept>
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
@@ -56,7 +56,7 @@ namespace boost
{
namespace detail
{
inline void* allocate_raw_heap_memory(unsigned size)
inline BOOST_THREAD_DECL 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 void free_raw_heap_memory(void* heap_memory)
inline BOOST_THREAD_DECL 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
@@ -31,18 +31,14 @@ namespace boost
unsigned const infinite=INFINITE;
unsigned const timeout=WAIT_TIMEOUT;
handle const invalid_handle_value=INVALID_HANDLE_VALUE;
unsigned const event_modify_state=EVENT_MODIFY_STATE;
unsigned const synchronize=SYNCHRONIZE;
# ifdef BOOST_NO_ANSI_APIS
using ::CreateMutexW;
using ::CreateEventW;
using ::OpenEventW;
using ::CreateSemaphoreW;
# else
using ::CreateMutexA;
using ::CreateEventA;
using ::OpenEventA;
using ::CreateSemaphoreA;
# endif
using ::CloseHandle;
@@ -94,7 +90,7 @@ namespace boost
{
namespace win32
{
# ifdef _WIN64
typedef unsigned __int64 ulong_ptr;
# else
@@ -104,8 +100,6 @@ namespace boost
unsigned const infinite=~0U;
unsigned const timeout=258U;
handle const invalid_handle_value=(handle)(-1);
unsigned const event_modify_state=2;
unsigned const synchronize=0x100000u;
extern "C"
{
@@ -114,12 +108,10 @@ namespace boost
__declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
__declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
# else
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
__declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
# endif
__declspec(dllimport) int __stdcall CloseHandle(void*);
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
@@ -170,20 +162,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,26 +185,17 @@ 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)
{
@@ -246,7 +229,7 @@ namespace boost
BOOST_VERIFY(CloseHandle(handle_to_manage));
}
}
public:
explicit handle_manager(handle handle_to_manage_):
handle_to_manage(handle_to_manage_)
@@ -254,7 +237,7 @@ namespace boost
handle_manager():
handle_to_manage(0)
{}
handle_manager& operator=(handle new_handle)
{
cleanup();
@@ -288,13 +271,13 @@ namespace boost
{
return !handle_to_manage;
}
~handle_manager()
{
cleanup();
}
};
}
}
}
@@ -327,7 +310,7 @@ namespace boost
{
return _interlockedbittestandreset(x,bit)!=0;
}
}
}
}
@@ -346,7 +329,7 @@ namespace boost
mov edx,x;
lock bts [edx],eax;
setc al;
};
};
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
@@ -356,9 +339,9 @@ namespace boost
mov edx,x;
lock btr [edx],eax;
setc al;
};
};
}
}
}
}

View File

@@ -22,18 +22,16 @@ namespace boost
pthread_key_t epoch_tss_key;
pthread_once_t epoch_tss_key_flag=PTHREAD_ONCE_INIT;
extern "C"
extern "C" void delete_epoch_tss_data(void* data)
{
static void delete_epoch_tss_data(void* data)
{
free(data);
}
static void create_epoch_tss_key()
{
BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data));
}
free(data);
}
extern "C" 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 __GLIBC__
#ifdef __linux__
#include <sys/sysinfo.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/types.h>
@@ -50,7 +50,7 @@ namespace boost
extern "C"
{
static void tls_destructor(void* data)
void tls_destructor(void* data)
{
boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
if(thread_info)
@@ -75,7 +75,7 @@ namespace boost
{
current=next;
++next;
if(current->second.func && (current->second.value!=0))
if(current->second.func && current->second.value)
{
(*current->second.func)(current->second.value);
}
@@ -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"
{
static void* thread_proxy(void* param)
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()
{}
@@ -196,18 +196,19 @@ namespace boost
detach();
}
detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
detail::thread_data_ptr thread::get_thread_info() const
{
lock_guard<mutex> l(thread_info_mutex);
return thread_info;
}
void thread::join()
{
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
bool do_join=false;
{
unique_lock<mutex> lock(local_thread_info->data_mutex);
while(!local_thread_info->done)
@@ -215,7 +216,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 +237,8 @@ namespace boost
local_thread_info->joined=true;
local_thread_info->done_condition.notify_all();
}
lock_guard<mutex> l1(thread_info_mutex);
if(thread_info==local_thread_info)
{
thread_info.reset();
@@ -246,11 +248,11 @@ namespace boost
bool thread::timed_join(system_time const& wait_until)
{
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
bool do_join=false;
{
unique_lock<mutex> lock(local_thread_info->data_mutex);
while(!local_thread_info->done)
@@ -261,7 +263,7 @@ namespace boost
}
}
do_join=!local_thread_info->join_started;
if(do_join)
{
local_thread_info->join_started=true;
@@ -282,7 +284,8 @@ namespace boost
local_thread_info->joined=true;
local_thread_info->done_condition.notify_all();
}
lock_guard<mutex> l1(thread_info_mutex);
if(thread_info==local_thread_info)
{
thread_info.reset();
@@ -293,15 +296,18 @@ namespace boost
bool thread::joinable() const
{
return (get_thread_info)();
return get_thread_info();
}
void thread::detach()
{
detail::thread_data_ptr local_thread_info;
thread_info.swap(local_thread_info);
{
lock_guard<mutex> l1(thread_info_mutex);
thread_info.swap(local_thread_info);
}
if(local_thread_info)
{
lock_guard<mutex> lock(local_thread_info->data_mutex);
@@ -316,15 +322,11 @@ 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);
@@ -333,7 +335,7 @@ namespace boost
else
{
xtime const xt=get_xtime(st);
for (int foo=0; foo < 5; ++foo)
{
# if defined(BOOST_HAS_PTHREAD_DELAY_NP)
@@ -343,7 +345,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);
@@ -379,6 +381,8 @@ namespace boost
{
#if defined(PTW32_VERSION) || defined(__hpux)
return pthread_num_processors_np();
#elif defined(_GNU_SOURCE)
return get_nprocs();
#elif defined(__APPLE__) || defined(__FreeBSD__)
int count;
size_t size=sizeof(count);
@@ -386,8 +390,6 @@ 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(__GLIBC__)
return get_nprocs();
#else
return 0;
#endif
@@ -395,7 +397,7 @@ namespace boost
thread::id thread::get_id() const
{
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
return id(local_thread_info);
@@ -408,14 +410,13 @@ namespace boost
void thread::interrupt()
{
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
lock_guard<mutex> lk(local_thread_info->data_mutex);
local_thread_info->interrupt_requested=true;
if(local_thread_info->current_cond)
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(local_thread_info->cond_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(local_thread_info->current_cond));
}
}
@@ -423,7 +424,7 @@ namespace boost
bool thread::interruption_requested() const
{
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
lock_guard<mutex> lk(local_thread_info->data_mutex);
@@ -437,7 +438,7 @@ namespace boost
thread::native_handle_type thread::native_handle()
{
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
lock_guard<mutex> lk(local_thread_info->data_mutex);
@@ -448,8 +449,8 @@ namespace boost
return pthread_t();
}
}
namespace this_thread
{
@@ -472,13 +473,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();
@@ -501,7 +502,7 @@ namespace boost
detail::get_current_thread_data()->interrupt_enabled=false;
}
}
disable_interruption::~disable_interruption()
{
if(detail::get_current_thread_data())
@@ -517,7 +518,7 @@ namespace boost
detail::get_current_thread_data()->interrupt_enabled=true;
}
}
restore_interruption::~restore_interruption()
{
if(detail::get_current_thread_data())
@@ -574,18 +575,18 @@ 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)
{
if(tss_data_node* const current_node=find_tss_data(key))
{
if(cleanup_existing && current_node->func && (current_node->value!=0))
if(cleanup_existing && current_node->func && current_node->value)
{
(*current_node->func)(current_node->value);
}
if(func || (tss_data!=0))
if(func || tss_data)
{
current_node->func=func;
current_node->value=tss_data;

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); (void)res;
BOOST_ASSERT(res == boost::TIME_UTC);
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
@@ -33,6 +33,7 @@ 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)
{
@@ -57,7 +58,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); (void)res;
BOOST_ASSERT(res == boost::TIME_UTC);
if (boost::xtime_cmp(xt, cur) <= 0)
{
@@ -88,7 +89,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); (void)res;
BOOST_ASSERT(res == boost::TIME_UTC);
if (boost::xtime_cmp(xt, cur) <= 0)
milliseconds = 0;
@@ -110,7 +111,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); (void)res;
BOOST_ASSERT(res == boost::TIME_UTC);
if (boost::xtime_cmp(xt, cur) <= 0)
microseconds = 0;

View File

@@ -8,15 +8,13 @@
#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST) || defined(UNDER_CE)) && (!defined(_MSC_VER) || defined(UNDER_CE))
namespace boost
{
/*
This file is a "null" implementation of tss cleanup; it's
purpose is to to eliminate link errors in cases
where it is known that tss cleanup is not needed.
*/
void tss_cleanup_implemented(void)
extern "C" void tss_cleanup_implemented(void)
{
/*
This function's sole purpose is to cause a link error in cases where
@@ -32,7 +30,5 @@ namespace boost
longer needed and can be removed.
*/
}
}
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && !defined(_MSC_VER)

View File

@@ -9,6 +9,7 @@
#include <boost/thread/thread.hpp>
#include <algorithm>
#include <windows.h>
#ifndef UNDER_CE
#include <process.h>
#endif
@@ -19,8 +20,6 @@
#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
{
@@ -33,12 +32,7 @@ namespace boost
{
tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in
current_thread_tls_key=TlsAlloc();
#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
BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES);
}
void cleanup_tls_key()
@@ -62,13 +56,10 @@ namespace boost
void set_current_thread_data(detail::thread_data_base* new_data)
{
boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
if(current_thread_tls_key)
BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
else
boost::throw_exception(thread_resource_error());
BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
}
#ifndef BOOST_HAS_THREADEX
#ifdef BOOST_NO_THREADEX
// Windows CE doesn't define _beginthreadex
struct ThreadProxyData
@@ -81,25 +72,22 @@ namespace boost
DWORD WINAPI ThreadProxy(LPVOID args)
{
std::auto_ptr<ThreadProxyData> data(reinterpret_cast<ThreadProxyData*>(args));
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,
data,initflag,&threadID);
if (hthread==0) {
delete data;
return 0;
}
*thrdaddr=threadID;
new ThreadProxyData(start_address,arglist),initflag,&threadID);
if (hthread!=0)
*thrdaddr=threadID;
return reinterpret_cast<uintptr_t const>(hthread);
}
@@ -166,11 +154,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));
@@ -222,7 +210,7 @@ namespace boost
++count;
interruption_enabled=false;
}
void run()
{}
private:
@@ -233,15 +221,7 @@ namespace boost
void make_external_thread_data()
{
externally_launched_thread* me=detail::heap_new<externally_launched_thread>();
try
{
set_current_thread_data(me);
}
catch(...)
{
detail::heap_delete(me);
throw;
}
set_current_thread_data(me);
}
detail::thread_data_base* get_or_make_current_thread_data()
@@ -254,27 +234,27 @@ namespace boost
}
return current_thread_data;
}
}
thread::~thread()
{
detach();
}
thread::id thread::get_id() const
{
return thread::id((get_thread_info)());
return thread::id(get_thread_info());
}
bool thread::joinable() const
{
return (get_thread_info)();
return get_thread_info();
}
void thread::join()
{
detail::thread_data_ptr local_thread_info=(get_thread_info)();
detail::thread_data_ptr local_thread_info=get_thread_info();
if(local_thread_info)
{
this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel());
@@ -284,7 +264,7 @@ namespace boost
bool thread::timed_join(boost::system_time const& wait_until)
{
detail::thread_data_ptr local_thread_info=(get_thread_info)();
detail::thread_data_ptr local_thread_info=get_thread_info();
if(local_thread_info)
{
if(!this_thread::interruptible_wait(local_thread_info->thread_handle,get_milliseconds_until(wait_until)))
@@ -295,7 +275,7 @@ namespace boost
}
return true;
}
void thread::detach()
{
release_handle();
@@ -303,39 +283,41 @@ namespace boost
void thread::release_handle()
{
lock_guard<mutex> l1(thread_info_mutex);
thread_info=0;
}
void thread::interrupt()
{
detail::thread_data_ptr local_thread_info=(get_thread_info)();
detail::thread_data_ptr local_thread_info=get_thread_info();
if(local_thread_info)
{
local_thread_info->interrupt();
}
}
bool thread::interruption_requested() const
{
detail::thread_data_ptr local_thread_info=(get_thread_info)();
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}};
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)();
detail::thread_data_ptr local_thread_info=get_thread_info();
return local_thread_info?(detail::win32::handle)local_thread_info->thread_handle:detail::win32::invalid_handle_value;
}
detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
detail::thread_data_ptr thread::get_thread_info() const
{
boost::mutex::scoped_lock l(thread_info_mutex);
return thread_info;
}
@@ -345,7 +327,7 @@ namespace boost
{
LARGE_INTEGER get_due_time(detail::timeout const& target_time)
{
LARGE_INTEGER due_time={{0}};
LARGE_INTEGER due_time={0};
if(target_time.relative)
{
unsigned long const elapsed_milliseconds=GetTickCount()-target_time.start;
@@ -374,29 +356,13 @@ namespace boost
else
{
long const hundred_nanoseconds_in_one_second=10000000;
posix_time::time_duration::tick_type const ticks_per_second=
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
ticks_per_hundred_nanoseconds=
ticks_per_second/hundred_nanoseconds_in_one_second;
due_time.QuadPart+=
target_time.abs_time.time_of_day().fractional_seconds()/
ticks_per_hundred_nanoseconds;
}
else
{
due_time.QuadPart+=
target_time.abs_time.time_of_day().fractional_seconds()*
(hundred_nanoseconds_in_one_second/ticks_per_second);
}
due_time.QuadPart+=target_time.abs_time.time_of_day().fractional_seconds()*(hundred_nanoseconds_in_one_second/target_time.abs_time.time_of_day().ticks_per_second());
}
}
return due_time;
}
}
bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
{
@@ -417,10 +383,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();
@@ -431,7 +397,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)
{
@@ -447,17 +413,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);
@@ -504,12 +470,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);
@@ -519,7 +485,7 @@ namespace boost
{
detail::win32::Sleep(0);
}
disable_interruption::disable_interruption():
interruption_was_enabled(interruption_enabled())
{
@@ -528,7 +494,7 @@ namespace boost
get_current_thread_data()->interruption_enabled=false;
}
}
disable_interruption::~disable_interruption()
{
if(get_current_thread_data())
@@ -544,7 +510,7 @@ namespace boost
get_current_thread_data()->interruption_enabled=true;
}
}
restore_interruption::~restore_interruption()
{
if(get_current_thread_data())
@@ -560,8 +526,8 @@ namespace boost
{
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
thread_exit_callback_node* const new_node=
heap_new<thread_exit_callback_node>(
func,current_thread_data->thread_exit_callbacks);
heap_new<thread_exit_callback_node>(func,
current_thread_data->thread_exit_callbacks);
current_thread_data->thread_exit_callbacks=new_node;
}
@@ -591,7 +557,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))
@@ -603,31 +569,30 @@ namespace boost
current_node->func=func;
current_node->value=tss_data;
}
else if(func && tss_data)
else
{
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
tss_data_node* const new_node=
heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data);
tss_data_node* const new_node=heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data);
current_thread_data->tss_data=new_node;
}
}
}
BOOST_THREAD_DECL void __cdecl on_process_enter()
{}
BOOST_THREAD_DECL void __cdecl on_thread_enter()
{}
BOOST_THREAD_DECL void __cdecl on_process_exit()
{
boost::cleanup_tls_key();
}
BOOST_THREAD_DECL void __cdecl on_thread_exit()
{
boost::run_thread_exit_callbacks();
}
}
extern "C" BOOST_THREAD_DECL void on_process_enter()
{}
extern "C" BOOST_THREAD_DECL void on_thread_enter()
{}
extern "C" BOOST_THREAD_DECL void on_process_exit()
{
boost::cleanup_tls_key();
}
extern "C" BOOST_THREAD_DECL void on_thread_exit()
{
boost::run_thread_exit_callbacks();
}

View File

@@ -24,27 +24,27 @@
{
case DLL_PROCESS_ATTACH:
{
boost::on_process_enter();
boost::on_thread_enter();
on_process_enter();
on_thread_enter();
break;
}
case DLL_THREAD_ATTACH:
{
boost::on_thread_enter();
on_thread_enter();
break;
}
case DLL_THREAD_DETACH:
{
boost::on_thread_exit();
on_thread_exit();
break;
}
case DLL_PROCESS_DETACH:
{
boost::on_thread_exit();
boost::on_process_exit();
on_thread_exit();
on_process_exit();
break;
}
}
@@ -52,9 +52,7 @@
return TRUE;
}
namespace boost
{
void tss_cleanup_implemented()
extern "C" void tss_cleanup_implemented(void)
{
/*
This function's sole purpose is to cause a link error in cases where
@@ -70,7 +68,5 @@ namespace boost
longer needed and can be removed.
*/
}
}
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)

View File

@@ -11,7 +11,7 @@
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
#if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__)
#if defined(__MINGW32__) && !defined(_WIN64)
#include <boost/thread/detail/tss_hooks.hpp>
@@ -19,10 +19,7 @@
#include <cstdlib>
namespace boost
{
void tss_cleanup_implemented() {}
}
extern "C" void tss_cleanup_implemented(void) {}
namespace {
void NTAPI on_tls_callback(void* h, DWORD dwReason, PVOID pv)
@@ -31,25 +28,33 @@ namespace {
{
case DLL_THREAD_DETACH:
{
boost::on_thread_exit();
on_thread_exit();
break;
}
}
}
void on_after_ctors(void)
{
on_process_enter();
}
void on_before_dtors(void)
{
on_thread_exit();
}
void on_after_dtors(void)
{
on_process_exit();
}
}
#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;
}
#else
extern "C" {
void (* after_ctors )() __attribute__((section(".ctors"))) = boost::on_process_enter;
void (* before_dtors)() __attribute__((section(".dtors"))) = boost::on_thread_exit;
void (* after_dtors )() __attribute__((section(".dtors.zzz"))) = boost::on_process_exit;
void (* after_ctors )(void) __attribute__((section(".ctors"))) = on_after_ctors;
void (* before_dtors)(void) __attribute__((section(".dtors"))) = on_before_dtors;
void (* after_dtors )(void) __attribute__((section(".dtors.zzz"))) = on_after_dtors;
ULONG __tls_index__ = 0;
char __tls_end__ __attribute__((section(".tls$zzz"))) = 0;
@@ -57,8 +62,10 @@ extern "C" {
PIMAGE_TLS_CALLBACK __crt_xl_start__ __attribute__ ((section(".CRT$XLA"))) = 0;
PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback;
PIMAGE_TLS_CALLBACK __crt_xl_end__ __attribute__ ((section(".CRT$XLZ"))) = 0;
}
extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) =
{
(DWORD) &__tls_start__,
@@ -68,7 +75,6 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
(DWORD) 0,
(DWORD) 0
};
#endif
#elif defined(_MSC_VER) && !defined(UNDER_CE)
@@ -83,13 +89,13 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
//Definitions required by implementation
#if (_MSC_VER < 1300) // 1300 == VC++ 7.0
typedef void (__cdecl *_PVFV)();
typedef void (__cdecl *_PVFV)(void);
#define INIRETSUCCESS
#define PVAPI void __cdecl
#define PVAPI void
#else
typedef int (__cdecl *_PVFV)();
typedef int (__cdecl *_PVFV)(void);
#define INIRETSUCCESS 0
#define PVAPI int __cdecl
#define PVAPI int
#endif
typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
@@ -106,9 +112,9 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
{
//Forward declarations
static PVAPI on_tls_prepare();
static PVAPI on_process_init();
static PVAPI on_process_term();
static PVAPI on_tls_prepare(void);
static PVAPI on_process_init(void);
static PVAPI on_process_term(void);
static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID);
//The .CRT$Xxx information is taken from Codeguru:
@@ -163,7 +169,7 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
#pragma warning(disable:4189)
#endif
PVAPI on_tls_prepare()
PVAPI on_tls_prepare(void)
{
//The following line has an important side effect:
//if the TLS directory is not already there, it will
@@ -204,7 +210,7 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
#pragma warning(pop)
#endif
PVAPI on_process_init()
PVAPI on_process_init(void)
{
//Schedule on_thread_exit() to be called for the main
//thread before destructors of global objects have been
@@ -215,18 +221,18 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
//for destructors of global objects, so that
//shouldn't be a problem.
atexit(boost::on_thread_exit);
atexit(on_thread_exit);
//Call Boost process entry callback here
boost::on_process_enter();
on_process_enter();
return INIRETSUCCESS;
}
PVAPI on_process_term()
PVAPI on_process_term(void)
{
boost::on_process_exit();
on_process_exit();
return INIRETSUCCESS;
}
@@ -235,7 +241,7 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
switch (dwReason)
{
case DLL_THREAD_DETACH:
boost::on_thread_exit();
on_thread_exit();
break;
}
}
@@ -245,10 +251,10 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
switch (dwReason)
{
case DLL_THREAD_DETACH:
boost::on_thread_exit();
on_thread_exit();
break;
case DLL_PROCESS_DETACH:
boost::on_process_exit();
on_process_exit();
break;
}
return true;
@@ -259,9 +265,8 @@ extern "C"
{
extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID)=&dll_callback;
}
namespace boost
{
void tss_cleanup_implemented()
extern "C" void tss_cleanup_implemented(void)
{
/*
This function's sole purpose is to cause a link error in cases where
@@ -277,8 +282,6 @@ namespace boost
longer needed and can be removed.
*/
}
}
#endif //defined(_MSC_VER) && !defined(UNDER_CE)
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)

View File

@@ -62,29 +62,4 @@ 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 ]
;
}

View File

@@ -1,10 +0,0 @@
#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;
}

View File

@@ -1,21 +0,0 @@
#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);
}

View File

@@ -1,42 +0,0 @@
#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;
}

View File

@@ -1,50 +0,0 @@
#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;
}

View File

@@ -1,45 +0,0 @@
#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;
}

View File

@@ -1,86 +0,0 @@
// 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;
}

View File

@@ -1,62 +0,0 @@
#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;
}

View File

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

View File

@@ -1,30 +0,0 @@
#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;
}

View File

@@ -1,22 +0,0 @@
#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;
}

View File

@@ -1,26 +0,0 @@
#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;
}

View File

@@ -1,35 +0,0 @@
#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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: condition test suite");
test->add(BOOST_TEST_CASE(&test_timed_wait_times_out));

View File

@@ -18,7 +18,7 @@
template<typename T>
typename boost::remove_reference<T>::type&& cast_to_rval(T&& t)
{
return static_cast<typename boost::remove_reference<T>::type&&>(t);
return t;
}
#else
template<typename T>
@@ -556,7 +556,7 @@ void wait_callback(boost::promise<int>& pi)
}
}
void do_nothing_callback(boost::promise<int>& /*pi*/)
void do_nothing_callback(boost::promise<int>& pi)
{
boost::lock_guard<boost::mutex> lk(callback_mutex);
++callback_called;
@@ -1041,8 +1041,6 @@ void test_wait_for_any_from_range()
}
boost::thread(::cast_to_rval(tasks[i]));
BOOST_CHECK(boost::wait_for_any(futures,futures)==futures);
boost::unique_future<int>* const future=boost::wait_for_any(futures,futures+count);
BOOST_CHECK(future==(futures+i));
@@ -1157,9 +1155,9 @@ void test_wait_for_all_five_futures()
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: futures test suite");
test->add(BOOST_TEST_CASE(test_initial_state));

View File

@@ -296,80 +296,10 @@ void test_lock_five_in_range()
}
}
class dummy_iterator:
public std::iterator<std::forward_iterator_tag,
dummy_mutex>
{
private:
dummy_mutex* p;
public:
explicit dummy_iterator(dummy_mutex* p_):
p(p_)
{}
bool operator==(dummy_iterator const& other) const
{
return p==other.p;
}
bool operator!=(dummy_iterator const& other) const
{
return p!=other.p;
}
bool operator<(dummy_iterator const& other) const
{
return p<other.p;
}
dummy_mutex& operator*() const
{
return *p;
}
dummy_mutex* operator->() const
{
return p;
}
dummy_iterator operator++(int)
{
dummy_iterator temp(*this);
++p;
return temp;
}
dummy_iterator& operator++()
{
++p;
return *this;
}
};
void test_lock_five_in_range_custom_iterator()
{
unsigned const num_mutexes=5;
dummy_mutex mutexes[num_mutexes];
boost::lock(dummy_iterator(mutexes),dummy_iterator(mutexes+num_mutexes));
for(unsigned i=0;i<num_mutexes;++i)
{
BOOST_CHECK(mutexes[i].is_locked);
}
}
class dummy_mutex2:
public dummy_mutex
{};
void test_lock_ten_in_range_inherited_mutex()
void test_lock_ten_in_range()
{
unsigned const num_mutexes=10;
dummy_mutex2 mutexes[num_mutexes];
dummy_mutex mutexes[num_mutexes];
boost::lock(mutexes,mutexes+num_mutexes);
@@ -568,9 +498,9 @@ void test_try_lock_five()
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: generic locks test suite");
test->add(BOOST_TEST_CASE(&test_lock_two_uncontended));
@@ -580,8 +510,7 @@ boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_order));
test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_different_order));
test->add(BOOST_TEST_CASE(&test_lock_five_in_range));
test->add(BOOST_TEST_CASE(&test_lock_five_in_range_custom_iterator));
test->add(BOOST_TEST_CASE(&test_lock_ten_in_range_inherited_mutex));
test->add(BOOST_TEST_CASE(&test_lock_ten_in_range));
test->add(BOOST_TEST_CASE(&test_lock_ten_other_thread_locks_in_different_order));
test->add(BOOST_TEST_CASE(&test_try_lock_two_uncontended));
test->add(BOOST_TEST_CASE(&test_try_lock_two_first_locked));

View File

@@ -11,9 +11,9 @@ void test_hardware_concurrency_is_non_zero()
BOOST_CHECK(boost::thread::hardware_concurrency()!=0);
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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,6 +4,7 @@
// 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>
@@ -545,9 +546,9 @@ void test_shared_lock()
BOOST_CHECK(dummy.shared_timed_locked_absolute);
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: lock concept test suite");
typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,

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,17 +89,10 @@ 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;
@@ -108,30 +101,16 @@ 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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite");
test->add(BOOST_TEST_CASE(&test_multiple_readers));

View File

@@ -138,14 +138,6 @@ void test_can_lock_upgrade_if_currently_locked_shared()
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count+1);
}
void test_can_lock_upgrade_to_unique_if_currently_locked_upgrade()
{
boost::shared_mutex mtx;
boost::upgrade_lock<boost::shared_mutex> l(mtx);
boost::upgrade_to_unique_lock<boost::shared_mutex> ul(l);
BOOST_CHECK(ul.owns_lock());
}
void test_if_other_thread_has_write_lock_try_lock_shared_returns_false()
{
@@ -283,14 +275,13 @@ void test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false()
writer.join();
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite");
test->add(BOOST_TEST_CASE(&test_only_one_upgrade_lock_permitted));
test->add(BOOST_TEST_CASE(&test_can_lock_upgrade_if_currently_locked_shared));
test->add(BOOST_TEST_CASE(&test_can_lock_upgrade_to_unique_if_currently_locked_upgrade));
test->add(BOOST_TEST_CASE(&test_if_other_thread_has_write_lock_try_lock_shared_returns_false));
test->add(BOOST_TEST_CASE(&test_if_no_thread_has_lock_try_lock_shared_returns_true));
test->add(BOOST_TEST_CASE(&test_if_other_thread_has_shared_lock_try_lock_shared_returns_true));

View File

@@ -251,9 +251,9 @@ void test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held()
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::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::test_suite* init_unit_test_suite(int, char*[])
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: xtime test suite");
test->add(BOOST_TEST_CASE(&test_xtime_cmp));