mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
1 Commits
boost-1.49
...
boost-1.38
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b9ba2351d |
22
CMakeLists.txt
Normal file
22
CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# This file was automatically generated from the original CMakeLists.txt file
|
||||
# Add a variable to hold the headers for the library
|
||||
set (lib_headers
|
||||
thread.hpp
|
||||
thread
|
||||
)
|
||||
|
||||
# Add a library target to the build system
|
||||
boost_library_project(
|
||||
thread
|
||||
SRCDIRS src
|
||||
TESTDIRS test
|
||||
HEADERS ${lib_headers}
|
||||
# DOCDIRS
|
||||
# DESCRIPTION
|
||||
MODULARIZED
|
||||
# AUTHORS
|
||||
# MAINTAINERS
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
;
|
||||
|
||||
@@ -181,6 +180,7 @@ rule requirements ( properties * )
|
||||
alias thread_sources
|
||||
: ## win32 sources ##
|
||||
win32/thread.cpp
|
||||
win32/exceptions.cpp
|
||||
win32/tss_dll.cpp
|
||||
win32/tss_pe.cpp
|
||||
: ## requirements ##
|
||||
@@ -190,6 +190,7 @@ alias thread_sources
|
||||
alias thread_sources
|
||||
: ## pthread sources ##
|
||||
pthread/thread.cpp
|
||||
pthread/exceptions.cpp
|
||||
pthread/once.cpp
|
||||
: ## requirements ##
|
||||
<threadapi>pthread
|
||||
|
||||
@@ -26,6 +26,30 @@ 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
|
||||
|
||||
# PDF Options:
|
||||
# TOC Generation: this is needed for FOP-0.9 and later:
|
||||
#<xsl:param>fop1.extensions=1
|
||||
# Or enable this if you're using XEP:
|
||||
<xsl:param>xep.extensions=1
|
||||
# TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
|
||||
<xsl:param>fop.extensions=0
|
||||
# No indent on body text:
|
||||
<xsl:param>body.start.indent=0pt
|
||||
# Margin size:
|
||||
<xsl:param>page.margin.inner=0.5in
|
||||
# Margin size:
|
||||
<xsl:param>page.margin.outer=0.5in
|
||||
# Yes, we want graphics for admonishments:
|
||||
<xsl:param>admon.graphics=1
|
||||
# Set this one for PDF generation *only*:
|
||||
# default pnd graphics are awful in PDF form,
|
||||
# better use SVG's instead:
|
||||
<format>pdf:<xsl:param>admon.graphics.extension=".svg"
|
||||
<format>pdf:<xsl:param>admon.graphics.path=$(boost-images)/
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -5,49 +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]
|
||||
|
||||
The 1.41.0 release of Boost adds futures to the thread library. There are also a few minor changes.
|
||||
|
||||
[heading Changes since boost 1.35]
|
||||
[section:changes Changes since boost 1.35]
|
||||
|
||||
The 1.36.0 release of Boost includes a few new features in the thread library:
|
||||
|
||||
@@ -123,22 +81,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]
|
||||
|
||||
|
||||
@@ -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]
|
||||
@@ -1,968 +0,0 @@
|
||||
[/
|
||||
(C) Copyright 2008-9 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).
|
||||
]
|
||||
|
||||
[section:reference Futures Reference]
|
||||
|
||||
[section:future_state `state` enum]
|
||||
|
||||
namespace future_state
|
||||
{
|
||||
enum state {uninitialized, waiting, ready};
|
||||
}
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:unique_future `unique_future` class template]
|
||||
|
||||
template <typename R>
|
||||
class unique_future
|
||||
{
|
||||
unique_future(unique_future & rhs);// = delete;
|
||||
unique_future& operator=(unique_future& rhs);// = delete;
|
||||
|
||||
public:
|
||||
typedef future_state::state state;
|
||||
|
||||
unique_future();
|
||||
~unique_future();
|
||||
|
||||
// move support
|
||||
unique_future(unique_future && other);
|
||||
unique_future& operator=(unique_future && other);
|
||||
|
||||
void swap(unique_future& other);
|
||||
|
||||
// retrieving the value
|
||||
R&& get();
|
||||
|
||||
// functions to check state
|
||||
state get_state() const;
|
||||
bool is_ready() const;
|
||||
bool has_exception() const;
|
||||
bool has_value() const;
|
||||
|
||||
// waiting for the result to be ready
|
||||
void wait() const;
|
||||
template<typename Duration>
|
||||
bool timed_wait(Duration const& rel_time) const;
|
||||
bool timed_wait_until(boost::system_time const& abs_time) const;
|
||||
};
|
||||
|
||||
[section:default_constructor Default Constructor]
|
||||
|
||||
unique_future();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs an uninitialized future.]]
|
||||
|
||||
[[Postconditions:] [[unique_future_is_ready_link `this->is_ready`] returns `false`. [unique_future_get_state_link
|
||||
`this->get_state()`] returns __uninitialized__.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:destructor Destructor]
|
||||
|
||||
~unique_future();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Destroys `*this`.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:move_constructor Move Constructor]
|
||||
|
||||
unique_future(unique_future && other);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a new future, and transfers ownership of the asynchronous result associated with `other` to `*this`.]]
|
||||
|
||||
[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
|
||||
call. `other->get_state()` returns __uninitialized__. If `other` was associated with an asynchronous result, that result is now
|
||||
associated with `*this`. `other` is not associated with any asynchronous result.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:move_assignment Move Assignment Operator]
|
||||
|
||||
unique_future& operator=(unique_future && other);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Transfers ownership of the asynchronous result associated with `other` to `*this`.]]
|
||||
|
||||
[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
|
||||
call. `other->get_state()` returns __uninitialized__. If `other` was associated with an asynchronous result, that result is now
|
||||
associated with `*this`. `other` is not associated with any asynchronous result. If `*this` was associated with an asynchronous
|
||||
result prior to the call, that result no longer has an associated __unique_future__ instance.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:swap Member function `swap()`]
|
||||
|
||||
void swap(unique_future & other);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Swaps ownership of the asynchronous results associated with `other` and `*this`.]]
|
||||
|
||||
[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
|
||||
call. `other->get_state()` returns the value of `this->get_state()` prior to the call. If `other` was associated with an
|
||||
asynchronous result, that result is now associated with `*this`, otherwise `*this` has no associated result. If `*this` was
|
||||
associated with an asynchronous result, that result is now associated with `other`, otherwise `other` has no associated result.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:get Member function `get()`]
|
||||
|
||||
R&& get();
|
||||
R& unique_future<R&>::get();
|
||||
void unique_future<void>::get();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready as-if by a call to
|
||||
__unique_future_wait__, and retrieves the result (whether that is a value or an exception).]]
|
||||
|
||||
[[Returns:] [If the result type `R` is a reference, returns the stored reference. If `R` is `void`, there is no return
|
||||
value. Otherwise, returns an rvalue-reference to the value stored in the asynchronous result.]]
|
||||
|
||||
[[Postconditions:] [[unique_future_is_ready_link `this->is_ready()`] returns `true`. [unique_future_get_state_link
|
||||
`this->get_state()`] returns __ready__.]]
|
||||
|
||||
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
|
||||
associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception stored in the
|
||||
asynchronous result in place of a value.]]
|
||||
|
||||
[[Notes:] [`get()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:wait Member function `wait()`]
|
||||
|
||||
void wait();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready. If the result is not ready on
|
||||
entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]
|
||||
|
||||
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
|
||||
associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
|
||||
['wait callback] if such a callback is called.]]
|
||||
|
||||
[[Postconditions:] [[unique_future_is_ready_link `this->is_ready()`] returns `true`. [unique_future_get_state_link
|
||||
`this->get_state()`] returns __ready__.]]
|
||||
|
||||
[[Notes:] [`wait()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:timed_wait_duration Member function `timed_wait()`]
|
||||
|
||||
template<typename Duration>
|
||||
bool timed_wait(Duration const& wait_duration);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time specified by
|
||||
`wait_duration` has elapsed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is
|
||||
invoked prior to waiting.]]
|
||||
|
||||
[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
|
||||
elapsed, `false` otherwise.]]
|
||||
|
||||
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
|
||||
associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
|
||||
['wait callback] if such a callback is called.]]
|
||||
|
||||
[[Postconditions:] [If this call returned `true`, then [unique_future_is_ready_link `this->is_ready()`] returns `true` and
|
||||
[unique_future_get_state_link `this->get_state()`] returns __ready__.]]
|
||||
|
||||
[[Notes:] [`timed_wait()` is an ['interruption point]. `Duration` must be a type that meets the Boost.DateTime time duration requirements.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:timed_wait_absolute Member function `timed_wait()`]
|
||||
|
||||
bool timed_wait(boost::system_time const& wait_timeout);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time point specified by
|
||||
`wait_timeout` has passed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is invoked
|
||||
prior to waiting.]]
|
||||
|
||||
[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
|
||||
passed, `false` otherwise.]]
|
||||
|
||||
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
|
||||
associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
|
||||
['wait callback] if such a callback is called.]]
|
||||
|
||||
[[Postconditions:] [If this call returned `true`, then [unique_future_is_ready_link `this->is_ready()`] returns `true` and
|
||||
[unique_future_get_state_link `this->get_state()`] returns __ready__.]]
|
||||
|
||||
[[Notes:] [`timed_wait()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:is_ready Member function `is_ready()`]
|
||||
|
||||
bool is_ready();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set.]]
|
||||
|
||||
[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready for retrieval, `false`
|
||||
otherwise.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:has_value Member function `has_value()`]
|
||||
|
||||
bool has_value();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with a value rather than an exception.]]
|
||||
|
||||
[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
|
||||
stored value, `false` otherwise.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:has_exception Member function `has_exception()`]
|
||||
|
||||
bool has_exception();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with an exception rather than a value.]]
|
||||
|
||||
[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
|
||||
stored exception, `false` otherwise.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:get_state Member function `get_state()`]
|
||||
|
||||
future_state::state get_state();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Determine the state of the asynchronous result associated with `*this`, if any.]]
|
||||
|
||||
[[Returns:] [__uninitialized__ if `*this` is not associated with an asynchronous result. __ready__ if the asynchronous result
|
||||
associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:shared_future `shared_future` class template]
|
||||
|
||||
template <typename R>
|
||||
class shared_future
|
||||
{
|
||||
public:
|
||||
typedef future_state::state state;
|
||||
|
||||
shared_future();
|
||||
~shared_future();
|
||||
|
||||
// copy support
|
||||
shared_future(shared_future const& other);
|
||||
shared_future& operator=(shared_future const& other);
|
||||
|
||||
// move support
|
||||
shared_future(shared_future && other);
|
||||
shared_future(unique_future<R> && other);
|
||||
shared_future& operator=(shared_future && other);
|
||||
shared_future& operator=(unique_future<R> && other);
|
||||
|
||||
void swap(shared_future& other);
|
||||
|
||||
// retrieving the value
|
||||
R get();
|
||||
|
||||
// functions to check state, and wait for ready
|
||||
state get_state() const;
|
||||
bool is_ready() const;
|
||||
bool has_exception() const;
|
||||
bool has_value() const;
|
||||
|
||||
// waiting for the result to be ready
|
||||
void wait() const;
|
||||
template<typename Duration>
|
||||
bool timed_wait(Duration const& rel_time) const;
|
||||
bool timed_wait_until(boost::system_time const& abs_time) const;
|
||||
};
|
||||
|
||||
[section:default_constructor Default Constructor]
|
||||
|
||||
shared_future();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs an uninitialized future.]]
|
||||
|
||||
[[Postconditions:] [[shared_future_is_ready_link `this->is_ready`] returns `false`. [shared_future_get_state_link
|
||||
`this->get_state()`] returns __uninitialized__.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:get Member function `get()`]
|
||||
|
||||
const R& get();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready as-if by a call to
|
||||
__shared_future_wait__, and returns a `const` reference to the result.]]
|
||||
|
||||
[[Returns:] [If the result type `R` is a reference, returns the stored reference. If `R` is `void`, there is no return
|
||||
value. Otherwise, returns a `const` reference to the value stored in the asynchronous result.]]
|
||||
|
||||
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the
|
||||
result associated with `*this` is not ready at the point of the call, and the current thread is interrupted.]]
|
||||
|
||||
[[Notes:] [`get()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:wait Member function `wait()`]
|
||||
|
||||
void wait();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready. If the result is not ready on
|
||||
entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]
|
||||
|
||||
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
|
||||
associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
|
||||
['wait callback] if such a callback is called.]]
|
||||
|
||||
[[Postconditions:] [[shared_future_is_ready_link `this->is_ready()`] returns `true`. [shared_future_get_state_link
|
||||
`this->get_state()`] returns __ready__.]]
|
||||
|
||||
[[Notes:] [`wait()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:timed_wait_duration Member function `timed_wait()`]
|
||||
|
||||
template<typename Duration>
|
||||
bool timed_wait(Duration const& wait_duration);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time specified by
|
||||
`wait_duration` has elapsed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is
|
||||
invoked prior to waiting.]]
|
||||
|
||||
[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
|
||||
elapsed, `false` otherwise.]]
|
||||
|
||||
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
|
||||
associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
|
||||
['wait callback] if such a callback is called.]]
|
||||
|
||||
[[Postconditions:] [If this call returned `true`, then [shared_future_is_ready_link `this->is_ready()`] returns `true` and
|
||||
[shared_future_get_state_link `this->get_state()`] returns __ready__.]]
|
||||
|
||||
[[Notes:] [`timed_wait()` is an ['interruption point]. `Duration` must be a type that meets the Boost.DateTime time duration requirements.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:timed_wait_absolute Member function `timed_wait()`]
|
||||
|
||||
bool timed_wait(boost::system_time const& wait_timeout);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time point specified by
|
||||
`wait_timeout` has passed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is invoked
|
||||
prior to waiting.]]
|
||||
|
||||
[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
|
||||
passed, `false` otherwise.]]
|
||||
|
||||
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
|
||||
associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
|
||||
['wait callback] if such a callback is called.]]
|
||||
|
||||
[[Postconditions:] [If this call returned `true`, then [shared_future_is_ready_link `this->is_ready()`] returns `true` and
|
||||
[shared_future_get_state_link `this->get_state()`] returns __ready__.]]
|
||||
|
||||
[[Notes:] [`timed_wait()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:is_ready Member function `is_ready()`]
|
||||
|
||||
bool is_ready();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set.]]
|
||||
|
||||
[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready for retrieval, `false`
|
||||
otherwise.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:has_value Member function `has_value()`]
|
||||
|
||||
bool has_value();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with a value rather than an exception.]]
|
||||
|
||||
[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
|
||||
stored value, `false` otherwise.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:has_exception Member function `has_exception()`]
|
||||
|
||||
bool has_exception();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with an exception rather than a value.]]
|
||||
|
||||
[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
|
||||
stored exception, `false` otherwise.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:get_state Member function `get_state()`]
|
||||
|
||||
future_state::state get_state();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Determine the state of the asynchronous result associated with `*this`, if any.]]
|
||||
|
||||
[[Returns:] [__uninitialized__ if `*this` is not associated with an asynchronous result. __ready__ if the asynchronous result
|
||||
associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:promise `promise` class template]
|
||||
|
||||
template <typename R>
|
||||
class promise
|
||||
{
|
||||
promise(promise & rhs);// = delete;
|
||||
promise & operator=(promise & rhs);// = delete;
|
||||
public:
|
||||
// template <class Allocator> explicit promise(Allocator a);
|
||||
|
||||
promise();
|
||||
~promise();
|
||||
|
||||
// Move support
|
||||
promise(promise && rhs);
|
||||
promise & operator=(promise&& rhs);
|
||||
|
||||
void swap(promise& other);
|
||||
// Result retrieval
|
||||
unique_future<R> get_future();
|
||||
|
||||
// Set the value
|
||||
void set_value(R& r);
|
||||
void set_value(R&& r);
|
||||
void set_exception(boost::exception_ptr e);
|
||||
|
||||
template<typename F>
|
||||
void set_wait_callback(F f);
|
||||
};
|
||||
|
||||
[section:default_constructor Default Constructor]
|
||||
|
||||
promise();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a new __promise__ with no associated result.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:move_constructor Move Constructor]
|
||||
|
||||
promise(promise && other);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a new __promise__, and transfers ownership of the result associated with `other` to `*this`, leaving `other`
|
||||
with no associated result.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:move_assignment Move Assignment Operator]
|
||||
|
||||
promise& operator=(promise && other);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Transfers ownership of the result associated with `other` to `*this`, leaving `other` with no associated result. If there
|
||||
was already a result associated with `*this`, and that result was not ['ready], sets any futures associated with that result to
|
||||
['ready] with a __broken_promise__ exception as the result. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:destructor Destructor]
|
||||
|
||||
~promise();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Destroys `*this`. If there was a result associated with `*this`, and that result is not ['ready], sets any futures
|
||||
associated with that task to ['ready] with a __broken_promise__ exception as the result.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:get_future Member Function `get_future()`]
|
||||
|
||||
unique_future<R> get_future();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [If `*this` was not associated with a result, allocate storage for a new asynchronous result and associate it with
|
||||
`*this`. Returns a __unique_future__ associated with the result associated with `*this`. ]]
|
||||
|
||||
[[Throws:] [__future_already_retrieved__ if the future associated with the task has already been retrieved. `std::bad_alloc` if any
|
||||
memory necessary could not be allocated.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:set_value Member Function `set_value()`]
|
||||
|
||||
void set_value(R&& r);
|
||||
void set_value(const R& r);
|
||||
void promise<R&>::set_value(R& r);
|
||||
void promise<void>::set_value();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [If `*this` was not associated with a result, allocate storage for a new asynchronous result and associate it with
|
||||
`*this`. Store the value `r` in the asynchronous result associated with `*this`. Any threads blocked waiting for the asynchronous
|
||||
result are woken.]]
|
||||
|
||||
[[Postconditions:] [All futures waiting on the asynchronous result are ['ready] and __unique_future_has_value__ or
|
||||
__shared_future_has_value__ for those futures shall return `true`.]]
|
||||
|
||||
[[Throws:] [__promise_already_satisfied__ if the result associated with `*this` is already ['ready]. `std::bad_alloc` if the memory
|
||||
required for storage of the result cannot be allocated. Any exception thrown by the copy or move-constructor of `R`.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:set_exception Member Function `set_exception()`]
|
||||
|
||||
void set_exception(boost::exception_ptr e);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [If `*this` was not associated with a result, allocate storage for a new asynchronous result and associate it with
|
||||
`*this`. Store the exception `e` in the asynchronous result associated with `*this`. Any threads blocked waiting for the asynchronous
|
||||
result are woken.]]
|
||||
|
||||
[[Postconditions:] [All futures waiting on the asynchronous result are ['ready] and __unique_future_has_exception__ or
|
||||
__shared_future_has_exception__ for those futures shall return `true`.]]
|
||||
|
||||
[[Throws:] [__promise_already_satisfied__ if the result associated with `*this` is already ['ready]. `std::bad_alloc` if the memory
|
||||
required for storage of the result cannot be allocated.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:set_wait_callback Member Function `set_wait_callback()`]
|
||||
|
||||
template<typename F>
|
||||
void set_wait_callback(F f);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [The expression `f(t)` where `t` is a lvalue of type __promise__ shall be well-formed. Invoking a copy of
|
||||
`f` shall have the same effect as invoking `f`]]
|
||||
|
||||
[[Effects:] [Store a copy of `f` with the asynchronous result associated with `*this` as a ['wait callback]. This will replace any
|
||||
existing wait callback store alongside that result. If a thread subsequently calls one of the wait functions on a __unique_future__
|
||||
or __shared_future__ associated with this result, and the result is not ['ready], `f(*this)` shall be invoked.]]
|
||||
|
||||
[[Throws:] [`std::bad_alloc` if memory cannot be allocated for the required storage.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:packaged_task `packaged_task` class template]
|
||||
|
||||
template<typename R>
|
||||
class packaged_task
|
||||
{
|
||||
packaged_task(packaged_task&);// = delete;
|
||||
packaged_task& operator=(packaged_task&);// = delete;
|
||||
|
||||
public:
|
||||
// construction and destruction
|
||||
template <class F>
|
||||
explicit packaged_task(F const& f);
|
||||
|
||||
explicit packaged_task(R(*f)());
|
||||
|
||||
template <class F>
|
||||
explicit packaged_task(F&& f);
|
||||
|
||||
// template <class F, class Allocator>
|
||||
// explicit packaged_task(F const& f, Allocator a);
|
||||
// template <class F, class Allocator>
|
||||
// explicit packaged_task(F&& f, Allocator a);
|
||||
|
||||
~packaged_task()
|
||||
{}
|
||||
|
||||
// move support
|
||||
packaged_task(packaged_task&& other);
|
||||
packaged_task& operator=(packaged_task&& other);
|
||||
|
||||
void swap(packaged_task& other);
|
||||
// result retrieval
|
||||
unique_future<R> get_future();
|
||||
|
||||
// execution
|
||||
void operator()();
|
||||
|
||||
template<typename F>
|
||||
void set_wait_callback(F f);
|
||||
};
|
||||
|
||||
[section:task_constructor Task Constructor]
|
||||
|
||||
template<typename F>
|
||||
packaged_task(F const &f);
|
||||
|
||||
packaged_task(R(*f)());
|
||||
|
||||
template<typename F>
|
||||
packaged_task(F&&f);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [`f()` is a valid expression with a return type convertible to `R`. Invoking a copy of `f` shall behave the same
|
||||
as invoking `f`.]]
|
||||
|
||||
[[Effects:] [Constructs a new __packaged_task__ with a copy of `f` stored as the associated task.]]
|
||||
|
||||
[[Throws:] [Any exceptions thrown by the copy (or move) constructor of `f`. `std::bad_alloc` if memory for the internal data
|
||||
structures could not be allocated.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:move_constructor Move Constructor]
|
||||
|
||||
packaged_task(packaged_task && other);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a new __packaged_task__, and transfers ownership of the task associated with `other` to `*this`, leaving `other`
|
||||
with no associated task.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:move_assignment Move Assignment Operator]
|
||||
|
||||
packaged_task& operator=(packaged_task && other);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Transfers ownership of the task associated with `other` to `*this`, leaving `other` with no associated task. If there
|
||||
was already a task associated with `*this`, and that task has not been invoked, sets any futures associated with that task to
|
||||
['ready] with a __broken_promise__ exception as the result. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:destructor Destructor]
|
||||
|
||||
~packaged_task();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Destroys `*this`. If there was a task associated with `*this`, and that task has not been invoked, sets any futures
|
||||
associated with that task to ['ready] with a __broken_promise__ exception as the result.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:get_future Member Function `get_future()`]
|
||||
|
||||
unique_future<R> get_future();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Returns a __unique_future__ associated with the result of the task associated with `*this`. ]]
|
||||
|
||||
[[Throws:] [__task_moved__ if ownership of the task associated with `*this` has been moved to another instance of
|
||||
__packaged_task__. __future_already_retrieved__ if the future associated with the task has already been retrieved.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:call_operator Member Function `operator()()`]
|
||||
|
||||
void operator()();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Invoke the task associated with `*this` and store the result in the corresponding future. If the task returns normally,
|
||||
the return value is stored as the asynchronous result, otherwise the exception thrown is stored. Any threads blocked waiting for the
|
||||
asynchronous result associated with this task are woken.]]
|
||||
|
||||
[[Postconditions:] [All futures waiting on the asynchronous result are ['ready]]]
|
||||
|
||||
[[Throws:] [__task_moved__ if ownership of the task associated with `*this` has been moved to another instance of
|
||||
__packaged_task__. __task_already_started__ if the task has already been invoked.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:set_wait_callback Member Function `set_wait_callback()`]
|
||||
|
||||
template<typename F>
|
||||
void set_wait_callback(F f);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[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 task associated with `*this` as a ['wait callback]. This will replace any existing wait
|
||||
callback store alongside that task. If a thread subsequently calls one of the wait functions on a __unique_future__ or
|
||||
__shared_future__ associated with this task, and the result of the task is not ['ready], `f(*this)` shall be invoked.]]
|
||||
|
||||
[[Throws:] [__task_moved__ if ownership of the task associated with `*this` has been moved to another instance of
|
||||
__packaged_task__.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:wait_for_any Non-member function `wait_for_any()`]
|
||||
|
||||
template<typename Iterator>
|
||||
Iterator wait_for_any(Iterator begin,Iterator end);
|
||||
|
||||
template<typename F1,typename F2>
|
||||
unsigned wait_for_any(F1& f1,F2& f2);
|
||||
|
||||
template<typename F1,typename F2,typename F3>
|
||||
unsigned wait_for_any(F1& f1,F2& f2,F3& f3);
|
||||
|
||||
template<typename F1,typename F2,typename F3,typename F4>
|
||||
unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4);
|
||||
|
||||
template<typename F1,typename F2,typename F3,typename F4,typename F5>
|
||||
unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [The types `Fn` shall be specializations of
|
||||
__unique_future__ or __shared_future__, and `Iterator` shall be a
|
||||
forward iterator with a `value_type` which is a specialization of
|
||||
__unique_future__ or __shared_future__.]]
|
||||
|
||||
[[Effects:] [Waits until at least one of the specified futures is ['ready].]]
|
||||
|
||||
[[Returns:] [The range-based overload returns an `Iterator` identifying the first future in the range that was detected as
|
||||
['ready]. The remaining overloads return the zero-based index of the first future that was detected as ['ready] (first parameter =>
|
||||
0, second parameter => 1, etc.).]]
|
||||
|
||||
[[Throws:] [__thread_interrupted__ if the current thread is interrupted. Any exception thrown by the ['wait callback] associated
|
||||
with any of the futures being waited for. `std::bad_alloc` if memory could not be allocated for the internal wait structures.]]
|
||||
|
||||
[[Notes:] [`wait_for_any()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:wait_for_all Non-member function `wait_for_all()`]
|
||||
|
||||
template<typename Iterator>
|
||||
void wait_for_all(Iterator begin,Iterator end);
|
||||
|
||||
template<typename F1,typename F2>
|
||||
void wait_for_all(F1& f1,F2& f2);
|
||||
|
||||
template<typename F1,typename F2,typename F3>
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3);
|
||||
|
||||
template<typename F1,typename F2,typename F3,typename F4>
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4);
|
||||
|
||||
template<typename F1,typename F2,typename F3,typename F4,typename F5>
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [The types `Fn` shall be specializations of
|
||||
__unique_future__ or __shared_future__, and `Iterator` shall be a
|
||||
forward iterator with a `value_type` which is a specialization of
|
||||
__unique_future__ or __shared_future__.]]
|
||||
|
||||
[[Effects:] [Waits until all of the specified futures are ['ready].]]
|
||||
|
||||
[[Throws:] [Any exceptions thrown by a call to `wait()` on the specified futures.]]
|
||||
|
||||
[[Notes:] [`wait_for_all()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
187
doc/futures.qbk
187
doc/futures.qbk
@@ -1,187 +0,0 @@
|
||||
[/
|
||||
(C) Copyright 2008-9 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).
|
||||
]
|
||||
|
||||
[section:futures Futures]
|
||||
|
||||
[template future_state_link[link_text] [link thread.synchronization.futures.reference.future_state [link_text]]]
|
||||
[def __uninitialized__ [future_state_link `boost::future_state::uninitialized`]]
|
||||
[def __ready__ [future_state_link `boost::future_state::ready`]]
|
||||
[def __waiting__ [future_state_link `boost::future_state::waiting`]]
|
||||
|
||||
[def __future_uninitialized__ `boost::future_uninitialized`]
|
||||
[def __broken_promise__ `boost::broken_promise`]
|
||||
[def __future_already_retrieved__ `boost::future_already_retrieved`]
|
||||
[def __task_moved__ `boost::task_moved`]
|
||||
[def __task_already_started__ `boost::task_already_started`]
|
||||
[def __promise_already_satisfied__ `boost::promise_already_satisfied`]
|
||||
|
||||
[def __thread_interrupted__ `boost::thread_interrupted`]
|
||||
|
||||
|
||||
[template unique_future_link[link_text] [link thread.synchronization.futures.reference.unique_future [link_text]]]
|
||||
[def __unique_future__ [unique_future_link `boost::unique_future`]]
|
||||
|
||||
[template unique_future_get_link[link_text] [link thread.synchronization.futures.reference.unique_future.get [link_text]]]
|
||||
[def __unique_future_get__ [unique_future_get_link `boost::unique_future<R>::get()`]]
|
||||
|
||||
[template unique_future_wait_link[link_text] [link thread.synchronization.futures.reference.unique_future.wait [link_text]]]
|
||||
[def __unique_future_wait__ [unique_future_wait_link `boost::unique_future<R>::wait()`]]
|
||||
|
||||
[template unique_future_is_ready_link[link_text] [link thread.synchronization.futures.reference.unique_future.is_ready [link_text]]]
|
||||
[def __unique_future_is_ready__ [unique_future_is_ready_link `boost::unique_future<R>::is_ready()`]]
|
||||
|
||||
[template unique_future_has_value_link[link_text] [link thread.synchronization.futures.reference.unique_future.has_value [link_text]]]
|
||||
[def __unique_future_has_value__ [unique_future_has_value_link `boost::unique_future<R>::has_value()`]]
|
||||
|
||||
[template unique_future_has_exception_link[link_text] [link thread.synchronization.futures.reference.unique_future.has_exception [link_text]]]
|
||||
[def __unique_future_has_exception__ [unique_future_has_exception_link `boost::unique_future<R>::has_exception()`]]
|
||||
|
||||
[template unique_future_get_state_link[link_text] [link thread.synchronization.futures.reference.unique_future.get_state [link_text]]]
|
||||
[def __unique_future_get_state__ [unique_future_get_state_link `boost::unique_future<R>::get_state()`]]
|
||||
|
||||
[template shared_future_link[link_text] [link thread.synchronization.futures.reference.shared_future [link_text]]]
|
||||
[def __shared_future__ [shared_future_link `boost::shared_future`]]
|
||||
|
||||
[template shared_future_get_link[link_text] [link thread.synchronization.futures.reference.shared_future.get [link_text]]]
|
||||
[def __shared_future_get__ [shared_future_get_link `boost::shared_future<R>::get()`]]
|
||||
|
||||
[template shared_future_wait_link[link_text] [link thread.synchronization.futures.reference.shared_future.wait [link_text]]]
|
||||
[def __shared_future_wait__ [shared_future_wait_link `boost::shared_future<R>::wait()`]]
|
||||
|
||||
[template shared_future_is_ready_link[link_text] [link thread.synchronization.futures.reference.shared_future.is_ready [link_text]]]
|
||||
[def __shared_future_is_ready__ [shared_future_is_ready_link `boost::shared_future<R>::is_ready()`]]
|
||||
|
||||
[template shared_future_has_value_link[link_text] [link thread.synchronization.futures.reference.shared_future.has_value [link_text]]]
|
||||
[def __shared_future_has_value__ [shared_future_has_value_link `boost::shared_future<R>::has_value()`]]
|
||||
|
||||
[template shared_future_has_exception_link[link_text] [link thread.synchronization.futures.reference.shared_future.has_exception [link_text]]]
|
||||
[def __shared_future_has_exception__ [shared_future_has_exception_link `boost::shared_future<R>::has_exception()`]]
|
||||
|
||||
[template shared_future_get_state_link[link_text] [link thread.synchronization.futures.reference.shared_future.get_state [link_text]]]
|
||||
[def __shared_future_get_state__ [shared_future_get_state_link `boost::shared_future<R>::get_state()`]]
|
||||
|
||||
[template promise_link[link_text] [link thread.synchronization.futures.reference.promise [link_text]]]
|
||||
[def __promise__ [promise_link `boost::promise`]]
|
||||
|
||||
[template packaged_task_link[link_text] [link thread.synchronization.futures.reference.packaged_task [link_text]]]
|
||||
[def __packaged_task__ [packaged_task_link `boost::packaged_task`]]
|
||||
|
||||
[template wait_for_any_link[link_text] [link thread.synchronization.futures.reference.wait_for_any [link_text]]]
|
||||
[def __wait_for_any__ [wait_for_any_link `boost::wait_for_any()`]]
|
||||
|
||||
[template wait_for_all_link[link_text] [link thread.synchronization.futures.reference.wait_for_all [link_text]]]
|
||||
[def __wait_for_all__ [wait_for_all_link `boost::wait_for_all()`]]
|
||||
|
||||
|
||||
[section:overview Overview]
|
||||
|
||||
The futures library provides a means of handling synchronous future values, whether those values are generated by another thread, or
|
||||
on a single thread in response to external stimuli, or on-demand.
|
||||
|
||||
This is done through the provision of four class templates: __unique_future__ and __shared_future__ which are used to retrieve the
|
||||
asynchronous results, and __promise__ and __packaged_task__ which are used to generate the asynchronous results.
|
||||
|
||||
An instance of __unique_future__ holds the one and only reference to a result. Ownership can be transferred between instances using
|
||||
the move constructor or move-assignment operator, but at most one instance holds a reference to a given asynchronous result. When
|
||||
the result is ready, it is returned from __unique_future_get__ by rvalue-reference to allow the result to be moved or copied as
|
||||
appropriate for the type.
|
||||
|
||||
On the other hand, many instances of __shared_future__ may reference the same result. Instances can be freely copied and assigned,
|
||||
and __shared_future_get__ returns a `const` reference so that multiple calls to __shared_future_get__ are safe. You can move an
|
||||
instance of __unique_future__ into an instance of __shared_future__, thus transferring ownership of the associated asynchronous
|
||||
result, but not vice-versa.
|
||||
|
||||
You can wait for futures either individually or with one of the __wait_for_any__ and __wait_for_all__ functions.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:creating Creating asynchronous values]
|
||||
|
||||
You can set the value in a future with either a __promise__ or a __packaged_task__. A __packaged_task__ is a callable object that
|
||||
wraps a function or callable object. When the packaged task is invoked, it invokes the contained function in turn, and populates a
|
||||
future with the return value. This is an answer to the perennial question: "how do I return a value from a thread?": package the
|
||||
function you wish to run as a __packaged_task__ and pass the packaged task to the thread constructor. The future retrieved from the
|
||||
packaged task can then be used to obtain the return value. If the function throws an exception, that is stored in the future in
|
||||
place of the return value.
|
||||
|
||||
int calculate_the_answer_to_life_the_universe_and_everything()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
||||
A __promise__ is a bit more low level: it just provides explicit functions to store a value or an exception in the associated
|
||||
future. A promise can therefore be used where the value may come from more than one possible source, or where a single operation may
|
||||
produce multiple values.
|
||||
|
||||
boost::promise<int> pi;
|
||||
boost::unique_future<int> fi;
|
||||
fi=pi.get_future();
|
||||
|
||||
pi.set_value(42);
|
||||
|
||||
assert(fi.is_ready());
|
||||
assert(fi.has_value());
|
||||
assert(!fi.has_exception());
|
||||
assert(fi.get_state()==boost::future_state::ready);
|
||||
assert(fi.get()==42);
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:lazy_futures Wait Callbacks and Lazy Futures]
|
||||
|
||||
Both __promise__ and __packaged_task__ support ['wait callbacks] that are invoked when a thread blocks in a call to `wait()` or
|
||||
`timed_wait()` on a future that is waiting for the result from the __promise__ or __packaged_task__, in the thread that is doing the
|
||||
waiting. These can be set using the `set_wait_callback()` member function on the __promise__ or __packaged_task__ in question.
|
||||
|
||||
This allows ['lazy futures] where the result is not actually computed until it is needed by some thread. In the example below, the
|
||||
call to `f.get()` invokes the callback `invoke_lazy_task`, which runs the task to set the value. If you remove the call to
|
||||
`f.get()`, the task is not ever run.
|
||||
|
||||
int calculate_the_answer_to_life_the_universe_and_everything()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
void invoke_lazy_task(boost::packaged_task<int>& task)
|
||||
{
|
||||
try
|
||||
{
|
||||
task();
|
||||
}
|
||||
catch(boost::task_already_started&)
|
||||
{}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::packaged_task<int> task(calculate_the_answer_to_life_the_universe_and_everything);
|
||||
task.set_wait_callback(invoke_lazy_task);
|
||||
boost::unique_future<int> f(task.get_future());
|
||||
|
||||
assert(f.get()==42);
|
||||
}
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[include future_ref.qbk]
|
||||
|
||||
[endsect]
|
||||
@@ -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>
|
||||
|
||||
@@ -45,15 +45,6 @@ all subsequent `call_once` invocations on the same `once_flag` object. ]]
|
||||
|
||||
[[Throws:] [`thread_resource_error` when the effects cannot be achieved. or any exception propagated from `func`.]]
|
||||
|
||||
[[Note:] [The function passed to `call_once` must not also call
|
||||
`call_once` passing the same `once_flag` object. This may cause
|
||||
deadlock, or invoking the passed function a second time. The
|
||||
alternative is to allow the second call to return immediately, but
|
||||
that assumes the code knows it has been called recursively, and can
|
||||
proceed even though the call to `call_once` didn't actually call the
|
||||
function, in which case it could also avoid calling `call_once`
|
||||
recursively.]]
|
||||
|
||||
]
|
||||
|
||||
void call_once(void (*func)(),once_flag& flag);
|
||||
|
||||
@@ -158,7 +158,6 @@
|
||||
[include condition_variables.qbk]
|
||||
[include once.qbk]
|
||||
[include barrier.qbk]
|
||||
[include futures.qbk]
|
||||
[endsect]
|
||||
|
||||
[include tss.qbk]
|
||||
@@ -166,5 +165,3 @@
|
||||
[include time.qbk]
|
||||
|
||||
[include acknowledgements.qbk]
|
||||
|
||||
[include compliance.qbk]
|
||||
|
||||
@@ -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.]]
|
||||
|
||||
@@ -1012,13 +916,6 @@ exits (even if the thread has been interrupted).]]
|
||||
[[Throws:] [`std::bad_alloc` if memory cannot be allocated for the copy of the function, __thread_resource_error__ if any other
|
||||
error occurs within the thread library. Any exception thrown whilst copying `func` into internal storage.]]
|
||||
|
||||
[[Note:] [This function is *not* called if the thread was terminated
|
||||
forcefully using platform-specific APIs, or if the thread is
|
||||
terminated due to a call to `exit()`, `abort()` or
|
||||
`std::terminate()`. In particular, returning from `main()` is
|
||||
equivalent to call to `exit()`, so will not call any functions
|
||||
registered with `at_thread_exit()`]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -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`]
|
||||
|
||||
|
||||
@@ -50,9 +50,8 @@ boost::mutex io_mutex;
|
||||
|
||||
void sender() {
|
||||
int n = 0;
|
||||
while (n < 1000000) {
|
||||
while (n < 100) {
|
||||
buf.send(n);
|
||||
if(!(n%10000))
|
||||
{
|
||||
boost::mutex::scoped_lock io_lock(io_mutex);
|
||||
std::cout << "sent: " << n << std::endl;
|
||||
@@ -66,24 +65,18 @@ void receiver() {
|
||||
int n;
|
||||
do {
|
||||
n = buf.receive();
|
||||
if(!(n%10000))
|
||||
{
|
||||
boost::mutex::scoped_lock io_lock(io_mutex);
|
||||
std::cout << "received: " << n << std::endl;
|
||||
}
|
||||
} while (n != -1); // -1 indicates end of buffer
|
||||
buf.send(-1);
|
||||
}
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
boost::thread thrd1(&sender);
|
||||
boost::thread thrd2(&receiver);
|
||||
boost::thread thrd3(&receiver);
|
||||
boost::thread thrd4(&receiver);
|
||||
thrd1.join();
|
||||
thrd2.join();
|
||||
thrd3.join();
|
||||
thrd4.join();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ int main(int argc, char* argv[])
|
||||
std::cout << "---Noise ON..." << std::endl;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000000000; ++i)
|
||||
for (int i = 0; i < 1000000; ++i)
|
||||
cond.notify_all();
|
||||
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// (C) Copyright 2008-9 Anthony Williams
|
||||
// (C) Copyright 2008 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)
|
||||
@@ -21,6 +21,5 @@
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/barrier.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#define BOOST_BARRIER_JDM030602_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
@@ -28,7 +27,7 @@ namespace boost
|
||||
: m_threshold(count), m_count(count), m_generation(0)
|
||||
{
|
||||
if (count == 0)
|
||||
boost::throw_exception(std::invalid_argument("count cannot be zero."));
|
||||
throw std::invalid_argument("count cannot be zero.");
|
||||
}
|
||||
|
||||
bool wait()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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> >, T >::type move(T& t)
|
||||
{
|
||||
return boost::detail::thread_move_t<T>(t);
|
||||
return T(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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -42,13 +39,10 @@ namespace boost
|
||||
public detail::thread_data_base
|
||||
{
|
||||
public:
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
thread_data(F&& f_):
|
||||
f(static_cast<F&&>(f_))
|
||||
{}
|
||||
thread_data(F& f_):
|
||||
f(f_)
|
||||
{}
|
||||
#else
|
||||
thread_data(F f_):
|
||||
f(f_)
|
||||
@@ -56,7 +50,7 @@ namespace boost
|
||||
thread_data(detail::thread_move_t<F> f_):
|
||||
f(f_)
|
||||
{}
|
||||
#endif
|
||||
#endif
|
||||
void run()
|
||||
{
|
||||
f();
|
||||
@@ -81,7 +75,7 @@ namespace boost
|
||||
thread_data(boost::reference_wrapper<F> f_):
|
||||
f(f_)
|
||||
{}
|
||||
|
||||
|
||||
void run()
|
||||
{
|
||||
f();
|
||||
@@ -100,14 +94,14 @@ namespace boost
|
||||
thread_data(const boost::reference_wrapper<F> f_):
|
||||
f(f_)
|
||||
{}
|
||||
|
||||
|
||||
void run()
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
class BOOST_THREAD_DECL thread
|
||||
{
|
||||
private:
|
||||
@@ -115,16 +109,17 @@ 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
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
template<typename F>
|
||||
static inline detail::thread_data_ptr make_thread_info(F&& f)
|
||||
{
|
||||
@@ -132,7 +127,7 @@ namespace boost
|
||||
}
|
||||
static inline detail::thread_data_ptr make_thread_info(void (*f)())
|
||||
{
|
||||
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(static_cast<void(*&&)()>(f)));
|
||||
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(f));
|
||||
}
|
||||
#else
|
||||
template<typename F>
|
||||
@@ -146,37 +141,25 @@ namespace boost
|
||||
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
|
||||
}
|
||||
|
||||
#endif
|
||||
struct dummy;
|
||||
public:
|
||||
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
|
||||
thread(const volatile thread&);
|
||||
#endif
|
||||
public:
|
||||
thread();
|
||||
~thread();
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#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)))
|
||||
{
|
||||
start_thread();
|
||||
}
|
||||
#else
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
template <class F>
|
||||
thread(F&& f):
|
||||
thread_info(make_thread_info(static_cast<F&&>(f)))
|
||||
{
|
||||
start_thread();
|
||||
}
|
||||
#endif
|
||||
|
||||
thread(thread&& other)
|
||||
{
|
||||
thread_info.swap(other.thread_info);
|
||||
}
|
||||
|
||||
|
||||
thread& operator=(thread&& other)
|
||||
{
|
||||
thread_info=other.thread_info;
|
||||
@@ -188,7 +171,7 @@ namespace boost
|
||||
{
|
||||
return static_cast<thread&&>(*this);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
#ifdef BOOST_NO_SFINAE
|
||||
template <class F>
|
||||
@@ -205,7 +188,7 @@ namespace boost
|
||||
start_thread();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
template <class F>
|
||||
explicit thread(detail::thread_move_t<F> f):
|
||||
thread_info(make_thread_info(f))
|
||||
@@ -218,26 +201,19 @@ 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;
|
||||
}
|
||||
#else
|
||||
|
||||
thread& operator=(detail::thread_move_t<thread> x)
|
||||
{
|
||||
thread new_thread(x);
|
||||
swap(new_thread);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
operator detail::thread_move_t<thread>()
|
||||
{
|
||||
return move();
|
||||
}
|
||||
|
||||
|
||||
detail::thread_move_t<thread> move()
|
||||
{
|
||||
detail::thread_move_t<thread> x(*this);
|
||||
@@ -313,7 +289,7 @@ namespace boost
|
||||
thread_info.swap(x.thread_info);
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE id;
|
||||
class id;
|
||||
id get_id() const;
|
||||
|
||||
|
||||
@@ -341,7 +317,7 @@ namespace boost
|
||||
{
|
||||
this_thread::yield();
|
||||
}
|
||||
|
||||
|
||||
static inline void sleep(const system_time& xt)
|
||||
{
|
||||
this_thread::sleep(xt);
|
||||
@@ -356,178 +332,152 @@ namespace boost
|
||||
{
|
||||
return lhs.swap(rhs);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
inline thread&& move(thread& t)
|
||||
{
|
||||
return static_cast<thread&&>(t);
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
inline thread&& move(thread&& t)
|
||||
{
|
||||
return static_cast<thread&&>(t);
|
||||
return t;
|
||||
}
|
||||
#else
|
||||
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
|
||||
inline thread move(detail::thread_move_t<thread> t)
|
||||
{
|
||||
return t;
|
||||
return thread(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
class BOOST_THREAD_DECL disable_interruption
|
||||
{
|
||||
disable_interruption(const disable_interruption&);
|
||||
disable_interruption& operator=(const disable_interruption&);
|
||||
|
||||
bool interruption_was_enabled;
|
||||
friend class restore_interruption;
|
||||
public:
|
||||
disable_interruption();
|
||||
~disable_interruption();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL restore_interruption
|
||||
{
|
||||
restore_interruption(const restore_interruption&);
|
||||
restore_interruption& operator=(const restore_interruption&);
|
||||
public:
|
||||
explicit restore_interruption(disable_interruption& d);
|
||||
~restore_interruption();
|
||||
};
|
||||
|
||||
thread::id BOOST_THREAD_DECL get_id();
|
||||
|
||||
void BOOST_THREAD_DECL interruption_point();
|
||||
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
|
||||
{
|
||||
virtual ~thread_exit_function_base()
|
||||
{}
|
||||
virtual void operator()()=0;
|
||||
virtual void operator()() const=0;
|
||||
};
|
||||
|
||||
|
||||
template<typename F>
|
||||
struct thread_exit_function:
|
||||
thread_exit_function_base
|
||||
{
|
||||
F f;
|
||||
|
||||
|
||||
thread_exit_function(F f_):
|
||||
f(f_)
|
||||
{}
|
||||
|
||||
void operator()()
|
||||
|
||||
void operator()() const
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
|
||||
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
|
||||
|
||||
void 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>
|
||||
@@ -537,6 +487,83 @@ namespace boost
|
||||
detail::add_thread_exit_function(thread_exit_func);
|
||||
}
|
||||
}
|
||||
|
||||
class thread_group:
|
||||
private noncopyable
|
||||
{
|
||||
public:
|
||||
~thread_group()
|
||||
{
|
||||
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
thread* create_thread(F threadfunc)
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
std::auto_ptr<thread> new_thread(new thread(threadfunc));
|
||||
threads.push_back(new_thread.get());
|
||||
return new_thread.release();
|
||||
}
|
||||
|
||||
void add_thread(thread* thrd)
|
||||
{
|
||||
if(thrd)
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
threads.push_back(thrd);
|
||||
}
|
||||
}
|
||||
|
||||
void remove_thread(thread* thrd)
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
std::list<thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd);
|
||||
if(it!=threads.end())
|
||||
{
|
||||
threads.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void join_all()
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
|
||||
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
(*it)->join();
|
||||
}
|
||||
}
|
||||
|
||||
void interrupt_all()
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
|
||||
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
(*it)->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
return threads.size();
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<thread*> threads;
|
||||
mutable mutex m;
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
#ifndef BOOST_THREAD_DETAIL_THREAD_GROUP_HPP
|
||||
#define BOOST_THREAD_DETAIL_THREAD_GROUP_HPP
|
||||
// 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-9 Anthony Williams
|
||||
|
||||
#include <list>
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4251)
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class thread_group
|
||||
{
|
||||
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();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
thread* create_thread(F threadfunc)
|
||||
{
|
||||
boost::lock_guard<shared_mutex> guard(m);
|
||||
std::auto_ptr<thread> new_thread(new thread(threadfunc));
|
||||
threads.push_back(new_thread.get());
|
||||
return new_thread.release();
|
||||
}
|
||||
|
||||
void add_thread(thread* thrd)
|
||||
{
|
||||
if(thrd)
|
||||
{
|
||||
boost::lock_guard<shared_mutex> guard(m);
|
||||
threads.push_back(thrd);
|
||||
}
|
||||
}
|
||||
|
||||
void remove_thread(thread* thrd)
|
||||
{
|
||||
boost::lock_guard<shared_mutex> guard(m);
|
||||
std::list<thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd);
|
||||
if(it!=threads.end())
|
||||
{
|
||||
threads.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void join_all()
|
||||
{
|
||||
boost::shared_lock<shared_mutex> guard(m);
|
||||
|
||||
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
(*it)->join();
|
||||
}
|
||||
}
|
||||
|
||||
void interrupt_all()
|
||||
{
|
||||
boost::shared_lock<shared_mutex> guard(m);
|
||||
|
||||
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
(*it)->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
boost::shared_lock<shared_mutex> guard(m);
|
||||
return threads.size();
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<thread*> threads;
|
||||
mutable shared_mutex m;
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -1,35 +0,0 @@
|
||||
#ifndef BOOST_THREAD_DETAIL_THREAD_INTERRUPTION_HPP
|
||||
#define BOOST_THREAD_DETAIL_THREAD_INTERRUPTION_HPP
|
||||
// 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-9 Anthony Williams
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace this_thread
|
||||
{
|
||||
class BOOST_THREAD_DECL disable_interruption
|
||||
{
|
||||
disable_interruption(const disable_interruption&);
|
||||
disable_interruption& operator=(const disable_interruption&);
|
||||
|
||||
bool interruption_was_enabled;
|
||||
friend class restore_interruption;
|
||||
public:
|
||||
disable_interruption();
|
||||
~disable_interruption();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL restore_interruption
|
||||
{
|
||||
restore_interruption(const restore_interruption&);
|
||||
restore_interruption& operator=(const restore_interruption&);
|
||||
public:
|
||||
explicit restore_interruption(disable_interruption& d);
|
||||
~restore_interruption();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright (C) 2007-9 Anthony Williams
|
||||
// Copyright (C) 2007-8 Anthony Williams
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -24,38 +24,25 @@
|
||||
namespace boost
|
||||
{
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE thread_interrupted
|
||||
class BOOST_THREAD_DECL thread_interrupted
|
||||
{};
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE thread_exception:
|
||||
public std::exception
|
||||
{
|
||||
protected:
|
||||
thread_exception():
|
||||
m_sys_err(0)
|
||||
{}
|
||||
|
||||
thread_exception(int sys_err_code):
|
||||
m_sys_err(sys_err_code)
|
||||
{}
|
||||
|
||||
class BOOST_THREAD_DECL thread_exception : public std::exception
|
||||
{
|
||||
protected:
|
||||
thread_exception();
|
||||
thread_exception(int sys_err_code);
|
||||
|
||||
public:
|
||||
~thread_exception() throw()
|
||||
{}
|
||||
|
||||
public:
|
||||
~thread_exception() throw();
|
||||
|
||||
int native_error() const
|
||||
{
|
||||
return m_sys_err;
|
||||
}
|
||||
|
||||
int native_error() const;
|
||||
|
||||
private:
|
||||
int m_sys_err;
|
||||
};
|
||||
private:
|
||||
int m_sys_err;
|
||||
};
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE condition_error:
|
||||
class condition_error:
|
||||
public std::exception
|
||||
{
|
||||
public:
|
||||
@@ -66,117 +53,62 @@ namespace boost
|
||||
};
|
||||
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE lock_error:
|
||||
public thread_exception
|
||||
{
|
||||
public:
|
||||
lock_error()
|
||||
{}
|
||||
|
||||
lock_error(int sys_err_code):
|
||||
thread_exception(sys_err_code)
|
||||
{}
|
||||
|
||||
~lock_error() throw()
|
||||
{}
|
||||
|
||||
class BOOST_THREAD_DECL lock_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
lock_error();
|
||||
lock_error(int sys_err_code);
|
||||
~lock_error() throw();
|
||||
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return "boost::lock_error";
|
||||
}
|
||||
};
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE thread_resource_error:
|
||||
public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_resource_error()
|
||||
{}
|
||||
|
||||
thread_resource_error(int sys_err_code):
|
||||
thread_exception(sys_err_code)
|
||||
{}
|
||||
|
||||
~thread_resource_error() throw()
|
||||
{}
|
||||
|
||||
class BOOST_THREAD_DECL thread_resource_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_resource_error();
|
||||
thread_resource_error(int sys_err_code);
|
||||
~thread_resource_error() throw();
|
||||
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return "boost::thread_resource_error";
|
||||
}
|
||||
|
||||
};
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE unsupported_thread_option:
|
||||
public thread_exception
|
||||
{
|
||||
public:
|
||||
unsupported_thread_option()
|
||||
{}
|
||||
|
||||
unsupported_thread_option(int sys_err_code):
|
||||
thread_exception(sys_err_code)
|
||||
{}
|
||||
|
||||
~unsupported_thread_option() throw()
|
||||
{}
|
||||
|
||||
class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception
|
||||
{
|
||||
public:
|
||||
unsupported_thread_option();
|
||||
unsupported_thread_option(int sys_err_code);
|
||||
~unsupported_thread_option() throw();
|
||||
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return "boost::unsupported_thread_option";
|
||||
}
|
||||
|
||||
};
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE invalid_thread_argument:
|
||||
public thread_exception
|
||||
{
|
||||
public:
|
||||
invalid_thread_argument()
|
||||
{}
|
||||
|
||||
invalid_thread_argument(int sys_err_code):
|
||||
thread_exception(sys_err_code)
|
||||
{}
|
||||
|
||||
~invalid_thread_argument() throw()
|
||||
{}
|
||||
|
||||
class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception
|
||||
{
|
||||
public:
|
||||
invalid_thread_argument();
|
||||
invalid_thread_argument(int sys_err_code);
|
||||
~invalid_thread_argument() throw();
|
||||
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return "boost::invalid_thread_argument";
|
||||
}
|
||||
|
||||
};
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE thread_permission_error:
|
||||
public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_permission_error()
|
||||
{}
|
||||
|
||||
thread_permission_error(int sys_err_code):
|
||||
thread_exception(sys_err_code)
|
||||
{}
|
||||
|
||||
~thread_permission_error() throw()
|
||||
{}
|
||||
|
||||
class BOOST_THREAD_DECL thread_permission_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_permission_error();
|
||||
thread_permission_error(int sys_err_code);
|
||||
~thread_permission_error() throw();
|
||||
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return "boost::thread_permission_error";
|
||||
}
|
||||
|
||||
};
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#endif // BOOST_THREAD_CONFIG_PDM070801_H
|
||||
|
||||
// Change log:
|
||||
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,10 @@ 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&);
|
||||
#endif
|
||||
unique_lock():
|
||||
m(0),is_locked(false)
|
||||
{}
|
||||
|
||||
|
||||
explicit unique_lock(Mutex& m_):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
@@ -311,7 +245,7 @@ namespace boost
|
||||
{
|
||||
timed_lock(target_time);
|
||||
}
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
unique_lock(unique_lock&& other):
|
||||
m(other.m),is_locked(other.is_locked)
|
||||
{
|
||||
@@ -326,16 +260,16 @@ namespace boost
|
||||
}
|
||||
|
||||
|
||||
unique_lock& operator=(unique_lock&& other)
|
||||
unique_lock& operator=(unique_lock<Mutex>&& other)
|
||||
{
|
||||
unique_lock temp(other.move());
|
||||
unique_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_lock& operator=(upgrade_lock<Mutex>&& other)
|
||||
{
|
||||
unique_lock temp(other.move());
|
||||
unique_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
@@ -363,20 +297,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;
|
||||
}
|
||||
#else
|
||||
unique_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
|
||||
{
|
||||
unique_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
unique_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
|
||||
{
|
||||
@@ -384,18 +310,18 @@ namespace boost
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
void swap(unique_lock& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
void swap(detail::thread_move_t<unique_lock<Mutex> > other)
|
||||
{
|
||||
std::swap(m,other->m);
|
||||
std::swap(is_locked,other->is_locked);
|
||||
}
|
||||
#endif
|
||||
void swap(unique_lock& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
|
||||
|
||||
~unique_lock()
|
||||
{
|
||||
if(owns_lock())
|
||||
@@ -407,7 +333,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->lock();
|
||||
is_locked=true;
|
||||
@@ -416,7 +342,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->try_lock();
|
||||
return is_locked;
|
||||
@@ -427,7 +353,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);
|
||||
@@ -442,12 +368,12 @@ namespace boost
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->unlock();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
|
||||
typedef void (unique_lock::*bool_type)();
|
||||
operator bool_type() const
|
||||
{
|
||||
@@ -479,50 +405,26 @@ namespace boost
|
||||
friend class upgrade_lock<Mutex>;
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
template<typename Mutex>
|
||||
void swap(unique_lock<Mutex>&& lhs,unique_lock<Mutex>&& rhs)
|
||||
{
|
||||
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
|
||||
#else
|
||||
template<typename Mutex>
|
||||
void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs)
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
template<typename Mutex>
|
||||
inline unique_lock<Mutex>&& move(unique_lock<Mutex>&& ul)
|
||||
{
|
||||
return static_cast<unique_lock<Mutex>&&>(ul);
|
||||
return ul;
|
||||
}
|
||||
|
||||
template<typename Mutex>
|
||||
inline unique_lock<Mutex>&& move(unique_lock<Mutex>& ul)
|
||||
{
|
||||
return static_cast<unique_lock<Mutex>&&>(ul);
|
||||
}
|
||||
#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>
|
||||
@@ -538,7 +440,7 @@ namespace boost
|
||||
shared_lock():
|
||||
m(0),is_locked(false)
|
||||
{}
|
||||
|
||||
|
||||
explicit shared_lock(Mutex& m_):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
@@ -560,9 +462,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,32 +523,31 @@ namespace boost
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
void swap(shared_lock&& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
#else
|
||||
void swap(shared_lock& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
void swap(boost::detail::thread_move_t<shared_lock<Mutex> > other)
|
||||
{
|
||||
std::swap(m,other->m);
|
||||
std::swap(is_locked,other->is_locked);
|
||||
}
|
||||
#endif
|
||||
void swap(shared_lock& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
|
||||
Mutex* mutex() const
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
~shared_lock()
|
||||
{
|
||||
if(owns_lock())
|
||||
@@ -660,7 +559,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->lock_shared();
|
||||
is_locked=true;
|
||||
@@ -669,7 +568,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->try_lock_shared();
|
||||
return is_locked;
|
||||
@@ -678,7 +577,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->timed_lock_shared(target_time);
|
||||
return is_locked;
|
||||
@@ -688,7 +587,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->timed_lock_shared(target_time);
|
||||
return is_locked;
|
||||
@@ -697,12 +596,12 @@ namespace boost
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->unlock_shared();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
|
||||
typedef void (shared_lock<Mutex>::*bool_type)();
|
||||
operator bool_type() const
|
||||
{
|
||||
@@ -719,25 +618,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
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
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 +645,7 @@ namespace boost
|
||||
upgrade_lock():
|
||||
m(0),is_locked(false)
|
||||
{}
|
||||
|
||||
|
||||
explicit upgrade_lock(Mutex& m_):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
@@ -776,39 +662,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 +704,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())
|
||||
@@ -870,7 +722,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->lock_upgrade();
|
||||
is_locked=true;
|
||||
@@ -879,7 +731,7 @@ namespace boost
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->try_lock_upgrade();
|
||||
return is_locked;
|
||||
@@ -888,12 +740,12 @@ namespace boost
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->unlock_upgrade();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
|
||||
typedef void (upgrade_lock::*bool_type)();
|
||||
operator bool_type() const
|
||||
{
|
||||
@@ -911,14 +763,8 @@ 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
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
template<typename Mutex>
|
||||
unique_lock<Mutex>::unique_lock(upgrade_lock<Mutex>&& other):
|
||||
m(other.m),is_locked(other.is_locked)
|
||||
@@ -926,7 +772,7 @@ namespace boost
|
||||
other.is_locked=false;
|
||||
if(is_locked)
|
||||
{
|
||||
m->unlock_upgrade_and_lock();
|
||||
m.unlock_upgrade_and_lock();
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -962,33 +808,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 +840,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 +850,7 @@ namespace boost
|
||||
public:
|
||||
try_lock_wrapper()
|
||||
{}
|
||||
|
||||
|
||||
explicit try_lock_wrapper(Mutex& m):
|
||||
base(m,try_to_lock)
|
||||
{}
|
||||
@@ -1040,28 +864,6 @@ namespace boost
|
||||
try_lock_wrapper(Mutex& m_,try_to_lock_t):
|
||||
base(m_,try_to_lock)
|
||||
{}
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
try_lock_wrapper(try_lock_wrapper&& other):
|
||||
base(other.move())
|
||||
{}
|
||||
|
||||
try_lock_wrapper&& move()
|
||||
{
|
||||
return static_cast<try_lock_wrapper&&>(*this);
|
||||
}
|
||||
|
||||
try_lock_wrapper& operator=(try_lock_wrapper<Mutex>&& other)
|
||||
{
|
||||
try_lock_wrapper temp(other.move());
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(try_lock_wrapper&& other)
|
||||
{
|
||||
base::swap(other);
|
||||
}
|
||||
#else
|
||||
try_lock_wrapper(detail::thread_move_t<try_lock_wrapper<Mutex> > other):
|
||||
base(detail::thread_move_t<base>(*other))
|
||||
{}
|
||||
@@ -1083,15 +885,22 @@ namespace boost
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
void swap(try_lock_wrapper&& other)
|
||||
{
|
||||
base::swap(other);
|
||||
}
|
||||
#else
|
||||
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();
|
||||
@@ -1128,17 +937,12 @@ namespace boost
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
template<typename Mutex>
|
||||
void swap(try_lock_wrapper<Mutex>&& lhs,try_lock_wrapper<Mutex>&& rhs)
|
||||
{
|
||||
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 +950,7 @@ namespace boost
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
template<typename MutexType1,typename MutexType2>
|
||||
unsigned try_lock_internal(MutexType1& m1,MutexType2& m2)
|
||||
{
|
||||
@@ -1275,13 +1079,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 +1107,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 +1138,7 @@ namespace boost
|
||||
{
|
||||
unsigned const lock_count=3;
|
||||
unsigned lock_first=0;
|
||||
for(;;)
|
||||
while(true)
|
||||
{
|
||||
switch(lock_first)
|
||||
{
|
||||
@@ -1366,7 +1170,7 @@ namespace boost
|
||||
{
|
||||
unsigned const lock_count=4;
|
||||
unsigned lock_first=0;
|
||||
for(;;)
|
||||
while(true)
|
||||
{
|
||||
switch(lock_first)
|
||||
{
|
||||
@@ -1404,7 +1208,7 @@ namespace boost
|
||||
{
|
||||
unsigned const lock_count=5;
|
||||
unsigned lock_first=0;
|
||||
for(;;)
|
||||
while(true)
|
||||
{
|
||||
switch(lock_first)
|
||||
{
|
||||
@@ -1448,7 +1252,7 @@ namespace boost
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
|
||||
template<typename Iterator>
|
||||
struct try_lock_impl_return<Iterator,false>
|
||||
{
|
||||
@@ -1464,7 +1268,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 +1310,7 @@ namespace boost
|
||||
{
|
||||
return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@@ -1515,13 +1319,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 +1350,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 +1372,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 +1381,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 +1402,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 +1420,9 @@ namespace boost
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
@@ -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()
|
||||
@@ -111,13 +57,13 @@ namespace boost
|
||||
int const res=pthread_mutex_init(&internal_mutex,NULL);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw 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());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
~condition_variable_any()
|
||||
@@ -125,21 +71,23 @@ 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());
|
||||
throw condition_error();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,26 +96,28 @@ 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;
|
||||
}
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(condition_error());
|
||||
throw condition_error();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
// (C) Copyright 2007-8 Anthony Williams
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <pthread.h>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
@@ -20,35 +19,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());
|
||||
throw 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 +46,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));
|
||||
|
||||
@@ -7,18 +7,17 @@
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#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 +26,10 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class mutex
|
||||
class mutex:
|
||||
boost::noncopyable
|
||||
{
|
||||
private:
|
||||
mutex(mutex const&);
|
||||
mutex& operator=(mutex const&);
|
||||
pthread_mutex_t m;
|
||||
public:
|
||||
mutex()
|
||||
@@ -39,53 +37,28 @@ namespace boost
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
~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 +74,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
|
||||
@@ -118,14 +89,14 @@ namespace boost
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
is_locked=false;
|
||||
#endif
|
||||
@@ -158,7 +129,7 @@ namespace boost
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(&m));
|
||||
}
|
||||
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
int const res=pthread_mutex_trylock(&m);
|
||||
@@ -196,7 +167,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);
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
|
||||
// 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
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#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 +34,7 @@ namespace boost
|
||||
BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
|
||||
BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
|
||||
}
|
||||
|
||||
|
||||
#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
|
||||
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace boost
|
||||
static boost::uintmax_t const being_initialized=uninitialized_flag+1;
|
||||
boost::uintmax_t const epoch=flag.epoch;
|
||||
boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
|
||||
|
||||
|
||||
if(epoch<this_thread_epoch)
|
||||
{
|
||||
pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
|
||||
@@ -58,13 +58,10 @@ namespace boost
|
||||
if(flag.epoch==uninitialized_flag)
|
||||
{
|
||||
flag.epoch=being_initialized;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif
|
||||
pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
|
||||
f();
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@@ -72,7 +69,6 @@ namespace boost
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
flag.epoch=--detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
@@ -17,8 +16,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,76 +25,43 @@
|
||||
#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)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
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());
|
||||
throw 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());
|
||||
throw 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 +71,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,38 +105,38 @@ 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)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||
if(set_attr_res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw 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());
|
||||
throw 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());
|
||||
throw 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());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
is_locked=false;
|
||||
count=0;
|
||||
@@ -224,7 +145,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 +156,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 +166,7 @@ namespace boost
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(&m));
|
||||
}
|
||||
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
int const res=pthread_mutex_trylock(&m);
|
||||
@@ -275,7 +196,7 @@ namespace boost
|
||||
++count;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
while(is_locked)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
|
||||
@@ -294,7 +215,7 @@ namespace boost
|
||||
}
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/detail/thread_interruption.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -12,34 +12,22 @@
|
||||
#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 <map>
|
||||
#include "condition_variable_fwd.hpp"
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class thread;
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct tss_cleanup_function;
|
||||
struct thread_exit_callback_node;
|
||||
struct tss_data_node
|
||||
{
|
||||
boost::shared_ptr<boost::detail::tss_cleanup_function> func;
|
||||
void* value;
|
||||
|
||||
tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
|
||||
void* value_):
|
||||
func(func_),value(value_)
|
||||
{}
|
||||
};
|
||||
struct tss_data_node;
|
||||
|
||||
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>
|
||||
{
|
||||
@@ -53,15 +41,14 @@ namespace boost
|
||||
bool join_started;
|
||||
bool joined;
|
||||
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
|
||||
std::map<void const*,boost::detail::tss_data_node> tss_data;
|
||||
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():
|
||||
done(false),join_started(false),joined(false),
|
||||
thread_exit_callbacks(0),
|
||||
thread_exit_callbacks(0),tss_data(0),
|
||||
interrupt_enabled(true),
|
||||
interrupt_requested(false),
|
||||
current_cond(0)
|
||||
@@ -78,8 +65,6 @@ namespace boost
|
||||
class interruption_checker
|
||||
{
|
||||
thread_data_base* const thread_info;
|
||||
pthread_mutex_t* m;
|
||||
bool set;
|
||||
|
||||
void check_for_interruption()
|
||||
{
|
||||
@@ -89,38 +74,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 +102,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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace boost
|
||||
return new T();
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
template<typename T,typename A1>
|
||||
inline T* heap_new(A1&& a1)
|
||||
{
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#endif
|
||||
|
||||
#include <boost/thread/detail/thread.hpp>
|
||||
#include <boost/thread/detail/thread_interruption.hpp>
|
||||
#include <boost/thread/detail/thread_group.hpp>
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,113 +1,111 @@
|
||||
#ifndef BOOST_THREAD_TSS_HPP
|
||||
#define BOOST_THREAD_TSS_HPP
|
||||
// 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-8 Anthony Williams
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread/detail/thread_heap_alloc.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct tss_cleanup_function
|
||||
{
|
||||
virtual ~tss_cleanup_function()
|
||||
{}
|
||||
|
||||
virtual void operator()(void* data)=0;
|
||||
};
|
||||
|
||||
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
|
||||
BOOST_THREAD_DECL void* get_tss_data(void const* key);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class thread_specific_ptr
|
||||
{
|
||||
private:
|
||||
thread_specific_ptr(thread_specific_ptr&);
|
||||
thread_specific_ptr& operator=(thread_specific_ptr&);
|
||||
|
||||
struct delete_data:
|
||||
detail::tss_cleanup_function
|
||||
{
|
||||
void operator()(void* data)
|
||||
{
|
||||
delete static_cast<T*>(data);
|
||||
}
|
||||
};
|
||||
|
||||
struct run_custom_cleanup_function:
|
||||
detail::tss_cleanup_function
|
||||
{
|
||||
void (*cleanup_function)(T*);
|
||||
|
||||
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
|
||||
cleanup_function(cleanup_function_)
|
||||
{}
|
||||
|
||||
void operator()(void* data)
|
||||
{
|
||||
cleanup_function(static_cast<T*>(data));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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>())
|
||||
{}
|
||||
explicit thread_specific_ptr(void (*func_)(T*))
|
||||
{
|
||||
if(func_)
|
||||
{
|
||||
cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
|
||||
}
|
||||
}
|
||||
~thread_specific_ptr()
|
||||
{
|
||||
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,true);
|
||||
}
|
||||
|
||||
T* get() const
|
||||
{
|
||||
return static_cast<T*>(detail::get_tss_data(this));
|
||||
}
|
||||
T* operator->() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
T& operator*() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
T* release()
|
||||
{
|
||||
T* const temp=get();
|
||||
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
|
||||
return temp;
|
||||
}
|
||||
void reset(T* new_value=0)
|
||||
{
|
||||
T* const current_value=get();
|
||||
if(current_value!=new_value)
|
||||
{
|
||||
detail::set_tss_data(this,cleanup,new_value,true);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#ifndef BOOST_THREAD_TSS_HPP
|
||||
#define BOOST_THREAD_TSS_HPP
|
||||
// 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-8 Anthony Williams
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread/detail/thread_heap_alloc.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct tss_cleanup_function
|
||||
{
|
||||
virtual ~tss_cleanup_function()
|
||||
{}
|
||||
|
||||
virtual void operator()(void* data)=0;
|
||||
};
|
||||
|
||||
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
|
||||
BOOST_THREAD_DECL void* get_tss_data(void const* key);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class thread_specific_ptr
|
||||
{
|
||||
private:
|
||||
thread_specific_ptr(thread_specific_ptr&);
|
||||
thread_specific_ptr& operator=(thread_specific_ptr&);
|
||||
|
||||
struct delete_data:
|
||||
detail::tss_cleanup_function
|
||||
{
|
||||
void operator()(void* data)
|
||||
{
|
||||
delete static_cast<T*>(data);
|
||||
}
|
||||
};
|
||||
|
||||
struct run_custom_cleanup_function:
|
||||
detail::tss_cleanup_function
|
||||
{
|
||||
void (*cleanup_function)(T*);
|
||||
|
||||
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
|
||||
cleanup_function(cleanup_function_)
|
||||
{}
|
||||
|
||||
void operator()(void* data)
|
||||
{
|
||||
cleanup_function(static_cast<T*>(data));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
|
||||
|
||||
public:
|
||||
thread_specific_ptr():
|
||||
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
|
||||
{}
|
||||
explicit thread_specific_ptr(void (*func_)(T*))
|
||||
{
|
||||
if(func_)
|
||||
{
|
||||
cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
|
||||
}
|
||||
}
|
||||
~thread_specific_ptr()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
T* get() const
|
||||
{
|
||||
return static_cast<T*>(detail::get_tss_data(this));
|
||||
}
|
||||
T* operator->() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
T& operator*() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
T* release()
|
||||
{
|
||||
T* const temp=get();
|
||||
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
|
||||
return temp;
|
||||
}
|
||||
void reset(T* new_value=0)
|
||||
{
|
||||
T* const current_value=get();
|
||||
if(current_value!=new_value)
|
||||
{
|
||||
detail::set_tss_data(this,cleanup,new_value,true);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,39 +52,24 @@ 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())
|
||||
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
|
||||
}
|
||||
bool timed_lock(::boost::system_time const& wait_until)
|
||||
{
|
||||
if(!win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit))
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
long old_count=active_count;
|
||||
mark_waiting_and_try_lock(old_count);
|
||||
|
||||
if(old_count&lock_flag_value)
|
||||
{
|
||||
bool lock_acquired=false;
|
||||
void* const sem=get_event();
|
||||
|
||||
do
|
||||
{
|
||||
BOOST_VERIFY(win32::WaitForSingleObject(
|
||||
sem,::boost::detail::win32::infinite)==0);
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
lock_acquired=!(old_count&lock_flag_value);
|
||||
}
|
||||
while(!lock_acquired);
|
||||
}
|
||||
}
|
||||
void mark_waiting_and_try_lock(long& old_count)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
|
||||
@@ -95,33 +80,6 @@ namespace boost
|
||||
}
|
||||
old_count=current;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_waiting_and_try_lock(long& old_count)
|
||||
{
|
||||
old_count&=~lock_flag_value;
|
||||
old_count|=event_set_flag_value;
|
||||
for(;;)
|
||||
{
|
||||
long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
|
||||
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
|
||||
if(current==old_count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_count=current;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool timed_lock(::boost::system_time const& wait_until)
|
||||
{
|
||||
if(try_lock())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
long old_count=active_count;
|
||||
mark_waiting_and_try_lock(old_count);
|
||||
|
||||
if(old_count&lock_flag_value)
|
||||
{
|
||||
@@ -135,7 +93,18 @@ namespace boost
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
}
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
old_count&=~lock_flag_value;
|
||||
old_count|=event_set_flag_value;
|
||||
for(;;)
|
||||
{
|
||||
long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
|
||||
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
|
||||
if(current==old_count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_count=current;
|
||||
}
|
||||
lock_acquired=!(old_count&lock_flag_value);
|
||||
}
|
||||
while(!lock_acquired);
|
||||
@@ -171,7 +140,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 +165,9 @@ namespace boost
|
||||
}
|
||||
return current_event;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -30,90 +30,81 @@ namespace std
|
||||
|
||||
namespace boost
|
||||
{
|
||||
struct once_flag
|
||||
{
|
||||
long status;
|
||||
long count;
|
||||
};
|
||||
typedef long once_flag;
|
||||
|
||||
#define BOOST_ONCE_INIT {0,0}
|
||||
#define BOOST_ONCE_INIT 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;
|
||||
struct win32_mutex_scoped_lock
|
||||
{
|
||||
void* const mutex_handle;
|
||||
explicit win32_mutex_scoped_lock(void* mutex_handle_):
|
||||
mutex_handle(mutex_handle_)
|
||||
{
|
||||
BOOST_VERIFY(!win32::WaitForSingleObject(mutex_handle,win32::infinite));
|
||||
}
|
||||
~win32_mutex_scoped_lock()
|
||||
{
|
||||
BOOST_VERIFY(win32::ReleaseMutex(mutex_handle)!=0);
|
||||
}
|
||||
private:
|
||||
void operator=(win32_mutex_scoped_lock&);
|
||||
};
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
template <class I>
|
||||
void int_to_string(I p, once_char_type* buf)
|
||||
void int_to_string(I p, wchar_t* buf)
|
||||
{
|
||||
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 = L'A' + static_cast<wchar_t>((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";
|
||||
template <class I>
|
||||
void int_to_string(I p, char* buf)
|
||||
{
|
||||
for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
|
||||
{
|
||||
*buf = 'A' + static_cast<char>((p >> (i*4)) & 0x0f);
|
||||
}
|
||||
*buf = 0;
|
||||
}
|
||||
#endif
|
||||
BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) ==
|
||||
(sizeof(once_char_type)*(once_mutex_name_fixed_length+1)));
|
||||
|
||||
// create a named mutex. It doesn't really matter what this name is
|
||||
// as long as it is unique both to this process, and to the address of "flag":
|
||||
inline void* create_once_mutex(void* flag_address)
|
||||
{
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
typedef wchar_t char_type;
|
||||
static const char_type fixed_mutex_name[]=L"{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
|
||||
#else
|
||||
typedef char char_type;
|
||||
static const char_type fixed_mutex_name[]="{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
|
||||
#endif
|
||||
unsigned const once_mutex_name_fixed_buffer_size=sizeof(fixed_mutex_name)/sizeof(char_type);
|
||||
unsigned const once_mutex_name_fixed_length=once_mutex_name_fixed_buffer_size-1;
|
||||
unsigned const once_mutex_name_length=once_mutex_name_fixed_buffer_size+sizeof(void*)*2+sizeof(unsigned long)*2;
|
||||
char_type mutex_name[once_mutex_name_length];
|
||||
|
||||
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)
|
||||
{
|
||||
name_once_mutex(mutex_name,flag_address);
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
return ::boost::detail::win32::OpenEventW(
|
||||
|
||||
BOOST_STATIC_ASSERT(sizeof(void*) == sizeof(std::ptrdiff_t));
|
||||
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);
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
return win32::CreateMutexW(0, 0, mutex_name);
|
||||
#else
|
||||
return ::boost::detail::win32::OpenEventA(
|
||||
return win32::CreateMutexA(0, 0, mutex_name);
|
||||
#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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -123,79 +114,19 @@ namespace boost
|
||||
// Try for a quick win: if the procedure has already been called
|
||||
// just skip through:
|
||||
long const function_complete_flag_value=0xc15730e2;
|
||||
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;
|
||||
|
||||
while((status=::boost::detail::interlocked_read_acquire(&flag.status))
|
||||
!=function_complete_flag_value)
|
||||
if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value)
|
||||
{
|
||||
status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0);
|
||||
if(!status)
|
||||
void* const mutex_handle(::boost::detail::create_once_mutex(&flag));
|
||||
BOOST_ASSERT(mutex_handle);
|
||||
detail::win32::handle_manager const closer(mutex_handle);
|
||||
detail::win32_mutex_scoped_lock const lock(mutex_handle);
|
||||
|
||||
if(flag!=function_complete_flag_value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(!event_handle)
|
||||
{
|
||||
event_handle=detail::open_once_event(mutex_name,&flag);
|
||||
}
|
||||
if(event_handle)
|
||||
{
|
||||
::boost::detail::win32::ResetEvent(event_handle);
|
||||
}
|
||||
f();
|
||||
if(!counted)
|
||||
{
|
||||
BOOST_INTERLOCKED_INCREMENT(&flag.count);
|
||||
counted=true;
|
||||
}
|
||||
BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value);
|
||||
if(!event_handle &&
|
||||
(::boost::detail::interlocked_read_acquire(&flag.count)>1))
|
||||
{
|
||||
event_handle=detail::create_once_event(mutex_name,&flag);
|
||||
}
|
||||
if(event_handle)
|
||||
{
|
||||
::boost::detail::win32::SetEvent(event_handle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
|
||||
if(!event_handle)
|
||||
{
|
||||
event_handle=detail::open_once_event(mutex_name,&flag);
|
||||
}
|
||||
if(event_handle)
|
||||
{
|
||||
::boost::detail::win32::SetEvent(event_handle);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
f();
|
||||
BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value);
|
||||
}
|
||||
|
||||
if(!counted)
|
||||
{
|
||||
BOOST_INTERLOCKED_INCREMENT(&flag.count);
|
||||
counted=true;
|
||||
status=::boost::detail::interlocked_read_acquire(&flag.status);
|
||||
if(status==function_complete_flag_value)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(!event_handle)
|
||||
{
|
||||
event_handle=detail::create_once_event(mutex_name,&flag);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
event_handle,::boost::detail::win32::infinite));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -5,10 +5,9 @@
|
||||
#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>
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
# include <windows.h>
|
||||
@@ -56,21 +55,21 @@ 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)
|
||||
{
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
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()
|
||||
{
|
||||
@@ -87,7 +86,7 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
template<typename T,typename A1>
|
||||
inline T* heap_new(A1&& a1)
|
||||
{
|
||||
@@ -226,7 +225,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 +371,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)
|
||||
{
|
||||
|
||||
@@ -3,15 +3,14 @@
|
||||
|
||||
// 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
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
@@ -31,18 +30,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 +89,7 @@ namespace boost
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
|
||||
|
||||
# ifdef _WIN64
|
||||
typedef unsigned __int64 ulong_ptr;
|
||||
# else
|
||||
@@ -104,8 +99,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 +107,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,49 +161,40 @@ 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());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
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());
|
||||
throw 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)
|
||||
{
|
||||
@@ -222,7 +204,7 @@ namespace boost
|
||||
bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
|
||||
if(!success)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
return new_handle;
|
||||
}
|
||||
@@ -246,7 +228,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 +236,7 @@ namespace boost
|
||||
handle_manager():
|
||||
handle_to_manage(0)
|
||||
{}
|
||||
|
||||
|
||||
handle_manager& operator=(handle new_handle)
|
||||
{
|
||||
cleanup();
|
||||
@@ -288,13 +270,13 @@ namespace boost
|
||||
{
|
||||
return !handle_to_manage;
|
||||
}
|
||||
|
||||
|
||||
~handle_manager()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,7 +309,7 @@ namespace boost
|
||||
{
|
||||
return _interlockedbittestandreset(x,bit)!=0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -346,7 +328,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 +338,9 @@ namespace boost
|
||||
mov edx,x;
|
||||
lock btr [edx],eax;
|
||||
setc al;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
module.cmake
Normal file
1
module.cmake
Normal file
@@ -0,0 +1 @@
|
||||
boost_module(thread DEPENDS date_time bind optional range)
|
||||
15
src/CMakeLists.txt
Normal file
15
src/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
if (WIN32)
|
||||
set(THREAD_SOURCES win32/thread.cpp win32/exceptions.cpp win32/tss_dll.cpp
|
||||
win32/tss_pe.cpp)
|
||||
else (WIN32)
|
||||
set(THREAD_SOURCES pthread/thread.cpp pthread/exceptions.cpp pthread/once.cpp)
|
||||
endif (WIN32)
|
||||
|
||||
boost_add_library(
|
||||
boost_thread
|
||||
${THREAD_SOURCES}
|
||||
SHARED_COMPILE_FLAGS "-DBOOST_THREAD_BUILD_DLL=1"
|
||||
STATIC_COMPILE_FLAGS "-DBOOST_THREAD_BUILD_LIB=1"
|
||||
NO_SINGLE_THREADED
|
||||
)
|
||||
|
||||
124
src/pthread/exceptions.cpp
Normal file
124
src/pthread/exceptions.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// 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>
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
|
||||
thread_exception::thread_exception()
|
||||
: m_sys_err(0)
|
||||
{
|
||||
}
|
||||
|
||||
thread_exception::thread_exception(int sys_err_code)
|
||||
: m_sys_err(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
thread_exception::~thread_exception() throw()
|
||||
{
|
||||
}
|
||||
|
||||
int thread_exception::native_error() const
|
||||
{
|
||||
return m_sys_err;
|
||||
}
|
||||
|
||||
lock_error::lock_error()
|
||||
{
|
||||
}
|
||||
|
||||
lock_error::lock_error(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
lock_error::~lock_error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* lock_error::what() const throw()
|
||||
{
|
||||
return "boost::lock_error";
|
||||
}
|
||||
|
||||
thread_resource_error::thread_resource_error()
|
||||
{
|
||||
}
|
||||
|
||||
thread_resource_error::thread_resource_error(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
thread_resource_error::~thread_resource_error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* thread_resource_error::what() const throw()
|
||||
{
|
||||
return "boost::thread_resource_error";
|
||||
}
|
||||
|
||||
unsupported_thread_option::unsupported_thread_option()
|
||||
{
|
||||
}
|
||||
|
||||
unsupported_thread_option::unsupported_thread_option(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
unsupported_thread_option::~unsupported_thread_option() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* unsupported_thread_option::what() const throw()
|
||||
{
|
||||
return "boost::unsupported_thread_option";
|
||||
}
|
||||
|
||||
invalid_thread_argument::invalid_thread_argument()
|
||||
{
|
||||
}
|
||||
|
||||
invalid_thread_argument::invalid_thread_argument(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
invalid_thread_argument::~invalid_thread_argument() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* invalid_thread_argument::what() const throw()
|
||||
{
|
||||
return "boost::invalid_thread_argument";
|
||||
}
|
||||
|
||||
thread_permission_error::thread_permission_error()
|
||||
{
|
||||
}
|
||||
|
||||
thread_permission_error::thread_permission_error(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
thread_permission_error::~thread_permission_error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* thread_permission_error::what() const throw()
|
||||
{
|
||||
return "boost::thread_permission_error";
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
@@ -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()
|
||||
|
||||
@@ -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>
|
||||
@@ -13,8 +13,7 @@
|
||||
#include <boost/thread/locks.hpp>
|
||||
#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>
|
||||
@@ -43,6 +42,19 @@ namespace boost
|
||||
{}
|
||||
};
|
||||
|
||||
struct tss_data_node
|
||||
{
|
||||
void const* key;
|
||||
boost::shared_ptr<boost::detail::tss_cleanup_function> func;
|
||||
void* value;
|
||||
tss_data_node* next;
|
||||
|
||||
tss_data_node(void const* key_,boost::shared_ptr<boost::detail::tss_cleanup_function> func_,void* value_,
|
||||
tss_data_node* next_):
|
||||
key(key_),func(func_),value(value_),next(next_)
|
||||
{}
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
|
||||
@@ -50,12 +62,12 @@ 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)
|
||||
{
|
||||
while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks)
|
||||
while(thread_info->tss_data || thread_info->thread_exit_callbacks)
|
||||
{
|
||||
while(thread_info->thread_exit_callbacks)
|
||||
{
|
||||
@@ -68,32 +80,29 @@ namespace boost
|
||||
}
|
||||
delete current_node;
|
||||
}
|
||||
for(std::map<void const*,tss_data_node>::iterator next=thread_info->tss_data.begin(),
|
||||
current,
|
||||
end=thread_info->tss_data.end();
|
||||
next!=end;)
|
||||
while(thread_info->tss_data)
|
||||
{
|
||||
current=next;
|
||||
++next;
|
||||
if(current->second.func && (current->second.value!=0))
|
||||
detail::tss_data_node* const current_node=thread_info->tss_data;
|
||||
thread_info->tss_data=current_node->next;
|
||||
if(current_node->func)
|
||||
{
|
||||
(*current->second.func)(current->second.value);
|
||||
(*current_node->func)(current_node->value);
|
||||
}
|
||||
thread_info->tss_data.erase(current);
|
||||
delete current_node;
|
||||
}
|
||||
}
|
||||
thread_info->self.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void create_current_thread_tls_key()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_key_create(¤t_thread_tls_key,&tls_destructor));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boost::detail::thread_data_base* get_current_thread_data()
|
||||
{
|
||||
boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
|
||||
@@ -106,12 +115,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 +155,7 @@ namespace boost
|
||||
{
|
||||
interrupt_enabled=false;
|
||||
}
|
||||
|
||||
|
||||
void run()
|
||||
{}
|
||||
|
||||
@@ -187,7 +196,7 @@ namespace boost
|
||||
if (res != 0)
|
||||
{
|
||||
thread_info->self.reset();
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,18 +205,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 +225,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 +246,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 +257,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 +272,7 @@ namespace boost
|
||||
}
|
||||
}
|
||||
do_join=!local_thread_info->join_started;
|
||||
|
||||
|
||||
if(do_join)
|
||||
{
|
||||
local_thread_info->join_started=true;
|
||||
@@ -282,7 +293,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 +305,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 +331,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 +344,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 +354,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 +390,8 @@ namespace boost
|
||||
{
|
||||
#if defined(PTW32_VERSION) || defined(__hpux)
|
||||
return pthread_num_processors_np();
|
||||
#elif defined(__linux__)
|
||||
return get_nprocs();
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
int count;
|
||||
size_t size=sizeof(count);
|
||||
@@ -386,8 +399,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 +406,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 +419,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 +433,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 +447,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 +458,8 @@ namespace boost
|
||||
return pthread_t();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
@@ -472,13 +482,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 +511,7 @@ namespace boost
|
||||
detail::get_current_thread_data()->interrupt_enabled=false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
disable_interruption::~disable_interruption()
|
||||
{
|
||||
if(detail::get_current_thread_data())
|
||||
@@ -517,7 +527,7 @@ namespace boost
|
||||
detail::get_current_thread_data()->interrupt_enabled=true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
restore_interruption::~restore_interruption()
|
||||
{
|
||||
if(detail::get_current_thread_data())
|
||||
@@ -542,11 +552,14 @@ namespace boost
|
||||
detail::thread_data_base* const current_thread_data(get_current_thread_data());
|
||||
if(current_thread_data)
|
||||
{
|
||||
std::map<void const*,tss_data_node>::iterator current_node=
|
||||
current_thread_data->tss_data.find(key);
|
||||
if(current_node!=current_thread_data->tss_data.end())
|
||||
detail::tss_data_node* current_node=current_thread_data->tss_data;
|
||||
while(current_node)
|
||||
{
|
||||
return ¤t_node->second;
|
||||
if(current_node->key==key)
|
||||
{
|
||||
return current_node;
|
||||
}
|
||||
current_node=current_node->next;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -560,47 +573,106 @@ namespace boost
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void add_new_tss_node(void const* key,
|
||||
boost::shared_ptr<tss_cleanup_function> func,
|
||||
void* tss_data)
|
||||
{
|
||||
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
|
||||
current_thread_data->tss_data.insert(std::make_pair(key,tss_data_node(func,tss_data)));
|
||||
}
|
||||
|
||||
void erase_tss_node(void const* key)
|
||||
{
|
||||
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)
|
||||
|
||||
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->func)(current_node->value);
|
||||
}
|
||||
if(func || (tss_data!=0))
|
||||
{
|
||||
current_node->func=func;
|
||||
current_node->value=tss_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
erase_tss_node(key);
|
||||
}
|
||||
current_node->func=func;
|
||||
current_node->value=tss_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
add_new_tss_node(key,func,tss_data);
|
||||
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
|
||||
tss_data_node* const new_node=new tss_data_node(key,func,tss_data,current_thread_data->tss_data);
|
||||
current_thread_data->tss_data=new_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// thread_group::thread_group()
|
||||
// {
|
||||
// }
|
||||
|
||||
// thread_group::~thread_group()
|
||||
// {
|
||||
// // We shouldn't have to scoped_lock here, since referencing this object
|
||||
// // from another thread while we're deleting it in the current thread is
|
||||
// // going to lead to undefined behavior any way.
|
||||
// for (std::list<thread*>::iterator it = m_threads.begin();
|
||||
// it != m_threads.end(); ++it)
|
||||
// {
|
||||
// delete (*it);
|
||||
// }
|
||||
// }
|
||||
|
||||
// thread* thread_group::create_thread(const function0<void>& threadfunc)
|
||||
// {
|
||||
// // No scoped_lock required here since the only "shared data" that's
|
||||
// // modified here occurs inside add_thread which does scoped_lock.
|
||||
// std::auto_ptr<thread> thrd(new thread(threadfunc));
|
||||
// add_thread(thrd.get());
|
||||
// return thrd.release();
|
||||
// }
|
||||
|
||||
// void thread_group::add_thread(thread* thrd)
|
||||
// {
|
||||
// mutex::scoped_lock scoped_lock(m_mutex);
|
||||
|
||||
// // For now we'll simply ignore requests to add a thread object multiple
|
||||
// // times. Should we consider this an error and either throw or return an
|
||||
// // error value?
|
||||
// std::list<thread*>::iterator it = std::find(m_threads.begin(),
|
||||
// m_threads.end(), thrd);
|
||||
// BOOST_ASSERT(it == m_threads.end());
|
||||
// if (it == m_threads.end())
|
||||
// m_threads.push_back(thrd);
|
||||
// }
|
||||
|
||||
// void thread_group::remove_thread(thread* thrd)
|
||||
// {
|
||||
// mutex::scoped_lock scoped_lock(m_mutex);
|
||||
|
||||
// // For now we'll simply ignore requests to remove a thread object that's
|
||||
// // not in the group. Should we consider this an error and either throw or
|
||||
// // return an error value?
|
||||
// std::list<thread*>::iterator it = std::find(m_threads.begin(),
|
||||
// m_threads.end(), thrd);
|
||||
// BOOST_ASSERT(it != m_threads.end());
|
||||
// if (it != m_threads.end())
|
||||
// m_threads.erase(it);
|
||||
// }
|
||||
|
||||
// void thread_group::join_all()
|
||||
// {
|
||||
// mutex::scoped_lock scoped_lock(m_mutex);
|
||||
// for (std::list<thread*>::iterator it = m_threads.begin();
|
||||
// it != m_threads.end(); ++it)
|
||||
// {
|
||||
// (*it)->join();
|
||||
// }
|
||||
// }
|
||||
|
||||
// void thread_group::interrupt_all()
|
||||
// {
|
||||
// boost::lock_guard<mutex> guard(m_mutex);
|
||||
|
||||
// for(std::list<thread*>::iterator it=m_threads.begin(),end=m_threads.end();
|
||||
// it!=end;
|
||||
// ++it)
|
||||
// {
|
||||
// (*it)->interrupt();
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// size_t thread_group::size() const
|
||||
// {
|
||||
// return m_threads.size();
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright (C) 2009 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)
|
||||
|
||||
// boostinspect:nounnamed
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace {
|
||||
const int MILLISECONDS_PER_SECOND = 1000;
|
||||
const int NANOSECONDS_PER_SECOND = 1000000000;
|
||||
@@ -21,7 +18,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;
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
|
||||
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
|
||||
@@ -33,6 +30,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 +55,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;
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
{
|
||||
@@ -88,7 +86,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;
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
milliseconds = 0;
|
||||
@@ -110,7 +108,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;
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
microseconds = 0;
|
||||
|
||||
@@ -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)
|
||||
|
||||
124
src/win32/exceptions.cpp
Normal file
124
src/win32/exceptions.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// 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>
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
|
||||
thread_exception::thread_exception()
|
||||
: m_sys_err(0)
|
||||
{
|
||||
}
|
||||
|
||||
thread_exception::thread_exception(int sys_err_code)
|
||||
: m_sys_err(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
thread_exception::~thread_exception() throw()
|
||||
{
|
||||
}
|
||||
|
||||
int thread_exception::native_error() const
|
||||
{
|
||||
return m_sys_err;
|
||||
}
|
||||
|
||||
lock_error::lock_error()
|
||||
{
|
||||
}
|
||||
|
||||
lock_error::lock_error(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
lock_error::~lock_error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* lock_error::what() const throw()
|
||||
{
|
||||
return "boost::lock_error";
|
||||
}
|
||||
|
||||
thread_resource_error::thread_resource_error()
|
||||
{
|
||||
}
|
||||
|
||||
thread_resource_error::thread_resource_error(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
thread_resource_error::~thread_resource_error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* thread_resource_error::what() const throw()
|
||||
{
|
||||
return "boost::thread_resource_error";
|
||||
}
|
||||
|
||||
unsupported_thread_option::unsupported_thread_option()
|
||||
{
|
||||
}
|
||||
|
||||
unsupported_thread_option::unsupported_thread_option(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
unsupported_thread_option::~unsupported_thread_option() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* unsupported_thread_option::what() const throw()
|
||||
{
|
||||
return "boost::unsupported_thread_option";
|
||||
}
|
||||
|
||||
invalid_thread_argument::invalid_thread_argument()
|
||||
{
|
||||
}
|
||||
|
||||
invalid_thread_argument::invalid_thread_argument(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
invalid_thread_argument::~invalid_thread_argument() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* invalid_thread_argument::what() const throw()
|
||||
{
|
||||
return "boost::invalid_thread_argument";
|
||||
}
|
||||
|
||||
thread_permission_error::thread_permission_error()
|
||||
{
|
||||
}
|
||||
|
||||
thread_permission_error::thread_permission_error(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
thread_permission_error::~thread_permission_error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* thread_permission_error::what() const throw()
|
||||
{
|
||||
return "boost::thread_permission_error";
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <algorithm>
|
||||
#include <windows.h>
|
||||
#ifndef UNDER_CE
|
||||
#include <process.h>
|
||||
#endif
|
||||
@@ -16,11 +17,8 @@
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#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 +31,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 +55,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 +71,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 +153,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));
|
||||
@@ -201,7 +188,7 @@ namespace boost
|
||||
uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
|
||||
if(!new_thread)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
throw thread_resource_error();
|
||||
}
|
||||
intrusive_ptr_add_ref(thread_info.get());
|
||||
thread_info->thread_handle=(detail::win32::handle)(new_thread);
|
||||
@@ -222,7 +209,7 @@ namespace boost
|
||||
++count;
|
||||
interruption_enabled=false;
|
||||
}
|
||||
|
||||
|
||||
void run()
|
||||
{}
|
||||
private:
|
||||
@@ -233,15 +220,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 +233,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 +263,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 +274,7 @@ namespace boost
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void thread::detach()
|
||||
{
|
||||
release_handle();
|
||||
@@ -303,39 +282,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 +326,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 +355,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 +382,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 +396,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 +412,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 +469,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 +484,7 @@ namespace boost
|
||||
{
|
||||
detail::win32::Sleep(0);
|
||||
}
|
||||
|
||||
|
||||
disable_interruption::disable_interruption():
|
||||
interruption_was_enabled(interruption_enabled())
|
||||
{
|
||||
@@ -528,7 +493,7 @@ namespace boost
|
||||
get_current_thread_data()->interruption_enabled=false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
disable_interruption::~disable_interruption()
|
||||
{
|
||||
if(get_current_thread_data())
|
||||
@@ -544,7 +509,7 @@ namespace boost
|
||||
get_current_thread_data()->interruption_enabled=true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
restore_interruption::~restore_interruption()
|
||||
{
|
||||
if(get_current_thread_data())
|
||||
@@ -560,8 +525,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,43 +556,42 @@ 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))
|
||||
{
|
||||
if(cleanup_existing && current_node->func.get() && current_node->value)
|
||||
if(cleanup_existing && current_node->func.get())
|
||||
{
|
||||
(*current_node->func)(current_node->value);
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
33
test/CMakeLists.txt
Normal file
33
test/CMakeLists.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
boost_additional_test_dependencies(thread BOOST_DEPENDS test )
|
||||
|
||||
|
||||
|
||||
set(TESTS
|
||||
test_thread
|
||||
test_thread_id
|
||||
test_hardware_concurrency
|
||||
test_thread_move
|
||||
test_thread_launching
|
||||
test_thread_mf
|
||||
test_move_function
|
||||
test_mutex
|
||||
test_condition_notify_one
|
||||
test_condition_timed_wait_times_out
|
||||
test_condition_notify_all
|
||||
test_condition
|
||||
test_tss
|
||||
test_once
|
||||
test_xtime
|
||||
test_barrier
|
||||
test_shared_mutex
|
||||
test_shared_mutex_part_2
|
||||
test_shared_mutex_timed_locks
|
||||
test_lock_concept
|
||||
test_generic_locks)
|
||||
|
||||
foreach (TEST ${TESTS})
|
||||
boost_test_run(${TEST} MULTI_THREADED DEPENDS boost_thread boost_unit_test_framework)
|
||||
endforeach (TEST ${TESTS})
|
||||
|
||||
boost_test_compile_fail(no_implicit_move_from_lvalue_thread)
|
||||
boost_test_compile_fail(no_implicit_assign_from_lvalue_thread)
|
||||
@@ -38,11 +38,8 @@ rule thread-run ( sources )
|
||||
[ thread-run test_thread_id.cpp ]
|
||||
[ thread-run test_hardware_concurrency.cpp ]
|
||||
[ thread-run test_thread_move.cpp ]
|
||||
[ thread-run test_thread_return_local.cpp ]
|
||||
[ thread-run test_thread_move_return.cpp ]
|
||||
[ thread-run test_thread_launching.cpp ]
|
||||
[ thread-run test_thread_mf.cpp ]
|
||||
[ thread-run test_thread_exit.cpp ]
|
||||
[ thread-run test_move_function.cpp ]
|
||||
[ thread-run test_mutex.cpp ]
|
||||
[ thread-run test_condition_notify_one.cpp ]
|
||||
@@ -58,33 +55,7 @@ rule thread-run ( sources )
|
||||
[ thread-run test_shared_mutex_timed_locks.cpp ]
|
||||
[ thread-run test_lock_concept.cpp ]
|
||||
[ thread-run test_generic_locks.cpp ]
|
||||
[ thread-run test_futures.cpp ]
|
||||
[ 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 ]
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
void run_thread() {
|
||||
return;
|
||||
}
|
||||
|
||||
int main() {
|
||||
boost::thread t(run_thread);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// (C) Copyright 2009 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/thread.hpp"
|
||||
#include "boost/thread/mutex.hpp"
|
||||
#include "boost/thread/condition.hpp"
|
||||
#include "boost/thread/future.hpp"
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
boost::thread::id exit_func_thread_id;
|
||||
|
||||
void exit_func()
|
||||
{
|
||||
exit_func_thread_id=boost::this_thread::get_id();
|
||||
}
|
||||
|
||||
void tf1()
|
||||
{
|
||||
boost::this_thread::at_thread_exit(exit_func);
|
||||
BOOST_CHECK(exit_func_thread_id!=boost::this_thread::get_id());
|
||||
}
|
||||
|
||||
void test_thread_exit_func_runs_when_thread_exits()
|
||||
{
|
||||
exit_func_thread_id=boost::thread::id();
|
||||
boost::thread t(tf1);
|
||||
boost::thread::id const t_id=t.get_id();
|
||||
t.join();
|
||||
BOOST_CHECK(exit_func_thread_id==t_id);
|
||||
}
|
||||
|
||||
struct fo
|
||||
{
|
||||
void operator()()
|
||||
{
|
||||
exit_func_thread_id=boost::this_thread::get_id();
|
||||
}
|
||||
};
|
||||
|
||||
void tf2()
|
||||
{
|
||||
boost::this_thread::at_thread_exit(fo());
|
||||
BOOST_CHECK(exit_func_thread_id!=boost::this_thread::get_id());
|
||||
}
|
||||
|
||||
|
||||
void test_can_use_function_object_for_exit_func()
|
||||
{
|
||||
exit_func_thread_id=boost::thread::id();
|
||||
boost::thread t(tf2);
|
||||
boost::thread::id const t_id=t.get_id();
|
||||
t.join();
|
||||
BOOST_CHECK(exit_func_thread_id==t_id);
|
||||
}
|
||||
|
||||
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: futures test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(test_thread_exit_func_runs_when_thread_exits));
|
||||
test->add(BOOST_TEST_CASE(test_can_use_function_object_for_exit_func));
|
||||
|
||||
return test;
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2007-9 Anthony Williams
|
||||
// Copyright (C) 2007 Anthony Williams
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -33,6 +33,21 @@ void test_move_from_function_return()
|
||||
BOOST_CHECK_EQUAL(the_id,x_id);
|
||||
}
|
||||
|
||||
boost::thread make_thread_return_lvalue(boost::thread::id* the_id)
|
||||
{
|
||||
boost::thread t(do_nothing,the_id);
|
||||
return boost::move(t);
|
||||
}
|
||||
|
||||
void test_move_from_function_return_lvalue()
|
||||
{
|
||||
boost::thread::id the_id;
|
||||
boost::thread x=make_thread_return_lvalue(&the_id);
|
||||
boost::thread::id x_id=x.get_id();
|
||||
x.join();
|
||||
BOOST_CHECK_EQUAL(the_id,x_id);
|
||||
}
|
||||
|
||||
void test_move_assign()
|
||||
{
|
||||
boost::thread::id the_id;
|
||||
@@ -44,13 +59,14 @@ 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));
|
||||
test->add(BOOST_TEST_CASE(test_move_from_function_return));
|
||||
test->add(BOOST_TEST_CASE(test_move_from_function_return_lvalue));
|
||||
test->add(BOOST_TEST_CASE(test_move_assign));
|
||||
return test;
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright (C) 2009 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/thread.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
void do_nothing(boost::thread::id* my_id)
|
||||
{
|
||||
*my_id=boost::this_thread::get_id();
|
||||
}
|
||||
|
||||
boost::thread make_thread_move_return(boost::thread::id* the_id)
|
||||
{
|
||||
boost::thread t(do_nothing,the_id);
|
||||
return boost::move(t);
|
||||
}
|
||||
|
||||
void test_move_from_function_move_return()
|
||||
{
|
||||
boost::thread::id the_id;
|
||||
boost::thread x=make_thread_move_return(&the_id);
|
||||
boost::thread::id x_id=x.get_id();
|
||||
x.join();
|
||||
BOOST_CHECK_EQUAL(the_id,x_id);
|
||||
}
|
||||
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: thread move test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(test_move_from_function_move_return));
|
||||
return test;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright (C) 2009 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/thread.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
void do_nothing(boost::thread::id* my_id)
|
||||
{
|
||||
*my_id=boost::this_thread::get_id();
|
||||
}
|
||||
|
||||
boost::thread make_thread_return_local(boost::thread::id* the_id)
|
||||
{
|
||||
boost::thread t(do_nothing,the_id);
|
||||
return t;
|
||||
}
|
||||
|
||||
void test_move_from_function_return_local()
|
||||
{
|
||||
boost::thread::id the_id;
|
||||
boost::thread x=make_thread_return_local(&the_id);
|
||||
boost::thread::id x_id=x.get_id();
|
||||
x.join();
|
||||
BOOST_CHECK_EQUAL(the_id,x_id);
|
||||
}
|
||||
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: thread move test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(test_move_from_function_return_local));
|
||||
return test;
|
||||
}
|
||||
@@ -310,50 +310,15 @@ void test_tss_does_no_cleanup_with_null_cleanup_function()
|
||||
timed_test(&do_test_tss_does_no_cleanup_with_null_cleanup_function, 2);
|
||||
}
|
||||
|
||||
void thread_with_local_tss_ptr()
|
||||
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
{
|
||||
boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup);
|
||||
|
||||
local_tss.reset(new Dummy);
|
||||
}
|
||||
BOOST_CHECK(tss_cleanup_called);
|
||||
tss_cleanup_called=false;
|
||||
}
|
||||
|
||||
|
||||
void test_tss_does_not_call_cleanup_after_ptr_destroyed()
|
||||
{
|
||||
boost::thread t(thread_with_local_tss_ptr);
|
||||
t.join();
|
||||
BOOST_CHECK(!tss_cleanup_called);
|
||||
}
|
||||
|
||||
void test_tss_cleanup_not_called_for_null_pointer()
|
||||
{
|
||||
boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup);
|
||||
local_tss.reset(new Dummy);
|
||||
tss_cleanup_called=false;
|
||||
local_tss.reset(0);
|
||||
BOOST_CHECK(tss_cleanup_called);
|
||||
tss_cleanup_called=false;
|
||||
local_tss.reset(new Dummy);
|
||||
BOOST_CHECK(!tss_cleanup_called);
|
||||
}
|
||||
|
||||
|
||||
|
||||
boost::unit_test::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));
|
||||
test->add(BOOST_TEST_CASE(test_tss_with_custom_cleanup));
|
||||
test->add(BOOST_TEST_CASE(test_tss_does_no_cleanup_after_release));
|
||||
test->add(BOOST_TEST_CASE(test_tss_does_no_cleanup_with_null_cleanup_function));
|
||||
test->add(BOOST_TEST_CASE(test_tss_does_not_call_cleanup_after_ptr_destroyed));
|
||||
test->add(BOOST_TEST_CASE(test_tss_cleanup_not_called_for_null_pointer));
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user