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

Compare commits

..

1 Commits

Author SHA1 Message Date
Christopher Hite
71d10aadc7 optional_optimization branch
[SVN r77091]
2012-02-22 10:37:27 +00:00
282 changed files with 3567 additions and 15387 deletions

View File

@@ -1,7 +1,6 @@
# $Id$
# Copyright 2006-2007 Roland Schwarz.
# Copyright 2007 Anthony Williams
# Copyright 2011-2012 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)
@@ -40,66 +39,18 @@ import path ;
project boost/thread
: source-location ../src
: requirements <threading>multi
#<link>static:<define>BOOST_THREAD_STATIC_LINK=1
#<link>shared:<define>BOOST_THREAD_DYN_LINK=1
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
<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
<define>BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
<define>BOOST_SYSTEM_NO_DEPRECATED
<library>/boost/system//boost_system
#-pedantic -ansi -std=gnu++0x -Wextra -fpermissive
<warnings>all
<toolset>gcc:<cxxflags>-Wextra
<toolset>gcc:<cxxflags>-pedantic
<toolset>gcc:<cxxflags>-Wno-long-long
#<toolset>gcc:<cxxflags>-ansi
#<toolset>gcc:<cxxflags>-fpermissive
<toolset>darwin:<cxxflags>-Wextra
<toolset>darwin:<cxxflags>-pedantic
<toolset>darwin:<cxxflags>-ansi
<toolset>darwin:<cxxflags>-fpermissive
<toolset>darwin:<cxxflags>-Wno-long-long
#<toolset>pathscale:<cxxflags>-Wextra
<toolset>pathscale:<cxxflags>-Wno-long-long
<toolset>pathscale:<cxxflags>-pedantic
<toolset>clang:<cxxflags>-Wextra
<toolset>clang:<cxxflags>-pedantic
<toolset>clang:<cxxflags>-ansi
#<toolset>clang:<cxxflags>-fpermissive
<toolset>clang:<cxxflags>-Wno-long-long
<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.6.3:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.7.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.8.0:<cxxflags>-fdiagnostics-show-option
<toolset>darwin-4.6.2:<cxxflags>-Wno-delete-non-virtual-dtor
<toolset>darwin-4.7.0:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.8:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.8:<cxxflags>-Wno-unused-function
#<toolset>clang-2.9:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.9:<cxxflags>-Wno-unused-function
<toolset>clang-3.0:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-3.0:<cxxflags>-Wno-unused-function
#<toolset>clang-3.0:<cxxflags>-Wno-unused-variable
# : default-build <threading>multi
: usage-requirements # pass these requirement to dependents (i.e. users)
#<link>static:<define>BOOST_THREAD_STATIC_LINK=1
#<link>shared:<define>BOOST_THREAD_DYN_LINK=1
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
<link>shared:<define>BOOST_THREAD_BUILD_DLL=1
<define>BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
<define>BOOST_SYSTEM_NO_DEPRECATED
<library>/boost/system//boost_system
;
@@ -117,19 +68,19 @@ feature.set-default threadapi : [ default_threadapi ] ;
rule tag ( name : type ? : property-set )
{
local result = $(name) ;
if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB
{
local api = [ $(property-set).get <threadapi> ] ;
# non native api gets additional tag
if $(api) != [ default_threadapi ] {
result = $(result)_$(api) ;
}
}
# forward to the boost tagging rule
return [ indirect.call $(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
return [ indirect.call $(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
$(result) : $(type) : $(property-set) ] ;
}
@@ -187,7 +138,7 @@ rule win32_pthread_paths ( properties * )
.notified = true ;
}
}
else
else
{
result += <include>$(include_path) ;
result += <library>$(lib_path) ;
@@ -210,9 +161,13 @@ rule usage-requirements ( properties * )
}
}
if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties)
if <toolset>vacpp in $(properties)
{
result += <library>/boost/chrono//boost_chrono ;
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
}
else
{
result += <library>/boost/chrono//boost_chrono ;
}
return $(result) ;
@@ -225,7 +180,7 @@ rule requirements ( properties * )
if <threadapi>pthread in $(properties)
{
result += <define>BOOST_THREAD_POSIX ;
if <target-os>windows in $(properties)
if <target-os>windows in $(properties)
{
local paths = [ win32_pthread_paths $(properties) ] ;
if $(paths)
@@ -238,7 +193,14 @@ rule requirements ( properties * )
}
}
}
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
if <toolset>vacpp in $(properties)
{
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
}
else
{
result += <library>/boost/chrono//boost_chrono ;
}
return $(result) ;
}

View File

@@ -8,156 +8,47 @@
[section:changes History]
[heading Version 3.1.0 - boost 1.52]
Deprecated Features:
Deprecated features since boost 1.50 available only until boost 1.55:
These deprecated features will be provided by default up to boost 1.52. If you don't want to include the deprecated features you could define BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0. Since 1.53 these features will not be included any more by default. Since this version, if you want to include the deprecated features yet you could define BOOST_THREAD_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0. These deprecated features will be only available until boost 1.55, that is you have yet 1 year to move to the new features.
* Time related functions don't using the Boost.Chrono library, use the chrono overloads instead.
Breaking changes when BOOST_THREAD_VERSION==3 (Default value since Boost 1.53):
There are some new features which share the same interface but with different behavior. These breaking features are provided by default when BOOST_THREAD_VERSION is 3, but the user can however choose the version 2 behavior by defining the corresponding macro. As for the deprecated features, these broken features will be only available until boost 1.55.
* [@http://svn.boost.org/trac/boost/ticket/6229 #6229] Rename the unique_future to future following the c++11.
* [@http://svn.boost.org/trac/boost/ticket/6266 #6266] Breaking change: thread destructor should call terminate if joinable.
* [@http://svn.boost.org/trac/boost/ticket/6269 #6269] Breaking change: thread move assignment should call terminate if joinable.
[heading Version 2.0.0 - boost 1.50]
New Features:
* [@http://svn.boost.org/trac/boost/ticket/2361 #2361] thread_specific_ptr: document nature of the key, complexity and rationale.
* [@http://svn.boost.org/trac/boost/ticket/4710 #4710] C++11 compliance: Missing async().
* [@http://svn.boost.org/trac/boost/ticket/7283 #7283] C++11 compliance: Add notify_all_at_thread_exit.
* [@http://svn.boost.org/trac/boost/ticket/7345 #7345] C++11 compliance: Add noexcept to recursive mutex try_lock.
Fixed Bugs:
* [@http://svn.boost.org/trac/boost/ticket/2797 #2797] Two problems with thread_specific_ptr.
* [@http://svn.boost.org/trac/boost/ticket/5274 #5274] failed to compile future.hpp with stlport 5.1.5 under msvc8.1, because of undefined class.
* [@http://svn.boost.org/trac/boost/ticket/5431 #5431] compile error in Windows CE 6.0(interlocked).
[/* [@http://svn.boost.org/trac/boost/ticket/5752 #5752] boost::call_once() is unreliable on some platforms.]
* [@http://svn.boost.org/trac/boost/ticket/5696 #5696] win32 detail::set_tss_data does nothing when tss_cleanup_function is NULL.
* [@http://svn.boost.org/trac/boost/ticket/6931 #6931] mutex waits forwever with Intel C++ Compiler XE 12.1.5.344 Build 20120612
* [@http://svn.boost.org/trac/boost/ticket/7045 #7045] Thread library does not automatically compile date_time.
* [@http://svn.boost.org/trac/boost/ticket/7173 #7173] wrong function name interrupt_point().
* [@http://svn.boost.org/trac/boost/ticket/7200 #7200] Unable to build boost.thread modularized.
* [@http://svn.boost.org/trac/boost/ticket/7220 #7220] gcc 4.6.2 warns about inline+dllimport functions.
* [@http://svn.boost.org/trac/boost/ticket/7238 #7238] this_thread::sleep_for() does not respond to interrupt().
* [@http://svn.boost.org/trac/boost/ticket/7245 #7245] Minor typos on documentation related to version 3.
* [@http://svn.boost.org/trac/boost/ticket/7272 #7272] win32/thread_primitives.hpp: (Unneccessary) Warning.
* [@http://svn.boost.org/trac/boost/ticket/7284 #7284] Clarify that there is no access priority between lock and shared_lock on shared mutex.
* [@http://svn.boost.org/trac/boost/ticket/7329 #7329] boost/thread/future.hpp does not compile on HPUX.
* [@http://svn.boost.org/trac/boost/ticket/7336 #7336] BOOST_THREAD_DONT_USE_SYSTEM doesn't work.
* [@http://svn.boost.org/trac/boost/ticket/7329 #7349] packaged_task holds reference to temporary.
* [@http://svn.boost.org/trac/boost/ticket/7350 #7350] allocator_destructor does not destroy object
* [@http://svn.boost.org/trac/boost/ticket/7360 #7360] Memory leak in pthread implementation of boost::thread_specific_ptr
* [@http://svn.boost.org/trac/boost/ticket/7370 #7370] Boost.Thread documentation
* [@http://svn.boost.org/trac/boost/ticket/7438 #7438] Segmentation fault in test_once regression test in group.join_all();
* [@http://svn.boost.org/trac/boost/ticket/7461 #7461] detail::win32::ReleaseSemaphore may be called with count_to_release equal to 0
* [@http://svn.boost.org/trac/boost/ticket/7499 #7499] call_once doesn't call even once
[heading Version 3.0.1 - boost 1.51]
Deprecated Features:
Deprecated features since boost 1.50 available only until boost 1.55:
These deprecated features will be provided by default up to boost 1.52. If you don't want to include the deprecated features you could define BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0. Since 1.53 these features will not be included any more by default. Since this version, if you want to include the deprecated features yet you could define BOOST_THREAD_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0. These deprecated features will be only available until boost 1.55, that is you have 1 year and a half to move to the new features.
* Time related functions don't using the Boost.Chrono library, use the chrono overloads instead.
Breaking changes when BOOST_THREAD_VERSION==3:
There are some new features which share the same interface but with different behavior. These breaking features are provided by default when BOOST_THREAD_VERSION is 3, but the user can however choose the version 2 behavior by defining the corresponding macro. As for the deprecated features, these broken features will be only available until boost 1.55.
* [@http://svn.boost.org/trac/boost/ticket/6229 #6229] Rename the unique_future to future following the c++11.
* [@http://svn.boost.org/trac/boost/ticket/6266 #6266] Breaking change: thread destructor should call terminate if joinable.
* [@http://svn.boost.org/trac/boost/ticket/6269 #6269] Breaking change: thread move assignment should call terminate if joinable.
Fixed Bugs:
* [@http://svn.boost.org/trac/boost/ticket/4258 #4258] Linking with boost thread does not work on mingw/gcc 4.5.
* [@http://svn.boost.org/trac/boost/ticket/4885 #4885] Access violation in set_tss_data at process exit due to invalid assumption about TlsAlloc.
* [@http://svn.boost.org/trac/boost/ticket/6931 #6931] mutex waits forwever with Intel Compiler and /debug:parallel
* [@http://svn.boost.org/trac/boost/ticket/7044 #7044] boost 1.50.0 header missing.
* [@http://svn.boost.org/trac/boost/ticket/7052 #7052] Thread: BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 only masks thread::operator==, thread::operator!= forward declarations, not definitions.
* [@http://svn.boost.org/trac/boost/ticket/7066 #7066] An attempt to fix current_thread_tls_key static initialization order.
* [@http://svn.boost.org/trac/boost/ticket/7074 #7074] Multiply defined symbol boost::allocator_arg.
* [@http://svn.boost.org/trac/boost/ticket/7078 #7078] Trivial 64-bit warning fix on Windows for thread attribute stack size
* [@http://svn.boost.org/trac/boost/ticket/7089 #7089] BOOST_THREAD_WAIT_BUG limits functionality without solving anything
[/
#6787 boost::thread::sleep() hangs if system time is rolled back
#7045 Thread library does not automatically compile date_time
]
[heading Version 3.0.0 - boost 1.50]
Breaking changes when BOOST_THREAD_VERSION==3:
* [@http://svn.boost.org/trac/boost/ticket/6229 #6229] Breaking change: Rename the unique_future to future following the c++11.
* [@http://svn.boost.org/trac/boost/ticket/6266 #6266] Breaking change: thread destructor should call terminate if joinable.
* [@http://svn.boost.org/trac/boost/ticket/6269 #6269] Breaking change: thread move assignment should call terminate if joinable.
New Features:
* [@http://svn.boost.org/trac/boost/ticket/1850 #1850] Request for unlock_guard to compliment lock_guard.
* [@http://svn.boost.org/trac/boost/ticket/2637 #2637] Request for shared_mutex duration timed_lock and timed_lock_shared.
* [@http://svn.boost.org/trac/boost/ticket/2741 #2741] Proposal to manage portable and non portable thread attributes.
* [@http://svn.boost.org/trac/boost/ticket/3567 #3567] Request for shared_lock_guard.
* [@http://svn.boost.org/trac/boost/ticket/6194 #6194] Adapt to Boost.Move.
* [@http://svn.boost.org/trac/boost/ticket/6195 #6195] c++11 compliance: Provide the standard time related interface using Boost.Chrono.
* [@http://svn.boost.org/trac/boost/ticket/6217 #6217] Enhance Boost.Thread shared mutex interface following Howard Hinnant proposal.
* [@http://svn.boost.org/trac/boost/ticket/6224 #6224] c++11 compliance: Add the use of standard noexcept on compilers supporting them.
* [@http://svn.boost.org/trac/boost/ticket/6225 #6225] Add the use of standard =delete defaulted operations on compilers supporting them.
* [@http://svn.boost.org/trac/boost/ticket/6226 #6226] c++11 compliance: Add explicit bool conversion from locks.
* [@http://svn.boost.org/trac/boost/ticket/6228 #6228] Add promise constructor with allocator following the standard c++11.
* [@http://svn.boost.org/trac/boost/ticket/6230 #6230] c++11 compliance: Follows the exception reporting mechanism as defined in the c++11.
* [@http://svn.boost.org/trac/boost/ticket/6231 #6231] Add BasicLockable requirements in the documentation to follow c++11.
* [@http://svn.boost.org/trac/boost/ticket/6272 #6272] c++11 compliance: Add thread::id hash specialization.
* [@http://svn.boost.org/trac/boost/ticket/6273 #6273] c++11 compliance: Add cv_status enum class and use it on the conditions wait functions.
* [@http://svn.boost.org/trac/boost/ticket/6342 #6342] c++11 compliance: Adapt the one_flag to the c++11 interface.
* [@http://svn.boost.org/trac/boost/ticket/6671 #6671] upgrade_lock: missing mutex and release functions.
* [@http://svn.boost.org/trac/boost/ticket/6672 #6672] upgrade_lock:: missing constructors from time related types.
* [@http://svn.boost.org/trac/boost/ticket/6675 #6675] upgrade_lock:: missing non-member swap.
* [@http://svn.boost.org/trac/boost/ticket/6676 #6676] lock conversion should be explicit.
* Added missing packaged_task::result_type and packaged_task:: constructor with allocator.
* Added packaged_task::reset()
* [@http://svn.boost.org/trac/boost/ticket/6194 #6194] Adapt to Boost.Move.
Fixed Bugs:
* [@http://svn.boost.org/trac/boost/ticket/2380 #2380] boost::move from lvalue does not work with gcc.
* [@http://svn.boost.org/trac/boost/ticket/2430 #2430] shared_mutex for win32 doesn't have timed_lock_upgrade.
* [@http://svn.boost.org/trac/boost/ticket/2575 #2575] Bug- Boost 1.36.0 on Itanium platform.
* [@http://svn.boost.org/trac/boost/ticket/3160 #3160] Duplicate tutorial code in boost::thread.
* [@http://svn.boost.org/trac/boost/ticket/4345 #4345] thread::id and joining problem with cascade of threads.
* [@http://svn.boost.org/trac/boost/ticket/4521 #4521] Error using boost::move on packaged_task (MSVC 10).
* [@http://svn.boost.org/trac/boost/ticket/4711 #4711] Must use implementation details to return move-only types.
* [@http://svn.boost.org/trac/boost/ticket/4921 #4921] BOOST_THREAD_USE_DLL and BOOST_THREAD_USE_LIB are crucial and need to be documented.
* [@http://svn.boost.org/trac/boost/ticket/5013 #5013] documentation: boost::thread: pthreas_exit causes terminate().
* [@http://svn.boost.org/trac/boost/ticket/5173 #5173] boost::this_thread::get_id is very slow.
* [@http://svn.boost.org/trac/boost/ticket/5351 #5351] interrupt a future get boost::unknown_exception.
* [@http://svn.boost.org/trac/boost/ticket/5516 #5516] Upgrade lock is not acquired when previous upgrade lock releases if another read lock is present.
* [@http://svn.boost.org/trac/boost/ticket/5990 #5990] shared_future<T>::get() has wrong return type.
* [@http://svn.boost.org/trac/boost/ticket/6174 #6174] packaged_task doesn't correctly handle moving results.
* [@http://svn.boost.org/trac/boost/ticket/6222 #6222] Compile error with SunStudio: unique_future move.
* [@http://svn.boost.org/trac/boost/ticket/6354 #6354] PGI: Compiler threading support is not turned on.
* [@http://svn.boost.org/trac/boost/ticket/6673 #6673] shared_lock: move assign doesn't works with c++11.
* [@http://svn.boost.org/trac/boost/ticket/6674 #6674] shared_mutex: try_lock_upgrade_until doesn't works.
* [@http://svn.boost.org/trac/boost/ticket/6908 #6908] Compile error due to unprotected definitions of _WIN32_WINNT and WINVER.
* [@http://svn.boost.org/trac/boost/ticket/6940 #6940] TIME_UTC is a macro in C11.
* [@http://svn.boost.org/trac/boost/ticket/6959 #6959] call of abs is ambiguous.
* Fix issue signaled on the ML with task_object(task_object const&) in presence of task_object(task_object &&)
[/
[heading Version 2.1.1 - boost 1.49]
Deprecated features since boost 1.50 available only until boost 1.55:
These deprecated features will be provided by default up to boost 1.52. If you don't want to include the deprecated features you could define BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V2_0_0. Since 1.53 these features will not be included any more by default. Since this version, if you want to include the deprecated features yet you could define BOOST_THREAD_PROVIDE_DEPRECATED_FEATURES_SINCE_V2_0_0. These deprecated features will be only available until boost 1.55, that is you have 1 year and a half to move to the new features.
* Time related functions don't using the Boost.Chrono library, use the chrono overloads instead.
Breaking changes:
There are some new features which share the same interface but with different behavior. These breaking features are not provided by default when BOOST_THREAD_VERSION is 2, but the user can however choose the version 1 behavior by defining the corresponding macro. As for the deprecated features, these broken features will be only available until boost 1.55.
* #6266 c++11 compliance: thread destructor should call terminate if joinable
* #6269 c++11 compliance: thread move assignment should call terminate if joinable
]
[heading boost 1.49]
Fixed Bugs:
@@ -188,7 +79,7 @@ Fixed Bugs:
* [@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 Version 2.1.0 - Changes since boost 1.40]
[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.
@@ -208,7 +99,7 @@ The 1.36.0 release of Boost includes a few new features in the thread library:
* Backwards-compatibility overloads added for `timed_lock` and `timed_wait` functions to allow use of `xtime` for timeouts.
[heading Version 2.0.0 - Changes since boost 1.34]
[heading Changes since boost 1.34]
Almost every line of code in __boost_thread__ has been changed since the 1.34 release of boost. However, most of the interface
changes have been extensions, so the new code is largely backwards-compatible with the old code. The new features and breaking
@@ -271,15 +162,15 @@ been moved to __thread_id__.
[section:future Future]
The following features will be included in next releases.
# Complete the C++11 missing features, in particular
* async with deferred and variadic rvalue reference args.
* [@http://svn.boost.org/trac/boost/ticket/6227 #6227] Use of variadic templates on Generic Locking Algorithms on compilers providing them.
* [@http://svn.boost.org/trac/boost/ticket/6270 #6270] Add thread constructor from movable callable and movable arguments following C++11.
The following features will be included in next releases. By order of priority:
* [@http://svn.boost.org/trac/boost/ticket/4710 #4710] Missing async().
* 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
* #2880 Request for Thread scheduler support for boost ..
* #3696 Boost Thread library lacks any way to set priority of threads
* #5956 Add optional stack_size argument to thread::start_thread()
[endsect]

View File

@@ -5,71 +5,71 @@
http://www.boost.org/LICENSE_1_0.txt).
]
[section:compliance Conformance and Extension]
[section:compliance Compliance with standard]
[section:cpp11 C++11 standard Thread library]
[table C++11 standard Conformance
[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] [Yes] [-] [-]]
[[30.2.2] [Exceptions] [Yes] [-] [#6230]]
[[30.2.3] [Native handles] [Yes] [-] [-]]
[[30.2.4] [Timing specifications] [Yes] [-] [-]]
[[30.2.5] [Requirements for Lockable types] [Yes] [-] [-]]
[[30.2.4] [Timing specifications] [Yes] [-] [#6195]]
[[30.2.5] [Requirements for Lockable types] [Partial] [-] [-]]
[[30.2.5.1] [In general] [-] [-] [-]]
[[30.2.5.2] [BasicLockable requirements] [Yes] [-] [-]]
[[30.2.5.2] [BasicLockable requirements] [No] [-] [#6231]]
[[30.2.5.3] [Lockable requirements] [yes] [-] [-]]
[[30.2.5.4] [TimedLockable requirements] [Yes] [-] [-]]
[[30.2.5.4] [TimedLockable requirements] [Yes] [-] [#6195]]
[[30.2.6] [decay_copy] [-] [-] [-]]
[[30.3] [Threads] [Partial] [-] [-]]
[[30.3.1] [Class thread] [Partial] [move,variadic,terminate] [#6270]]
[[30.3.1.1] [Class thread::id] [Yes] [-] [-]]
[[30.3.1.2] [thread constructors] [Partial] [move,variadic] [#6270]]
[[30.3.1.3] [thread destructor] [Yes] [-] [-]]
[[30.3.1.4] [thread assignment] [Yes] [-] [-]]
[[30.3.1.5] [thread members] [Yes] [-] [-]]
[[30.3.1.6] [thread static members] [Yes] [-] [-]]
[[30.3.1] [Class thread] [Partial] [move,terminate] [-]]
[[30.3.1.1] [Class thread::id] [Yes] [-] [#6224,#6272]]
[[30.3.1.2] [thread constructors] [Partial] [move] [#6224,#6194, #6270]]
[[30.3.1.3] [thread destructor] [Partial] [terminate] [#6266]]
[[30.3.1.4] [thread assignment] [Partial] [move, terminate] [#6269]]
[[30.3.1.5] [thread members] [Yes] [-] [#6224,#6195]]
[[30.3.1.6] [thread static members] [Yes] [-] [#6224]]
[[30.3.1.7] [thread specialized algorithms] [Yes] [-] [-]]
[[30.3.2] [Namespace this_thread] [Yes] [-] [-]]
[[30.4] [Mutual exclusion] [Partial] [-] [-]]
[[30.3.2] [Namespace this_thread] [Yes] [-] [#6195]]
[[30.4] [Mutual exclusion] [Partial] [move] [-]]
[[30.4.1] [Mutex requirements] [Yes] [-] [-]]
[[30.4.1.1] [In general] [Yes] [-] [-]]
[[30.4.1.2] [Mutex types] [Yes] [-] [-]]
[[30.4.1.2.1] [Class mutex] [Yes] [-] [-]]
[[30.4.1.2.2] [Class recursive_mutex] [Yes] [-] [-]]
[[30.4.1.3] [Timed mutex types] [Yes] [-] [-]]
[[30.4.1.3.1] [Class timed_mutex] [Yes] [-] [-]]
[[30.4.1.3.1] [Class recursive_timed_mutex] [Yes] [-] [-]]
[[30.4.2] [Locks] [Partial] [variadic] [#6227]]
[[30.4.2.1] [Class template lock_guard] [Yes] [-] [-]]
[[30.4.2.2] [Class template unique_lock] [Yes] [-] [-]]
[[30.4.2.2.1] [unique_lock constructors, destructor, and assignment] [Yes] [-] [-]]
[[30.4.2.2.2] [unique_lock locking] [Yes] [-] [-]]
[[30.4.1.2] [Mutex types] [Yes] [-] [#6224,#6225]]
[[30.4.1.2.1] [Class mutex] [Yes] [-] [#6224,#6225]]
[[30.4.1.2.2] [Class recursive_mutex] [Yes] [-] [#6224,#6225]]
[[30.4.1.3] [Timed mutex types] [Yes] [-] [#6224,#6195,#6225]]
[[30.4.1.3.1] [Class timed_mutex] [Yes] [-] [#6224,#6195,#6225]]
[[30.4.1.3.1] [Class recursive_timed_mutex] [Yes] [-] [#6224,#6195,#6225]]
[[30.4.2] [Locks] [Partial] [move] [#6224,#6195,#6225,#6227]]
[[30.4.2.1] [Class template lock_guard] [Yes] [-] [#6225]]
[[30.4.2.2] [Class template unique_lock] [Yes] [move] [#6224,#6195,#6225,#6227]]
[[30.4.2.2.1] [unique_lock constructors, destructor, and assignment] [Partial] [move] [#6224,#6195,#6225,#6227]]
[[30.4.2.2.2] [unique_lock locking] [Yes] [-] [#6195]]
[[30.4.2.2.3] [unique_lock modifiers] [Yes] [-] [-]]
[[30.4.2.2.4] [unique_lock observers] [Yes] [] [-]]
[[30.4.2.2.4] [unique_lock observers] [Yes] [] [#6227]]
[[30.4.3] [Generic locking algorithms] [Partial] [variadic] [#6227]]
[[30.4.4] [Call once] [Partial] [call_once] [#7285]]
[[30.4.4.1] [Struct once_flag] [Yes] [-] [-]]
[[30.4.4.2] [Function call_once] [Partial] [interface] [#7285]]
[[30.5] [Condition variables] [Partial] [notify_all_at_thread_exit] [#7283]]
[[30.5 6-10] [Function notify_all_at_thread_exit] [No] [-] [#7283]]
[[30.5.1] [Class condition_variable] [Yes] [-] [-]]
[[30.5.2] [Class condition_variable_any] [Yes] [-] [-]]
[[30.6] [Futures] [Partial] [async,at_thread_exit] [#4710,#7280]]
[[30.4.4] [Call once] [Partial] [move,variadic,] [#6194,#7]]
[[30.4.4.1] [Struct once_flag] [Partial] [interface] [#xx]]
[[30.4.4.2] [Function call_once] [Partial] [move,variadic,interface] [#xx]]
[[30.5] [Condition variables] [Partial] [notify_all_at_thread_exit] [#6195,#6273,#9]]
[[30.5 6-10] [Function notify_all_at_thread_exit] [No] [-] [#9]]
[[30.5.1] [Class condition_variable] [Yes] [-] [#6195,#6273]]
[[30.5.2] [Class condition_variable_any] [Yes] [-] [#6195,#6273]]
[[30.6] [Futures] [Partial] [-] [-]]
[[30.6.1] [Overview] [Partial] [-] [-]]
[[30.6.2] [Error handling] [Yes] [-] [-]]
[[30.6.3] [Class future_error] [Partial] [noexcept] [#7279]]
[[30.6.4] [Shared state] [-] [-] [-]]
[[30.6.5] [Class template promise] [Partial] [at_thread_exit] [#7280]]
[[30.6.6] [Class template future] [Yes] [-] [-]]
[[30.6.7] [Class template shared_future] [Yes] [-] [-]]
[[30.6.8] [Function template async] [Partial] [deferred not implemented and only a copyable functor is allowed yet] [#4710]]
[[30.6.9] [Class template packaged_task] [Partial] [args,make_ready_at_thread_exit] [#7281,#7282]]
[[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] [#6228,#6194,#6225]]
[[30.6.6] [Class template future] [No] [unique_future is the closest to future] [##6229,#6228]]
[[30.6.7] [Class template shared_future] [Partial] [allocator,move] [#6228,#6194,#6225]]
[[30.6.8] [Function template async] [No] [async] [#4710]]
[[30.6.8] [Class template packaged_task] [Partial] [move] [#6194]]
]
[/
@@ -86,25 +86,16 @@
]
[endsect]
[/
[section:shared Shared Mutex library extension]
[section:shared Shared Locking extensions]
[table Howard's Shared Locking Proposal Conformance
[[Section] [Description] [Status] [Comments]]
[[X] [Shared Locking] [Yes] [Needs `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION]]
[[X.1] [Shared Lockables Concepts] [Yes] [ - ]]
[[X.1.1] [SharedLockable concept] [Yes] [ - ]]
[[X.1.2] [UpgradeLockable concept] [Yes] [ - ]]
[[X.2] [Shared Mutex Types] [Yes] [ - ]]
[[X.2.1] [shared_mutex class] [Yes] [ - ]]
[[X.2.2] [upgrade_mutex class] [Yes] [ - ]]
[[X.3] [Locks] [Yes] [-]]
[[X.3.1] [unique_lock class adaptations] [Yes] [-]]
[[X.3.2] [shared_lock class] [Yes] [ - ]]
[[X.3.3] [upgrade_lock class] [Yes] [-]]
[table Clock Requirements
[[Section] [Description] [Status] [Comments]]
[[XXXX] [DDDD] [SSSS] [CCCC]]
[[XXXX] [DDDD] [SSSS] [CCCC]]
]
[endsect]
]
[endsect]

View File

@@ -19,7 +19,6 @@
};
class condition_variable;
class condition_variable_any;
void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
}
The classes `condition_variable` and `condition_variable_any` provide a
@@ -87,7 +86,7 @@ optimizations in some cases, based on the knowledge of the mutex type;
[section:condition_variable Class `condition_variable`]
//#include <boost/thread/condition_variable.hpp>
#include <boost/thread/condition_variable.hpp>
namespace boost
{
@@ -105,6 +104,17 @@ optimizations in some cases, based on the knowledge of the mutex type;
template<typename predicate_type>
void wait(boost::unique_lock<boost::mutex>& lock,predicate_type predicate);
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time); // DEPRECATED V2
template<typename duration_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time); // DEPRECATED V2
template<typename predicate_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time,predicate_type predicate); // DEPRECATED V2
template<typename duration_type,typename predicate_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time,predicate_type predicate); // DEPRECATED V2
template <class Clock, class Duration>
typename cv_status::type
wait_until(
@@ -131,20 +141,12 @@ optimizations in some cases, based on the knowledge of the mutex type;
const chrono::duration<Rep, Period>& d,
Predicate pred);
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time);
template<typename duration_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time);
template<typename predicate_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time,predicate_type predicate);
template<typename duration_type,typename predicate_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time,predicate_type predicate);
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time);
// backwards compatibility
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time); // DEPRECATED V2
template<typename predicate_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time,predicate_type predicate);
#endif
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time,predicate_type predicate); // DEPRECATED V2
};
}
@@ -244,7 +246,7 @@ while(!pred())
[endsect]
[section:timed_wait `bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time)`]
[section:timed_wait `bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time)` DEPRECATED V2]
[variablelist
@@ -275,7 +277,7 @@ __interrupt__ on the __thread__ object associated with the current thread of exe
[endsect]
[section:timed_wait_rel `template<typename duration_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time)`]
[section:timed_wait_rel `template<typename duration_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time)` DEPRECATED V2]
[variablelist
@@ -308,7 +310,7 @@ __interrupt__ on the __thread__ object associated with the current thread of exe
[endsect]
[section:timed_wait_predicate `template<typename predicate_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock, boost::system_time const& abs_time, predicate_type pred)`]
[section:timed_wait_predicate `template<typename predicate_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock, boost::system_time const& abs_time, predicate_type pred)` DEPRECATED V2]
[variablelist
@@ -440,7 +442,7 @@ return true;
[section:condition_variable_any Class `condition_variable_any`]
//#include <boost/thread/condition_variable.hpp>
#include <boost/thread/condition_variable.hpp>
namespace boost
{
@@ -459,6 +461,18 @@ return true;
template<typename lock_type,typename predicate_type>
void wait(lock_type& lock,predicate_type predicate);
template<typename lock_type>
bool timed_wait(lock_type& lock,boost::system_time const& abs_time) // DEPRECATED V2;
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& lock,duration_type const& rel_time) // DEPRECATED V2;
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& lock,boost::system_time const& abs_time,predicate_type predicate) // DEPRECATED V2;
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& lock,duration_type const& rel_time,predicate_type predicate) // DEPRECATED V2;
template <class lock_type, class Clock, class Duration>
cv_status wait_until(
lock_type& lock,
@@ -482,20 +496,13 @@ return true;
const chrono::duration<Rep, Period>& d,
Predicate pred);
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
// backwards compatibility
template<typename lock_type>
bool timed_wait(lock_type& lock,boost::system_time const& abs_time);
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& lock,duration_type const& rel_time);
bool timed_wait(lock_type>& lock,boost::xtime const& abs_time) // DEPRECATED V2;
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& lock,boost::system_time const& abs_time,predicate_type predicate);
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& lock,duration_type const& rel_time,predicate_type predicate);
template<typename lock_type>
bool timed_wait(lock_type>& lock,boost::xtime const& abs_time);
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& lock,boost::xtime const& abs_time,predicate_type predicate);
#endif
bool timed_wait(lock_type& lock,boost::xtime const& abs_time,predicate_type predicate) // DEPRECATED V2;
};
}
@@ -589,7 +596,7 @@ while(!pred())
[endsect]
[section:timed_wait `template<typename lock_type> bool timed_wait(lock_type& lock,boost::system_time const& abs_time)`]
[section:timed_wait `template<typename lock_type> bool timed_wait(lock_type& lock,boost::system_time const& abs_time)` DEPRECATED V2]
[variablelist
@@ -614,7 +621,7 @@ __interrupt__ on the __thread__ object associated with the current thread of exe
[endsect]
[section:timed_wait_rel `template<typename lock_type,typename duration_type> bool timed_wait(lock_type& lock,duration_type const& rel_time)`]
[section:timed_wait_rel `template<typename lock_type,typename duration_type> bool timed_wait(lock_type& lock,duration_type const& rel_time)` DEPRECATED V2]
[variablelist
@@ -641,7 +648,7 @@ __interrupt__ on the __thread__ object associated with the current thread of exe
[endsect]
[section:timed_wait_predicate `template<typename lock_type,typename predicate_type> bool timed_wait(lock_type& lock, boost::system_time const& abs_time, predicate_type pred)`]
[section:timed_wait_predicate `template<typename lock_type,typename predicate_type> bool timed_wait(lock_type& lock, boost::system_time const& abs_time, predicate_type pred)` DEPRECATED V2]
[variablelist
@@ -752,53 +759,14 @@ return true;
[endsect]
[section:condition Typedef `condition` DEPRECATED V3]
[section:condition Typedef `condition`]
// #include <boost/thread/condition.hpp>
namespace boost
{
#include <boost/thread/condition.hpp>
typedef condition_variable_any condition;
}
The typedef `condition` is provided for backwards compatibility with previous boost releases.
[endsect]
[section:notify_all_at_thread_exit Non-member Function `notify_all_at_thread_exit`()]
// #include <boost/thread/condition_variable.hpp>
namespace boost
{
void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
}
[variablelist
[[Requires:] [`lk` is locked by the calling thread and either no other thread is waiting on `cond`, or `lk.mutex()` returns the same value for each of the lock arguments supplied by all concurrently waiting (via `wait`, `wait_for`, or `wait_until`) threads.]]
[[Effects:] [transfers ownership of the lock associated with `lk` into internal storage and schedules `cond` to be notified when the current thread exits, after all objects of thread storage duration associated with the current thread have been destroyed. This notification shall be as if
``
lk.unlock();
cond.notify_all();
``
]]
]
[/
[[Synchronization:] [The call to notify_all_at_thread_exit and the completion of the destructors for all the current threadÕs variables of thread storage duration synchronize with (1.10) calls to functions waiting on cond.
]]
[[Note:] [The supplied lock will be held until the thread exits, and care must be taken to ensure that this does not cause deadlock due to lock ordering issues. After calling notify_all_at_thread_exit it is recommended that the thread should be exited as soon as possible, and that no blocking or time-consuming tasks are run on that thread.
]]
[[Note:] [It is the userÕs responsibility to ensure that waiting threads do not erroneously assume that the thread has finished if they experience spurious wakeups. This typically requires that the condition being waited for is satisfied while holding the lock on lk, and that this lock is not released and reacquired prior to calling notify_all_at_thread_exit.
]]
]
[endsect]
[endsect]

View File

@@ -1,214 +0,0 @@
[/
(C) Copyright 20012 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:configuration Configuration]
[section:chrono Boost.Chrono]
Boost.Thread uses by default Boost.Chrono for the time related functions. For backward compatibility and also for compilers that don't work well with Boost.Chrono the user can define `BOOST_THREAD_DONT_USE_CHRONO`.
`BOOST_THREAD_USES_CHRONO` is defined when Boost.Thread uses Boost.Chrono.
[endsect]
[section:move Boost.Move]
Boost.Thread uses by default an internal move semantic implementation. Since version 3.0.0 you can use the move emulation emulation provided by Boost.Move.
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_USES_MOVE ` if you want to use Boost.Move interface.
When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_DONT_USE_MOVE ` if you don't want to use Boost.Move interface.
[endsect]
[section:shared_gen Shared Locking Generic]
The shared mutex implementation on Windows platform provides currently less functionality than the generic one that is used for PTheads based platforms. In order to have access to these functions, the user needs to define `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` to use the generic implementation, that while could be less efficient, provides all the functions.
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN ` if you want these features.
When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN ` if you don't want these features.
[endsect]
[section:shared_upwards Shared Locking Upwards Conversion]
Boost.Threads includes in version 3 the Shared Locking Upwards Conversion as defined in [@http://home.roadrunner.com/~hinnant/bloomington/shared_mutex.html Shared Locking].
These conversions need to be used carefully to avoid deadlock or livelock. The user need to define explicitly `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION` to get these upwards conversions.
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION ` if you want these features.
When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSION ` if you don't want these features.
[endsect]
[section:explicit_cnv Explicit Lock Conversion]
In [@http://home.roadrunner.com/~hinnant/bloomington/shared_mutex.html Shared Locking] the lock conversions are explicit. As this explicit conversion breaks the lock interfaces, it is provided only if the `BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION` is defined.
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION ` if you want these features.
When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION ` if you don't want these features.
[endsect]
[section:future unique_future versus future]
C++11 uses `std::future`. Versions of Boost.Thread previous to version 3.0.0 uses `boost:unique_future`.
Since version 3.0.0 `boost::future` replaces `boost::unique_future` when `BOOST_THREAD_PROVIDES_FUTURE` is defined. The documentation doesn't contains anymore however `boost::unique_future`.
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_PROVIDES_FUTURE` if you want to use boost::future.
When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_DONT_PROVIDE_FUTURE` if you want to use boost::unique_future.
[endsect]
[section:lazy promise lazy initialization]
C++11 promise initialize the associated state at construction time. Versions of Boost.Thread previous to version 3.0.0 initialize it lazily at any point in time in which this associated state is needed.
Since version 3.0.0 this difference in behavior can be configured. When `BOOST_THREAD_PROVIDES_PROMISE_LAZY` is defined the backward compatible behavior is provided.
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY ` if you want to use boost::future.
When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_PROVIDES_PROMISE_LAZY ` if you want to use boost::unique_future.
[endsect]
[section:alloc promise Allocator constructor]
C++11 std::promise provides constructors with allocators.
template <typename R>
class promise
{
public:
template <class Allocator>
explicit promise(allocator_arg_t, Allocator a);
// ...
};
template <class R, class Alloc> struct uses_allocator<promise<R>,Alloc>: true_type {};
where
struct allocator_arg_t { };
constexpr allocator_arg_t allocator_arg = allocator_arg_t();
template <class T, class Alloc> struct uses_allocator;
Since version 3.0.0 Boost.Thread implements this constructor using the following interface
namespace boost
{
typedef container::allocator_arg_t allocator_arg_t;
constexpr allocator_arg_t allocator_arg = {};
namespace container
{
template <class R, class Alloc>
struct uses_allocator<promise<R>,Alloc>: true_type {};
}
template <class T, class Alloc>
struct uses_allocator : public container::uses_allocator<T, Alloc> {};
}
which introduces a dependency on Boost.Container. This feature is provided only if `BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS` is defined.
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS ` if you want these features.
When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS ` if you don't want these features.
[endsect]
[section:terminate Call to terminate if joinable]
C++11 has a different semantic for the thread destructor and the move assignment. Instead of detaching the thread, calls to terminate() if the thread was joinable. When `BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE` and `BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE` is defined Boost.Thread provides the C++ semantic.
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE ` if you want these features.
When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE ` if you don't want these features.
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE ` if you want these features.
When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE ` if you don't want these features.
[endsect]
[section:once_flag once_flag]
C++11 defines a default constructor for once_flag. When `BOOST_THREAD_PROVIDES_ONCE_CXX11 ` is defined Boost.Thread provides this C++ semantics. In this case, the previous aggregate syntax is not supported.
boost::once_flag once = BOOST_ONCE_INIT;
You should now just do
boost::once_flag once;
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_PROVIDES_ONCE_CXX11` if you want these features.
When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11` if you don't want these features.
[endsect]
[section:deprecated Deprecated]
Version 3.0.0 deprecates some Boost.Thread features.
These deprecated features will be provided by default up to boost 1.52. If you don't want to include the deprecated features you could define `BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0`. Since 1.53 these features will not be included any more by default. Since this version, if you want to include the deprecated features yet you could define `BOOST_THREAD_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0`. These deprecated features will be only available until boost 1.55, that is you have 1 year and a half to move to the new features.
[endsect]
[section:version Version]
`BOOST_THREAD_VERSION` defines the Boost.Thread version.
The default version is 2. In this case the following breaking or extending macros are defined if the opposite is not requested:
* `BOOST_THREAD_PROVIDES_PROMISE_LAZY`
* `BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0`
The user can request the version 3 by defining `BOOST_THREAD_VERSION` to 3. In this case the following breaking or extending macros are defined if the opposite is not requested:
* Breaking change `BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION `
* Breaking change `BOOST_THREAD_PROVIDES_FUTURE`
* Uniformity `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN`
* Extension `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION`
* Conformity `BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS`
* Breaking change BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
* Breaking change BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
* Breaking change `BOOST_THREAD_PROVIDES_ONCE_CXX11`
* Breaking change `BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY`
* Breaking change `BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0`
The default value for `BOOST_THREAD_VERSION` will be changed to 3 since Boost 1.53.
[endsect]
[endsect]
[section:limitations Limitations]
Some compilers don't work correctly with some of the added features.
[section:sun SunPro]
If __SUNPRO_CC < 0x5100 the library defines
* `BOOST_THREAD_DONT_USE_MOVE`
If __SUNPRO_CC < 0x5100 the library defines
* `BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS`
[endsect]
[section:vacpp VACPP]
If __IBMCPP__ < 1100 the library defines
* `BOOST_THREAD_DONT_USE_CHRONO`
And Boost.Thread doesn't links with Boost.Chrono.
[endsect]
[endsect]

View File

@@ -1,365 +0,0 @@
[/
(C) Copyright 20012 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:emulations Emulations]
[section:delete `=delete` emulation]
C++11 allows to delete some implicitly generated functions as constructors and assignment using '= delete' as in
public:
thread(thread const&) = delete;
On compilers not supporting this feature, Boost.Thread relays on a partial simulation, it declares the function as private without definition.
private:
thread(thread &);
The emulation is partial as the private function can be used for overload resolution for some compilers and prefer it to other overloads that need a conversion. See below the consequences on the move semantic emulation.
[endsect]
[section:move Move semantics]
In order to implement Movable classes, move parameters and return types Boost.Thread uses the rvalue reference when the compiler support it.
On compilers not supporting it Boost.Thread uses either the emulation provided by Boost.Move or the emulation provided by the previous versions of Boost.Thread depending whether `BOOST_THREAD_USES_MOVE` is defined or not. This macros is unset by default when `BOOST_THREAD_VERSION` is 2. Since `BOOST_THREAD_VERSION` 3, `BOOST_THREAD_USES_MOVE` is defined.
[section:deprecated Deprecated Version 2 interface]
Previous to version 1.50, Boost.Thread make use of its own move semantic emulation which had more limitations than the provided by Boost.Move. In addition, it is of interest of the whole Boost community that Boost.Thread uses Boost.Move so that boost::thread can be stored on Movable aware containers.
To preserve backward compatibility at least during some releases, Boost.Thread allows the user to use the deprecated move semantic emulation defining BOOST_THREAD_DONT_USE_MOVE.
Many aspects of move semantics can be emulated for compilers not supporting rvalue references and Boost.Thread legacy offers tools for that purpose.
[section:Helper Helpers class and function]
Next follows the interface of the legacy move semantic helper class and function.
namespace boost
{
namespace detail
{
template<typename T>
struct thread_move_t
{
explicit thread_move_t(T& t_);
T& operator*() const;
T* operator->() const;
private:
void operator=(thread_move_t&);
};
}
template<typename T>
boost::detail::thread_move_t<T> move(boost::detail::thread_move_t<T> t);
}
[endsect]
[section:movable Movable emulation]
We can write a MovableOny class as follows. You just need to follow these simple steps:
* Add a conversion to the `detail::thread_move_t<classname>`
* Make the copy constructor private.
* Write a constructor taking the parameter as `detail::thread_move_t<classname>`
* Write an assignment taking the parameter as `detail::thread_move_t<classname>`
For example the thread class defines the following:
class thread
{
// ...
private:
thread(thread&);
thread& operator=(thread&);
public:
detail::thread_move_t<thread> move()
{
detail::thread_move_t<thread> x(*this);
return x;
}
operator detail::thread_move_t<thread>()
{
return move();
}
thread(detail::thread_move_t<thread> x)
{
thread_info=x->thread_info;
x->thread_info.reset();
}
thread& operator=(detail::thread_move_t<thread> x)
{
thread new_thread(x);
swap(new_thread);
return *this;
}
// ...
};
[endsect]
[endsect]
[section:portable Portable interface]
In order to make the library code portable Boost.Thread uses some macros that will use either the ones provided by Boost.Move or the deprecated move semantics provided by previous versions of Boost.Thread.
See the Boost.Move documentation for a complete description on how to declare new Movable classes and its limitations.
* `BOOST_THREAD_RV_REF(TYPE)` is the equivalent of `BOOST_RV_REF(TYPE)`
* `BOOST_THREAD_RV_REF_BEG` is the equivalent of `BOOST_RV_REF_BEG(TYPE)`
* `BOOST_THREAD_RV_REF_END` is the equivalent of `BOOST_RV_REF_END(TYPE)`
* `BOOST_THREAD_FWD_REF(TYPE)` is the equivalent of `BOOST_FWD_REF(TYPE)
In addition the following macros are needed to make the code portable:
* `BOOST_THREAD_RV(V)` macro to access the rvalue from a BOOST_THREAD_RV_REF(TYPE),
* `BOOST_THREAD_MAKE_RV_REF(RVALUE)` makes a rvalue.
* `BOOST_THREAD_DCL_MOVABLE(CLASS)` to avoid conflicts with Boost.Move
* `BOOST_THREAD_DCL_MOVABLE_BEG(T1)` and `BOOST_THREAD_DCL_MOVABLE_END` are variant of `BOOST_THREAD_DCL_MOVABLE` when the parameter is a template instantiation.
Other macros are provided and must be included on the public section:
* `BOOST_THREAD_NO_COPYABLE` declares a class no-copyable either deleting the copy constructors and copy assignment or moving them to the private section.
* `BOOST_THREAD_MOVABLE(CLASS)` declares all the implicit conversions to an rvalue-reference.
* `BOOST_THREAD_MOVABLE_ONLY(CLASS)` is the equivalent of `BOOST_MOVABLE_BUT_NOT_COPYABLE(CLASS)`
* `BOOST_THREAD_COPYABLE_AND_MOVABLE(CLASS)` is the equivalent of `BOOST_COPYABLE_AND_MOVABLE(CLASS)`
[section:NO_COPYABLE `BOOST_THREAD_NO_COPYABLE(CLASS)`]
This macro marks a class as no copyable, disabling copy construction and assignment.
[endsect]
[section:MOVABLE `BOOST_THREAD_MOVABLE(CLASS)`]
This macro marks a class as movable, declaring all the implicit conversions to an rvalue-reference.
[endsect]
[section:MOVABLE_ONLY `BOOST_THREAD_MOVABLE_ONLY(CLASS)`]
This macro marks a type as movable but not copyable, disabling copy construction and assignment. The user will need to write a move constructor/assignment to fully write a movable but not copyable class.
[endsect]
[section:COPYABLE_AND_MOVABLE `BOOST_THREAD_COPYABLE_AND_MOVABLE(CLASS)`]
This macro marks a type as copyable and movable. The user will need to write a move constructor/assignment and a copy assignment to fully write a copyable and movable class.
[endsect]
[section:RV_REF `BOOST_THREAD_RV_REF(TYPE)`, `BOOST_THREAD_RV_REF_BEG` and `BOOST_THREAD_RV_REF_END`]
This macro is used to achieve portable syntax in move constructors and assignments for classes marked as `BOOST_THREAD_COPYABLE_AND_MOVABLE` or `BOOST_THREAD_MOVABLE_ONLY`.
`BOOST_THREAD_RV_REF_BEG` and `BOOST_THREAD_RV_REF_END` are used when the parameter end with a `>` to avoid the compiler error.
[endsect]
[section:RV `BOOST_THREAD_RV(V)`]
While Boost.Move emulation allows to access an rvalue reference `BOOST_THREAD_RV_REF(TYPE)` using the dot operator, the legacy defines the `operator->`. We need then a macro `BOOST_THREAD_RV` that mask this difference. E.g.
thread(BOOST_THREAD_RV_REF(thread) x)
{
thread_info=BOOST_THREAD_RV(x).thread_info;
BOOST_THREAD_RV(x).thread_info.reset();
}
The use of this macros has reduced considerably the size of the Boost.Thread move related code.
[endsect]
[section:MAKE_RV_REF `BOOST_THREAD_MAKE_RV_REF(RVALUE)`]
While Boost.Move is the best C++03 move emulation there are some limitations that impact the way the library can be used.
For example, with the following declarations
class thread {
// ...
private:
thread(thread &);
public:
thread(rv<thread>&);
// ...
};
This could not work on some compilers even if thread is convertible to `rv<thread>` because the compiler prefers the private copy constructor.
thread mkth()
{
return thread(f);
}
On these compilers we need to use instead an explicit conversion. The library provides a move member function that allows to workaround the issue.
thread mkth()
{
return thread(f).move();
}
Note that `::boost::move` can not be used in this case as thread is not implicitly convertible to `thread&`.
thread mkth()
{
return ::boost::move(thread(f));
}
To make the code portable Boost.Thread the user needs to use a macro `BOOST_THREAD_MAKE_RV_REF` that can be used as in
thread mkth()
{
return BOOST_THREAD_MAKE_RV_REF(thread(f));
}
Note that this limitation is shared also by the legacy Boost.Thread move emulation.
[endsect]
[section:DCL_MOVABLE `BOOST_THREAD_DCL_MOVABLE`, `BOOST_THREAD_DCL_MOVABLE_BEG(T1)` and `BOOST_THREAD_DCL_MOVABLE_END`]
As Boost.Move defines also the `boost::move` function we need to specialize the `has_move_emulation_enabled_aux` metafunction.
template <>
struct has_move_emulation_enabled_aux<thread>
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
so that the following Boost.Move overload is disabled
template <class T>
inline typename BOOST_MOVE_BOOST_NS::disable_if<has_move_emulation_enabled_aux<T>, T&>::type move(T& x);
The macros `BOOST_THREAD_DCL_MOVABLE(CLASS)`, `BOOST_THREAD_DCL_MOVABLE_BEG(T1)` and `BOOST_THREAD_DCL_MOVABLE_END` are used for this purpose. E.g.
BOOST_THREAD_DCL_MOVABLE(thread)
and
BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
[endsect]
[endsect]
[endsect]
[section:bool_explicit_conversion Bool explicit conversion]
Locks provide an explicit bool conversion operator when the compiler provides them.
explicit operator bool() const;
The library provides un implicit conversion to an undefined type that can be used as a conditional expression.
#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
operator ``['unspecified-bool-type]``() const;
bool operator!() const;
#else
explicit operator bool() const;
#endif
The user should use the lock.owns_lock() when a explicit conversion is required.
[section:bool_conversion `operator `['unspecified-bool-type]`() const`]
[variablelist
[[Returns:] [If __owns_lock_ref__ would return `true`, a value that evaluates to
`true` in boolean contexts, otherwise a value that evaluates to `false` in
boolean contexts.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:operator_not `bool operator!() const`]
[variablelist
[[Returns:] [`!` __owns_lock_ref__.]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]
[section:scoped_enums Scoped Enums]
Some of the enumerations defined in the standard library are scoped enums.
On compilers that don't support them, the library uses a class to wrap the underlying type. Instead of
enum class future_errc
{
broken_promise,
future_already_retrieved,
promise_already_satisfied,
no_state
};
the library declare these types as
BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc)
{
broken_promise,
future_already_retrieved,
promise_already_satisfied,
no_state
}
BOOST_SCOPED_ENUM_DECLARE_END(future_errc)
These macros allows to use 'future_errc' in almost all the cases as an scoped enum.
There are however some limitations:
* The type is not a C++ enum, so 'is_enum<future_errc>' will be false_type.
* The emulated scoped enum can not be used in switch nor in template arguments. For these cases the user needs to use some macros.
Instead of
switch (ev)
{
case future_errc::broken_promise:
// ...
use
switch (boost::native_value(ev))
{
case future_errc::broken_promise:
And instead of
#ifdef BOOST_NO_SCOPED_ENUMS
template <>
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type { };
#endif
use
#ifdef BOOST_NO_SCOPED_ENUMS
template <>
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { };
#endif
[endsect]
[endsect]

File diff suppressed because it is too large Load Diff

View File

@@ -23,26 +23,25 @@
[template unique_future_link[link_text] [link thread.synchronization.futures.reference.unique_future [link_text]]]
[def __unique_future__ [unique_future_link `future`]]
[def __unique_future `future`]
[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::future<R>::get()`]]
[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::future<R>::wait()`]]
[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::future<R>::is_ready()`]]
[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::future<R>::has_value()`]]
[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::future<R>::has_exception()`]]
[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::future<R>::get_state()`]]
[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`]]
@@ -70,7 +69,6 @@
[template packaged_task_link[link_text] [link thread.synchronization.futures.reference.packaged_task [link_text]]]
[def __packaged_task__ [packaged_task_link `boost::packaged_task`]]
[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()`]]
@@ -116,7 +114,7 @@ place of the return value.
}
boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything);
boost::__unique_future__<int> fi=pt.get_future();
boost::unique_future<int> fi=pt.get_future();
boost::thread task(boost::move(pt)); // launch task on a thread
@@ -134,7 +132,7 @@ future. A promise can therefore be used where the value may come from more than
produce multiple values.
boost::promise<int> pi;
boost::__unique_future__<int> fi;
boost::unique_future<int> fi;
fi=pi.get_future();
pi.set_value(42);
@@ -176,7 +174,7 @@ call to `f.get()` invokes the callback `invoke_lazy_task`, which runs the task t
{
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());
boost::unique_future<int> f(task.get_future());
assert(f.get()==42);
}

File diff suppressed because it is too large Load Diff

View File

@@ -76,6 +76,9 @@ __try_mutex__ is a `typedef` to __mutex__, provided for backwards compatibility
void lock();
void unlock();
bool try_lock();
bool timed_lock(system_time const & abs_time); // DEPRECATED V2
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time); // DEPRECATED V2
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
@@ -88,13 +91,6 @@ __try_mutex__ is a `typedef` to __mutex__, provided for backwards compatibility
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef unspecified-type scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
bool timed_lock(system_time const & abs_time);
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time);
#endif
};
__timed_mutex__ implements the __timed_lockable_concept__ to provide an exclusive-ownership mutex. At most one thread can own the
@@ -131,7 +127,7 @@ implementation. If no such instance exists, `native_handle()` and `native_handle
~recursive_mutex();
void lock();
bool try_lock() noexcept;
bool try_lock();
void unlock();
typedef platform-specific-type native_handle_type;
@@ -187,9 +183,12 @@ __recursive_try_mutex__ is a `typedef` to __recursive_mutex__, provided for back
~recursive_timed_mutex();
void lock();
bool try_lock() noexcept;
bool try_lock();
void unlock();
bool timed_lock(system_time const & abs_time); // DEPRECATED V2
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time); // DEPRECATED V2
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
@@ -202,13 +201,6 @@ __recursive_try_mutex__ is a `typedef` to __recursive_mutex__, provided for back
typedef unique_lock<recursive_timed_mutex> scoped_lock;
typedef unspecified-type scoped_try_lock;
typedef scoped_lock scoped_timed_lock;
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
bool timed_lock(system_time const & abs_time);
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time);
#endif
};
__recursive_timed_mutex__ implements the __timed_lockable_concept__ to provide an exclusive-ownership recursive mutex. At most one

View File

@@ -7,37 +7,16 @@
[section:once One-time Initialization]
#include <boost/thread/once.hpp>
namespace boost
{
struct once_flag;
template<typename Callable>
void call_once(once_flag& flag,Callable func);
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
void call_once(void (*func)(),once_flag& flag);
#endif
}
`boost::call_once` provides a mechanism for ensuring that an initialization routine is run exactly once without data races or deadlocks.
[section:once_flag Typedef `once_flag`]
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
struct once_flag
{
constexprr once_flag() noexcept;
once_flag(const once_flag&) = delete;
once_flag& operator=(const once_flag&) = delete;
};
#else
#include <boost/thread/once.hpp>
typedef platform-specific-type once_flag;
#define BOOST_ONCE_INIT platform-specific-initializer
#endif
Objects of type `boost::once_flag` shall be initialized with `BOOST_ONCE_INIT` if BOOST_THREAD_PROVIDES_ONCE_CXX11 is not defined
Objects of type `boost::once_flag` shall be initialized with `BOOST_ONCE_INIT`:
boost::once_flag f=BOOST_ONCE_INIT;
@@ -45,6 +24,8 @@ Objects of type `boost::once_flag` shall be initialized with `BOOST_ONCE_INIT` i
[section:call_once Non-member function `call_once`]
#include <boost/thread/once.hpp>
template<typename Callable>
void call_once(once_flag& flag,Callable func);

View File

@@ -12,18 +12,14 @@ __boost_thread__ enables the use of multiple threads of execution with shared da
functions for managing the threads themselves, along with others for synchronizing data between the threads or providing separate
copies of data specific to individual threads.
The __boost_thread__ library was originally written and designed by William E. Kempf (version 1).
Anthony Williams version (version 2) was a major rewrite designed to
The __boost_thread__ library was originally written and designed by William E. Kempf (version 0). Anthony Williams version (version 1) was a major rewrite designed to
closely follow the proposals presented to the C++ Standards Committee, in particular
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html N2497],
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2320.html N2320],
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2184.html N2184],
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2139.html N2139], and
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2094.html N2094]
Vicente J. Botet Escriba started (version 3) the adaptation to comply with the accepted Thread C++11 library (Make use of Boost.Chrono and Boost.Move) and the [@http://home.roadrunner.com/~hinnant/bloomington/shared_mutex.html Shared Locking] Howard Hinnant proposal except for the upward conversions.
Some minor non-standard features have been added also as thread attributes, reverse_lock, shared_lock_guard.
Vicente J. Botet Escriba started in version 2 the adaptation to comply with the accepted Thread C++11 library.
In order to use the classes and functions described here, you can
either include the specific headers specified by the descriptions of
@@ -44,31 +40,5 @@ The definition of these macros determines whether BOOST_THREAD_USE_DLL is define
The source code compiled when building the library defines a macros BOOST_THREAD_SOURCE that is used to import or export it. The user must not define this macro in any case.
Boost.Thread depends on some non header-only libraries.
* Boost.System: This dependency is mandatory and you will need to link with the library.
* Boost.Chrono: This dependency is optional (see below how to configure) and you will need to link with the library if you use some of the time related interfaces.
* Boost.DateTime: This dependency is mandatory, but even if Boost.DateTime is a non header-only library Boost.Thread uses only parts that are header-only, so in principle you should not need to link with the library.
It seems that there are some IDE (as e.g. Visual Studio) that deduce the libraries that a program needs to link to inspecting the sources. Such IDE could force to link to Boost.DateTime and/or Boost.Chrono.
As the single mandatory dependency is to Boost.System, the following
bjam toolset=msvc-11.0 --build-type=complete --with-thread
will install only boost_thread and boost_system.
Users of such IDE should force the Boost.Chrono and Boost.DateTime build using
bjam toolset=msvc-11.0 --build-type=complete --with-thread --with-chrono --with-date_time
The following section describes all the macros used to configure Boost.Thread.
[include configuration.qbk]
[endsect]

View File

@@ -12,30 +12,19 @@
class shared_mutex
{
public:
shared_mutex(shared_mutex const&) = delete;
shared_mutex& operator=(shared_mutex const&) = delete;
shared_mutex();
~shared_mutex();
void lock_shared();
bool try_lock_shared();
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
bool timed_lock_shared(system_time const& timeout);
void unlock_shared();
void lock();
bool try_lock();
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
bool timed_lock(system_time const& timeout);
void unlock();
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
// use upgrade_mutex instead.
void lock_upgrade();
void unlock_upgrade();
@@ -43,102 +32,13 @@
void unlock_and_lock_upgrade();
void unlock_and_lock_shared();
void unlock_upgrade_and_lock_shared();
#endif
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
bool timed_lock_shared(system_time const& timeout);
bool timed_lock(system_time const& timeout);
#endif
};
The class `boost::shared_mutex` provides an implementation of a multiple-reader / single-writer mutex. It implements the
__shared_lockable_concept__.
Multiple concurrent calls to __lock_ref__, __try_lock_ref__, `__try_lock_for()`, `__try_lock_until()`, __timed_lock_ref__, __lock_shared_ref__,
`__try_lock_shared_for()`, `__try_lock_shared_until()`, __try_lock_shared_ref__ and __timed_lock_shared_ref__ are permitted.
Note the the lack of reader-writer priority policies in shared_mutex. This is due to an algorithm credited to Alexander Terekhov which lets the OS decide which thread is the next to get the lock without caring whether a unique lock or shared lock is being sought. This results in a complete lack of reader or writer starvation. It is simply fair.
[endsect]
[section:upgrade_mutex Class `upgrade_mutex`]
#include <boost/thread/shared_mutex.hpp>
class upgrade_mutex
{
public:
upgrade_mutex(upgrade_mutex const&) = delete;
upgrade_mutex& operator=(upgrade_mutex const&) = delete;
upgrade_mutex();
~upgrade_mutex();
void lock_shared();
bool try_lock_shared();
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock_shared();
void lock();
bool try_lock();
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock();
void lock_upgrade();
template <class Rep, class Period>
bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock_upgrade();
// Shared <-> Exclusive
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock();
template <class Rep, class Period>
bool try_unlock_shared_and_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_unlock_shared_and_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
#endif
void unlock_and_lock_shared();
// Shared <-> Upgrade
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock_upgrade();
template <class Rep, class Period>
bool try_unlock_shared_and_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_unlock_shared_and_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time);
#endif
void unlock_upgrade_and_lock_shared();
// Upgrade <-> Exclusive
void unlock_upgrade_and_lock();
#if defined(BOOST_THREAD_PLATFORM_PTHREAD)
|| defined(BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN)
bool try_unlock_upgrade_and_lock();
template <class Rep, class Period>
bool try_unlock_upgrade_and_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_unlock_upgrade_and_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
#endif
void unlock_and_lock_upgrade();
};
The class `boost::upgrade_mutex` provides an implementation of a multiple-reader / single-writer mutex. It implements the
__upgrade_lockable_concept__.
Multiple concurrent calls to __lock_ref__, __try_lock_ref__, `__try_lock_for()`, `__try_lock_until()`, __timed_lock_ref__, __lock_shared_ref__,
`__try_lock_shared_for()`, `__try_lock_shared_until()`, __try_lock_shared_ref__ and __timed_lock_shared_ref__ are permitted.
Multiple concurrent calls to __lock_ref__, __try_lock_ref__, __timed_lock_ref__, __lock_shared_ref__, __try_lock_shared_ref__ and
__timed_lock_shared_ref__ shall be permitted.
[endsect]

View File

@@ -1,14 +0,0 @@
[/
(C) Copyright 2012 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:tutorial Tutorial]
[@http://home.roadrunner.com/~hinnant/mutexes/locking.html Handling mutexes in C++] is an excellent tutorial. You need just replace std and ting by boost.
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html Mutex, Lock, Condition Variable Rationale] adds rationale for the design decisions made for mutexes, locks and condition variables.
[endsect]

View File

@@ -6,9 +6,8 @@
http://www.boost.org/LICENSE_1_0.txt).
]
[library Thread
[article Thread
[quickbook 1.5]
[version 3.1.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
[copyright 2011-12 Vicente J. Botet Escriba]
@@ -24,11 +23,6 @@
[template lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.lockable [link_text]]]
[def __lockable_concept__ [lockable_concept_link `Lockable` concept]]
[def __lockable_concept_type__ [lockable_concept_link `Lockable`]]
[def __BasicLockable [link thread.synchronization.mutex_concepts.basic_lockable `BasicLockable`]]
[def __Lockable [link thread.synchronization.mutex_concepts.lockable `Lockable`]]
[def __TimedLockable [link thread.synchronization.mutex_concepts.timed_lockable `TimedLockable `]]
[def __SharedLockable [link thread.synchronization.mutex_concepts.shared_lockable `SharedLockable `]]
[def __UpgradeLockable [link thread.synchronization.mutex_concepts.upgrade_lockable `UpgradeLockable `]]
[template timed_lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable [link_text]]]
[def __timed_lockable_concept__ [timed_lockable_concept_link `TimedLockable` concept]]
@@ -43,9 +37,8 @@
[def __upgrade_lockable_concept_type__ [upgrade_lockable_concept_link `UpgradeLockable`]]
[template lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.basic_lockable.lock [link_text]]]
[template lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.lock [link_text]]]
[def __lock_ref__ [lock_ref_link `lock()`]]
[def __lock [link thread.synchronization.mutex_concepts.basic_lockable.lock `lock`]]
[template lock_multiple_ref_link[link_text] [link thread.synchronization.lock_functions.lock_multiple [link_text]]]
[def __lock_multiple_ref__ [lock_multiple_ref_link `lock()`]]
@@ -53,89 +46,53 @@
[template try_lock_multiple_ref_link[link_text] [link thread.synchronization.lock_functions.try_lock_multiple [link_text]]]
[def __try_lock_multiple_ref__ [try_lock_multiple_ref_link `try_lock()`]]
[template unlock_ref_link[link_text] [link thread.synchronization.mutex_concepts.basic_lockable.unlock [link_text]]]
[template unlock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.unlock [link_text]]]
[def __unlock_ref__ [unlock_ref_link `unlock()`]]
[def __unlock [link thread.synchronization.mutex_concepts.basic_lockable.unlock `unlock`]]
[template try_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.try_lock [link_text]]]
[def __try_lock_ref__ [try_lock_ref_link `try_lock()`]]
[def __try_lock [link thread.synchronization.mutex_concepts.lockable.try_lock `try_lock`]]
[template timed_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock [link_text]]]
[def __timed_lock_ref__ [timed_lock_ref_link `timed_lock()`]]
[def __timed_lock [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock `timed_lock`]]
[def __try_lock_for [link thread.synchronization.mutex_concepts.timed_lockable.try_lock_for `try_lock_for`]]
[def __try_lock_until [link thread.synchronization.mutex_concepts.timed_lockable.try_lock_until `try_lock_until`]]
[template timed_lock_duration_ref_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock_duration [link_text]]]
[def __timed_lock_duration_ref__ [timed_lock_duration_ref_link `timed_lock()`]]
[def __timed_lock_duration [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock_duration `timed_lock`]]
[template lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.lock_shared [link_text]]]
[def __lock_shared_ref__ [lock_shared_ref_link `lock_shared()`]]
[def __lock_shared [link thread.synchronization.mutex_concepts.shared_lockable.lock_shared `lock_shared()`]]
[template unlock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.unlock_shared [link_text]]]
[def __unlock_shared_ref__ [unlock_shared_ref_link `unlock_shared()`]]
[def __unlock_shared [link thread.synchronization.mutex_concepts.shared_lockable.unlock_shared `unlock_shared()`]]
[template try_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared [link_text]]]
[def __try_lock_shared_ref__ [try_lock_shared_ref_link `try_lock_shared()`]]
[def __try_lock_shared [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared `try_lock_shared`]]
[template timed_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.timed_lock_shared [link_text]]]
[def __timed_lock_shared_ref__ [timed_lock_shared_ref_link `timed_lock_shared()`]]
[def __try_lock_shared_for [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared_for `try_lock_shared_for`]]
[def __try_lock_shared_for [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared_until `try_lock_shared_until`]]
[template timed_lock_shared_duration_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.timed_lock_shared_duration [link_text]]]
[def __timed_lock_shared_duration_ref__ [timed_lock_shared_duration_ref_link `timed_lock_shared()`]]
[def __try_lock_shared_for [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared_for `try_lock_shared_for`]]
[def __try_lock_shared_until [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared_until `try_lock_shared_until`]]
[template lock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.lock_upgrade [link_text]]]
[def __lock_upgrade_ref__ [lock_upgrade_ref_link `lock_upgrade()`]]
[def __lock_upgrade [link thread.synchronization.mutex_concepts.upgrade_lockable.lock_upgrade `lock_upgrade`]]
[def __try_lock_upgrade [link thread.synchronization.mutex_concepts.upgrade_lockable.try_lock_upgrade `try_lock_upgrade`]]
[def __try_lock_upgrade_for [link thread.synchronization.mutex_concepts.upgrade_lockable.try_lock_upgrade_for `try_lock_upgrade_for`]]
[def __try_lock_upgrade_until [link thread.synchronization.mutex_concepts.upgrade_lockable.try_lock_upgrade_until `try_lock_upgrade_until`]]
[template unlock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade [link_text]]]
[def __unlock_upgrade_ref__ [unlock_upgrade_ref_link `unlock_upgrade()`]]
[def __unlock_upgrade [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade `unlock_upgrade`]]
[template unlock_upgrade_and_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock [link_text]]]
[def __unlock_upgrade_and_lock_ref__ [unlock_upgrade_and_lock_ref_link `unlock_upgrade_and_lock()`]]
[def __unlock_upgrade_and_lock [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock `unlock_upgrade_and_lock`]]
[template unlock_and_lock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_and_lock_upgrade [link_text]]]
[def __unlock_and_lock_upgrade_ref__ [unlock_and_lock_upgrade_ref_link `unlock_and_lock_upgrade()`]]
[def __unlock_and_lock_upgrade [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_and_lock_upgrade `unlock_and_lock_upgrade`]]
[template unlock_upgrade_and_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock_shared [link_text]]]
[def __unlock_upgrade_and_lock_shared_ref__ [unlock_upgrade_and_lock_shared_ref_link `unlock_upgrade_and_lock_shared()`]]
[def __unlock_upgrade_and_lock_shared [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock_shared `unlock_upgrade_and_lock_shared`]]
[def __try_unlock_shared_and_lock [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock `try_unlock_shared_and_lock`]]
[def __try_unlock_shared_and_lock_for [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock_for `try_unlock_shared_and_lock_for`]]
[def __try_unlock_shared_and_lock_until [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock_until `try_unlock_shared_and_lock_until`]]
[def __unlock_and_lock_shared [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_and_lock_shared `unlock_and_lock_shared`]]
[def __try_unlock_shared_and_lock_upgrade [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock_upgrade `try_unlock_shared_and_lock_upgrade`]]
[def __try_unlock_shared_and_lock_upgrade_for [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock_upgrade_for `try_unlock_shared_and_lock_upgrade_for`]]
[def __try_unlock_shared_and_lock_upgrade_until [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock_upgrade_until `try_unlock_shared_and_lock_upgrade_until`]]
[def __try_unlock_upgrade_and_lock [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_upgrade_and_lock `try_unlock_upgrade_and_lock`]]
[def __try_unlock_upgrade_and_lock_for [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_upgrade_and_lock_for `try_unlock_upgrade_and_lock_for`]]
[def __try_unlock_upgrade_and_lock_until [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_upgrade_and_lock_until `try_unlock_upgrade_and_lock_until`]]
[template owns_lock_ref_link[link_text] [link thread.synchronization.locks.unique_lock.owns_lock [link_text]]]
[def __owns_lock_ref__ [owns_lock_ref_link `owns_lock()`]]
[def __owns_lock [owns_lock_ref_link `owns_lock()`]]
[template owns_lock_shared_ref_link[link_text] [link thread.synchronization.locks.shared_lock.owns_lock [link_text]]]
[def __owns_lock_shared_ref__ [owns_lock_shared_ref_link `owns_lock()`]]
@@ -159,17 +116,13 @@
[def __lock_guard__ [link thread.synchronization.locks.lock_guard `boost::lock_guard`]]
[def __unique_lock__ [unique_lock_link `boost::unique_lock`]]
[def __unique_lock [unique_lock_link `boost::unique_lock`]]
[def __shared_lock__ [link thread.synchronization.locks.shared_lock `boost::shared_lock`]]
[def __upgrade_lock__ [link thread.synchronization.locks.upgrade_lock `boost::upgrade_lock`]]
[def __upgrade_to_unique_lock__ [link thread.synchronization.locks.upgrade_to_unique_lock `boost::upgrade_to_unique_lock`]]
[def __reverse_lock [link thread.synchronization.other_locks.reverse_lock `reverse_lock`]]
[def __shared_lock_guard [link thread.synchronization.other_locks.shared_lock_guard `shared_lock_guard`]]
[def __shared_lock_guard_constructor_adopt [link thread.synchronization.other_locks.shared_lock_guard `shared_lock_guard`]]
[def __thread__ [link thread.thread_management.thread `boost::thread`]]
[def __thread [link thread.thread_management.thread `thread`]]
[def __thread [link thread.thread_management.thread `boost::thread`]]
[def __thread_id__ [link thread.thread_management.thread.id `boost::thread::id`]]
[template join_link[link_text] [link thread.thread_management.thread.join [link_text]]]
[def __join__ [join_link `join()`]]
@@ -185,8 +138,6 @@
[def __sleep__ [link thread.thread_management.this_thread.sleep `boost::this_thread::sleep()`]]
[def __sleep_for [link thread.thread_management.this_thread.sleep_for `sleep_for`]]
[def __sleep_until [link thread.thread_management.this_thread.sleep_until `sleep_until`]]
[def __yield [link thread.thread_management.this_thread.yield `yield`]]
[def __get_id [link thread.thread_management.thread.get_id `get_id`]]
[def __interruption_enabled__ [link thread.thread_management.this_thread.interruption_enabled `boost::this_thread::interruption_enabled()`]]
[def __interruption_requested__ [link thread.thread_management.this_thread.interruption_requested `boost::this_thread::interruption_requested()`]]
@@ -225,7 +176,6 @@
[include thread_ref.qbk]
[section:synchronization Synchronization]
[include sync_tutorial.qbk]
[include mutex_concepts.qbk]
[include mutexes.qbk]
[include condition_variables.qbk]
@@ -238,8 +188,6 @@
[include time.qbk]
[include emulations.qbk]
[include acknowledgements.qbk]
[include compliance.qbk]

View File

@@ -10,39 +10,28 @@
[section:synopsis Synopsis]
#include <boost/thread/thread.hpp>
namespace boost
{
class thread;
void swap(thread& lhs,thread& rhs) noexcept;
void swap(thread& lhs,thread& rhs);
namespace this_thread
{
thread::id get_id() noexcept;
template<typename TimeDuration>
void sleep(TimeDuration const& rel_time); // DEPRECATED
void sleep(system_time const& abs_time) // DEPRECATED
void yield() noexcept;
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
template<typename Callable>
void at_thread_exit(Callable func); // EXTENSION
void interruption_point(); // EXTENSION
bool interruption_requested() noexcept; // EXTENSION
bool interruption_enabled() noexcept; // EXTENSION
class disable_interruption; // EXTENSION
class restore_interruption; // EXTENSION
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
void sleep(TimeDuration const& rel_time);
void sleep(system_time const& abs_time);
#endif
void interruption_point();
bool interruption_requested();
bool interruption_enabled();
class disable_interruption;
class restore_interruption;
}
class thread_group; // EXTENSION
}
[endsect] [/section:synopsis Synopsis]
@@ -271,18 +260,18 @@ The following functions are ['interruption points], which will throw __thread_in
current thread, and interruption is requested for the current thread:
* [join_link `boost::thread::join()`]
* [timed_join_link `boost::thread::timed_join()`]
* [timed_join_link `boost::thread::timed_join()` DEPRECATED V2]
* `boost::__thread::__try_join_for()`,
* `boost::__thread::__try_join_until()`,
* [cond_wait_link `boost::condition_variable::wait()`]
* [cond_timed_wait_link `boost::condition_variable::timed_wait()`]
* [cond_timed_wait_link `boost::condition_variable::timed_wait()` DEPRECATED V2]
* `boost::__condition_variable::__wait_for()`
* `boost::__condition_variable::__wait_until()`
* [cond_any_wait_link `boost::condition_variable_any::wait()`]
* [cond_any_timed_wait_link `boost::condition_variable_any::timed_wait()`]
* [cond_any_timed_wait_link `boost::condition_variable_any::timed_wait()` DEPRECATED V2]
* `boost::__condition_variable_any::__cvany_wait_for()`
* `boost::__condition_variable_any::__cvany_wait_until()`
* [link thread.thread_management.thread.sleep `boost::thread::sleep()`]
* [link thread.thread_management.thread.sleep `boost::thread::sleep()` DEPRECATED V2]
* `boost::this_thread::__sleep_for()`
* `boost::this_thread::__sleep_until()`
* __interruption_point__
@@ -338,7 +327,7 @@ The user can access to some synchronization functions related to the native curr
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::interruption_point()` will be just ignored.
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.
@@ -369,38 +358,35 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
template <class F>
explicit thread(F f);
template <class F>
thread(F &&f);
template <class F,class A1,class A2,...>
thread(F f,A1 a1,A2 a2,...);
// template <class F, class ...Args>
// explicit thread(F&& f, Args&&... args); // NOT YET IMPLEMENTED
template <class F>
explicit thread(attributes& attrs, F f); // EXTENSION
template <class F>
thread(attributes& attrs, F &&f); // EXTENSION
// template <class F, class ...Args>
// explicit thread(attributes& attrs, F&& f, Args&&... args); // NOT YET IMPLEMENTED
thread(detail::thread_move_t<F> f);
template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
// move support
thread(thread && x) noexcept;
thread& operator=(thread && x) noexcept;
thread(detail::thread_move_t<thread> x);
thread& operator=(detail::thread_move_t<thread> x);
operator detail::thread_move_t<thread>();
detail::thread_move_t<thread> move();
void swap(thread& x) noexcept;
class id;
class attributes; // EXTENSION
id get_id() const noexcept;
bool joinable() const noexcept;
void join();
bool timed_join(const system_time& wait_until); // DEPRECATED V2
template<typename TimeDuration>
bool timed_join(TimeDuration const& rel_time); // DEPRECATED V2
template <class Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time); // EXTENSION
bool try_join_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_join_until(const chrono::time_point<Clock, Duration>& t); // EXTENSION
bool try_join_until(const chrono::time_point<Clock, Duration>& t);
void detach();
@@ -409,38 +395,29 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
void interrupt(); // EXTENSION
bool interruption_requested() const noexcept; // EXTENSION
void interrupt();
bool interruption_requested() const;
// backwards compatibility
bool operator==(const thread& other) const; // DEPRECATED V2
bool operator!=(const thread& other) const; // DEPRECATED V2
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
bool timed_join(const system_time& wait_until);
template<typename TimeDuration>
bool timed_join(TimeDuration const& rel_time);
#endif
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
bool operator==(const thread& other) const;
bool operator!=(const thread& other) const;
static void yield();
static void sleep(const system_time& xt);
#endif
static void yield(); // DEPRECATED V2
static void sleep(const system_time& xt); // DEPRECATED V2
};
void swap(thread& lhs,thread& rhs) noexcept;
void swap(thread& lhs,thread& rhs) noexcep;
detail::thread_move_t<thread> move(detail::thread_move_t<thread> t);
[section:default_constructor Default Constructor]
thread() noexcept;
thread() noexcep;
[variablelist
[[Effects:] [Constructs a __thread__ instance that refers to __not_a_thread__.]]
[[Postconditions:] [`this->get_id()==thread::id()`]]
[[Throws:] [Nothing]]
]
@@ -450,12 +427,13 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
[section:move_constructor Move Constructor]
thread(thread&& other) noexcept;
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()` and `get_id()` returns the value of `other.get_id()` prior to the construction]]
[[Postconditions:] [`other->get_id()==thread::id()`]]
[[Throws:] [Nothing]]
@@ -466,14 +444,15 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
[section:move_assignment Move assignment operator]
thread& operator=(thread&& other) noexcept;
thread& operator=(detail::thread_move_t<thread> other);
[variablelist
[[Effects:] [Transfers ownership of the thread managed by `other` (if
any) to `*this`. Version 2: If there was a thread previously associated with
`*this` then that thread is detached, Version 3: If the thread is joinable calls to std::terminate.]]
any) to `*this`. If there was a thread previously associated with
`*this` then that thread is detached.]]
[[Postconditions:] [`other->get_id()==thread::id()` and `get_id()` returns the value of `other.get_id()` prior to the assignment.]]
[[Postconditions:] [`other->get_id()==thread::id()`]]
[[Throws:] [Nothing]]
@@ -488,68 +467,13 @@ any) to `*this`. Version 2: If there was a thread previously associated with
[variablelist
[[Requires:] [`Callable` must by Copyable and `func()` must be a valid expression.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
not of type __thread_interrupted__, then `std::terminate()` will be called. Any return value from this invocation is ignored.]]
[[Postconditions:] [`*this` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
[[Throws:] [__thread_resource_error__ if an error occurs. ]]
[[Error Conditions:] [
[*resource_unavailable_try_again] : the system lacked the necessary resources to create an- other thread, or the system-imposed limit on the number of threads in a process would be exceeded.
]]
]
[endsect]
[section:attr_callable_constructor Thread Attributes Constructor EXTENSION]
template<typename Callable>
thread(attributes& attrs, Callable func);
[variablelist
[[Preconditions:] [`Callable` must by copyable.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
not of type __thread_interrupted__, then `std::terminate()` will be called. Any return value from this invocation is ignored.
If the attributes declare the native thread as detached, the boost::thread will be detached.]]
[[Postconditions:] [`*this` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
[[Throws:] [__thread_resource_error__ if an error occurs. ]]
[[Error Conditions:] [
[*resource_unavailable_try_again] : the system lacked the necessary resources to create an- other thread, or the system-imposed limit on the number of threads in a process would be exceeded.
]]
]
[endsect]
[section:callable_move_constructor Thread Callable Move Constructor]
template<typename Callable>
thread(Callable &&func);
[variablelist
[[Preconditions:] [`Callable` must by Movable.]]
[[Effects:] [`func` is moved into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
not of type __thread_interrupted__, then `std::terminate()` will be called. Any return value from this invocation is ignored.]]
not of type __thread_interrupted__, then `std::terminate()` will be called.]]
[[Postconditions:] [`*this` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
[[Postconditions:] [`*this` refers to the newly created thread of execution.]]
[[Throws:] [__thread_resource_error__ if an error occurs. ]]
@@ -563,35 +487,6 @@ not of type __thread_interrupted__, then `std::terminate()` will be called. Any
[endsect]
[section:attr_callable_move_constructor Thread Attributes Move Constructor EXTENSION]
template<typename Callable>
thread(attributes& attrs, Callable func);
[variablelist
[[Preconditions:] [`Callable` must by copyable.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
not of type __thread_interrupted__, then `std::terminate()` will be called. Any return value from this invocation is ignored.
If the attributes declare the native thread as detached, the boost::thread will be detached.]]
[[Postconditions:] [`*this` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
[[Throws:] [__thread_resource_error__ if an error occurs. ]]
[[Error Conditions:] [
[*resource_unavailable_try_again] : the system lacked the necessary resources to create an- other thread, or the system-imposed limit on the number of threads in a process would be exceeded.
]]
]
[endsect]
[section:multiple_argument_constructor Thread Constructor with arguments]
template <class F,class A1,class A2,...>
@@ -628,7 +523,7 @@ are copied into internal storage for access by the new thread.]]]
[variablelist
[[Effects:] [Version 2: If `*this` has an associated thread of execution, calls __detach__, Version 3: If the thread is joinable calls to std::terminate. Destroys `*this`.]]
[[Effects:] [If `*this` has an associated thread of execution, calls __detach__. Destroys `*this`.]]
[[Throws:] [Nothing.]]
@@ -636,25 +531,6 @@ are copied into internal storage for access by the new thread.]]]
[endsect]
[/
[section:v2_destructor V3 Thread Destructor]
~thread();
[variablelist
[[Effects:] [If `*this` has an associated thread of execution, calls terminate. Destroys `*this`.]]
[[Note:] [Either implicitly detaching or joining a `joinable()` thread in its destructor could result in difficult to debug correctness (for `detach`) or performance (for `join`) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable.]]
[[Throws:] [Nothing.]]
]
[endsect]
]
[section:joinable Member function `joinable()`]
bool joinable() const noexcept;
@@ -676,7 +552,7 @@ are copied into internal storage for access by the new thread.]]]
[variablelist
[[Preconditions:] [the thread is joinable.]]
[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
[[Effects:] [If `*this` refers to a thread of execution, waits for that thread of execution to complete.]]
@@ -686,14 +562,12 @@ are copied into internal storage for access by the new thread.]]]
[[Error Conditions:] [
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == std::this_thread::get_id().
[/
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable.
]
]]
@@ -704,7 +578,7 @@ are copied into internal storage for access by the new thread.]]]
[endsect]
[section:timed_join Member function `timed_join()`]
[section:timed_join Member function `timed_join()` DEPRECATED V2]
bool timed_join(const system_time& wait_until);
@@ -713,7 +587,7 @@ are copied into internal storage for access by the new thread.]]]
[variablelist
[[Preconditions:] [the thread is joinable.]]
[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
[[Effects:] [If `*this` refers to a thread of execution, waits for that thread of execution to complete, the time `wait_until` has
been reach or the specified duration `rel_time` has elapsed. If `*this` doesn't refer to a thread of execution, returns immediately.]]
@@ -729,13 +603,12 @@ unchanged.]]
[[Error Conditions:] [
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == std::this_thread::get_id().
[/
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable.
]
]]
@@ -746,14 +619,14 @@ unchanged.]]
[endsect]
[section:try_join_for Member function `try_join_for()` EXTENSION]
[section:try_join_for Member function `try_join_for()`]
template <class Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time);
[variablelist
[[Preconditions:] [the thread is joinable.]]
[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
[[Effects:] [If `*this` refers to a thread of execution, waits for that thread of execution to complete,
the specified duration `rel_time` has elapsed. If `*this` doesn't refer to a thread of execution, returns immediately.]]
@@ -769,13 +642,12 @@ unchanged.]]
[[Error Conditions:] [
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == std::this_thread::get_id().
[/
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable.
]
]]
@@ -786,14 +658,14 @@ unchanged.]]
[endsect]
[section:try_join_until Member function `try_join_until()` EXTENSION]
[section:try_join_until Member function `try_join_until()`]
template <class Clock, class Duration>
bool try_join_until(const chrono::time_point<Clock, Duration>& abs_time);
[variablelist
[[Preconditions:] [the thread is joinable.]]
[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
[[Effects:] [If `*this` refers to a thread of execution, waits for that thread of execution to complete, the time `abs_time` has
been reach. If `*this` doesn't refer to a thread of execution, returns immediately.]]
@@ -809,14 +681,12 @@ unchanged.]]
[[Error Conditions:] [
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == std::this_thread::get_id().
[/
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable.
]
]]
@@ -835,21 +705,11 @@ unchanged.]]
[variablelist
[[Preconditions:] [the thread is joinable.]]
[[Effects:] [The thread of execution becomes detached, and no longer has an associated __thread__ object.]]
[[Effects:] [If `*this` refers to a thread of execution, that thread of execution becomes detached, and no longer has an associated __thread__ object.]]
[[Postconditions:] [`*this` no longer refers to any thread of execution.]]
[[Throws:] [`system_error`]]
[[Error Conditions:] [
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRROW_IF_PRECONDITION_NOT_SATISFIED is defined.
]]
[[Throws:] [Nothing]]
]
@@ -919,7 +779,7 @@ implementation. If no such instance exists, `native_handle()` and `native_handle
[endsect]
[section:equals `operator==` DEPRECATED V3]
[section:equals `operator==`]
bool operator==(const thread& other) const;
@@ -927,13 +787,11 @@ implementation. If no such instance exists, `native_handle()` and `native_handle
[[Returns:] [`get_id()==other.get_id()`]]
[[See:] [Use `a.__get_id()==b.__get_id()` instead]]
]
[endsect]
[section:not_equals `operator!=` DEPRECATED V3]
[section:not_equals `operator!=`]
bool operator!=(const thread& other) const;
@@ -941,13 +799,11 @@ implementation. If no such instance exists, `native_handle()` and `native_handle
[[Returns:] [`get_id()!=other.get_id()`]]
[[See:] [Use `a.__get_id()!=b.__get_id()` instead`]]
]
[endsect]
[section:sleep Static member function `sleep()`]
[section:sleep Static member function `sleep()` DEPRECATED V2]
void sleep(system_time const& abs_time);
@@ -959,13 +815,11 @@ implementation. If no such instance exists, `native_handle()` and `native_handle
[[Notes:] [`sleep()` is one of the predefined __interruption_points__.]]
[[See:] [Use `this_thread::__sleep_for()` or `this_thread::__sleep_until()`]]
]
[endsect]
[section:yield Static member function `yield()`]
[section:yield Static member function `yield()` DEPRECATED V2]
void yield();
@@ -973,8 +827,6 @@ implementation. If no such instance exists, `native_handle()` and `native_handle
[[Effects:] [See [link thread.thread_management.this_thread.yield `boost::this_thread::yield()`].]]
[[See:] [Use `this_thread::__yield()`]]
]
[endsect]
@@ -1011,6 +863,26 @@ 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`]
@@ -1158,88 +1030,8 @@ instances of __thread_id__ `a` and `b` is the same if `a==b`, and different if `
[endsect]
[section:attributes Class `boost::thread::attributes` EXTENSION]
class thread::attributes {
public:
attributes() noexcept;
~ attributes()=default;
// stack
void set_stack_size(std::size_t size) noexcept;
std::size_t get_stack_size() const noexcept;
#if defined BOOST_THREAD_DEFINES_THREAD_ATTRIBUTES_NATIVE_HANDLE
typedef platform-specific-type native_handle_type;
native_handle_type* native_handle() noexcept;
const native_handle_type* native_handle() const noexcept;
#endif
};
[section:constructor Default constructor]
thread_attributes() noexcept;
[variablelist
[[Effects:] [Constructs a thread atrributes instance with its default values.]]
[[Throws:] [Nothing]]
]
[endsect]
[section: set_stack_size Member function `set_stack_size()`]
void set_stack_size(std::size_t size) noexcept;
[variablelist
[[Effects:] [Stores the stack size to be used to create a thread. This is an hint that the implementation can choose a better size if to small or too big or not aligned to a page.]]
[[Postconditions:] [`this-> get_stack_size()` returns the chosen stack size.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:get_stack_size Member function `get_stack_size()`]
std::size_t get_stack_size() const noexcept;
[variablelist
[[Returns:] [The stack size to be used on the creation of a thread. Note that this function can return 0 meaning the default.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:nativehandle Member function `native_handle()`]
typedef platform-specific-type native_handle_type;
typedef platform-specific-type native_handle_type;
native_handle_type* native_handle() noexcept;
const native_handle_type* native_handle() const noexcept;
[variablelist
[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
thread attributes implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present and `BOOST_THREAD_DEFINES_THREAD_ATTRIBUTES_NATIVE_HANDLE` is not defined.]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect] [/ thread::attributes ]
[endsect] [/ thread ]
[section:this_thread Namespace `this_thread`]
@@ -1247,25 +1039,19 @@ thread attributes implementation. If no such instance exists, `native_handle()`
namespace this_thread {
thread::id get_id() noexcept;
template<typename TimeDuration>
void sleep(TimeDuration const& rel_time); // DEPRECATED V2
void sleep(system_time const& abs_time) // DEPRECATED V2
void yield() noexcept;
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
template<typename Callable>
void at_thread_exit(Callable func); // EXTENSION
void interruption_point(); // EXTENSION
bool interruption_requested() noexcept; // EXTENSION
bool interruption_enabled() noexcept; // EXTENSION
class disable_interruption; // EXTENSION
class restore_interruption; // EXTENSION
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
void sleep(TimeDuration const& rel_time);
void sleep(system_time const& abs_time)
#endif
void interruption_point();
bool interruption_requested();
bool interruption_enabled();
class disable_interruption;
class restore_interruption;
}
}
@@ -1288,7 +1074,7 @@ thread attributes implementation. If no such instance exists, `native_handle()`
[endsect]
[section:interruption_point Non-member function `interruption_point()` EXTENSION]
[section:interruption_point Non-member function `interruption_point()`]
#include <boost/thread/thread.hpp>
@@ -1307,13 +1093,13 @@ thread attributes implementation. If no such instance exists, `native_handle()`
[endsect]
[section:interruption_requested Non-member function `interruption_requested()` EXTENSION]
[section:interruption_requested Non-member function `interruption_requested()`]
#include <boost/thread/thread.hpp>
namespace this_thread
{
bool interruption_requested() noexcept;
bool interruption_requested();
}
[variablelist
@@ -1326,13 +1112,13 @@ thread attributes implementation. If no such instance exists, `native_handle()`
[endsect]
[section:interruption_enabled Non-member function `interruption_enabled()` EXTENSION]
[section:interruption_enabled Non-member function `interruption_enabled()`]
#include <boost/thread/thread.hpp>
namespace this_thread
{
bool interruption_enabled() noexcept;
bool interruption_enabled();
}
[variablelist
@@ -1345,7 +1131,7 @@ thread attributes implementation. If no such instance exists, `native_handle()`
[endsect]
[section:sleep Non-member function `sleep()`]
[section:sleep Non-member function `sleep()` DEPRECATED V2]
#include <boost/thread/thread.hpp>
@@ -1366,8 +1152,6 @@ specified by `rel_time` has elapsed or the time point specified by
[[Notes:] [`sleep()` is one of the predefined __interruption_points__.]]
[[See:] [Use `__sleep_for()` and `__sleep_until()` instead.]]
]
[endsect]
@@ -1427,7 +1211,7 @@ do not throw exceptions. __thread_interrupted__ if the current thread of executi
namespace this_thread
{
void yield() noexcept;
void yield();
}
[variablelist
@@ -1440,7 +1224,7 @@ do not throw exceptions. __thread_interrupted__ if the current thread of executi
[endsect]
[section:disable_interruption Class `disable_interruption` EXTENSION]
[section:disable_interruption Class `disable_interruption`]
#include <boost/thread/thread.hpp>
@@ -1449,10 +1233,8 @@ do not throw exceptions. __thread_interrupted__ if the current thread of executi
class disable_interruption
{
public:
disable_interruption(const disable_interruption&) = delete;
disable_interruption& operator=(const disable_interruption&) = delete;
disable_interruption() noexcept;
~disable_interruption() noexcept;
disable_interruption();
~disable_interruption();
};
}
@@ -1461,7 +1243,7 @@ interruption state on destruction. Instances of `disable_interruption` cannot be
[section:constructor Constructor]
disable_interruption() noexcept;
disable_interruption();
[variablelist
@@ -1477,7 +1259,7 @@ interruption state on destruction. Instances of `disable_interruption` cannot be
[section:destructor Destructor]
~disable_interruption() noexcept;
~disable_interruption();
[variablelist
@@ -1495,7 +1277,7 @@ interruption state on destruction. Instances of `disable_interruption` cannot be
[endsect]
[section:restore_interruption Class `restore_interruption` EXTENSION]
[section:restore_interruption Class `restore_interruption`]
#include <boost/thread/thread.hpp>
@@ -1504,10 +1286,8 @@ interruption state on destruction. Instances of `disable_interruption` cannot be
class restore_interruption
{
public:
restore_interruption(const restore_interruption&) = delete;
restore_interruption& operator=(const restore_interruption&) = delete;
explicit restore_interruption(disable_interruption& disabler) noexcept;
~restore_interruption() noexcept;
explicit restore_interruption(disable_interruption& disabler);
~restore_interruption();
};
}
@@ -1517,7 +1297,7 @@ is destroyed, interruption is again disabled. Instances of `restore_interruption
[section:constructor Constructor]
explicit restore_interruption(disable_interruption& disabler) noexcept;
explicit restore_interruption(disable_interruption& disabler);
[variablelist
@@ -1535,7 +1315,7 @@ is destroyed, interruption is again disabled. Instances of `restore_interruption
[section:destructor Destructor]
~restore_interruption() noexcept;
~restore_interruption();
[variablelist
@@ -1553,7 +1333,7 @@ is destroyed, interruption is again disabled. Instances of `restore_interruption
[endsect]
[section:atthreadexit Non-member function template `at_thread_exit()` EXTENSION]
[section:atthreadexit Non-member function template `at_thread_exit()`]
#include <boost/thread/thread.hpp>

View File

@@ -5,33 +5,19 @@
http://www.boost.org/LICENSE_1_0.txt).
]
[section:time Time Requirements]
[section:time Date and Time Requirements]
As of Boost 1.50.0, the __boost_thread__ library uses Boost.Chrono library for all operations that require a
time out as defined in the standard c++11. These include (but are not limited to):
* `boost::this_thread::__sleep_for`
* `boost::this_thread::__sleep_until`
* `boost::__thread::__try_join_for`
* `boost::__thread::__try_join_until`
* `boost::__condition_variable::__wait_for`
* `boost::__condition_variable::__wait_until`
* `boost::__condition_variable_any::__cvany_wait_for`
* `boost::__condition_variable_any::__cvany_wait_until`
* `__TimedLockable::__try_lock_for`
* `__TimedLockable::__try_lock_until`
[section:deprecated Deprecated]
The time related functions introduced in Boost 1.35.0, using the [link date_time Boost.Date_Time] library are deprecated. These include (but are not limited to):
As of Boost 1.35.0, the __boost_thread__ library uses the [link date_time Boost.Date_Time] library for all operations that require a
time out. These include (but are not limited to):
* __sleep__
* __timed_join__
* __cond_timed_wait__
* __timed_lock_ref__
For the overloads that accept an absolute time parameter, an object of type [link thread.time.deprecated.system_time `boost::system_time`] is
For the overloads that accept an absolute time parameter, an object of type [link thread.time.system_time `boost::system_time`] is
required. Typically, this will be obtained by adding a duration to the current time, obtained with a call to [link
thread.time.deprecated.get_system_time `boost::get_system_time()`]. e.g.
thread.time.get_system_time `boost::get_system_time()`]. e.g.
boost::system_time const timeout=boost::get_system_time() + boost::posix_time::milliseconds(500);
@@ -84,7 +70,6 @@ See the documentation for [link date_time.posix_time.ptime_class `boost::posix_t
]
[endsect]
[endsect]
[endsect]

View File

@@ -47,16 +47,10 @@ 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.
[heading Rationale about the nature of the key]
Boost.Thread uses the address of the `thread_specific_ptr` instance as key of the thread specific pointers. This avoids to create/destroy a key which will need a lock to protect from race conditions. This has a little performance liability, as the access must be done using an associative container.
[section:thread_specific_ptr Class `thread_specific_ptr`]
// #include <boost/thread/tss.hpp>
#include <boost/thread/tss.hpp>
namespace boost
{
template <typename T>
class thread_specific_ptr
{
@@ -72,7 +66,6 @@ Boost.Thread uses the address of the `thread_specific_ptr` instance as key of th
T* release();
void reset(T* new_value=0);
};
}
[section:default_constructor `thread_specific_ptr();`]
@@ -109,14 +102,10 @@ supplied `cleanup_function` will be used to destroy any thread-local objects whe
[variablelist
[[Requires:] [All the thread specific instances associated to this thread_specific_ptr (except maybe the one associated to this thread) must be null.]]
[[Effects:] [Calls `this->reset()` to clean up the associated value for the current thread, and destroys `*this`.]]
[[Throws:] [Nothing.]]
[[Remarks:] [The requirement is due to the fact that in order to delete all these instances, the implementation should be forced to maintain a list of all the threads having an associated specific ptr, which is against the goal of thread specific data.]]
]
[note Care needs to be taken to ensure that any threads still running after an instance of `boost::thread_specific_ptr` has been

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <iostream>

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <vector>
@@ -89,7 +89,6 @@ private:
template <typename M>
void do_test(M* dummy=0)
{
(void)dummy;
typedef buffer_t<M> buffer_type;
buffer_type::get_buffer();
boost::thread thrd1(&buffer_type::do_receiver_thread);

View File

@@ -1,22 +1,15 @@
// 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)
#define BOOST_THREAD_PROVIDES_ONCE_CXX11
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
#include <cassert>
int value=0;
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
boost::once_flag once;
#else
boost::once_flag once = BOOST_ONCE_INIT;
boost::once_flag once2 = once;
#endif
void init()
{
@@ -28,7 +21,7 @@ void thread_proc()
boost::call_once(&init, once);
}
int main()
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i=0; i<5; ++i)

View File

@@ -1,143 +0,0 @@
// Copyright (C) 2012 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)
#include <iostream>
#include <boost/thread/mutex.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/thread.hpp>
#if defined BOOST_THREAD_DONT_USE_CHRONO
#include <boost/chrono/chrono_io.hpp>
#endif
#include <cassert>
#include <vector>
#define EXCLUSIVE 1
#define SHARED 2
#define MODE SHARED
class A
{
#if MODE == EXCLUSIVE
typedef boost::mutex mutex_type;
#elif MODE == SHARED
typedef boost::shared_mutex mutex_type;
#else
#error MODE not set
#endif
typedef std::vector<double> C;
mutable mutex_type mut_;
C data_;
public:
A() : data_(10000000) {}
A(const A& a);
A& operator=(const A& a);
void compute(const A& x, const A& y);
};
A::A(const A& a)
{
#if MODE == EXCLUSIVE
boost::unique_lock<mutex_type> lk(a.mut_);
#elif MODE == SHARED
boost::shared_lock<mutex_type> lk(a.mut_);
#else
#error MODE not set
#endif
data_ = a.data_;
}
A&
A::operator=(const A& a)
{
if (this != &a)
{
boost::unique_lock<mutex_type> lk1(mut_, boost::defer_lock);
#if MODE == EXCLUSIVE
boost::unique_lock<mutex_type> lk2(a.mut_, boost::defer_lock);
#elif MODE == SHARED
boost::shared_lock<mutex_type> lk2(a.mut_, boost::defer_lock);
#else
#error MODE not set
#endif
boost::lock(lk1, lk2);
data_ = a.data_;
}
return *this;
}
void
A::compute(const A& x, const A& y)
{
boost::unique_lock<mutex_type> lk1(mut_, boost::defer_lock);
#if MODE == EXCLUSIVE
boost::unique_lock<mutex_type> lk2(x.mut_, boost::defer_lock);
boost::unique_lock<mutex_type> lk3(y.mut_, boost::defer_lock);
#elif MODE == SHARED
boost::shared_lock<mutex_type> lk2(x.mut_, boost::defer_lock);
boost::shared_lock<mutex_type> lk3(y.mut_, boost::defer_lock);
#else
#error MODE not set
#endif
boost::lock(lk1, lk2, lk3);
assert(data_.size() == x.data_.size());
assert(data_.size() == y.data_.size());
for (unsigned i = 0; i < data_.size(); ++i)
data_[i] = (x.data_[i] + y.data_[i]) / 2;
}
A a1;
A a2;
void test_s()
{
A la3 = a1;
for (int i = 0; i < 150; ++i)
{
la3.compute(a1, a2);
}
}
void test_w()
{
A la3 = a1;
for (int i = 0; i < 10; ++i)
{
la3.compute(a1, a2);
a1 = la3;
a2 = la3;
#if defined BOOST_THREAD_DONT_USE_CHRONO
boost::this_thread::sleep_for(boost::chrono::seconds(1));
#endif
}
}
int main()
{
#if defined BOOST_THREAD_DONT_USE_CHRONO
typedef boost::chrono::high_resolution_clock Clock;
typedef boost::chrono::duration<double> sec;
Clock::time_point t0 = Clock::now();
#endif
std::vector<boost::thread*> v;
boost::thread thw(test_w);
v.push_back(&thw);
boost::thread thr0(test_w);
v.push_back(&thr0);
boost::thread thr1(test_w);
v.push_back(&thr1);
boost::thread thr2(test_w);
v.push_back(&thr2);
boost::thread thr3(test_w);
v.push_back(&thr3);
for (std::size_t i = 0; i < v.size(); ++i)
v[i]->join();
#if defined BOOST_THREAD_DONT_USE_CHRONO
Clock::time_point t1 = Clock::now();
std::cout << sec(t1-t0) << '\n';
#endif
return 0;
}

View File

@@ -1,745 +0,0 @@
// Copyright (C) 2012 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)
#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
#include <iostream>
#include <boost/thread/mutex.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/thread.hpp>
#include <vector>
#if defined BOOST_THREAD_USES_CHRONO
#include <boost/chrono/chrono_io.hpp>
enum {reading, writing};
int state = reading;
#if 1
boost::mutex&
cout_mut()
{
static boost::mutex m;
return m;
}
void
print(const char* tag, unsigned count, char ch)
{
boost::lock_guard<boost::mutex> _(cout_mut());
std::cout << tag << count << ch;
}
#elif 0
boost::recursive_mutex&
cout_mut()
{
static boost::recursive_mutex m;
return m;
}
void print() {}
template <class A0, class ...Args>
void
print(const A0& a0, const Args& ...args)
{
boost::lock_guard<boost::recursive_mutex> _(cout_mut());
std::cout << a0;
print(args...);
}
#else
template <class A0, class A1, class A2>
void
print(const A0&, const A1& a1, const A2&)
{
assert(a1 > 10000);
}
#endif
namespace S
{
boost::shared_mutex mut;
void reader()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
mut.lock_shared();
assert(state == reading);
++count;
mut.unlock_shared();
}
print("reader = ", count, '\n');
}
void writer()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
mut.lock();
state = writing;
assert(state == writing);
state = reading;
++count;
mut.unlock();
}
print("writer = ", count, '\n');
}
void try_reader()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_shared())
{
assert(state == reading);
++count;
mut.unlock_shared();
}
}
print("try_reader = ", count, '\n');
}
void try_writer()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock())
{
state = writing;
assert(state == writing);
state = reading;
++count;
mut.unlock();
}
}
print("try_writer = ", count, '\n');
}
void try_for_reader()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_shared_for(boost::chrono::microseconds(5)))
{
assert(state == reading);
++count;
mut.unlock_shared();
}
}
print("try_for_reader = ", count, '\n');
}
void try_for_writer()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_for(boost::chrono::microseconds(5)))
{
state = writing;
assert(state == writing);
state = reading;
++count;
mut.unlock();
}
}
print("try_for_writer = ", count, '\n');
}
void
test_shared_mutex()
{
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
{
boost::thread t1(reader);
boost::thread t2(writer);
boost::thread t3(reader);
t1.join();
t2.join();
t3.join();
}
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
{
boost::thread t1(try_reader);
boost::thread t2(try_writer);
boost::thread t3(try_reader);
t1.join();
t2.join();
t3.join();
}
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
{
boost::thread t1(try_for_reader);
boost::thread t2(try_for_writer);
boost::thread t3(try_for_reader);
t1.join();
t2.join();
t3.join();
}
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
}
}
namespace U
{
boost::upgrade_mutex mut;
void reader()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
mut.lock_shared();
assert(state == reading);
++count;
mut.unlock_shared();
}
print("reader = ", count, '\n');
}
void writer()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
mut.lock();
state = writing;
assert(state == writing);
state = reading;
++count;
mut.unlock();
}
print("writer = ", count, '\n');
}
void try_reader()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_shared())
{
assert(state == reading);
++count;
mut.unlock_shared();
}
}
print("try_reader = ", count, '\n');
}
void try_writer()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock())
{
state = writing;
assert(state == writing);
state = reading;
++count;
mut.unlock();
}
}
print("try_writer = ", count, '\n');
}
void try_for_reader()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_shared_for(boost::chrono::microseconds(5)))
{
assert(state == reading);
++count;
mut.unlock_shared();
}
}
print("try_for_reader = ", count, '\n');
}
void try_for_writer()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_for(boost::chrono::microseconds(5)))
{
state = writing;
assert(state == writing);
state = reading;
++count;
mut.unlock();
}
}
print("try_for_writer = ", count, '\n');
}
void upgradable()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
mut.lock_upgrade();
assert(state == reading);
++count;
mut.unlock_upgrade();
}
print("upgradable = ", count, '\n');
}
void try_upgradable()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_upgrade())
{
assert(state == reading);
++count;
mut.unlock_upgrade();
}
}
print("try_upgradable = ", count, '\n');
}
void try_for_upgradable()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_upgrade_for(boost::chrono::microseconds(5)))
{
assert(state == reading);
++count;
mut.unlock_upgrade();
}
}
print("try_for_upgradable = ", count, '\n');
}
void clockwise()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
mut.lock_shared();
assert(state == reading);
if (mut.try_unlock_shared_and_lock())
{
state = writing;
}
else if (mut.try_unlock_shared_and_lock_upgrade())
{
assert(state == reading);
mut.unlock_upgrade_and_lock();
state = writing;
}
else
{
mut.unlock_shared();
continue;
}
assert(state == writing);
state = reading;
mut.unlock_and_lock_upgrade();
assert(state == reading);
mut.unlock_upgrade_and_lock_shared();
assert(state == reading);
mut.unlock_shared();
++count;
}
print("clockwise = ", count, '\n');
}
void counter_clockwise()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
mut.lock_upgrade();
assert(state == reading);
mut.unlock_upgrade_and_lock();
assert(state == reading);
state = writing;
assert(state == writing);
state = reading;
mut.unlock_and_lock_shared();
assert(state == reading);
mut.unlock_shared();
++count;
}
print("counter_clockwise = ", count, '\n');
}
void try_clockwise()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_shared())
{
assert(state == reading);
if (mut.try_unlock_shared_and_lock())
{
state = writing;
}
else if (mut.try_unlock_shared_and_lock_upgrade())
{
assert(state == reading);
mut.unlock_upgrade_and_lock();
state = writing;
}
else
{
mut.unlock_shared();
continue;
}
assert(state == writing);
state = reading;
mut.unlock_and_lock_upgrade();
assert(state == reading);
mut.unlock_upgrade_and_lock_shared();
assert(state == reading);
mut.unlock_shared();
++count;
}
}
print("try_clockwise = ", count, '\n');
}
void try_for_clockwise()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_shared_for(boost::chrono::microseconds(5)))
{
assert(state == reading);
if (mut.try_unlock_shared_and_lock_for(boost::chrono::microseconds(5)))
{
state = writing;
}
else if (mut.try_unlock_shared_and_lock_upgrade_for(boost::chrono::microseconds(5)))
{
assert(state == reading);
mut.unlock_upgrade_and_lock();
state = writing;
}
else
{
mut.unlock_shared();
continue;
}
assert(state == writing);
state = reading;
mut.unlock_and_lock_upgrade();
assert(state == reading);
mut.unlock_upgrade_and_lock_shared();
assert(state == reading);
mut.unlock_shared();
++count;
}
}
print("try_for_clockwise = ", count, '\n');
}
void try_counter_clockwise()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_upgrade())
{
assert(state == reading);
if (mut.try_unlock_upgrade_and_lock())
{
assert(state == reading);
state = writing;
assert(state == writing);
state = reading;
mut.unlock_and_lock_shared();
assert(state == reading);
mut.unlock_shared();
++count;
}
else
{
mut.unlock_upgrade();
}
}
}
print("try_counter_clockwise = ", count, '\n');
}
void try_for_counter_clockwise()
{
typedef boost::chrono::steady_clock Clock;
unsigned count = 0;
Clock::time_point until = Clock::now() + boost::chrono::seconds(3);
while (Clock::now() < until)
{
if (mut.try_lock_upgrade_for(boost::chrono::microseconds(5)))
{
assert(state == reading);
if (mut.try_unlock_upgrade_and_lock_for(boost::chrono::microseconds(5)))
{
assert(state == reading);
state = writing;
assert(state == writing);
state = reading;
mut.unlock_and_lock_shared();
assert(state == reading);
mut.unlock_shared();
++count;
}
else
{
mut.unlock_upgrade();
}
}
}
print("try_for_counter_clockwise = ", count, '\n');
}
void
test_upgrade_mutex()
{
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
{
boost::thread t1(reader);
boost::thread t2(writer);
boost::thread t3(reader);
t1.join();
t2.join();
t3.join();
}
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
{
boost::thread t1(try_reader);
boost::thread t2(try_writer);
boost::thread t3(try_reader);
t1.join();
t2.join();
t3.join();
}
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
{
boost::thread t1(try_for_reader);
boost::thread t2(try_for_writer);
boost::thread t3(try_for_reader);
t1.join();
t2.join();
t3.join();
}
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
{
boost::thread t1(reader);
boost::thread t2(writer);
boost::thread t3(upgradable);
t1.join();
t2.join();
t3.join();
}
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
{
boost::thread t1(reader);
boost::thread t2(writer);
boost::thread t3(try_upgradable);
t1.join();
t2.join();
t3.join();
}
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
{
boost::thread t1(reader);
boost::thread t2(writer);
boost::thread t3(try_for_upgradable);
t1.join();
t2.join();
t3.join();
}
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
{
state = reading;
boost::thread t1(clockwise);
boost::thread t2(counter_clockwise);
boost::thread t3(clockwise);
boost::thread t4(counter_clockwise);
t1.join();
t2.join();
t3.join();
t4.join();
}
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
{
state = reading;
boost::thread t1(try_clockwise);
boost::thread t2(try_counter_clockwise);
t1.join();
t2.join();
}
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
// {
// state = reading;
// boost::thread t1(try_for_clockwise);
// boost::thread t2(try_for_counter_clockwise);
// t1.join();
// t2.join();
// }
// std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
}
}
namespace Assignment
{
class A
{
typedef boost::upgrade_mutex mutex_type;
typedef boost::shared_lock<mutex_type> SharedLock;
typedef boost::upgrade_lock<mutex_type> UpgradeLock;
typedef boost::unique_lock<mutex_type> Lock;
mutable mutex_type mut_;
std::vector<double> data_;
public:
A(const A& a)
{
SharedLock _(a.mut_);
data_ = a.data_;
}
A& operator=(const A& a)
{
if (this != &a)
{
Lock this_lock(mut_, boost::defer_lock);
SharedLock that_lock(a.mut_, boost::defer_lock);
boost::lock(this_lock, that_lock);
data_ = a.data_;
}
return *this;
}
void swap(A& a)
{
Lock this_lock(mut_, boost::defer_lock);
Lock that_lock(a.mut_, boost::defer_lock);
boost::lock(this_lock, that_lock);
data_.swap(a.data_);
}
void average(A& a)
{
assert(data_.size() == a.data_.size());
assert(this != &a);
Lock this_lock(mut_, boost::defer_lock);
UpgradeLock share_that_lock(a.mut_, boost::defer_lock);
boost::lock(this_lock, share_that_lock);
for (unsigned i = 0; i < data_.size(); ++i)
data_[i] = (data_[i] + a.data_[i]) / 2;
SharedLock share_this_lock(boost::move(this_lock));
Lock that_lock(boost::move(share_that_lock));
a.data_ = data_;
}
};
} // Assignment
void temp()
{
using namespace boost;
static upgrade_mutex mut;
unique_lock<upgrade_mutex> ul(mut);
shared_lock<upgrade_mutex> sl;
sl = BOOST_THREAD_MAKE_RV_REF(shared_lock<upgrade_mutex>(boost::move(ul)));
}
int main()
{
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
typedef boost::chrono::high_resolution_clock Clock;
typedef boost::chrono::duration<double> sec;
Clock::time_point t0 = Clock::now();
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
S::test_shared_mutex();
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
U::test_upgrade_mutex();
std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl;
Clock::time_point t1 = Clock::now();
std::cout << sec(t1 - t0) << '\n';
return 0;
}
#else
#error "This platform doesn't support Boost.Chrono"
#endif

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/mutex.hpp>
@@ -50,7 +50,7 @@ public:
<< "very hot ..." << std::endl;
}
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC_);
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 3;
boost::thread::sleep(xt);
m_chickens += value;
@@ -85,7 +85,7 @@ void chef()
std::cout << "(" << clock() << ") Chef: cooking ..." << std::endl;
}
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC_);
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 2;
boost::thread::sleep(xt);
{
@@ -111,7 +111,7 @@ struct phil
if (m_id > 0)
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC_);
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 3;
boost::thread::sleep(xt);
}
@@ -164,7 +164,7 @@ private:
void* _param;
};
int main()
int main(int argc, char* argv[])
{
boost::thread thrd_chef(&chef);
phil p[] = { phil(0), phil(1), phil(2), phil(3), phil(4) };

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/mutex.hpp>
@@ -104,7 +104,7 @@ int main(int argc, char* argv[])
boost::thread thrdb(thread_adapter(&player, (void*)PLAYER_B));
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC_);
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 1;
boost::thread::sleep(xt);
{

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
@@ -14,7 +14,7 @@ struct thread_alarm
void operator()()
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC_);
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += m_secs;
boost::thread::sleep(xt);
@@ -25,7 +25,7 @@ struct thread_alarm
int m_secs;
};
int main()
int main(int argc, char* argv[])
{
int secs = 5;
std::cout << "setting alarm for 5 seconds..." << std::endl;

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
@@ -16,7 +16,7 @@ void increment_count()
std::cout << "count = " << ++count << std::endl;
}
int main()
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i = 0; i < 10; ++i)

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
@@ -27,7 +27,7 @@ void thread_proc()
}
}
int main()
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i=0; i<5; ++i)

View File

@@ -1,16 +1,16 @@
// 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)
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
int main()
int main(int argc, char* argv[])
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC_);
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 1;
boost::thread::sleep(xt); // Sleep for 1 second
}

View File

@@ -9,7 +9,7 @@
#ifndef BOOST_THREAD_CV_STATUS_HPP
#define BOOST_THREAD_CV_STATUS_HPP
#include <boost/detail/scoped_enum_emulation.hpp>
#include <boost/thread/detail/scoped_enum.hpp>
namespace boost
{

View File

@@ -1,6 +1,5 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2011-2012 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)
@@ -8,131 +7,29 @@
#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP
#define BOOST_THREAD_CONFIG_WEK01032003_HPP
// Force SIG_ATOMIC_MAX to be defined
//#ifndef __STDC_LIMIT_MACROS
//#define __STDC_LIMIT_MACROS
//#endif
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#ifdef BOOST_NO_NOEXCEPT
# define BOOST_THREAD_NOEXCEPT_OR_THROW throw()
#else
# define BOOST_THREAD_NOEXCEPT_OR_THROW noexcept
#endif
// This compiler doesn't support Boost.Chrono
#if defined __IBMCPP__ && (__IBMCPP__ < 1100) && ! defined BOOST_THREAD_DONT_USE_CHRONO
#define BOOST_THREAD_DONT_USE_CHRONO
#endif
// This compiler doesn't support Boost.Move
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) && ! defined BOOST_THREAD_DONT_USE_MOVE
#define BOOST_THREAD_DONT_USE_MOVE
#endif
// This compiler doesn't support Boost.Container Allocators files
#if defined __SUNPRO_CC && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#endif
#if defined _WIN32_WCE && _WIN32_WCE==0x501 && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_BASIC_THREAD_ID && ! defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#define BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#endif
// Default version is 2
#if !defined BOOST_THREAD_VERSION
#define BOOST_THREAD_VERSION 2
#define BOOST_THREAD_VERSION 1
#else
#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3
#error "BOOST_THREAD_VERSION must be 2 or 3"
#if BOOST_THREAD_VERSION!=1 && BOOST_THREAD_VERSION!=2
#error "BOOST_THREAD_VERSION must be 1 or 2"
#endif
#endif
// Uses Boost.Chrono by default if not stated the opposite defining BOOST_THREAD_DONT_USE_CHRONO
#if ! defined BOOST_THREAD_DONT_USE_CHRONO && ! defined BOOST_THREAD_USES_CHRONO
#if ! defined BOOST_THREAD_DONT_USE_SYSTEM
#define BOOST_THREAD_USES_SYSTEM
#endif
#if ! defined BOOST_THREAD_DONT_USE_CHRONO && ! defined BOOST_THREAD_DONT_USE_SYSTEM
#define BOOST_THREAD_USES_CHRONO
#endif
// Don't provided by default in version 1.
#if defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION explicit
#else
#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION
#endif
#if BOOST_THREAD_VERSION==2
#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY && ! defined BOOST_THREAD_PROMISE_LAZY
#define BOOST_THREAD_PROMISE_LAZY
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0
#define BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
#endif
#endif
#if BOOST_THREAD_VERSION==3
#if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11 \
&& ! defined BOOST_THREAD_PROVIDES_ONCE_CXX11
#define BOOST_THREAD_PROVIDES_ONCE_CXX11
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE \
&& ! defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
#define BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE \
&& ! defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
#define BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE \
&& ! defined BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_PROVIDES_FUTURE
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS \
&& ! defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#define BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSIONS \
&& ! defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION \
&& ! defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN \
&& ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
#endif
#if ! defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 \
&& ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_
#define BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0
#endif
#if ! defined BOOST_THREAD_DONT_USE_MOVE \
&& ! defined BOOST_THREAD_USES_MOVE
#if ! defined BOOST_THREAD_DONT_USE_MOVE
#define BOOST_THREAD_USES_MOVE
#endif
#endif
// BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN is defined if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
#if defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS \
&& ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
#endif
// BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.52
// BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.55
#if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 \
&& ! defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
#define BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
#endif
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
# pragma warn -8008 // Condition always true/false
# pragma warn -8080 // Identifier declared but never used
@@ -140,11 +37,11 @@
# pragma warn -8066 // Unreachable code
#endif
#include <boost/thread/detail/platform.hpp>
#include "platform.hpp"
// provided for backwards compatibility, since this
// macro was used for several releases by mistake.
#if defined(BOOST_THREAD_DYN_DLL) && ! defined BOOST_THREAD_DYN_LINK
#if defined(BOOST_THREAD_DYN_DLL)
# define BOOST_THREAD_DYN_LINK
#endif

View File

@@ -1,45 +0,0 @@
// Copyright (C) 2012 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)
#ifndef BOOST_THREAD_DETAIL_DELETE_HPP
#define BOOST_THREAD_DETAIL_DELETE_HPP
#include <boost/config.hpp>
/**
* BOOST_THREAD_DELETE_COPY_CTOR deletes the copy constructor when the compiler supports it or
* makes it private.
*
* BOOST_THREAD_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or
* makes it private.
*/
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
CLASS(CLASS const&) = delete; \
#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \
CLASS& operator=(CLASS const&) = delete;
#else // BOOST_NO_CXX11_DELETED_FUNCTIONS
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
private: \
CLASS(CLASS&); \
public:
#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \
private: \
CLASS& operator=(CLASS&); \
public:
#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
/**
* BOOST_THREAD_NO_COPYABLE deletes the copy constructor and assignment when the compiler supports it or
* makes them private.
*/
#define BOOST_THREAD_NO_COPYABLE(CLASS) \
BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS)
#endif // BOOST_THREAD_DETAIL_DELETE_HPP

View File

@@ -1,156 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_THREAD_DETAIL_MEMORY_HPP
#define BOOST_THREAD_DETAIL_MEMORY_HPP
#include <boost/config.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
namespace boost
{
namespace thread_detail
{
template <class _Alloc>
class allocator_destructor
{
typedef container::allocator_traits<_Alloc> alloc_traits;
public:
typedef typename alloc_traits::pointer pointer;
typedef typename alloc_traits::size_type size_type;
private:
_Alloc alloc_;
size_type s_;
public:
allocator_destructor(_Alloc& a, size_type s)BOOST_NOEXCEPT
: alloc_(a), s_(s)
{}
void operator()(pointer p)BOOST_NOEXCEPT
{
alloc_traits::destroy(alloc_, p);
alloc_traits::deallocate(alloc_, p, s_);
}
};
} //namespace thread_detail
typedef container::allocator_arg_t allocator_arg_t;
BOOST_CONSTEXPR_OR_CONST allocator_arg_t allocator_arg = {};
template <class T, class Alloc>
struct uses_allocator: public container::uses_allocator<T, Alloc>
{
};
template <class Ptr>
struct pointer_traits
{
typedef Ptr pointer;
// typedef <details> element_type;
// typedef <details> difference_type;
// template <class U> using rebind = <details>;
//
// static pointer pointer_to(<details>);
};
template <class T>
struct pointer_traits<T*>
{
typedef T* pointer;
typedef T element_type;
typedef ptrdiff_t difference_type;
// template <class U> using rebind = U*;
//
// static pointer pointer_to(<details>) noexcept;
};
namespace thread_detail {
template <class _Ptr1, class _Ptr2,
bool = is_same<typename remove_cv<typename pointer_traits<_Ptr1>::element_type>::type,
typename remove_cv<typename pointer_traits<_Ptr2>::element_type>::type
>::value
>
struct same_or_less_cv_qualified_imp
: is_convertible<_Ptr1, _Ptr2> {};
template <class _Ptr1, class _Ptr2>
struct same_or_less_cv_qualified_imp<_Ptr1, _Ptr2, false>
: false_type {};
template <class _Ptr1, class _Ptr2, bool = is_scalar<_Ptr1>::value &&
!is_pointer<_Ptr1>::value>
struct same_or_less_cv_qualified
: same_or_less_cv_qualified_imp<_Ptr1, _Ptr2> {};
template <class _Ptr1, class _Ptr2>
struct same_or_less_cv_qualified<_Ptr1, _Ptr2, true>
: false_type {};
}
template <class T>
struct BOOST_SYMBOL_VISIBLE default_delete
{
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() = default;
#else
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {}
#endif
template <class U>
BOOST_SYMBOL_VISIBLE
default_delete(const default_delete<U>&,
typename enable_if<is_convertible<U*, T*> >::type* = 0) BOOST_NOEXCEPT {}
BOOST_SYMBOL_VISIBLE
void operator() (T* ptr) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
delete ptr;
}
};
template <class T>
struct BOOST_SYMBOL_VISIBLE default_delete<T[]>
{
public:
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() = default;
#else
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {}
#endif
template <class U>
BOOST_SYMBOL_VISIBLE
default_delete(const default_delete<U[]>&,
typename enable_if<thread_detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) BOOST_NOEXCEPT {}
template <class U>
BOOST_SYMBOL_VISIBLE
void operator() (U* ptr,
typename enable_if<thread_detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
delete [] ptr;
}
};
} // namespace boost
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP

View File

@@ -2,7 +2,6 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#ifndef BOOST_THREAD_MOVE_HPP
#define BOOST_THREAD_MOVE_HPP
@@ -12,12 +11,10 @@
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/decay.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/move/move.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
@@ -25,8 +22,6 @@ namespace boost
namespace detail
{
template <typename T>
struct has_move_emulation_enabled_aux_dummy_specialization;
template<typename T>
struct thread_move_t
{
@@ -49,7 +44,6 @@ 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)
@@ -63,184 +57,10 @@ namespace boost
{
return t;
}
}
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END
#define BOOST_THREAD_RV(V) V
#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE
#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_THREAD_DCL_MOVABLE(TYPE)
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
struct has_move_emulation_enabled_aux_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, true> \
{}; \
}
#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_MSVC
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END
#define BOOST_THREAD_RV(V) V
#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE
#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_THREAD_DCL_MOVABLE(TYPE)
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
struct has_move_emulation_enabled_aux_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, true> \
{}; \
}
#else
#if defined BOOST_THREAD_USES_MOVE
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END
#define BOOST_THREAD_RV(V) V
#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_THREAD_DCL_MOVABLE(TYPE)
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
struct has_move_emulation_enabled_aux_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, true> \
{}; \
}
#else
#define BOOST_THREAD_RV_REF(TYPE) boost::detail::thread_move_t< TYPE >
#define BOOST_THREAD_RV_REF_BEG boost::detail::thread_move_t<
#define BOOST_THREAD_RV_REF_END >
#define BOOST_THREAD_RV(V) (*V)
#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_THREAD_DCL_MOVABLE(TYPE) \
template <> \
struct has_move_emulation_enabled_aux< TYPE > \
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true> \
{};
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
template <typename T> \
struct has_move_emulation_enabled_aux<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true> \
{};
#endif
namespace boost
{
namespace detail
{
template <typename T>
BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type)
make_rv_ref(T v) BOOST_NOEXCEPT
{
return (BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v);
}
// template <typename T>
// BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type)
// make_rv_ref(T &v) BOOST_NOEXCEPT
// {
// return (BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v);
// }
// template <typename T>
// const BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type)
// make_rv_ref(T const&v) BOOST_NOEXCEPT
// {
// return (const BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v);
// }
}
}
#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE.move()
//#define BOOST_THREAD_MAKE_RV_REF(RVALUE) boost::detail::make_rv_ref(RVALUE)
#endif
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_MOVABLE(TYPE)
#else
#if defined BOOST_THREAD_USES_MOVE
#define BOOST_THREAD_MOVABLE(TYPE) \
::boost::rv<TYPE>& move() BOOST_NOEXCEPT \
{ \
return *static_cast< ::boost::rv<TYPE>* >(this); \
} \
const ::boost::rv<TYPE>& move() const BOOST_NOEXCEPT \
{ \
return *static_cast<const ::boost::rv<TYPE>* >(this); \
} \
operator ::boost::rv<TYPE>&() \
{ \
return *static_cast< ::boost::rv<TYPE>* >(this); \
} \
operator const ::boost::rv<TYPE>&() const \
{ \
return *static_cast<const ::boost::rv<TYPE>* >(this); \
}\
#else
#define BOOST_THREAD_MOVABLE(TYPE) \
operator ::boost::detail::thread_move_t<TYPE>() BOOST_NOEXCEPT \
{ \
return move(); \
} \
::boost::detail::thread_move_t<TYPE> move() BOOST_NOEXCEPT \
{ \
::boost::detail::thread_move_t<TYPE> x(*this); \
return x; \
} \
#endif
#endif
#define BOOST_THREAD_MOVABLE_ONLY(TYPE) \
BOOST_THREAD_NO_COPYABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
#define BOOST_THREAD_COPYABLE_AND_MOVABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
namespace boost
{ namespace thread_detail
{
template <class T>
typename decay<T>::type
decay_copy(T&& t)
{
return boost::forward<T>(t);
}
}
}
#endif
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -19,7 +19,6 @@
// choose platform
#if defined(linux) || defined(__linux) || defined(__linux__)
# define BOOST_THREAD_LINUX
//# define BOOST_THREAD_WAIT_BUG boost::posix_time::microseconds(100000)
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
# define BOOST_THREAD_BSD
#elif defined(sun) || defined(__sun)
@@ -36,7 +35,6 @@
# define BOOST_THREAD_BEOS
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
# define BOOST_THREAD_MACOS
//# define BOOST_THREAD_WAIT_BUG boost::posix_time::microseconds(1000)
#elif defined(__IBMCPP__) || defined(_AIX)
# define BOOST_THREAD_AIX
#elif defined(__amigaos__)
@@ -57,7 +55,7 @@
// dispatcher table. If there is no entry for a platform but pthreads is
// available on the platform, pthread is choosen as default. If nothing is
// available the preprocessor will fail with a diagnostic message.
#if defined(BOOST_THREAD_POSIX)
# define BOOST_THREAD_PLATFORM_PTHREAD
#else

View File

@@ -0,0 +1,113 @@
// Copyright (C) 2012
// 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)
#ifndef BOOST_THREAD_DETAIL_SCOPED_ENUM_HPP
#define BOOST_THREAD_DETAIL_SCOPED_ENUM_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
namespace boost
{
#ifdef BOOST_NO_SCOPED_ENUMS
template <typename NT>
struct underlying_type
{
typedef typename NT::underlying_type type;
};
template <typename UT, typename NT>
UT underlying_cast(NT v)
{
return v.underlying();
}
template <typename EC>
inline
typename EC::enum_type native_value(EC e)
{
return e.native();
}
#else // BOOST_NO_SCOPED_ENUMS
template <typename NT>
struct underlying_type
{
//typedef typename std::underlying_type<NT>::type type;
};
template <typename UT, typename NT>
UT underlying_cast(NT v)
{
return static_cast<UT>(v);
}
template <typename EC>
inline
EC native_value(EC e)
{
return e;
}
#endif
}
#ifdef BOOST_NO_SCOPED_ENUMS
#ifndef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS
#define BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR \
explicit operator underlying_type() const { return underlying(); }
#else
#define BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR
#endif
#define BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(NT, UT) \
struct NT { \
typedef UT underlying_type; \
enum enum_type
#define BOOST_SCOPED_ENUM_DECLARE_END(NT) \
; \
NT() {} \
NT(enum_type v) : v_(v) {} \
explicit NT(underlying_type v) : v_(v) {} \
underlying_type underlying() const { return v_; } \
enum_type native() const { return enum_type(v_); } \
BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR \
friend bool operator ==(NT lhs, enum_type rhs) { return enum_type(lhs.v_)==rhs; } \
friend bool operator ==(enum_type lhs, NT rhs) { return lhs==enum_type(rhs.v_); } \
friend bool operator !=(NT lhs, enum_type rhs) { return enum_type(lhs.v_)!=rhs; } \
friend bool operator !=(enum_type lhs, NT rhs) { return lhs!=enum_type(rhs.v_); } \
private: \
underlying_type v_; \
};
#define BOOST_SCOPED_ENUM_DECLARE_BEGIN(NT) \
BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(NT,int)
#define BOOST_SCOPED_ENUM_NATIVE(NT) NT::enum_type
#define BOOST_SCOPED_ENUM_FORWARD_DECLARE(NT) struct NT
#else // BOOST_NO_SCOPED_ENUMS
#define BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(NT,UT) enum class NT:UT
#define BOOST_SCOPED_ENUM_DECLARE_BEGIN(NT) enum class NT
#define BOOST_SCOPED_ENUM_DECLARE_END(NT) ;
#define BOOST_SCOPED_ENUM_NATIVE(NT) NT
#define BOOST_SCOPED_ENUM_FORWARD_DECLARE(NT) enum class NT
#endif // BOOST_NO_SCOPED_ENUMS
#endif // BOOST_THREAD_DETAIL_SCOPED_ENUM_HPP

View File

@@ -11,10 +11,15 @@
#ifndef BOOST_NO_IOSTREAM
#include <ostream>
#endif
#if defined BOOST_THREAD_USES_MOVE
#include <boost/move/move.hpp>
#else
#include <boost/thread/detail/move.hpp>
#endif
#include <boost/thread/mutex.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/detail/thread_heap_alloc.hpp>
#include <boost/utility.hpp>
#include <boost/assert.hpp>
#include <list>
#include <algorithm>
@@ -23,8 +28,6 @@
#include <boost/bind.hpp>
#include <stdlib.h>
#include <memory>
//#include <vector>
//#include <utility>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/io/ios_state.hpp>
@@ -46,6 +49,18 @@
namespace boost
{
#ifndef BOOST_NO_RVALUE_REFERENCES
namespace thread_detail
{
template <class T>
typename decay<T>::type
decay_copy(T&& t)
{
return boost::forward<T>(t);
}
}
#endif
namespace detail
{
template<typename F>
@@ -53,33 +68,37 @@ namespace boost
public detail::thread_data_base
{
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
thread_data(BOOST_THREAD_RV_REF(F) f_):
f(boost::forward<F>(f_))
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
thread_data(F&& f_):
f(boost::forward<F>(f_))
{}
// This overloading must be removed if we want the packaged_task's tests to pass.
// thread_data(F& f_):
// f(f_)
// {}
#else
thread_data(BOOST_THREAD_RV_REF(F) f_):
f(f_)
{}
thread_data(F f_):
f(f_)
{}
#if defined BOOST_THREAD_USES_MOVE
thread_data(boost::rv<F>& f_):
f(boost::move(f_))
{}
#else
thread_data(detail::thread_move_t<F> f_):
f(f_)
{}
#endif
#endif
//thread_data() {}
void run()
{
f();
}
private:
F f;
void operator=(thread_data&);
thread_data(thread_data&);
};
template<typename F>
@@ -88,11 +107,14 @@ namespace boost
{
private:
F& f;
void operator=(thread_data&);
thread_data(thread_data&);
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
thread_data(boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
@@ -105,11 +127,13 @@ namespace boost
{
private:
F& f;
void operator=(thread_data&);
thread_data(thread_data&);
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
thread_data(const boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
@@ -120,9 +144,30 @@ namespace boost
class BOOST_THREAD_DECL thread
{
public:
typedef int boost_move_emulation_t;
typedef thread_attributes attributes;
BOOST_THREAD_MOVABLE_ONLY(thread)
#ifndef BOOST_NO_DELETED_FUNCTIONS
public:
thread(thread const&) = delete;
thread& operator=(thread const&) = delete;
#else // BOOST_NO_DELETED_FUNCTIONS
private:
// BOOST_MOVABLE_BUT_NOT_COPYABLE(thread)
#if defined BOOST_THREAD_USES_MOVE
private:
//thread(thread const&);
thread(thread &);
//thread& operator=(thread const&);
thread& operator=(thread &);
#else
private:
thread(thread&);
thread& operator=(thread&);
#endif
public:
#endif // BOOST_NO_DELETED_FUNCTIONS
private:
void release_handle();
@@ -136,9 +181,9 @@ namespace boost
detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_NO_RVALUE_REFERENCES
template<typename F>
static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
static inline detail::thread_data_ptr make_thread_info(F&& f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(
boost::forward<F>(f)));
@@ -154,36 +199,44 @@ namespace boost
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
#if defined BOOST_THREAD_USES_MOVE
template<typename F>
static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
static inline detail::thread_data_ptr make_thread_info(boost::rv<F>& f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(boost::move(f)));
}
#else
template<typename F>
static inline detail::thread_data_ptr make_thread_info(boost::detail::thread_move_t<F> f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
#endif
#endif
struct dummy;
public:
#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
thread(const volatile thread&);
#endif
#endif
thread() BOOST_NOEXCEPT;
~thread()
~thread();
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_MSVCXX
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)))
{
#if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
if (joinable()) {
std::terminate();
}
#else
detach();
#endif
start_thread();
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#else
template <
class F
//, class Dummy = typename disable_if< is_same<typename decay<F>::type, thread> >::type
>
explicit thread(BOOST_THREAD_RV_REF(F) f
explicit thread(F&& f
, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
):
thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
@@ -192,12 +245,33 @@ namespace boost
}
template <
class F
//, class Dummy = typename disable_if< is_same<typename decay<F>::type, thread> >::type
>
thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f):
thread(attributes& attrs, F&& f
, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
):
thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
{
start_thread(attrs);
}
#endif
thread(thread&& other) BOOST_NOEXCEPT
{
thread_info.swap(other.thread_info);
}
thread& operator=(thread&& other) BOOST_NOEXCEPT
{
thread_info=other.thread_info;
other.thread_info.reset();
return *this;
}
// thread&& move()
// {
// return static_cast<thread&&>(*this);
// }
#else
#ifdef BOOST_NO_SFINAE
@@ -214,63 +288,140 @@ namespace boost
start_thread(attrs);
}
#else
#if defined BOOST_THREAD_USES_MOVE
template <class F>
explicit thread(F f
// todo Disable also if Or is_same<typename decay<F>::type, thread>
, typename disable_if<boost::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0):
explicit thread(F f,typename disable_if<boost::is_convertible<F&,boost::rv<F>& >, dummy* >::type=0):
thread_info(make_thread_info(f))
{
start_thread();
}
template <class F>
thread(attributes& attrs, F f
, typename disable_if<boost::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0):
thread(attributes& attrs, F f,typename disable_if<boost::is_convertible<F&,boost::rv<F>& >, dummy* >::type=0):
thread_info(make_thread_info(f))
{
start_thread(attrs);
}
#else
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(f))
{
start_thread();
}
template <class F>
thread(attributes& attrs, F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0):
thread_info(make_thread_info(f))
{
start_thread(attrs);
}
#endif
#endif
#if defined BOOST_THREAD_USES_MOVE
template <class F>
explicit thread(BOOST_THREAD_RV_REF(F) f
, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
):
explicit thread(boost::rv<F>& f):
thread_info(make_thread_info(boost::move(f)))
{
start_thread();
}
// explicit thread(void (*f)()):
// thread_info(make_thread_info(f))
// {
// start_thread();
// }
//
// template <class F>
// explicit thread(BOOST_FWD_REF(F) f):
// thread_info(make_thread_info(boost::forward<F>(f)))
// {
// start_thread();
// }
template <class F>
thread(attributes& attrs, boost::rv<F>& f):
thread_info(make_thread_info(boost::move(f)))
{
start_thread(attrs);
}
thread(boost::rv<thread>& x)
//thread(BOOST_RV_REF(thread) x)
{
thread_info=x.thread_info;
x.thread_info.reset();
}
#else
template <class F>
explicit thread(detail::thread_move_t<F> f):
thread_info(make_thread_info(f))
{
start_thread();
}
template <class F>
thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f):
thread(attributes& attrs, detail::thread_move_t<F> f):
thread_info(make_thread_info(f))
{
start_thread(attrs);
}
#endif
thread(BOOST_THREAD_RV_REF(thread) x)
thread(detail::thread_move_t<thread> x)
{
thread_info=BOOST_THREAD_RV(x).thread_info;
BOOST_THREAD_RV(x).thread_info.reset();
thread_info=x->thread_info;
x->thread_info.reset();
}
#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
#endif
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
thread& operator=(thread x)
{
swap(x);
return *this;
}
#endif
#endif
thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT
#else
#if defined BOOST_THREAD_USES_MOVE
thread& operator=(boost::rv<thread>& x)
{
#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
if (joinable()) std::terminate();
#endif
thread_info=BOOST_THREAD_RV(other).thread_info;
BOOST_THREAD_RV(other).thread_info.reset();
thread new_thread(boost::move(x));
swap(new_thread);
return *this;
}
#else
thread& operator=(detail::thread_move_t<thread> x)
{
thread new_thread(x);
swap(new_thread);
return *this;
}
#endif
#endif
#if defined BOOST_THREAD_USES_MOVE
operator ::boost::rv<thread>&()
{
return *static_cast< ::boost::rv<thread>* >(this);
}
operator const ::boost::rv<thread>&() const
{
return *static_cast<const ::boost::rv<thread>* >(this);
}
#else
operator detail::thread_move_t<thread>()
{
return move();
}
detail::thread_move_t<thread> move()
{
detail::thread_move_t<thread> x(*this);
return x;
}
#endif
#endif
template <class F,class A1>
thread(F f,A1 a1,typename disable_if<boost::is_convertible<F&,thread_attributes >, dummy* >::type=0):
@@ -345,6 +496,34 @@ namespace boost
bool joinable() const BOOST_NOEXCEPT;
void join();
#if defined(BOOST_THREAD_PLATFORM_WIN32)
bool timed_join(const system_time& abs_time);
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_join_for(chrono::ceil<chrono::milliseconds>(rel_time));
}
template <class Clock, class Duration>
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
typename Clock::time_point c_now = Clock::now();
return try_join_for(chrono::ceil<chrono::milliseconds>(t - c_now));
}
#endif
private:
#ifdef BOOST_THREAD_USES_CHRONO
bool do_try_join_for(chrono::milliseconds const &rel_time_in_milliseconds);
#endif
public:
#else
bool timed_join(const system_time& abs_time) {
struct timespec const ts=detail::get_timespec(abs_time);
return do_try_join_until(ts);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
@@ -366,28 +545,6 @@ namespace boost
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
#endif
#if defined(BOOST_THREAD_PLATFORM_WIN32)
bool timed_join(const system_time& abs_time);
private:
bool do_try_join_until(uintmax_t milli);
public:
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
return do_try_join_until(rel_time.count());
}
#endif
#else
bool timed_join(const system_time& abs_time)
{
struct timespec const ts=detail::get_timespec(abs_time);
return do_try_join_until(ts);
}
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
using namespace chrono;
@@ -419,12 +576,10 @@ namespace boost
typedef detail::thread_data_base::native_handle_type native_handle_type;
native_handle_type native_handle();
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
// Use thread::id when comparisions are needed
// backwards compatibility
bool operator==(const thread& other) const;
bool operator!=(const thread& other) const;
#endif
static inline void yield() BOOST_NOEXCEPT
{
this_thread::yield();
@@ -437,7 +592,7 @@ namespace boost
// extensions
void interrupt();
bool interruption_requested() const BOOST_NOEXCEPT;
bool interruption_requested() const;
};
inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT
@@ -445,22 +600,40 @@ namespace boost
return lhs.swap(rhs);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
inline thread&& move(thread& t) BOOST_NOEXCEPT
#ifndef BOOST_NO_RVALUE_REFERENCES
inline thread&& move(thread& t)
{
return static_cast<thread&&>(t);
}
inline thread&& move(thread&& t)
{
return static_cast<thread&&>(t);
}
#else
#if !defined BOOST_THREAD_USES_MOVE
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
{
return t;
}
#endif
#endif
BOOST_THREAD_DCL_MOVABLE(thread)
#ifdef BOOST_NO_RVALUE_REFERENCES
#if !defined BOOST_THREAD_USES_MOVE
template <>
struct has_move_emulation_enabled_aux<thread>
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
{};
#endif
#endif
namespace this_thread
{
thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT;
void BOOST_THREAD_DECL interruption_point();
bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
bool BOOST_THREAD_DECL interruption_enabled();
bool BOOST_THREAD_DECL interruption_requested();
inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time)
{
@@ -475,40 +648,19 @@ namespace boost
std::size_t
hash_value(const thread::id &v)
{
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
return hash_value(v.thread_data);
#else
return hash_value(v.thread_data.get());
#endif
}
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#if defined(BOOST_THREAD_PLATFORM_WIN32)
typedef unsigned int data;
#else
typedef thread::native_handle_type data;
#endif
#else
typedef detail::thread_data_ptr data;
#endif
data thread_data;
detail::thread_data_ptr thread_data;
id(data 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() BOOST_NOEXCEPT;
public:
id() BOOST_NOEXCEPT:
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#if defined(BOOST_THREAD_PLATFORM_WIN32)
thread_data(0)
#else
thread_data(0)
#endif
#else
thread_data()
#endif
thread_data()
{}
id(const id& other) BOOST_NOEXCEPT :
@@ -570,8 +722,7 @@ namespace boost
{
if(thread_data)
{
io::ios_flags_saver ifs( os );
return os<< std::hex << thread_data;
return os<<thread_data;
}
else
{
@@ -593,7 +744,6 @@ namespace boost
}
#endif
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
inline bool thread::operator==(const thread& other) const
{
return get_id()==other.get_id();
@@ -603,7 +753,6 @@ namespace boost
{
return get_id()!=other.get_id();
}
#endif
namespace detail
{

View File

@@ -4,10 +4,6 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-9 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
namespace boost
{
@@ -15,20 +11,23 @@ namespace boost
{
class BOOST_THREAD_DECL disable_interruption
{
bool interruption_was_enabled;
friend class restore_interruption;
disable_interruption(const disable_interruption&);
disable_interruption& operator=(const disable_interruption&);
bool interruption_was_enabled;
friend class restore_interruption;
public:
BOOST_THREAD_NO_COPYABLE(disable_interruption)
disable_interruption() BOOST_NOEXCEPT;
~disable_interruption() BOOST_NOEXCEPT;
disable_interruption();
~disable_interruption();
};
class BOOST_THREAD_DECL restore_interruption
{
restore_interruption(const restore_interruption&);
restore_interruption& operator=(const restore_interruption&);
public:
BOOST_THREAD_NO_COPYABLE(restore_interruption)
explicit restore_interruption(disable_interruption& d) BOOST_NOEXCEPT;
~restore_interruption() BOOST_NOEXCEPT;
explicit restore_interruption(disable_interruption& d);
~restore_interruption();
};
}
}

View File

@@ -1,7 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007-9 Anthony Williams
// (C) Copyright 2011-2012 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)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -22,8 +22,7 @@
namespace boost
{
// template<class Callable, class ...Args> void
// call_once(once_flag& flag, Callable&& func, Args&&... args);
// template<class Callable, class ...Args> void call_once(once_flag& flag, Callable func, Args&&... args);
inline void call_once(void (*func)(),once_flag& flag)
{
call_once(flag,func);

View File

@@ -14,7 +14,6 @@
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -112,8 +111,17 @@ namespace boost
pthread_mutex_t internal_mutex;
pthread_cond_t cond;
#ifndef BOOST_NO_DELETED_FUNCTIONS
public:
condition_variable_any(condition_variable_any const&) = delete;
condition_variable_any& operator=(condition_variable_any const&) = delete;
#else // BOOST_NO_DELETED_FUNCTIONS
private:
condition_variable_any(condition_variable_any&);
condition_variable_any& operator=(condition_variable_any&);
#endif // BOOST_NO_DELETED_FUNCTIONS
public:
BOOST_THREAD_NO_COPYABLE(condition_variable_any)
condition_variable_any()
{
int const res=pthread_mutex_init(&internal_mutex,NULL);

View File

@@ -18,8 +18,7 @@
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/date_time/posix_time/posix_time_duration.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
@@ -31,8 +30,17 @@ namespace boost
pthread_mutex_t internal_mutex;
pthread_cond_t cond;
#ifndef BOOST_NO_DELETED_FUNCTIONS
public:
condition_variable(condition_variable const&) = delete;
condition_variable& operator=(condition_variable const&) = delete;
#else // BOOST_NO_DELETED_FUNCTIONS
private:
condition_variable(condition_variable const&);
condition_variable& operator=(condition_variable const&);
#endif // BOOST_NO_DELETED_FUNCTIONS
public:
BOOST_THREAD_NO_COPYABLE(condition_variable)
condition_variable()
{
int const res=pthread_mutex_init(&internal_mutex,NULL);
@@ -65,18 +73,12 @@ namespace boost
while(!pred()) wait(m);
}
inline bool timed_wait(
unique_lock<mutex>& m,
boost::system_time const& wait_until)
{
#if defined BOOST_THREAD_WAIT_BUG
struct timespec const timeout=detail::get_timespec(wait_until + BOOST_THREAD_WAIT_BUG);
return do_timed_wait(m, timeout);
#else
struct timespec const timeout=detail::get_timespec(wait_until);
return do_timed_wait(m, timeout);
#endif
}
bool timed_wait(
unique_lock<mutex>& m,
@@ -229,11 +231,8 @@ namespace boost
unique_lock<mutex>& lock,
struct timespec const &timeout);
};
BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,12 +1,12 @@
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 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)
#include <pthread.h>
#include <boost/utility.hpp>
#include <boost/throw_exception.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
@@ -20,7 +20,6 @@
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0 && _POSIX_C_SOURCE>=200112L
@@ -34,11 +33,18 @@ namespace boost
{
class mutex
{
#ifndef BOOST_NO_DELETED_FUNCTIONS
public:
mutex(mutex const&) = delete;
mutex& operator=(mutex const&) = delete;
#else // BOOST_NO_DELETED_FUNCTIONS
private:
mutex(mutex const&);
mutex& operator=(mutex const&);
#endif // BOOST_NO_DELETED_FUNCTIONS
private:
pthread_mutex_t m;
public:
BOOST_THREAD_NO_COPYABLE(mutex)
mutex()
{
int const res=pthread_mutex_init(&m,NULL);
@@ -91,7 +97,7 @@ namespace boost
// The following throw_exception has been replaced by an assertion and just return false,
// as this is an internal error and the user can do nothing with the exception.
//boost::throw_exception(lock_error(res,"boost: mutex try_lock failed in pthread_mutex_trylock"));
BOOST_ASSERT_MSG(false ,"boost: mutex try_lock failed in pthread_mutex_trylock");
BOOST_ASSERT(false && "boost: mutex try_lock failed in pthread_mutex_trylock");
return false;
}
@@ -113,6 +119,16 @@ namespace boost
class timed_mutex
{
#ifndef BOOST_NO_DELETED_FUNCTIONS
public:
timed_mutex(timed_mutex const&) = delete;
timed_mutex& operator=(timed_mutex const&) = delete;
#else // BOOST_NO_DELETED_FUNCTIONS
private:
timed_mutex(timed_mutex const&);
timed_mutex& operator=(timed_mutex const&);
public:
#endif // BOOST_NO_DELETED_FUNCTIONS
private:
pthread_mutex_t m;
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
@@ -120,7 +136,6 @@ namespace boost
bool is_locked;
#endif
public:
BOOST_THREAD_NO_COPYABLE(timed_mutex)
timed_mutex()
{
int const res=pthread_mutex_init(&m,NULL);

View File

@@ -4,7 +4,6 @@
// once.hpp
//
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -12,63 +11,53 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
#include <boost/cstdint.hpp>
#include <pthread.h>
#include <csignal>
#include <boost/assert.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/cstdint.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
namespace thread_detail
{
//#ifdef SIG_ATOMIC_MAX
// typedef sig_atomic_t uintmax_atomic_t;
// #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C SIG_ATOMIC_MAX
//#else
typedef unsigned long uintmax_atomic_t;
#define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(value) value##ul
#define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(~0)
//#endif
}
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
#if BOOST_THREAD_VERSION==3
struct once_flag
{
BOOST_THREAD_NO_COPYABLE(once_flag)
BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
: epoch(BOOST_ONCE_INITIAL_FLAG_VALUE)
: epoch(0)
{}
#ifndef BOOST_NO_DELETED_FUNCTIONS
once_flag(const once_flag&) = delete;
once_flag& operator=(const once_flag&) = delete;
#else // BOOST_NO_DELETED_FUNCTIONS
private:
volatile thread_detail::uintmax_atomic_t epoch;
template<typename Function>
friend
void call_once(once_flag& flag,Function f);
once_flag(const once_flag&);
once_flag& operator=(const once_flag&);
public:
#endif // BOOST_NO_DELETED_FUNCTIONS
private:
boost::uintmax_t epoch;
};
#else // BOOST_THREAD_PROVIDES_ONCE_CXX11
#else // BOOST_THREAD_VERSION==3
struct once_flag
{
volatile thread_detail::uintmax_atomic_t epoch;
boost::uintmax_t epoch;
};
#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
#endif // BOOST_THREAD_VERSION==3
namespace detail
{
BOOST_THREAD_DECL thread_detail::uintmax_atomic_t& get_once_per_thread_epoch();
BOOST_THREAD_DECL extern thread_detail::uintmax_atomic_t once_global_epoch;
BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
BOOST_THREAD_DECL extern boost::uintmax_t once_global_epoch;
BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
}
@@ -78,10 +67,10 @@ namespace boost
template<typename Function>
void call_once(once_flag& flag,Function f)
{
static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
thread_detail::uintmax_atomic_t const epoch=flag.epoch;
thread_detail::uintmax_atomic_t& this_thread_epoch=detail::get_once_per_thread_epoch();
static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
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)
{
@@ -92,18 +81,21 @@ namespace boost
if(flag.epoch==uninitialized_flag)
{
flag.epoch=being_initialized;
BOOST_TRY
#ifndef BOOST_NO_EXCEPTIONS
try
{
#endif
pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
f();
#ifndef BOOST_NO_EXCEPTIONS
}
BOOST_CATCH (...)
catch(...)
{
flag.epoch=uninitialized_flag;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
BOOST_RETHROW
throw;
}
BOOST_CATCH_END
#endif
flag.epoch=--detail::once_global_epoch;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
}

View File

@@ -1,12 +1,12 @@
#ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 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)
#include <pthread.h>
#include <boost/utility.hpp>
#include <boost/throw_exception.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
@@ -23,7 +23,6 @@
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0
@@ -41,6 +40,15 @@ namespace boost
{
class recursive_mutex
{
#ifndef BOOST_NO_DELETED_FUNCTIONS
public:
recursive_mutex(recursive_mutex const&) = delete;
recursive_mutex& operator=(recursive_mutex const&) = delete;
#else // BOOST_NO_DELETED_FUNCTIONS
private:
recursive_mutex(recursive_mutex const&);
recursive_mutex& operator=(recursive_mutex const&);
#endif // BOOST_NO_DELETED_FUNCTIONS
private:
pthread_mutex_t m;
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
@@ -50,7 +58,6 @@ namespace boost
unsigned count;
#endif
public:
BOOST_THREAD_NO_COPYABLE(recursive_mutex)
recursive_mutex()
{
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
@@ -110,7 +117,7 @@ namespace boost
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock() BOOST_NOEXCEPT
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
@@ -175,6 +182,15 @@ namespace boost
class recursive_timed_mutex
{
#ifndef BOOST_NO_DELETED_FUNCTIONS
public:
recursive_timed_mutex(recursive_timed_mutex const&) = delete;
recursive_timed_mutex& operator=(recursive_timed_mutex const&) = delete;
#else // BOOST_NO_DELETED_FUNCTIONS
private:
recursive_timed_mutex(recursive_timed_mutex const&);
recursive_timed_mutex& operator=(recursive_timed_mutex const&);
#endif // BOOST_NO_DELETED_FUNCTIONS
private:
pthread_mutex_t m;
#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
@@ -184,7 +200,6 @@ namespace boost
unsigned count;
#endif
public:
BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex)
recursive_timed_mutex()
{
#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
@@ -294,7 +309,7 @@ namespace boost
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
bool try_lock() BOOST_NOEXCEPT
bool try_lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && !pthread_equal(owner,pthread_self()))

View File

@@ -2,7 +2,6 @@
#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -17,7 +16,6 @@
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -48,8 +46,17 @@ namespace boost
shared_cond.notify_all();
}
#ifndef BOOST_NO_DELETED_FUNCTIONS
public:
shared_mutex(shared_mutex const&) = delete;
shared_mutex& operator=(shared_mutex const&) = delete;
#else // BOOST_NO_DELETED_FUNCTIONS
private:
shared_mutex(shared_mutex const&);
shared_mutex& operator=(shared_mutex const&);
#endif // BOOST_NO_DELETED_FUNCTIONS
public:
BOOST_THREAD_NO_COPYABLE(shared_mutex)
shared_mutex()
{
@@ -113,7 +120,18 @@ namespace boost
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
if(cv_status::timeout==shared_cond.wait_for(lk,rel_time))
{
return false;
}
}
++state.shared_count;
return true;
}
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
@@ -199,7 +217,25 @@ namespace boost
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
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;
if(cv_status::timeout == exclusive_cond.wait_for(lk,rel_time))
{
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=false;
release_waiters();
return false;
}
break;
}
}
state.exclusive=true;
return true;
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
@@ -292,7 +328,22 @@ namespace boost
template <class Rep, class Period>
bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
if(cv_status::no_timeout == shared_cond.wait_for(lk,rel_time))
{
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
break;
}
}
++state.shared_count;
state.upgrade=true;
return true;
}
template <class Clock, class Duration>
bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
@@ -301,7 +352,7 @@ namespace boost
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
if(cv_status::no_timeout == shared_cond.wait_until(lk,abs_time))
{
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
@@ -369,54 +420,16 @@ namespace boost
release_waiters();
}
bool try_unlock_upgrade_and_lock()
{
boost::mutex::scoped_lock lk(state_change);
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& state.upgrade
&& state.shared_count==1)
{
state.shared_count=0;
state.exclusive=true;
state.upgrade=false;
return true;
}
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
#if 0 // To be added
bool try_unlock_upgrade_and_lock();
template <class Rep, class Period>
bool
try_unlock_upgrade_and_lock_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_upgrade_and_lock_until(
chrono::steady_clock::now() + rel_time);
}
bool
try_unlock_upgrade_and_lock_for(
const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool
try_unlock_upgrade_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
if (state.shared_count != 1)
{
for (;;)
{
cv_status status = shared_cond.wait_until(lk,abs_time);
if (state.shared_count == 1)
break;
if(status == cv_status::timeout)
return false;
}
}
state.upgrade=false;
state.exclusive=true;
state.exclusive_waiting_blocked=false;
state.shared_count=0;
return true;
}
bool
try_unlock_upgrade_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time);
#endif
// Shared <-> Exclusive
@@ -429,55 +442,16 @@ namespace boost
release_waiters();
}
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock()
{
boost::mutex::scoped_lock lk(state_change);
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& !state.upgrade
&& state.shared_count==1)
{
state.shared_count=0;
state.exclusive=true;
return true;
}
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
#if 0 // To be added
bool try_unlock_shared_and_lock();
template <class Rep, class Period>
bool
try_unlock_shared_and_lock_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_shared_and_lock_until(
chrono::steady_clock::now() + rel_time);
}
const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool
try_unlock_shared_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
if (state.shared_count != 1)
{
for (;;)
{
cv_status status = shared_cond.wait_until(lk,abs_time);
if (state.shared_count == 1)
break;
if(status == cv_status::timeout)
return false;
}
}
state.upgrade=false;
state.exclusive=true;
state.exclusive_waiting_blocked=false;
state.shared_count=0;
return true;
}
#endif
const chrono::time_point<Clock, Duration>& abs_time);
#endif
// Shared <-> Upgrade
@@ -489,61 +463,19 @@ namespace boost
release_waiters();
}
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock_upgrade()
{
boost::mutex::scoped_lock lk(state_change);
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& !state.upgrade
)
{
state.upgrade=true;
return true;
}
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
#if 0 // To be added
bool try_unlock_shared_and_lock_upgrade();
template <class Rep, class Period>
bool
try_unlock_shared_and_lock_upgrade_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_shared_and_lock_upgrade_until(
chrono::steady_clock::now() + rel_time);
}
const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool
try_unlock_shared_and_lock_upgrade_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
if( state.exclusive
|| state.exclusive_waiting_blocked
|| state.upgrade
)
{
for (;;)
{
cv_status status = exclusive_cond.wait_until(lk,abs_time);
if( ! state.exclusive
&& ! state.exclusive_waiting_blocked
&& ! state.upgrade
)
break;
if(status == cv_status::timeout)
return false;
}
}
state.upgrade=true;
return true;
}
#endif
const chrono::time_point<Clock, Duration>& abs_time);
#endif
};
typedef shared_mutex upgrade_mutex;
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -4,36 +4,28 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/pthread/condition_variable_fwd.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#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 <unistd.h>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#endif
#include <map>
#include <vector>
#include <utility>
#include <pthread.h>
#include <unistd.h>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class thread_attributes {
public:
thread_attributes() BOOST_NOEXCEPT {
thread_attributes() {
int res = pthread_attr_init(&val_);
BOOST_VERIFY(!res && "pthread_attr_init failed");
}
@@ -42,7 +34,7 @@ namespace boost
BOOST_VERIFY(!res && "pthread_attr_destroy failed");
}
// stack
void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
void set_stack_size(std::size_t size) {
if (size==0) return;
std::size_t page_size = getpagesize();
#ifdef PTHREAD_STACK_MIN
@@ -53,19 +45,18 @@ namespace boost
BOOST_VERIFY(!res && "pthread_attr_setstacksize failed");
}
std::size_t get_stack_size() const BOOST_NOEXCEPT {
std::size_t get_stack_size() const {
std::size_t size;
int res = pthread_attr_getstacksize(&val_, &size);
BOOST_VERIFY(!res && "pthread_attr_getstacksize failed");
return size;
}
#define BOOST_THREAD_DEFINES_THREAD_ATTRIBUTES_NATIVE_HANDLE
typedef pthread_attr_t native_handle_type;
native_handle_type* native_handle() BOOST_NOEXCEPT {
native_handle_type* native_handle() {
return &val_;
}
const native_handle_type* native_handle() const BOOST_NOEXCEPT {
const native_handle_type* native_handle() const {
return &val_;
}
@@ -111,28 +102,19 @@ namespace boost
bool interrupt_requested;
pthread_mutex_t* cond_mutex;
pthread_cond_t* current_cond;
typedef std::vector<std::pair<condition_variable*, mutex*>
//, hidden_allocator<std::pair<condition_variable*, mutex*> >
> notify_list_t;
notify_list_t notify;
thread_data_base():
done(false),join_started(false),joined(false),
thread_exit_callbacks(0),
interrupt_enabled(true),
interrupt_requested(false),
current_cond(0),
notify()
current_cond(0)
{}
virtual ~thread_data_base();
typedef pthread_t native_handle_type;
virtual void run()=0;
void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
{
notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
}
};
BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
@@ -145,13 +127,11 @@ namespace boost
void check_for_interruption()
{
#ifndef BOOST_NO_EXCEPTIONS
if(thread_info->interrupt_requested)
{
thread_info->interrupt_requested=false;
throw thread_interrupted(); // BOOST_NO_EXCEPTIONS protected
throw thread_interrupted();
}
#endif
}
void operator=(interruption_checker&);
@@ -193,43 +173,7 @@ namespace boost
namespace this_thread
{
#ifdef BOOST_THREAD_USES_CHRONO
inline
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
{
using namespace chrono;
boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data();
if(thread_info)
{
unique_lock<mutex> lk(thread_info->sleep_mutex);
while(cv_status::no_timeout==thread_info->sleep_condition.wait_for(lk,ns)) {}
}
else
{
if (ns >= nanoseconds::zero())
{
# if defined(BOOST_HAS_PTHREAD_DELAY_NP)
timespec ts;
ts.tv_sec = static_cast<long>(duration_cast<seconds>(ns).count());
ts.tv_nsec = static_cast<long>((ns - seconds(ts.tv_sec)).count());
BOOST_VERIFY(!pthread_delay_np(&ts));
# elif defined(BOOST_HAS_NANOSLEEP)
timespec ts;
ts.tv_sec = static_cast<long>(duration_cast<seconds>(ns).count());
ts.tv_nsec = static_cast<long>((ns - seconds(ts.tv_sec)).count());
// nanosleep takes a timespec that is an offset, not
// an absolute time.
nanosleep(&ts, 0);
# else
mutex mx;
mutex::scoped_lock lock(mx);
condition_variable cond;
cond.wait_for(lock, ns);
# endif
}
}
}
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns);
#endif
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;

View File

@@ -17,7 +17,7 @@ namespace boost
return new T();
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_NO_RVALUE_REFERENCES
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
@@ -72,7 +72,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)
{
@@ -218,8 +218,8 @@ namespace boost
{
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
#endif
#endif
template<typename T>
inline void heap_delete(T* data)
{

View File

@@ -1,58 +0,0 @@
// 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 2012 Vicente J. Botet Escriba
#ifndef BOOST_THREAD_REVERSE_LOCK_HPP
#define BOOST_THREAD_REVERSE_LOCK_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/detail/delete.hpp>
namespace boost
{
template<typename Lock>
class reverse_lock
{
public:
typedef typename Lock::mutex_type mutex_type;
BOOST_THREAD_NO_COPYABLE(reverse_lock)
explicit reverse_lock(Lock& m_)
: m(m_), mtx(0)
{
if (m.owns_lock())
{
m.unlock();
}
mtx=m.release();
}
~reverse_lock()
{
if (mtx) {
mtx->lock();
m = BOOST_THREAD_MAKE_RV_REF(Lock(*mtx, adopt_lock));
}
}
private:
Lock& m;
mutex_type* mtx;
};
#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
template<typename T>
struct is_mutex_type<reverse_lock<T> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
#endif
}
#endif // header

View File

@@ -1,52 +0,0 @@
// 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 2012 Vicente J. Botet Escriba
#ifndef BOOST_THREAD_SHARED_LOCK_GUARD_HPP
#define BOOST_THREAD_SHARED_LOCK_GUARD_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/detail/delete.hpp>
namespace boost
{
template<typename SharedMutex>
class shared_lock_guard
{
private:
SharedMutex& m;
public:
typedef SharedMutex mutex_type;
BOOST_THREAD_NO_COPYABLE(shared_lock_guard)
explicit shared_lock_guard(SharedMutex& m_):
m(m_)
{
m.lock_shared();
}
shared_lock_guard(SharedMutex& m_,adopt_lock_t):
m(m_)
{}
~shared_lock_guard()
{
m.unlock_shared();
}
};
#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
template<typename T>
struct is_mutex_type<shared_lock_guard<T> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
#endif
}
#endif // header

View File

@@ -3,20 +3,15 @@
// shared_mutex.hpp
//
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// (C) Copyright 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)
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#if defined(BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN)
#include <boost/thread/pthread/shared_mutex.hpp>
#else
#include <boost/thread/win32/shared_mutex.hpp>
#endif
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/shared_mutex.hpp>
#else

View File

@@ -4,7 +4,6 @@
// basic_recursive_mutex.hpp
//
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -42,7 +41,7 @@ namespace boost
mutex.destroy();
}
bool try_lock() BOOST_NOEXCEPT
bool try_lock()
{
long const current_thread_id=win32::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
@@ -93,7 +92,7 @@ namespace boost
}
private:
bool try_recursive_lock(long current_thread_id) BOOST_NOEXCEPT
bool try_recursive_lock(long current_thread_id)
{
if(::boost::detail::interlocked_read_acquire(&locking_thread_id)==current_thread_id)
{
@@ -103,7 +102,7 @@ namespace boost
return false;
}
bool try_basic_lock(long current_thread_id) BOOST_NOEXCEPT
bool try_basic_lock(long current_thread_id)
{
if(mutex.try_lock())
{

View File

@@ -4,7 +4,6 @@
// basic_timed_mutex_win32.hpp
//
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -58,7 +57,7 @@ namespace boost
}
bool try_lock() BOOST_NOEXCEPT
bool try_lock()
{
return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
}
@@ -146,7 +145,34 @@ namespace boost
}
return true;
}
bool try_lock_for(chrono::milliseconds const& rel_time)
{
if(try_lock())
{
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
{
if(win32::WaitForSingleObject(sem,static_cast<unsigned long>(rel_time.count()))!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
}
return true;
}
template<typename Duration>
bool timed_lock(Duration const& timeout)
@@ -159,58 +185,19 @@ namespace boost
return timed_lock(system_time(timeout));
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
if(try_lock())
{
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
{
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
if(win32::WaitForSingleObject(sem,static_cast<unsigned long>(rel_time.count()))!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
}
return true;
}
#endif
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
using namespace chrono;
return try_lock_for(ceil<milliseconds>(rel_time));
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
typename Clock::time_point c_now = Clock::now();
return try_lock_for(ceil<milliseconds>(t - c_now));
}
void unlock()
{

View File

@@ -4,29 +4,25 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/thread_data.hpp>
#include <boost/thread/win32/thread_data.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/thread/cv_status.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <limits.h>
#include <boost/assert.hpp>
#include <algorithm>
#include <boost/thread/cv_status.hpp>
//#include <boost/thread/thread.hpp>
#include <boost/thread/win32/thread_data.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/thread/xtime.hpp>
#include <vector>
#include <boost/intrusive_ptr.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <limits.h>
#include <algorithm>
#include <vector>
#include <boost/config/abi_prefix.hpp>
namespace boost
@@ -46,8 +42,10 @@ namespace boost
bool notified;
long references;
basic_cv_list_entry(basic_cv_list_entry&);
void operator=(basic_cv_list_entry&);
public:
BOOST_THREAD_NO_COPYABLE(basic_cv_list_entry)
explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_):
semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)),
wake_sem(wake_sem_.duplicate()),
@@ -85,9 +83,9 @@ namespace boost
return notified;
}
bool wait(timeout abs_time)
bool wait(timeout wait_until)
{
return this_thread::interruptible_wait(semaphore,abs_time);
return this_thread::interruptible_wait(semaphore,wait_until);
}
bool woken()
@@ -137,7 +135,6 @@ namespace boost
template<typename lock_type>
struct relocker
{
BOOST_THREAD_NO_COPYABLE(relocker)
lock_type& lock;
bool unlocked;
@@ -157,6 +154,9 @@ namespace boost
}
}
private:
relocker(relocker&);
void operator=(relocker&);
};
@@ -188,29 +188,29 @@ namespace boost
{
entry_ptr const entry;
BOOST_THREAD_NO_COPYABLE(entry_manager)
entry_manager(entry_ptr const& entry_):
entry(entry_)
{}
~entry_manager()
{
if(! entry->is_notified())
{
entry->remove_waiter();
}
}
list_entry* operator->()
{
return entry.get();
}
private:
void operator=(entry_manager&);
entry_manager(entry_manager&);
};
protected:
template<typename lock_type>
bool do_wait(lock_type& lock,timeout abs_time)
bool do_wait(lock_type& lock,timeout wait_until)
{
relocker<lock_type> locker(lock);
@@ -221,7 +221,7 @@ namespace boost
bool woken=false;
while(!woken)
{
if(!entry->wait(abs_time))
if(!entry->wait(wait_until))
{
return false;
}
@@ -232,11 +232,11 @@ namespace boost
}
template<typename lock_type,typename predicate_type>
bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred)
bool do_wait(lock_type& m,timeout const& wait_until,predicate_type pred)
{
while (!pred())
{
if(!do_wait(m, abs_time))
if(!do_wait(m, wait_until))
return pred();
}
return true;
@@ -301,8 +301,10 @@ namespace boost
class condition_variable:
private detail::basic_condition_variable
{
private:
condition_variable(condition_variable&);
void operator=(condition_variable&);
public:
BOOST_THREAD_NO_COPYABLE(condition_variable)
condition_variable()
{}
@@ -321,14 +323,14 @@ namespace boost
}
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time)
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
{
return do_wait(m,abs_time);
return do_wait(m,wait_until);
}
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time)
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until)
{
return do_wait(m,system_time(abs_time));
return do_wait(m,system_time(wait_until));
}
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
@@ -337,14 +339,14 @@ namespace boost
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time,predicate_type pred)
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
{
return do_wait(m,abs_time,pred);
return do_wait(m,wait_until,pred);
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time,predicate_type pred)
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until,predicate_type pred)
{
return do_wait(m,system_time(abs_time),pred);
return do_wait(m,system_time(wait_until),pred);
}
template<typename duration_type,typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
@@ -408,8 +410,10 @@ namespace boost
class condition_variable_any:
private detail::basic_condition_variable
{
private:
condition_variable_any(condition_variable_any&);
void operator=(condition_variable_any&);
public:
BOOST_THREAD_NO_COPYABLE(condition_variable_any)
condition_variable_any()
{}
@@ -429,15 +433,15 @@ namespace boost
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& abs_time)
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{
return do_wait(m,abs_time);
return do_wait(m,wait_until);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::xtime const& abs_time)
bool timed_wait(lock_type& m,boost::xtime const& wait_until)
{
return do_wait(m,system_time(abs_time));
return do_wait(m,system_time(wait_until));
}
template<typename lock_type,typename duration_type>
@@ -447,15 +451,15 @@ namespace boost
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred)
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
{
return do_wait(m,abs_time,pred);
return do_wait(m,wait_until,pred);
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred)
bool timed_wait(lock_type& m,boost::xtime const& wait_until,predicate_type pred)
{
return do_wait(m,system_time(abs_time),pred);
return do_wait(m,system_time(wait_until),pred);
}
template<typename lock_type,typename duration_type,typename predicate_type>
@@ -517,7 +521,6 @@ namespace boost
#endif
};
BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -3,15 +3,13 @@
// interlocked_read_win32.hpp
//
// (C) Copyright 2005-8 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
// (C) Copyright 2005-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/detail/interlocked.hpp>
#include <boost/thread/detail/config.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -24,25 +22,25 @@ namespace boost
{
namespace detail
{
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
inline long interlocked_read_acquire(long volatile* x)
{
long const res=*x;
_ReadWriteBarrier();
return res;
}
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
inline void* interlocked_read_acquire(void* volatile* x)
{
void* const res=*x;
_ReadWriteBarrier();
return res;
}
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
inline void interlocked_write_release(long volatile* x,long value)
{
_ReadWriteBarrier();
*x=value;
}
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
inline void interlocked_write_release(void* volatile* x,void* value)
{
_ReadWriteBarrier();
*x=value;
@@ -56,19 +54,19 @@ namespace boost
{
namespace detail
{
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
inline long interlocked_read_acquire(long volatile* x)
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0);
}
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
inline void* interlocked_read_acquire(void* volatile* x)
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
}
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
inline void interlocked_write_release(long volatile* x,long value)
{
BOOST_INTERLOCKED_EXCHANGE(x,value);
}
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
inline void interlocked_write_release(void* volatile* x,void* value)
{
BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value);
}

View File

@@ -1,12 +1,12 @@
#ifndef BOOST_THREAD_WIN32_MUTEX_HPP
#define BOOST_THREAD_WIN32_MUTEX_HPP
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2011-2012 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)
#include <boost/thread/win32/basic_timed_mutex.hpp>
#include <boost/utility.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
@@ -22,8 +22,10 @@ namespace boost
class mutex:
public ::boost::detail::underlying_mutex
{
private:
mutex(mutex const&);
mutex& operator=(mutex const&);
public:
BOOST_THREAD_NO_COPYABLE(mutex)
mutex()
{
initialize();
@@ -42,8 +44,10 @@ namespace boost
class timed_mutex:
public ::boost::detail::basic_timed_mutex
{
private:
timed_mutex(timed_mutex const&);
timed_mutex& operator=(timed_mutex const&);
public:
BOOST_THREAD_NO_COPYABLE(timed_mutex)
timed_mutex()
{
initialize();

View File

@@ -3,9 +3,8 @@
// once.hpp
//
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2005 John Maddock
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -31,25 +30,6 @@ namespace std
namespace boost
{
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
struct once_flag
{
BOOST_THREAD_NO_COPYABLE(once_flag)
BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
: status(0), count(0)
{}
private:
long status;
long count;
template<typename Function>
friend
void call_once(once_flag& flag,Function f);
};
#define BOOST_ONCE_INIT once_flag()
#else // BOOST_THREAD_PROVIDES_ONCE_CXX11
struct once_flag
{
long status;
@@ -57,7 +37,6 @@ namespace boost
};
#define BOOST_ONCE_INIT {0,0}
#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
namespace detail
{
@@ -92,29 +71,29 @@ namespace boost
#else
static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
#endif
BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) ==
BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) ==
(sizeof(once_char_type)*(once_mutex_name_fixed_length+1)));
std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address),
detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address),
mutex_name + once_mutex_name_fixed_length);
detail::int_to_string(win32::GetCurrentProcessId(),
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
#ifdef BOOST_NO_ANSI_APIS
return ::boost::detail::win32::OpenEventW(
#else
return ::boost::detail::win32::OpenEventA(
#endif
::boost::detail::win32::synchronize |
::boost::detail::win32::synchronize |
::boost::detail::win32::event_modify_state,
false,
mutex_name);
@@ -126,7 +105,7 @@ namespace boost
{
name_once_mutex(mutex_name,flag_address);
}
#ifdef BOOST_NO_ANSI_APIS
#ifdef BOOST_NO_ANSI_APIS
return ::boost::detail::win32::CreateEventW(
#else
return ::boost::detail::win32::CreateEventA(
@@ -136,7 +115,7 @@ namespace boost
mutex_name);
}
}
template<typename Function>
void call_once(once_flag& flag,Function f)
@@ -157,9 +136,7 @@ namespace boost
status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0);
if(!status)
{
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
if(!event_handle)
{
@@ -176,7 +153,7 @@ namespace boost
counted=true;
}
BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value);
if(!event_handle &&
if(!event_handle &&
(::boost::detail::interlocked_read_acquire(&flag.count)>1))
{
event_handle=detail::create_once_event(mutex_name,&flag);
@@ -187,8 +164,7 @@ namespace boost
}
break;
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...) // BOOST_NO_EXCEPTIONS protected
catch(...)
{
BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
if(!event_handle)
@@ -199,9 +175,8 @@ namespace boost
{
::boost::detail::win32::SetEvent(event_handle);
}
throw; // BOOST_NO_EXCEPTIONS protected
throw;
}
#endif
}
if(!counted)

View File

@@ -10,6 +10,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/utility.hpp>
#include <boost/thread/win32/basic_recursive_mutex.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
@@ -21,8 +22,10 @@ namespace boost
class recursive_mutex:
public ::boost::detail::basic_recursive_mutex
{
private:
recursive_mutex(recursive_mutex const&);
recursive_mutex& operator=(recursive_mutex const&);
public:
BOOST_THREAD_NO_COPYABLE(recursive_mutex)
recursive_mutex()
{
::boost::detail::basic_recursive_mutex::initialize();
@@ -41,8 +44,10 @@ namespace boost
class recursive_timed_mutex:
public ::boost::detail::basic_recursive_timed_mutex
{
private:
recursive_timed_mutex(recursive_timed_mutex const&);
recursive_timed_mutex& operator=(recursive_timed_mutex const&);
public:
BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex)
recursive_timed_mutex()
{
::boost::detail::basic_recursive_timed_mutex::initialize();

View File

@@ -2,7 +2,6 @@
#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -13,12 +12,8 @@
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/static_assert.hpp>
#include <limits.h>
#include <boost/utility.hpp>
#include <boost/thread/thread_time.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -26,6 +21,9 @@ namespace boost
{
class shared_mutex
{
private:
shared_mutex(shared_mutex const&);
shared_mutex& operator=(shared_mutex const&);
private:
struct state_data
{
@@ -78,7 +76,6 @@ namespace boost
public:
BOOST_THREAD_NO_COPYABLE(shared_mutex)
shared_mutex()
{
semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
@@ -221,115 +218,6 @@ namespace boost
}
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_shared_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_shared_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
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);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
chrono::system_clock::time_point n = chrono::system_clock::now();
unsigned long res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n);
res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],
static_cast<unsigned long>(rel_time.count()));
} else {
res=detail::win32::timeout;
}
if(res==detail::win32::timeout)
{
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
if(new_state.shared_waiting)
{
--new_state.shared_waiting;
}
}
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);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
return false;
}
BOOST_ASSERT(res==0);
}
}
#endif
void unlock_shared()
{
state_data old_state=state;
@@ -492,116 +380,6 @@ namespace boost
}
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
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
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
#ifndef UNDER_CE
const bool wait_all = true;
#else
const bool wait_all = false;
#endif
chrono::system_clock::time_point n = chrono::system_clock::now();
unsigned long wait_res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,
static_cast<unsigned long>(rel_time.count()));
} else {
wait_res=detail::win32::timeout;
}
if(wait_res==detail::win32::timeout)
{
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
if(new_state.exclusive_waiting)
{
if(!--new_state.exclusive_waiting)
{
new_state.exclusive_waiting_blocked=false;
}
}
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
return false;
}
BOOST_ASSERT(wait_res<2);
}
}
#endif
void unlock()
{
state_data old_state=state;
@@ -785,27 +563,6 @@ namespace boost
}
release_waiters(old_state);
}
// bool try_unlock_upgrade_and_lock()
// {
// return false;
// }
//#ifdef BOOST_THREAD_USES_CHRONO
// template <class Rep, class Period>
// bool
// try_unlock_upgrade_and_lock_for(
// const chrono::duration<Rep, Period>& rel_time)
// {
// return try_unlock_upgrade_and_lock_until(
// chrono::steady_clock::now() + rel_time);
// }
// template <class Clock, class Duration>
// bool
// try_unlock_upgrade_and_lock_until(
// const chrono::time_point<Clock, Duration>& abs_time)
// {
// return false;
// }
//#endif
void unlock_and_lock_shared()
{
@@ -831,6 +588,7 @@ namespace boost
}
release_waiters(old_state);
}
void unlock_upgrade_and_lock_shared()
{
state_data old_state=state;
@@ -856,8 +614,6 @@ namespace boost
}
};
typedef shared_mutex upgrade_mutex;
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -4,43 +4,33 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2008 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#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 <boost/intrusive_ptr.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#endif
#include <map>
#include <vector>
#include <utility>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class condition_variable;
class mutex;
class thread_attributes {
public:
thread_attributes() BOOST_NOEXCEPT {
thread_attributes() {
val_.stack_size = 0;
//val_.lpThreadAttributes=0;
}
~thread_attributes() {
}
// stack size
void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
void set_stack_size(std::size_t size) {
val_.stack_size = size;
}
std::size_t get_stack_size() const BOOST_NOEXCEPT {
std::size_t get_stack_size() const {
return val_.stack_size;
}
@@ -67,47 +57,32 @@ namespace boost
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;
void intrusive_ptr_add_ref(thread_data_base * p);
void intrusive_ptr_release(thread_data_base * p);
struct BOOST_THREAD_DECL thread_data_base
struct BOOST_SYMBOL_VISIBLE thread_data_base
{
long count;
detail::win32::handle_manager thread_handle;
detail::win32::handle_manager interruption_handle;
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 interruption_enabled;
unsigned id;
typedef std::vector<std::pair<condition_variable*, mutex*>
//, hidden_allocator<std::pair<condition_variable*, mutex*> >
> notify_list_t;
notify_list_t notify;
thread_data_base():
count(0),thread_handle(detail::win32::invalid_handle_value),
interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)),
thread_exit_callbacks(0),tss_data(),
thread_exit_callbacks(0),tss_data(0),
interruption_enabled(true),
id(0),
notify()
id(0)
{}
virtual ~thread_data_base()
{}
virtual ~thread_data_base();
friend void intrusive_ptr_add_ref(thread_data_base * p)
{
@@ -130,12 +105,6 @@ namespace boost
typedef detail::win32::handle native_handle_type;
virtual void run()=0;
void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
{
notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
}
};
typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;

View File

@@ -75,180 +75,144 @@ namespace boost
inline T* heap_new()
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
T* const data=new (heap_memory) T();
return data;
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...) // BOOST_NO_EXCEPTIONS protected
catch(...)
{
free_raw_heap_memory(heap_memory);
throw; // BOOST_NO_EXCEPTIONS protected
throw;
}
#endif
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_NO_RVALUE_REFERENCES
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1));
return data;
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...) // BOOST_NO_EXCEPTIONS protected
catch(...)
{
free_raw_heap_memory(heap_memory);
throw; // BOOST_NO_EXCEPTIONS protected
throw;
}
#endif
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1&& a1,A2&& a2)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2));
return data;
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...) // BOOST_NO_EXCEPTIONS protected
catch(...)
{
free_raw_heap_memory(heap_memory);
throw; // BOOST_NO_EXCEPTIONS protected
throw;
}
#endif
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3));
return data;
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...) // BOOST_NO_EXCEPTIONS protected
catch(...)
{
free_raw_heap_memory(heap_memory);
throw; // BOOST_NO_EXCEPTIONS protected
throw;
}
#endif
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3),static_cast<A4&&>(a4));
return data;
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...) // BOOST_NO_EXCEPTIONS protected
catch(...)
{
free_raw_heap_memory(heap_memory);
throw; // BOOST_NO_EXCEPTIONS protected
throw;
}
#endif
}
#else
template<typename T,typename A1>
inline T* heap_new_impl(A1 a1)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
T* const data=new (heap_memory) T(a1);
return data;
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...) // BOOST_NO_EXCEPTIONS protected
catch(...)
{
free_raw_heap_memory(heap_memory);
throw; // BOOST_NO_EXCEPTIONS protected
throw;
}
#endif
}
template<typename T,typename A1,typename A2>
inline T* heap_new_impl(A1 a1,A2 a2)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
T* const data=new (heap_memory) T(a1,a2);
return data;
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...) // BOOST_NO_EXCEPTIONS protected
catch(...)
{
free_raw_heap_memory(heap_memory);
throw; // BOOST_NO_EXCEPTIONS protected
throw;
}
#endif
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
T* const data=new (heap_memory) T(a1,a2,a3);
return data;
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...) // BOOST_NO_EXCEPTIONS protected
catch(...)
{
free_raw_heap_memory(heap_memory);
throw; // BOOST_NO_EXCEPTIONS protected
throw;
}
#endif
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
T* const data=new (heap_memory) T(a1,a2,a3,a4);
return data;
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...) // BOOST_NO_EXCEPTIONS protected
catch(...)
{
free_raw_heap_memory(heap_memory);
throw; // BOOST_NO_EXCEPTIONS protected
throw;
}
#endif
}

View File

@@ -10,7 +10,7 @@
// 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 <boost/throw_exception.hpp>
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
@@ -341,48 +341,22 @@ namespace boost
{
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
#ifndef BOOST_INTEL_CXX_VERSION
__asm {
mov eax,bit;
mov edx,x;
lock bts [edx],eax;
setc al;
};
#else
bool ret;
__asm {
mov eax,bit
mov edx,x
lock bts [edx],eax
setc al
mov ret, al
};
return ret;
#endif
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
#ifndef BOOST_INTEL_CXX_VERSION
__asm {
mov eax,bit;
mov edx,x;
lock btr [edx],eax;
setc al;
};
#else
bool ret;
__asm {
mov eax,bit
mov edx,x
lock btr [edx],eax
setc al
mov ret, al
};
return ret;
#endif
}
}

View File

@@ -2,7 +2,7 @@
// William E. Kempf
// Copyright (C) 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_XTIME_WEK070601_HPP
@@ -20,7 +20,7 @@ namespace boost {
enum xtime_clock_types
{
TIME_UTC_=1
TIME_UTC=1
// TIME_TAI,
// TIME_MONOTONIC,
// TIME_PROCESS,
@@ -53,14 +53,14 @@ struct xtime
boost::posix_time::microseconds((nsec+500)/1000);
#endif
}
};
inline xtime get_xtime(boost::system_time const& abs_time)
{
xtime res;
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
res.sec=static_cast<xtime::xtime_sec_t>(time_since_epoch.total_seconds());
res.nsec=static_cast<xtime::xtime_nsec_t>(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second()));
return res;
@@ -68,7 +68,7 @@ inline xtime get_xtime(boost::system_time const& abs_time)
inline int xtime_get(struct xtime* xtp, int clock_type)
{
if (clock_type == TIME_UTC_)
if (clock_type == TIME_UTC)
{
*xtp=get_xtime(get_system_time());
return clock_type;
@@ -81,7 +81,7 @@ inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
{
if (xt1.sec == xt2.sec)
return (int)(xt1.nsec - xt2.nsec);
else
else
return (xt1.sec > xt2.sec) ? 1 : -1;
}

View File

@@ -3,10 +3,6 @@
// 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>
#ifndef BOOST_NO_EXCEPTIONS
#include <boost/thread/future.hpp>
namespace boost
@@ -51,11 +47,22 @@ namespace boost
}
const system::error_category&
future_category() BOOST_NOEXCEPT
future_category()
{
static thread_detail::future_error_category f;
return f;
}
future_error::future_error(system::error_code ec)
: logic_error(ec.message()),
ec_(ec)
{
}
// future_error::~future_error() //BOOST_NOEXCEPT
// {
// }
}
#endif

View File

@@ -14,7 +14,7 @@ namespace boost
{
namespace detail
{
BOOST_THREAD_DECL thread_detail::uintmax_atomic_t once_global_epoch=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C;
BOOST_THREAD_DECL boost::uintmax_t once_global_epoch=UINTMAX_C(~0);
BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER;
BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER;
@@ -55,17 +55,17 @@ namespace boost
#endif
}
thread_detail::uintmax_atomic_t& get_once_per_thread_epoch()
boost::uintmax_t& get_once_per_thread_epoch()
{
BOOST_VERIFY(!pthread_once(&epoch_tss_key_flag,create_epoch_tss_key));
void* data=pthread_getspecific(epoch_tss_key);
if(!data)
{
data=malloc(sizeof(thread_detail::uintmax_atomic_t));
data=malloc(sizeof(boost::uintmax_t));
BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data));
*static_cast<thread_detail::uintmax_atomic_t*>(data)=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C;
*static_cast<boost::uintmax_t*>(data)=UINTMAX_C(~0);
}
return *static_cast<thread_detail::uintmax_atomic_t*>(data);
return *static_cast<boost::uintmax_t*>(data);
}
}

View File

@@ -10,12 +10,11 @@
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/tss.hpp>
#include <boost/throw_exception.hpp>
#ifdef __GLIBC__
#include <sys/sysinfo.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
@@ -25,23 +24,14 @@
#include <unistd.h>
#endif
#include "./timeconv.inl"
#include "timeconv.inl"
namespace boost
{
namespace detail
{
thread_data_base::~thread_data_base()
{
{
for (notify_list_t::iterator i = notify.begin(), e = notify.end();
i != e; ++i)
{
i->second->unlock();
i->first->notify_all();
}
}
}
{}
struct thread_exit_callback_node
{
@@ -56,11 +46,7 @@ namespace boost
namespace
{
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
boost::once_flag current_thread_tls_init_flag;
#else
boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
#endif
pthread_key_t current_thread_tls_key;
extern "C"
@@ -148,17 +134,16 @@ namespace boost
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
thread_info->self.reset();
detail::set_current_thread_data(thread_info.get());
BOOST_TRY
try
{
thread_info->run();
}
BOOST_CATCH (thread_interrupted const&)
catch(thread_interrupted const&)
{
}
BOOST_CATCH_END
// Removed as it stops the debugger identifying the cause of the exception
// Unhandled exceptions still cause the application to terminate
// BOOST_CATCH(...)
// catch(...)
// {
// std::terminate();
// }
@@ -182,8 +167,6 @@ namespace boost
void run()
{}
void notify_all_at_thread_exit(condition_variable*, mutex*)
{}
private:
externally_launched_thread(externally_launched_thread&);
@@ -234,14 +217,14 @@ namespace boost
if (res != 0)
{
thread_info->self.reset();
boost::throw_exception(thread_resource_error());
throw thread_resource_error();
}
int detached_state;
res = pthread_attr_getdetachstate(h, &detached_state);
if (res != 0)
{
thread_info->self.reset();
boost::throw_exception(thread_resource_error());
throw thread_resource_error();
}
if (PTHREAD_CREATE_DETACHED==detached_state)
{
@@ -261,7 +244,10 @@ namespace boost
}
}
thread::~thread()
{
detach();
}
detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
{
@@ -313,12 +299,6 @@ namespace boost
thread_info.reset();
}
}
else
{
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
#endif
}
}
bool thread::do_try_join_until(struct timespec const &timeout)
@@ -368,14 +348,8 @@ namespace boost
{
thread_info.reset();
}
return true;
}
else
{
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
#endif
}
return true;
}
bool thread::joinable() const BOOST_NOEXCEPT
@@ -415,7 +389,7 @@ namespace boost
if(thread_info)
{
unique_lock<mutex> lk(thread_info->sleep_mutex);
while(thread_info->sleep_condition.timed_wait(lk,st)) {}
while(thread_info->sleep_condition.timed_wait(lk,st));
}
else
{
@@ -441,13 +415,40 @@ namespace boost
cond.timed_wait(lock, xt);
# endif
xtime cur;
xtime_get(&cur, TIME_UTC_);
xtime_get(&cur, TIME_UTC);
if (xtime_cmp(xt, cur) <= 0)
return;
}
}
}
#ifdef BOOST_THREAD_USES_CHRONO
void
sleep_for(const chrono::nanoseconds& ns)
{
using namespace chrono;
if (ns >= nanoseconds::zero())
{
timespec ts;
ts.tv_sec = static_cast<long>(duration_cast<seconds>(ns).count());
ts.tv_nsec = static_cast<long>((ns - seconds(ts.tv_sec)).count());
# if defined(BOOST_HAS_PTHREAD_DELAY_NP)
BOOST_VERIFY(!pthread_delay_np(&ts));
# elif defined(BOOST_HAS_NANOSLEEP)
// nanosleep takes a timespec that is an offset, not
// an absolute time.
nanosleep(&ts, 0);
# else
mutex mx;
mutex::scoped_lock lock(mx);
condition_variable cond;
cond.wait_for(lock, ns);
# endif
}
}
#endif
void yield() BOOST_NOEXCEPT
{
# if defined(BOOST_HAS_SCHED_YIELD)
@@ -456,7 +457,7 @@ namespace boost
BOOST_VERIFY(!pthread_yield());
# else
xtime xt;
xtime_get(&xt, TIME_UTC_);
xtime_get(&xt, TIME_UTC);
sleep(xt);
# endif
}
@@ -481,10 +482,6 @@ namespace boost
thread::id thread::get_id() const BOOST_NOEXCEPT
{
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
//return local_thread_info->thread_handle;
return const_cast<thread*>(this)->native_handle();
#else
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
if(local_thread_info)
{
@@ -492,9 +489,8 @@ namespace boost
}
else
{
return id();
return id();
}
#endif
}
void thread::interrupt()
@@ -512,7 +508,7 @@ namespace boost
}
}
bool thread::interruption_requested() const BOOST_NOEXCEPT
bool thread::interruption_requested() const
{
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
if(local_thread_info)
@@ -546,17 +542,12 @@ namespace boost
{
thread::id get_id() BOOST_NOEXCEPT
{
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
return pthread_self();
#else
boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
return thread::id(thread_info?thread_info->shared_from_this():detail::thread_data_ptr());
#endif
}
void interruption_point()
{
#ifndef BOOST_NO_EXCEPTIONS
boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
if(thread_info && thread_info->interrupt_enabled)
{
@@ -567,16 +558,15 @@ namespace boost
throw thread_interrupted();
}
}
#endif
}
bool interruption_enabled() BOOST_NOEXCEPT
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_NOEXCEPT
bool interruption_requested()
{
boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
if(!thread_info)
@@ -590,7 +580,7 @@ namespace boost
}
}
disable_interruption::disable_interruption() BOOST_NOEXCEPT:
disable_interruption::disable_interruption():
interruption_was_enabled(interruption_enabled())
{
if(interruption_was_enabled)
@@ -599,7 +589,7 @@ namespace boost
}
}
disable_interruption::~disable_interruption() BOOST_NOEXCEPT
disable_interruption::~disable_interruption()
{
if(detail::get_current_thread_data())
{
@@ -607,7 +597,7 @@ namespace boost
}
}
restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT
restore_interruption::restore_interruption(disable_interruption& d)
{
if(d.interruption_was_enabled)
{
@@ -615,7 +605,7 @@ namespace boost
}
}
restore_interruption::~restore_interruption() BOOST_NOEXCEPT
restore_interruption::~restore_interruption()
{
if(detail::get_current_thread_data())
{
@@ -646,7 +636,7 @@ namespace boost
return &current_node->second;
}
}
return 0;
return NULL;
}
void* get_tss_data(void const* key)
@@ -655,7 +645,7 @@ namespace boost
{
return current_node->value;
}
return 0;
return NULL;
}
void add_new_tss_node(void const* key,
@@ -692,21 +682,12 @@ namespace boost
erase_tss_node(key);
}
}
else if(func || (tss_data!=0))
else
{
add_new_tss_node(key,func,tss_data);
}
}
}
BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
{
detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
if(current_thread_data)
{
current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
}
}
}

View File

@@ -20,8 +20,8 @@ const int NANOSECONDS_PER_MICROSECOND = 1000;
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;
res = boost::xtime_get(&xt, boost::TIME_UTC);
BOOST_ASSERT(res == boost::TIME_UTC); (void)res;
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
@@ -56,8 +56,8 @@ 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;
res = boost::xtime_get(&cur, boost::TIME_UTC);
BOOST_ASSERT(res == boost::TIME_UTC); (void)res;
if (boost::xtime_cmp(xt, cur) <= 0)
{
@@ -87,8 +87,8 @@ 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;
res = boost::xtime_get(&cur, boost::TIME_UTC);
BOOST_ASSERT(res == boost::TIME_UTC); (void)res;
if (boost::xtime_cmp(xt, cur) <= 0)
milliseconds = 0;
@@ -109,8 +109,8 @@ 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;
res = boost::xtime_get(&cur, boost::TIME_UTC);
BOOST_ASSERT(res == boost::TIME_UTC); (void)res;
if (boost::xtime_cmp(xt, cur) <= 0)
microseconds = 0;

View File

@@ -8,7 +8,7 @@
#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
namespace boost
{
/*
This file is a "null" implementation of tss cleanup; it's
@@ -32,7 +32,7 @@ namespace boost
longer needed and can be removed.
*/
}
}
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && !defined(_MSC_VER)

View File

@@ -4,80 +4,56 @@
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2007 David Deakins
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
#endif
#ifndef WINVER
#define WINVER 0x400
#endif
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/tss.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/detail/tss_hooks.hpp>
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
#include <memory>
#include <algorithm>
#ifndef UNDER_CE
#include <process.h>
#endif
#include <stdio.h>
#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
{
namespace detail
{
thread_data_base::~thread_data_base()
{
{
for (notify_list_t::iterator i = notify.begin(), e = notify.end();
i != e; ++i)
{
i->second->unlock();
i->first->notify_all();
}
}
}
}
namespace
{
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
boost::once_flag current_thread_tls_init_flag;
#else
boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
#endif
#if defined(UNDER_CE)
#if defined(UNDER_CE)
// Windows CE does not define the TLS_OUT_OF_INDEXES constant.
#define TLS_OUT_OF_INDEXES 0xFFFFFFFF
#endif
DWORD current_thread_tls_key=TLS_OUT_OF_INDEXES;
DWORD tls_out_of_index=0xFFFFFFFF;
#else
DWORD tls_out_of_index=TLS_OUT_OF_INDEXES;
#endif
DWORD current_thread_tls_key=tls_out_of_index;
void create_current_thread_tls_key()
{
tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in
current_thread_tls_key=TlsAlloc();
BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES);
BOOST_ASSERT(current_thread_tls_key!=tls_out_of_index);
}
void cleanup_tls_key()
{
if(current_thread_tls_key!=TLS_OUT_OF_INDEXES)
if(current_thread_tls_key!=tls_out_of_index)
{
TlsFree(current_thread_tls_key);
current_thread_tls_key=TLS_OUT_OF_INDEXES;
current_thread_tls_key=tls_out_of_index;
}
}
detail::thread_data_base* get_current_thread_data()
{
if(current_thread_tls_key==TLS_OUT_OF_INDEXES)
if(current_thread_tls_key==tls_out_of_index)
{
return 0;
}
@@ -87,7 +63,7 @@ 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!=TLS_OUT_OF_INDEXES)
if(current_thread_tls_key!=tls_out_of_index)
BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
else
boost::throw_exception(thread_resource_error());
@@ -113,7 +89,7 @@ namespace boost
typedef void* uintptr_t;
inline uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
inline uintptr_t const _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
void* arglist, unsigned initflag, unsigned* thrdaddr)
{
DWORD threadID;
@@ -145,6 +121,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
@@ -154,7 +143,7 @@ namespace boost
detail::thread_data_ptr current_thread_data(get_current_thread_data(),false);
if(current_thread_data)
{
while(! current_thread_data->tss_data.empty() || current_thread_data->thread_exit_callbacks)
while(current_thread_data->tss_data || current_thread_data->thread_exit_callbacks)
{
while(current_thread_data->thread_exit_callbacks)
{
@@ -167,18 +156,15 @@ namespace boost
}
boost::detail::heap_delete(current_node);
}
for(std::map<void const*,detail::tss_data_node>::iterator next=current_thread_data->tss_data.begin(),
current,
end=current_thread_data->tss_data.end();
next!=end;)
while(current_thread_data->tss_data)
{
current=next;
++next;
if(current->second.func && (current->second.value!=0))
detail::tss_data_node* const current_node=current_thread_data->tss_data;
current_thread_data->tss_data=current_node->next;
if(current_node->func)
{
(*current->second.func)(current->second.value);
(*current_node->func)(current_node->value);
}
current_thread_data->tss_data.erase(current);
boost::detail::heap_delete(current_node);
}
}
@@ -190,20 +176,16 @@ namespace boost
{
detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param));
set_current_thread_data(thread_info);
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
thread_info->run();
}
#ifndef BOOST_NO_EXCEPTIONS
catch(thread_interrupted const&) // BOOST_NO_EXCEPTIONS protected
catch(thread_interrupted const&)
{
}
#endif
// Removed as it stops the debugger identifying the cause of the exception
// Unhandled exceptions still cause the application to terminate
// catch(...) // BOOST_NO_EXCEPTIONS protected
// catch(...)
// {
// std::terminate();
// }
@@ -230,7 +212,7 @@ namespace boost
void thread::start_thread(const attributes& attr)
{
//uintptr_t const new_thread=_beginthreadex(attr.get_security(),attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
uintptr_t const new_thread=_beginthreadex(0,static_cast<unsigned int>(attr.get_stack_size()),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
uintptr_t const new_thread=_beginthreadex(0,attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
if(!new_thread)
{
boost::throw_exception(thread_resource_error());
@@ -257,9 +239,6 @@ namespace boost
void run()
{}
void notify_all_at_thread_exit(condition_variable*, mutex*)
{}
private:
externally_launched_thread(externally_launched_thread&);
void operator=(externally_launched_thread&);
@@ -268,19 +247,15 @@ namespace boost
void make_external_thread_data()
{
externally_launched_thread* me=detail::heap_new<externally_launched_thread>();
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
try
{
set_current_thread_data(me);
}
#ifndef BOOST_NO_EXCEPTIONS
catch(...) // BOOST_NO_EXCEPTIONS protected
catch(...)
{
detail::heap_delete(me);
throw; // BOOST_NO_EXCEPTIONS protected
throw;
}
#endif
}
detail::thread_data_base* get_or_make_current_thread_data()
@@ -296,21 +271,21 @@ namespace boost
}
thread::~thread()
{
detach();
}
thread::id thread::get_id() const BOOST_NOEXCEPT
{
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
detail::thread_data_ptr local_thread_info=(get_thread_info)();
return local_thread_info?local_thread_info->id:0;
//return const_cast<thread*>(this)->native_handle();
#else
return thread::id((get_thread_info)());
#endif
}
bool thread::joinable() const BOOST_NOEXCEPT
{
return (get_thread_info)();
}
void thread::join()
{
if (this_thread::get_id() == get_id())
@@ -323,42 +298,45 @@ namespace boost
this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel());
release_handle();
}
else
{
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
#endif
}
}
bool thread::timed_join(boost::system_time const& wait_until)
{
return do_try_join_until(get_milliseconds_until(wait_until));
if (this_thread::get_id() == get_id())
{
boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
}
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)))
{
return false;
}
release_handle();
}
return true;
}
bool thread::do_try_join_until(uintmax_t milli)
{
#ifdef BOOST_THREAD_USES_CHRONO
bool thread::do_try_join_for(chrono::milliseconds const &rel_time_in_milliseconds) {
if (this_thread::get_id() == get_id())
{
boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
}
detail::thread_data_ptr local_thread_info=(get_thread_info)();
if(local_thread_info)
{
if(!this_thread::interruptible_wait(local_thread_info->thread_handle,milli))
if(!this_thread::interruptible_wait(local_thread_info->thread_handle,rel_time_in_milliseconds.count()))
{
return false;
}
release_handle();
return true;
}
else
{
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
#endif
}
return true;
}
#endif
void thread::detach()
{
@@ -379,7 +357,7 @@ namespace boost
}
}
bool thread::interruption_requested() const BOOST_NOEXCEPT
bool thread::interruption_requested() const
{
detail::thread_data_ptr local_thread_info=(get_thread_info)();
return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0);
@@ -557,12 +535,7 @@ namespace boost
thread::id get_id() BOOST_NOEXCEPT
{
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
//return detail::win32::GetCurrentThread();
return detail::win32::GetCurrentThreadId();
#else
return thread::id(get_or_make_current_thread_data());
#endif
}
void interruption_point()
@@ -574,12 +547,12 @@ namespace boost
}
}
bool interruption_enabled() BOOST_NOEXCEPT
bool interruption_enabled()
{
return get_current_thread_data() && get_current_thread_data()->interruption_enabled;
}
bool interruption_requested() BOOST_NOEXCEPT
bool interruption_requested()
{
return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0);
}
@@ -589,7 +562,7 @@ namespace boost
detail::win32::Sleep(0);
}
disable_interruption::disable_interruption() BOOST_NOEXCEPT:
disable_interruption::disable_interruption():
interruption_was_enabled(interruption_enabled())
{
if(interruption_was_enabled)
@@ -598,7 +571,7 @@ namespace boost
}
}
disable_interruption::~disable_interruption() BOOST_NOEXCEPT
disable_interruption::~disable_interruption()
{
if(get_current_thread_data())
{
@@ -606,7 +579,7 @@ namespace boost
}
}
restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT
restore_interruption::restore_interruption(disable_interruption& d)
{
if(d.interruption_was_enabled)
{
@@ -614,7 +587,7 @@ namespace boost
}
}
restore_interruption::~restore_interruption() BOOST_NOEXCEPT
restore_interruption::~restore_interruption()
{
if(get_current_thread_data())
{
@@ -639,11 +612,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 &current_node->second;
if(current_node->key==key)
{
return current_node;
}
current_node=current_node->next;
}
}
return NULL;
@@ -658,43 +634,23 @@ 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.get() && current_node->value)
{
(*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 if(func || (tss_data!=0))
else if(func && tss_data)
{
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=
heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data);
current_thread_data->tss_data=new_node;
}
}
}
@@ -714,14 +670,6 @@ namespace boost
boost::run_thread_exit_callbacks();
}
BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
{
detail::thread_data_base* const current_thread_data(get_current_thread_data());
if(current_thread_data)
{
current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
}
}
}

View File

@@ -17,8 +17,8 @@ const int NANOSECONDS_PER_MICROSECOND = 1000;
inline void to_time(int milliseconds, boost::xtime& xt)
{
int res = 0;
res = boost::xtime_get(&xt, boost::TIME_UTC_);
assert(res == boost::TIME_UTC_);
res = boost::xtime_get(&xt, boost::TIME_UTC);
assert(res == boost::TIME_UTC);
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
@@ -54,8 +54,8 @@ 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_);
assert(res == boost::TIME_UTC_);
res = boost::xtime_get(&cur, boost::TIME_UTC);
assert(res == boost::TIME_UTC);
if (boost::xtime_cmp(xt, cur) <= 0)
{
@@ -85,8 +85,8 @@ inline void to_duration(boost::xtime xt, int& milliseconds)
{
boost::xtime cur;
int res = 0;
res = boost::xtime_get(&cur, boost::TIME_UTC_);
assert(res == boost::TIME_UTC_);
res = boost::xtime_get(&cur, boost::TIME_UTC);
assert(res == boost::TIME_UTC);
if (boost::xtime_cmp(xt, cur) <= 0)
milliseconds = 0;
@@ -107,8 +107,8 @@ inline void to_microduration(boost::xtime xt, int& microseconds)
{
boost::xtime cur;
int res = 0;
res = boost::xtime_get(&cur, boost::TIME_UTC_);
assert(res == boost::TIME_UTC_);
res = boost::xtime_get(&cur, boost::TIME_UTC);
assert(res == boost::TIME_UTC);
if (boost::xtime_cmp(xt, cur) <= 0)
microseconds = 0;

View File

@@ -5,7 +5,6 @@
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
#include <boost/thread/detail/tss_hooks.hpp>

View File

@@ -11,7 +11,7 @@
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
#if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR)
#if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__)
#include <boost/thread/detail/tss_hooks.hpp>
@@ -25,7 +25,7 @@ namespace boost
}
namespace {
void NTAPI on_tls_callback(void* , DWORD dwReason, PVOID )
void NTAPI on_tls_callback(void* h, DWORD dwReason, PVOID pv)
{
switch (dwReason)
{
@@ -38,7 +38,7 @@ namespace {
}
}
#if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || (__MINGW32_MAJOR_VERSION >3) || \
#if defined(__MINGW64__) || (__MINGW32_MAJOR_VERSION >3) || \
((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18))
extern "C"
{

View File

@@ -1,6 +1,5 @@
# (C) Copyright William E. Kempf 2001.
# (C) Copyright 2007 Anthony Williams.
# (C) Copyright 2011-2012 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)
#
@@ -20,52 +19,8 @@
import testing ;
project
: requirements
<threading>multi
<warnings>all
<toolset>gcc:<cxxflags>-Wextra
<toolset>gcc:<cxxflags>-pedantic
<toolset>gcc:<cxxflags>-Wno-long-long
#<toolset>gcc:<cxxflags>-ansi
#<toolset>gcc:<cxxflags>-fpermissive
<toolset>darwin:<cxxflags>-Wextra
<toolset>darwin:<cxxflags>-pedantic
<toolset>darwin:<cxxflags>-Wno-long-long
#<toolset>darwin:<cxxflags>-ansi # doesn't work for 4.1.2
<toolset>darwin:<cxxflags>-fpermissive
#<toolset>pathscale:<cxxflags>-Wextra
<toolset>pathscale:<cxxflags>-Wno-long-long
<toolset>pathscale:<cxxflags>-pedantic
<toolset>clang:<cxxflags>-Wextra
<toolset>clang:<cxxflags>-pedantic
<toolset>clang:<cxxflags>-Wno-long-long
<toolset>clang:<cxxflags>-ansi
#<toolset>clang:<cxxflags>-fpermissive # doesn't work
<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.6.3:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.7.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.8.0:<cxxflags>-fdiagnostics-show-option
<toolset>darwin-4.6.2:<cxxflags>-ansi
#<toolset>darwin-4.6.2:<cxxflags>-Wno-delete-non-virtual-dtor # doesn't work
<toolset>darwin-4.7.0:<cxxflags>-ansi
<toolset>darwin-4.7.0:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.8:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.8:<cxxflags>-Wno-unused-function
#<toolset>clang-2.9:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.9:<cxxflags>-Wno-unused-function
<toolset>clang-3.0:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-3.0:<cxxflags>-Wno-unused-function
#<toolset>clang-3.0:<cxxflags>-Wno-unused-variable
: requirements <library>/boost/test//boost_unit_test_framework/<link>static
<threading>multi
;
rule thread-run ( sources )
@@ -77,108 +32,67 @@ rule thread-run ( sources )
;
}
rule thread-test ( sources )
{
return
[ run $(sources) ../build//boost_thread : : :
<library>/boost/test//boost_unit_test_framework/<link>static
]
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
: : :
<library>/boost/test//boost_unit_test_framework/<link>static
: $(sources[1]:B)_lib
]
;
}
rule thread-run2 ( sources : name )
{
return
[ run $(sources) ../build//boost_thread : : :
[ run $(sources) ../build//boost_thread : : :
: $(name) ]
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
: : :
: $(name)_lib ]
;
}
rule thread-run-lib2 ( sources : name )
{
return
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
: : :
: : :
: $(name)_lib ]
;
}
rule thread-compile-fail ( sources : reqs * : name )
rule thread-compile-fail-V2 ( sources : reqs * : name )
{
return
[ compile-fail $(sources)
: $(reqs)
: $(reqs)
: $(name) ]
;
}
{
test-suite t_threads
test-suite threads
:
[ thread-test test_thread.cpp ]
[ thread-test test_thread_id.cpp ]
[ thread-test test_hardware_concurrency.cpp ]
[ thread-test test_thread_move.cpp ]
[ thread-test test_thread_return_local.cpp ]
[ thread-test test_thread_move_return.cpp ]
[ thread-test test_thread_launching.cpp ]
[ thread-test test_thread_mf.cpp ]
[ thread-test test_thread_exit.cpp ]
[ thread-test test_move_function.cpp ]
[ thread-run test_thread.cpp ]
[ 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 ]
[ thread-run test_condition_timed_wait_times_out.cpp ]
[ thread-run test_condition_notify_all.cpp ]
[ thread-run test_condition.cpp ]
[ thread-run test_tss.cpp ]
[ thread-run test_once.cpp ]
[ thread-run test_xtime.cpp ]
[ thread-run test_barrier.cpp ]
[ thread-run test_shared_mutex.cpp ]
[ thread-run test_shared_mutex_part_2.cpp ]
[ thread-run test_shared_mutex_timed_locks.cpp ]
#[ thread-run test_shared_mutex_timed_locks_chrono.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 ]
[ thread-test test_tss.cpp ]
[ thread-test test_xtime.cpp ]
;
test-suite t_sync
:
[ thread-test test_mutex.cpp ]
[ thread-test test_condition_notify_one.cpp ]
[ thread-test test_condition_timed_wait_times_out.cpp ]
[ thread-test test_condition_notify_all.cpp ]
[ thread-test test_condition.cpp ]
[ thread-test test_once.cpp ]
[ thread-test test_barrier.cpp ]
[ thread-test test_lock_concept.cpp ]
[ thread-test test_generic_locks.cpp ]
;
test-suite t_shared
:
[ thread-test test_shared_mutex.cpp ]
[ thread-test test_shared_mutex_part_2.cpp ]
[ thread-test test_shared_mutex_timed_locks.cpp ]
[ thread-test test_shared_mutex_timed_locks_chrono.cpp ]
#uncomment the following once these works on windows
#[ thread-test test_vhh_shared_mutex.cpp ]
#[ thread-test test_vhh_shared_mutex_part_2.cpp ]
#[ thread-test test_vhh_shared_mutex_timed_locks.cpp ]
;
#explicit t_futures ;
test-suite t_futures
:
[ thread-test test_futures.cpp ]
;
#explicit tickets ;
test-suite tickets
:
[ thread-test test_2309.cpp ]
[ thread-run test_2309.cpp ]
[ thread-run test_2501.cpp ]
[ thread-test test_2741.cpp ]
[ thread-run test_3628.cpp ]
[ thread-run test_2741.cpp ]
[ thread-run test_4521.cpp ]
[ thread-run test_4648.cpp ]
[ thread-run test_4882.cpp ]
@@ -189,8 +103,6 @@ rule thread-compile-fail ( sources : reqs * : name )
[ thread-run test_6130.cpp ]
[ thread-run test_6170.cpp ]
[ thread-run test_6174.cpp ]
[ thread-run test_7160.cpp ]
[ thread-run test_7328.cpp ]
;
@@ -203,339 +115,166 @@ rule thread-compile-fail ( sources : reqs * : name )
#explicit ts_conditions ;
test-suite ts_conditions
#explicit conditions ;
test-suite conditions
:
[ thread-compile-fail ./sync/conditions/condition_variable/assign_fail.cpp : : condition_variable__assign_f ]
[ thread-compile-fail ./sync/conditions/condition_variable/copy_fail.cpp : : condition_variable__copy_f ]
[ thread-run2 ./sync/conditions/condition_variable/default_pass.cpp : condition_variable__default_p ]
[ thread-run2 ./sync/conditions/condition_variable/dtor_pass.cpp : condition_variable__dtor_p ]
[ thread-run2 ./sync/conditions/condition_variable/native_handle_pass.cpp : condition_variable__native_handle_p ]
[ thread-run2 ./sync/conditions/condition_variable/wait_for_pass.cpp : condition_variable__wait_for_p ]
[ thread-run2 ./sync/conditions/condition_variable/wait_for_pred_pass.cpp : condition_variable__wait_for_pred_p ]
[ thread-run2 ./sync/conditions/condition_variable/wait_until_pass.cpp : condition_variable__wait_until_p ]
[ thread-run2 ./sync/conditions/condition_variable/wait_until_pred_pass.cpp : condition_variable__wait_until_pred_p ]
[ thread-compile-fail-V2 ./sync/conditions/condition_variable/assign_fail.cpp : : conditions__condition_variable__assign_fail ]
[ thread-compile-fail-V2 ./sync/conditions/condition_variable/copy_fail.cpp : : conditions__condition_variable__copy_fail ]
[ thread-run2 ./sync/conditions/condition_variable/default_pass.cpp : conditions__condition_variable__default_pass ]
[ thread-run2 ./sync/conditions/condition_variable/dtor_pass.cpp : conditions__condition_variable__dtor_pass ]
[ thread-run2 ./sync/conditions/condition_variable/native_handle_pass.cpp : conditions__condition_variable__native_handle_pass ]
[ thread-run2 ./sync/conditions/condition_variable/wait_for_pass.cpp : conditions__condition_variable__wait_for_pass ]
[ thread-run2 ./sync/conditions/condition_variable/wait_for_pred_pass.cpp : conditions__condition_variable__wait_for_pred_pass ]
[ thread-run2 ./sync/conditions/condition_variable/wait_until_pass.cpp : conditions__condition_variable__wait_until_pass ]
[ thread-run2 ./sync/conditions/condition_variable/wait_until_pred_pass.cpp : conditions__condition_variable__wait_until_pred_pass ]
[ thread-compile-fail ./sync/conditions/condition_variable_any/assign_fail.cpp : : condition_variable_any__assign_f ]
[ thread-compile-fail ./sync/conditions/condition_variable_any/copy_fail.cpp : : condition_variable_any__copy_f ]
[ thread-run2 ./sync/conditions/condition_variable_any/default_pass.cpp : condition_variable_any__default_p ]
[ thread-run2 ./sync/conditions/condition_variable_any/dtor_pass.cpp : condition_variable_any__dtor_p ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_for_pass.cpp : condition_variable_any__wait_for_p ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_for_pred_pass.cpp : condition_variable_any__wait_for_pred_p ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_until_pass.cpp : condition_variable_any__wait_until_p ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_until_pred_pass.cpp : condition_variable_any__wait_until_pred_p ]
[ thread-run2 ./sync/conditions/cv_status/cv_status_pass.cpp : cv_status__cv_status_p ]
[ thread-run2 ./sync/conditions/notify_all_at_thread_exit_pass.cpp : notify_all_at_thread_exit_p ]
[ thread-compile-fail-V2 ./sync/conditions/condition_variable_any/assign_fail.cpp : : conditions__condition_variable_any__assign_fail ]
[ thread-compile-fail-V2 ./sync/conditions/condition_variable_any/copy_fail.cpp : : conditions__condition_variable_any__copy_fail ]
[ thread-run2 ./sync/conditions/condition_variable_any/default_pass.cpp : conditions__condition_variable_any__default_pass ]
[ thread-run2 ./sync/conditions/condition_variable_any/dtor_pass.cpp : conditions__condition_variable_any__dtor_pass ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_for_pass.cpp : conditions__condition_variable_any__wait_for_pass ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_for_pred_pass.cpp : conditions__condition_variable_any__wait_for_pred_pass ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_until_pass.cpp : conditions__condition_variable_any__wait_until_pass ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_until_pred_pass.cpp : conditions__condition_variable_any__wait_until_pred_pass ]
[ thread-run2 ./sync/conditions/cv_status/cv_status_pass.cpp : conditions__cv_status__cv_status_pass ]
;
explicit ts_async ;
test-suite ts_async
#explicit futures ;
test-suite futures
:
[ thread-run2 ./sync/futures/async/async_pass.cpp : async__async_p ]
# [ thread-run2 ./sync/futures/async/async_pass.cpp : futures__async__async_pass ]
[ thread-run2 ./sync/futures/promise/default_pass.cpp : futures__promise__default_pass ]
[ thread-run2 ./sync/futures/promise/dtor_pass.cpp : futures__promise__dtor_pass ]
[ thread-run2 ./sync/futures/promise/get_future_pass.cpp : futures__promise__get_future_pass ]
;
#explicit ts_promise ;
test-suite ts_promise
explicit tt ;
test-suite tt
:
[ thread-compile-fail ./sync/futures/promise/copy_assign_fail.cpp : : promise__copy_assign_f ]
[ thread-compile-fail ./sync/futures/promise/copy_ctor_fail.cpp : : promise__copy_ctor_f ]
[ thread-run2 ./sync/futures/promise/alloc_ctor_pass.cpp : promise__alloc_ctor_p ]
[ thread-run2 ./sync/futures/promise/default_pass.cpp : promise__default_p ]
[ thread-run2 ./sync/futures/promise/dtor_pass.cpp : promise__dtor_p ]
[ thread-run2 ./sync/futures/promise/get_future_pass.cpp : promise__get_future_p ]
[ thread-run2 ./sync/futures/promise/move_ctor_pass.cpp : promise__move_ctor_p ]
[ thread-run2 ./sync/futures/promise/move_assign_pass.cpp : promise__move_asign_p ]
[ thread-run2 ./sync/futures/promise/use_allocator_pass.cpp : promise__use_allocator_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp : xmutual_exclusion__locks__unique_lock__cons__try_to_lock_pass ]
;
#explicit ts_future ;
test-suite ts_future
#explicit mutual_exclusion ;
test-suite mutual_exclusion
:
[ thread-compile-fail ./sync/futures/future/copy_assign_fail.cpp : : future__copy_assign_f ]
[ thread-compile-fail ./sync/futures/future/copy_ctor_fail.cpp : : future__copy_ctor_f ]
[ thread-run2 ./sync/futures/future/default_pass.cpp : future__default_p ]
[ thread-run2 ./sync/futures/future/dtor_pass.cpp : future__dtor_p ]
#[ thread-run2 ./sync/futures/future/get_pass.cpp : future__get_p ]
[ thread-run2 ./sync/futures/future/move_ctor_pass.cpp : future__move_ctor_p ]
[ thread-run2 ./sync/futures/future/move_assign_pass.cpp : future__move_asign_p ]
[ thread-run2 ./sync/futures/future/share_pass.cpp : future__share_p ]
;
#explicit ts_packaged_task ;
test-suite ts_packaged_task
:
[ thread-run2 ./sync/futures/packaged_task/alloc_ctor_pass.cpp : packaged_task__alloc_ctor_p ]
[ thread-compile-fail ./sync/futures/packaged_task/copy_assign_fail.cpp : : packaged_task__copy_assign_f ]
[ thread-compile-fail ./sync/futures/packaged_task/copy_ctor_fail.cpp : : packaged_task__copy_ctor_f ]
[ thread-run2 ./sync/futures/packaged_task/default_ctor_pass.cpp : packaged_task__default_ctor_p ]
[ thread-run2 ./sync/futures/packaged_task/func_ctor_pass.cpp : packaged_task__func_ctor_p ]
#[ thread-run2 ./sync/futures/packaged_task/dtor_pass.cpp : packaged_task__dtor_p ]
[ thread-run2 ./sync/futures/packaged_task/get_future_pass.cpp : packaged_task__get_future_p ]
[ thread-run2 ./sync/futures/packaged_task/move_ctor_pass.cpp : packaged_task__move_ctor_p ]
[ thread-run2 ./sync/futures/packaged_task/move_assign_pass.cpp : packaged_task__move_asign_p ]
#[ thread-run2 ./sync/futures/packaged_task/operator_pass.cpp : packaged_task__operator_p ]
[ thread-run2 ./sync/futures/packaged_task/reset_pass.cpp : packaged_task__reset_p ]
[ thread-run2 ./sync/futures/packaged_task/use_allocator_pass.cpp : packaged_task__use_allocator_p ]
[ thread-run2 ./sync/futures/packaged_task/types_pass.cpp : packaged_task__types_p ]
[ thread-run2 ./sync/futures/packaged_task/member_swap_pass.cpp : packaged_task__member_swap_p ]
[ thread-run2 ./sync/futures/packaged_task/non_member_swap_pass.cpp : packaged_task__non_member_swap_p ]
;
[ thread-compile-fail-V2 ./sync/mutual_exclusion/locks/unique_lock/cons/copy_assign_fail.cpp : : mutual_exclusion__locks__unique_lock__cons__copy_assign_fail ]
[ thread-compile-fail-V2 ./sync/mutual_exclusion/locks/unique_lock/cons/copy_ctor_fail.cpp : : mutual_exclusion__locks__unique_lock__cons__copy_ctor_fail ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/adopt_lock_pass.cpp : mutual_exclusion__locks__unique_lock__cons__adopt_lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/default_pass.cpp : mutual_exclusion__locks__unique_lock__cons__default_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/defer_lock_pass.cpp : mutual_exclusion__locks__unique_lock__cons__defer_lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp : mutual_exclusion__locks__unique_lock__cons__duration_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp : mutual_exclusion__locks__unique_lock__cons__move_assign_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp : mutual_exclusion__locks__unique_lock__cons__move_ctor_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp : mutual_exclusion__locks__unique_lock__cons__mutex_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp : mutual_exclusion__locks__unique_lock__cons__time_point_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp : mutual_exclusion__locks__unique_lock__cons__try_to_lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/lock_pass.cpp : mutual_exclusion__locks__unique_lock__locking__lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_for_pass.cpp : mutual_exclusion__locks__unique_lock__locking__try_lock_for_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_pass.cpp : mutual_exclusion__locks__unique_lock__locking__try_lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_until_pass.cpp : mutual_exclusion__locks__unique_lock__locking__try_lock_until_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/unlock_pass.cpp : mutual_exclusion__locks__unique_lock__locking__unlock_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/mod/member_swap_pass.cpp : mutual_exclusion__locks__unique_lock__mod__member_swap_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/mod/non_member_swap_pass.cpp : mutual_exclusion__locks__unique_lock__mod__non_member_swap_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/mod/release_pass.cpp : mutual_exclusion__locks__unique_lock__mod__release_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/obs/mutex_pass.cpp : mutual_exclusion__locks__unique_lock__obs__mutex_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/obs/op_bool_pass.cpp : mutual_exclusion__locks__unique_lock__obs__op_bool_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/obs/owns_lock_pass.cpp : mutual_exclusion__locks__unique_lock__obs__owns_lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/types_pass.cpp : mutual_exclusion__locks__unique_lock__types_pass ]
#[ thread-compile-fail-V2 ./sync/mutual_exclusion/locks/shared_lock/cons/copy_assign_fail.cpp : : mutual_exclusion__locks__shared_lock__cons__copy_assign_fail ]
#[ thread-compile-fail-V2 ./sync/mutual_exclusion/locks/shared_lock/cons/copy_ctor_fail.cpp : : mutual_exclusion__locks__shared_lock__cons__copy_ctor_fail ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/adopt_lock_pass.cpp : mutual_exclusion__locks__shared_lock__cons__adopt_lock_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp : mutual_exclusion__locks__shared_lock__cons__default_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp : mutual_exclusion__locks__shared_lock__cons__defer_lock_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp : mutual_exclusion__locks__shared_lock__cons__duration_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp : mutual_exclusion__locks__shared_lock__cons__move_assign_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp : mutual_exclusion__locks__shared_lock__cons__move_ctor_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp : mutual_exclusion__locks__shared_lock__cons__mutex_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp : mutual_exclusion__locks__shared_lock__cons__time_point_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp : mutual_exclusion__locks__shared_lock__cons__try_to_lock_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/lock_pass.cpp : mutual_exclusion__locks__shared_lock__locking__lock_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_for_pass.cpp : mutual_exclusion__locks__shared_lock__locking__try_lock_for_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_pass.cpp : mutual_exclusion__locks__shared_lock__locking__try_lock_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_until_pass.cpp : mutual_exclusion__locks__shared_lock__locking__try_lock_until_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/unlock_pass.cpp : mutual_exclusion__locks__shared_lock__locking__unlock_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/mod/member_swap_pass.cpp : mutual_exclusion__locks__shared_lock__mod__member_swap_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/mod/non_member_swap_pass.cpp : mutual_exclusion__locks__shared_lock__mod__non_member_swap_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/mod/release_pass.cpp : mutual_exclusion__locks__shared_lock__mod__release_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/obs/mutex_pass.cpp : mutual_exclusion__locks__shared_lock__obs__mutex_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/obs/op_bool_pass.cpp : mutual_exclusion__locks__shared_lock__obs__op_bool_pass ]
#[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/obs/owns_lock_pass.cpp : mutual_exclusion__locks__shared_lock__obs__owns_lock_pass ]
#explicit ts_lock_guard ;
test-suite ts_lock_guard
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/lock_guard/copy_assign_fail.cpp : : lock_guard__cons__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/lock_guard/copy_ctor_fail.cpp : : lock_guard__cons__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/lock_guard/adopt_lock_pass.cpp : lock_guard__cons__adopt_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/lock_guard/default_pass.cpp : lock_guard__cons__default_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/lock_guard/types_pass.cpp : lock_guard__types_p ]
;
[ thread-compile-fail-V2 ./sync/mutual_exclusion/mutex/assign_fail.cpp : : mutual_exclusion__mutex__assign_fail ]
[ thread-compile-fail-V2 ./sync/mutual_exclusion/mutex/copy_fail.cpp : : mutual_exclusion__mutex__copy_fail ]
[ thread-run2 ./sync/mutual_exclusion/mutex/default_pass.cpp : mutual_exclusion__mutex__default_pass ]
[ thread-run2 ./sync/mutual_exclusion/mutex/lock_pass.cpp : mutual_exclusion__mutex__lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/mutex/native_handle_pass.cpp : mutual_exclusion__mutex__native_handle_pass ]
[ thread-run2 ./sync/mutual_exclusion/mutex/try_lock_pass.cpp : mutual_exclusion__mutex__try_lock_pass ]
#explicit ts_unique_lock ;
test-suite ts_unique_lock
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/cons/copy_assign_fail.cpp : : unique_lock__cons__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/cons/copy_ctor_fail.cpp : : unique_lock__cons__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/adopt_lock_pass.cpp : unique_lock__cons__adopt_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/default_pass.cpp : unique_lock__cons__default_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/defer_lock_pass.cpp : unique_lock__cons__defer_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp : unique_lock__cons__duration_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp : unique_lock__cons__move_assign_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp : unique_lock__cons__move_ctor_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_try_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_until_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp : unique_lock__cons__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp : unique_lock__cons__time_point_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp : unique_lock__cons__try_to_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/lock_pass.cpp : unique_lock__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_for_pass.cpp : unique_lock__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_pass.cpp : unique_lock__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_until_pass.cpp : unique_lock__try_lock_until_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/unlock_pass.cpp : unique_lock__unlock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/mod/member_swap_pass.cpp : unique_lock__member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/mod/non_member_swap_pass.cpp : unique_lock__non_member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/mod/release_pass.cpp : unique_lock__release_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/obs/mutex_pass.cpp : unique_lock__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/obs/op_bool_pass.cpp : unique_lock__op_bool_p ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/obs/op_int_fail.cpp : : unique_lock__op_int_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/obs/owns_lock_pass.cpp : unique_lock__owns_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/types_pass.cpp : unique_lock__types_p ]
;
[ thread-compile-fail-V2 ./sync/mutual_exclusion/recursive_mutex/assign_fail.cpp : : mutual_exclusion__recursive_mutex__assign_fail ]
[ thread-compile-fail-V2 ./sync/mutual_exclusion/recursive_mutex/copy_fail.cpp : : mutual_exclusion__recursive_mutex__copy_fail ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/default_pass.cpp : mutual_exclusion__recursive_mutex__default_pass ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/lock_pass.cpp : mutual_exclusion__recursive_mutex__lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/native_handle_pass.cpp : mutual_exclusion__recursive_mutex__native_handle_pass ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/try_lock_pass.cpp : mutual_exclusion__recursive_mutex__try_lock_pass ]
#explicit ts_shared_lock ;
test-suite ts_shared_lock
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock/cons/copy_assign_fail.cpp : : shared_lock__cons__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock/cons/copy_ctor_fail.cpp : : shared_lock__cons__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/adopt_lock_pass.cpp : shared_lock__cons__adopt_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp : shared_lock__cons__default_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp : shared_lock__cons__defer_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp : shared_lock__cons__duration_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp : shared_lock__cons__move_assign_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp : shared_lock__cons__move_ctor_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp : shared_lock__cons__move_ctor_unique_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp : shared_lock__cons__move_ctor_upgrade_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp : shared_lock__cons__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp : shared_lock__cons__time_point_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp : shared_lock__cons__try_to_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/lock_pass.cpp : shared_lock__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_for_pass.cpp : shared_lock__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_pass.cpp : shared_lock__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_until_pass.cpp : shared_lock__try_lock_until_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/unlock_pass.cpp : shared_lock__unlock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/mod/member_swap_pass.cpp : shared_lock__member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/mod/non_member_swap_pass.cpp : shared_lock__non_member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/mod/release_pass.cpp : shared_lock__release_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/obs/mutex_pass.cpp : shared_lock__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/obs/op_bool_pass.cpp : shared_lock__op_bool_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/obs/owns_lock_pass.cpp : shared_lock__owns_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/types_pass.cpp : shared_lock__types_p ]
;
[ thread-compile-fail-V2 ./sync/mutual_exclusion/recursive_timed_mutex/assign_fail.cpp : : mutual_exclusion__recursive_timed_mutex__assign_fail ]
[ thread-compile-fail-V2 ./sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp : : mutual_exclusion__recursive_timed_mutex__copy_fail ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp : mutual_exclusion__recursive_timed_mutex__default_pass ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp : mutual_exclusion__recursive_timed_mutex__lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp : mutual_exclusion__recursive_timed_mutex__native_handle_pass ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp : mutual_exclusion__recursive_timed_mutex__try_lock_for_pass ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp : mutual_exclusion__recursive_timed_mutex__try_lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp : mutual_exclusion__recursive_timed_mutex__try_lock_until_pass ]
#explicit ts_upgrade_lock ;
test-suite ts_upgrade_lock
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/upgrade_lock/cons/copy_assign_fail.cpp : : upgrade_lock__cons__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/upgrade_lock/cons/copy_ctor_fail.cpp : : upgrade_lock__cons__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/adopt_lock_pass.cpp : upgrade_lock__cons__adopt_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/default_pass.cpp : upgrade_lock__cons__default_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/defer_lock_pass.cpp : upgrade_lock__cons__defer_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp : upgrade_lock__cons__duration_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp : upgrade_lock__cons__move_assign_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp : upgrade_lock__cons__move_ctor_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp : upgrade_lock__cons__move_ctor_unique_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp : upgrade_lock__cons__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp : upgrade_lock__cons__time_point_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp : upgrade_lock__cons__try_to_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/locking/lock_pass.cpp : upgrade_lock__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_for_pass.cpp : upgrade_lock__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_pass.cpp : upgrade_lock__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_until_pass.cpp : upgrade_lock__try_lock_until_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/locking/unlock_pass.cpp : upgrade_lock__unlock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/mod/member_swap_pass.cpp : upgrade_lock__member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/mod/non_member_swap_pass.cpp : upgrade_lock__non_member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/mod/release_pass.cpp : upgrade_lock__release_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/obs/mutex_pass.cpp : upgrade_lock__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/obs/op_bool_pass.cpp : upgrade_lock__op_bool_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/obs/owns_lock_pass.cpp : upgrade_lock__owns_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/types_pass.cpp : upgrade_lock__types_p ]
;
[ thread-compile-fail-V2 ./sync/mutual_exclusion/timed_mutex/assign_fail.cpp : : mutual_exclusion__timed_mutex__assign_fail ]
[ thread-compile-fail-V2 ./sync/mutual_exclusion/timed_mutex/copy_fail.cpp : : mutual_exclusion__timed_mutex__copy_fail ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/default_pass.cpp : mutual_exclusion__timed_mutex__default_pass ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/lock_pass.cpp : mutual_exclusion__timed_mutex__lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp : mutual_exclusion__timed_mutex__native_handle_pass ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp : mutual_exclusion__timed_mutex__try_lock_for_pass ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp : mutual_exclusion__timed_mutex__try_lock_pass ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp : mutual_exclusion__timed_mutex__try_lock_until_pass ]
#explicit ts_mutex ;
test-suite ts_mutex
:
[ thread-compile-fail ./sync/mutual_exclusion/mutex/assign_fail.cpp : : mutex__assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/mutex/copy_fail.cpp : : mutex__copy_f ]
[ thread-run2 ./sync/mutual_exclusion/mutex/default_pass.cpp : mutex__default_p ]
[ thread-run2 ./sync/mutual_exclusion/mutex/lock_pass.cpp : mutex__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/mutex/native_handle_pass.cpp : mutex__native_handle_p ]
[ thread-run2 ./sync/mutual_exclusion/mutex/try_lock_pass.cpp : mutex__try_lock_p ]
;
#explicit ts_recursive_mutex ;
test-suite ts_recursive_mutex
:
[ thread-compile-fail ./sync/mutual_exclusion/recursive_mutex/assign_fail.cpp : : recursive_mutex__assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/recursive_mutex/copy_fail.cpp : : recursive_mutex__copy_f ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/default_pass.cpp : recursive_mutex__default_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/lock_pass.cpp : recursive_mutex__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/native_handle_pass.cpp : recursive_mutex__native_handle_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/try_lock_pass.cpp : recursive_mutex__try_lock_p ]
;
#explicit ts_recursive_timed_mutex ;
test-suite ts_recursive_timed_mutex
:
[ thread-compile-fail ./sync/mutual_exclusion/recursive_timed_mutex/assign_fail.cpp : : recursive_timed_mutex__assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp : : recursive_timed_mutex__copy_f ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp : recursive_timed_mutex__default_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp : recursive_timed_mutex__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp : recursive_timed_mutex__native_handle_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp : recursive_timed_mutex__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp : recursive_timed_mutex__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp : recursive_timed_mutex__try_lock_until_p ]
;
#explicit ts_timed_mutex ;
test-suite ts_timed_mutex
:
[ thread-compile-fail ./sync/mutual_exclusion/timed_mutex/assign_fail.cpp : : timed_mutex__assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/timed_mutex/copy_fail.cpp : : timed_mutex__copy_f ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/default_pass.cpp : timed_mutex__default_p ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/lock_pass.cpp : timed_mutex__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp : timed_mutex__native_handle_p ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp : timed_mutex__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp : timed_mutex__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp : timed_mutex__try_lock_until_p ]
;
#explicit ts_shared_mutex ;
test-suite ts_shared_mutex
:
[ thread-compile-fail ./sync/mutual_exclusion/shared_mutex/assign_fail.cpp : : shared_mutex__assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/shared_mutex/copy_fail.cpp : : shared_mutex__copy_f ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/default_pass.cpp : shared_mutex__default_p ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/lock_pass.cpp : shared_mutex__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp : shared_mutex__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp : shared_mutex__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp : shared_mutex__try_lock_until_p ]
[ thread-compile-fail-V2 ./sync/mutual_exclusion/shared_mutex/assign_fail.cpp : : mutual_exclusion__shared_mutex__assign_fail ]
[ thread-compile-fail-V2 ./sync/mutual_exclusion/shared_mutex/copy_fail.cpp : : mutual_exclusion__shared_mutex__copy_fail ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/default_pass.cpp : mutual_exclusion__shared_mutex__default_pass ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/lock_pass.cpp : mutual_exclusion__shared_mutex__lock_pass ]
#[ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp : mutual_exclusion__shared_mutex__try_lock_for_pass ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp : mutual_exclusion__shared_mutex__try_lock_pass ]
#[ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp : mutual_exclusion__shared_mutex__try_lock_until_pass ]
;
#explicit ts_this_thread ;
test-suite ts_this_thread
#explicit this_thread ;
test-suite this_thread
:
[ thread-run2 ./threads/this_thread/get_id/get_id_pass.cpp : this_thread__get_id_p ]
[ thread-run2 ./threads/this_thread/sleep_for/sleep_for_pass.cpp : this_thread__sleep_for_p ]
[ thread-run2 ./threads/this_thread/sleep_until/sleep_until_pass.cpp : this_thread__sleep_until_p ]
[ thread-run2 ./threads/this_thread/get_id/get_id_pass.cpp : this_thread__get_id__get_id_pass ]
[ thread-run2 ./threads/this_thread/sleep_for/sleep_for_pass.cpp : this_thread__sleep_for__sleep_for_pass ]
[ thread-run2 ./threads/this_thread/sleep_until/sleep_until_pass.cpp : this_thread__sleep_until__sleep_until_pass ]
;
#explicit ts_thread ;
test-suite ts_thread
#explicit thread ;
test-suite thread
:
[ thread-compile-fail ./threads/thread/assign/copy_fail.cpp : : thread__assign__copy_f ]
[ thread-run2 ./threads/thread/assign/move_pass.cpp : thread__assign__move_p ]
[ thread-compile-fail ./threads/thread/constr/copy_fail.cpp : : thread__constr__copy_f ]
[ thread-run2 ./threads/thread/constr/default_pass.cpp : thread__constr__default_p ]
[ thread-run-lib2 ./threads/thread/constr/F_pass.cpp : thread__constr__F_p ]
[ thread-run-lib2 ./threads/thread/constr/FArgs_pass.cpp : thread__constr__FArgs_p ]
[ thread-run2 ./threads/thread/constr/Frvalue_pass.cpp : thread__constr__Frvalue_p ]
#[ thread-run2 ./threads/thread/constr/FrvalueArgs_pass.cpp : thread__constr__FrvalueArgs_p ]
[ thread-run2 ./threads/thread/constr/move_pass.cpp : thread__constr__move_p ]
[ thread-run2 ./threads/thread/destr/dtor_pass.cpp : thread__destr__dtor_p ]
[ thread-run2 ./threads/thread/id/hash_pass.cpp : thread__id__hash_p ]
[ thread-run2 ./threads/thread/members/detach_pass.cpp : thread__detach_p ]
[ thread-run2 ./threads/thread/members/get_id_pass.cpp : thread__get_id_p ]
[ thread-run2 ./threads/thread/members/join_pass.cpp : thread__join_p ]
[ thread-run2 ./threads/thread/members/try_join_until_pass.cpp : thread__join_until_p ]
[ thread-run2 ./threads/thread/members/try_join_for_pass.cpp : thread__join_for_p ]
[ thread-run2 ./threads/thread/members/joinable_pass.cpp : thread__joinable_p ]
[ thread-run2 ./threads/thread/members/native_handle_pass.cpp : thread__native_handle_p ]
[ thread-run2 ./threads/thread/members/swap_pass.cpp : thread__swap_p ]
[ thread-run2 ./threads/thread/non_members/swap_pass.cpp : swap_threads_p ]
[ thread-run2 ./threads/thread/static/hardware_concurrency_pass.cpp : thread__hardware_concurrency_p ]
[ thread-compile-fail-V2 ./threads/thread/assign/copy_fail.cpp : : thread__assign__copy_fail ]
[ thread-run2 ./threads/thread/assign/move_pass.cpp : thread__assign__move_pass ]
[ thread-compile-fail-V2 ./threads/thread/constr/copy_fail.cpp : : thread__constr__copy_fail ]
[ thread-run2 ./threads/thread/constr/default_pass.cpp : thread__constr__default_pass ]
[ thread-run2 ./threads/thread/constr/F_pass.cpp : thread__constr__F_pass ]
[ thread-run2 ./threads/thread/constr/Frvalue_pass.cpp : thread__constr__Frvalue_pass ]
#[ thread-run2 ./threads/thread/constr/FrvalueArgs_pass.cpp : thread__constr__FrvalueArgs_pass ]
[ thread-run2 ./threads/thread/constr/move_pass.cpp : thread__constr__move_pass ]
[ thread-run2 ./threads/thread/destr/dtor_pass.cpp : thread__destr__dtor_pass ]
[ thread-run2 ./threads/thread/id/hash_pass.cpp : thread__id__hash_pass ]
[ thread-run2 ./threads/thread/members/detach_pass.cpp : thread__members__detach_pass ]
[ thread-run2 ./threads/thread/members/get_id_pass.cpp : thread__members__get_id_pass ]
[ thread-run2 ./threads/thread/members/join_pass.cpp : thread__members__join_pass ]
[ thread-run2 ./threads/thread/members/joinable_pass.cpp : thread__members__joinable_pass ]
[ thread-run2 ./threads/thread/members/native_handle_pass.cpp : thread__members__native_handle_pass ]
[ thread-run2 ./threads/thread/members/swap_pass.cpp : thread__members__swap_pass ]
[ thread-run2 ./threads/thread/non_members/swap_pass.cpp : thread__non_members__swap_pass ]
[ thread-run2 ./threads/thread/static/hardware_concurrency_pass.cpp : thread__static__hardware_concurrency_pass ]
;
#explicit ts_container ;
test-suite ts_container
:
[ thread-run2 ./threads/container/thread_vector_pass.cpp : container__thread_vector_p ]
[ thread-run2 ./threads/container/thread_ptr_list_pass.cpp : container__thread_ptr_list_p ]
;
#explicit ts_examples ;
test-suite ts_examples
:
[ thread-run ../example/monitor.cpp ]
[ compile ../example/starvephil.cpp ]
#[ compile ../example/tennis.cpp ]
[ compile ../example/condition.cpp ]
[ thread-run ../example/mutex.cpp ]
[ thread-run ../example/once.cpp ]
[ thread-run ../example/recursive_mutex.cpp ]
[ thread-run2 ../example/thread.cpp : ex_thread ]
[ thread-run ../example/thread_group.cpp ]
[ thread-run ../example/tss.cpp ]
[ thread-run ../example/xtime.cpp ]
[ thread-run ../example/shared_monitor.cpp ]
[ thread-run ../example/shared_mutex.cpp ]
#[ thread-run ../example/vhh_shared_monitor.cpp ]
#[ thread-run ../example/vhh_shared_mutex.cpp ]
;
#explicit ts_shared_upwards ;
test-suite ts_shared_upwards
:
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp : unique_lock__cons__move_ctor_shared_lock_try_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp : unique_lock__cons__move_ctor_shared_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp : unique_lock__cons__move_ctor_shared_lock_until_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_try_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_until_p ]
;
#explicit ts_shared_lock_guard ;
test-suite ts_shared_lock_guard
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock_guard/copy_assign_fail.cpp : : shared_lock_guard__cons__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock_guard/copy_ctor_fail.cpp : : shared_lock_guard__cons__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock_guard/adopt_lock_pass.cpp : shared_lock_guard__cons__adopt_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock_guard/default_pass.cpp : shared_lock_guard__cons__default_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock_guard/types_pass.cpp : shared_lock_guard__types_p ]
;
#explicit ts_reverse_lock ;
test-suite ts_reverse_lock
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/reverse_lock/copy_assign_fail.cpp : : reverse_lock__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/reverse_lock/copy_ctor_fail.cpp : : reverse_lock__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/reverse_lock/unique_lock_ctor_pass.cpp : reverse_lock__unique_lock_ctor_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp : reverse_lock__types_p ]
;
}

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2008 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>
@@ -13,5 +13,3 @@ void test()
boost::thread t2;
t2=t1;
}
#include "./remove_error_code_unused_warning.hpp"

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2008 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>
@@ -12,5 +12,3 @@ void test()
boost::thread t1(do_nothing);
boost::thread t2(t1);
}
#include "./remove_error_code_unused_warning.hpp"

View File

@@ -1,17 +0,0 @@
// Copyright (C) 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)
#include <boost/thread/thread.hpp>
void remove_unused_warning()
{
//../../../boost/system/error_code.hpp:214:36: warning: 'boost::system::posix_category' defined but not used [-Wunused-variable]
//../../../boost/system/error_code.hpp:215:36: warning: 'boost::system::errno_ecat' defined but not used [-Wunused-variable]
//../../../boost/system/error_code.hpp:216:36: warning: 'boost::system::native_ecat' defined but not used [-Wunused-variable]
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -19,13 +19,10 @@
#include <boost/thread/condition_variable.hpp>
void fail()
int fail()
{
boost::condition_variable cv0;
boost::condition_variable cv1;
cv1 = cv0;
}
#include "../../../remove_error_code_unused_warning.hpp"

View File

@@ -20,11 +20,9 @@
#include <boost/thread/condition_variable.hpp>
#include <boost/detail/lightweight_test.hpp>
void fail()
int fail()
{
boost::condition_variable cv0;
boost::condition_variable cv1(cv0);
}
#include "../../../remove_error_code_unused_warning.hpp"

View File

@@ -25,3 +25,4 @@ int main()
boost::condition_variable cv0;
return boost::report_errors();
}

View File

@@ -57,8 +57,7 @@ void f()
cv.notify_one();
Clock::time_point t0 = Clock::now();
int count=0;
//bool r =
(void)cv.wait_for(lk, milliseconds(250), Pred(test2));
bool r = cv.wait_for(lk, milliseconds(250), Pred(test2));
count++;
Clock::time_point t1 = Clock::now();
if (runs == 0)

View File

@@ -19,12 +19,10 @@
#include <boost/thread/condition_variable.hpp>
void fail()
int fail()
{
boost::condition_variable_any cv0;
boost::condition_variable_any cv1;
cv1 = cv0;
}
#include "../../../remove_error_code_unused_warning.hpp"

View File

@@ -20,11 +20,9 @@
#include <boost/thread/condition_variable.hpp>
#include <boost/detail/lightweight_test.hpp>
void fail()
int fail()
{
boost::condition_variable_any cv0;
boost::condition_variable_any cv1(cv0);
}
#include "../../../remove_error_code_unused_warning.hpp"

View File

@@ -60,8 +60,7 @@ void f()
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
//bool r =
(void)cv.wait_for(lk, milliseconds(250), Pred(test2));
bool r = cv.wait_for(lk, milliseconds(250), Pred(test2));
Clock::time_point t1 = Clock::now();
if (runs == 0)
{

View File

@@ -1,51 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/condition_variable.hpp>
// void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
#define BOOST_THREAD_USES_MOVE
#define BOOST_THREAD_VESRION 3
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread.hpp>
#include <boost/chrono/chrono.hpp>
#include <boost/detail/lightweight_test.hpp>
boost::condition_variable cv;
boost::mutex mut;
typedef boost::chrono::milliseconds ms;
typedef boost::chrono::high_resolution_clock Clock;
void func()
{
boost::unique_lock < boost::mutex > lk(mut);
boost::notify_all_at_thread_exit(cv, boost::move(lk));
boost::this_thread::sleep_for(ms(300));
}
int main()
{
boost::unique_lock < boost::mutex > lk(mut);
boost::thread(func).detach();
Clock::time_point t0 = Clock::now();
cv.wait(lk);
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 > ms(250));
return boost::report_errors();
}

View File

@@ -22,52 +22,14 @@
// future<typename result_of<F(Args...)>::type>
// async(launch policy, F&& f, Args&&... args);
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/thread/thread.hpp>
#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
#include <memory>
#include <boost/detail/lightweight_test.hpp>
typedef boost::chrono::high_resolution_clock Clock;
typedef boost::chrono::milliseconds ms;
class A
{
long data_;
public:
typedef int result_type;
explicit A(long i) : data_(i) {}
long operator()() const
{
boost::this_thread::sleep_for(ms(200));
return data_;
}
};
class MoveOnly
{
public:
typedef int result_type;
BOOST_THREAD_MOVABLE_ONLY(MoveOnly)
MoveOnly()
{
}
MoveOnly(BOOST_THREAD_RV_REF(MoveOnly))
{}
int operator()()
{
boost::this_thread::sleep_for(ms(200));
return 3;
}
};
int f0()
{
boost::this_thread::sleep_for(ms(200));
@@ -87,21 +49,18 @@ void f2()
boost::this_thread::sleep_for(ms(200));
}
boost::interprocess::unique_ptr<int, boost::default_delete<int> > f3(int i)
boost::unique_ptr<int> f3(int i)
{
boost::this_thread::sleep_for(ms(200));
return boost::interprocess::unique_ptr<int, boost::default_delete<int> >(new int(i));
return boost::unique_ptr<int>(new int(i));
}
typedef boost::interprocess::unique_ptr<int, boost::default_delete<int> > XXT;
boost::interprocess::unique_ptr<int, boost::default_delete<int> > f4(
BOOST_THREAD_RV_REF(boost::interprocess::unique_ptr<int, boost::default_delete<int> > ) p)
boost::unique_ptr<int> f4(boost::unique_ptr<int>&& p)
{
boost::this_thread::sleep_for(ms(200));
return boost::move(p);
}
int main()
{
{
@@ -120,22 +79,6 @@ int main()
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 < ms(100));
}
{
boost::future<int> f = boost::async(boost::launch::async, A(3));
boost::this_thread::sleep_for(ms(300));
Clock::time_point t0 = Clock::now();
BOOST_TEST(f.get() == 3);
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 < ms(100));
}
{
boost::future<int> f = boost::async(boost::launch::async, BOOST_THREAD_MAKE_RV_REF(MoveOnly()));
boost::this_thread::sleep_for(ms(300));
Clock::time_point t0 = Clock::now();
BOOST_TEST(f.get() == 3);
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 < ms(100));
}
{
boost::future<int> f = boost::async(boost::launch::any, f0);
boost::this_thread::sleep_for(ms(300));
@@ -144,15 +87,15 @@ int main()
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 < ms(100));
}
// {
// boost::future<int> f = boost::async(boost::launch::deferred, f0);
// boost::this_thread::sleep_for(ms(300));
// Clock::time_point t0 = Clock::now();
// BOOST_TEST(f.get() == 3);
// Clock::time_point t1 = Clock::now();
// BOOST_TEST(t1 - t0 > ms(100));
// }
//
{
boost::future<int> f = boost::async(boost::launch::deferred, f0);
boost::this_thread::sleep_for(ms(300));
Clock::time_point t0 = Clock::now();
BOOST_TEST(f.get() == 3);
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 > ms(100));
}
{
boost::future<int&> f = boost::async(f1);
boost::this_thread::sleep_for(ms(300));
@@ -177,15 +120,15 @@ int main()
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 < ms(100));
}
// {
// boost::future<int&> f = boost::async(boost::launch::deferred, f1);
// boost::this_thread::sleep_for(ms(300));
// Clock::time_point t0 = Clock::now();
// BOOST_TEST(&f.get() == &i);
// Clock::time_point t1 = Clock::now();
// BOOST_TEST(t1 - t0 > ms(100));
// }
//
{
boost::future<int&> f = boost::async(boost::launch::deferred, f1);
boost::this_thread::sleep_for(ms(300));
Clock::time_point t0 = Clock::now();
BOOST_TEST(&f.get() == &i);
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 > ms(100));
}
{
boost::future<void> f = boost::async(f2);
boost::this_thread::sleep_for(ms(300));
@@ -210,32 +153,32 @@ int main()
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 < ms(100));
}
// {
// boost::future<void> f = boost::async(boost::launch::deferred, f2);
// boost::this_thread::sleep_for(ms(300));
// Clock::time_point t0 = Clock::now();
// f.get();
// Clock::time_point t1 = Clock::now();
// BOOST_TEST(t1 - t0 > ms(100));
// }
{
boost::future<void> f = boost::async(boost::launch::deferred, f2);
boost::this_thread::sleep_for(ms(300));
Clock::time_point t0 = Clock::now();
f.get();
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 > ms(100));
}
// {
// boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(f3, 3);
// boost::this_thread::sleep_for(ms(300));
// Clock::time_point t0 = Clock::now();
// BOOST_TEST(*f.get() == 3);
// Clock::time_point t1 = Clock::now();
// BOOST_TEST(t1 - t0 < ms(100));
// }
{
boost::future<boost::unique_ptr<int>> f = boost::async(f3, 3);
boost::this_thread::sleep_for(ms(300));
Clock::time_point t0 = Clock::now();
BOOST_TEST(*f.get() == 3);
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 < ms(100));
}
// {
// boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(f4, boost::interprocess::unique_ptr<int, boost::default_delete<int> >(new int(3)));
// boost::this_thread::sleep_for(ms(300));
// Clock::time_point t0 = Clock::now();
// BOOST_TEST(*f.get() == 3);
// Clock::time_point t1 = Clock::now();
// BOOST_TEST(t1 - t0 < ms(100));
// }
{
boost::future<boost::unique_ptr<int>> f = boost::async(f4, boost::unique_ptr<int>(new int(3)));
boost::this_thread::sleep_for(ms(300));
Clock::time_point t0 = Clock::now();
BOOST_TEST(*f.get() == 3);
Clock::time_point t1 = Clock::now();
BOOST_TEST(t1 - t0 < ms(100));
}
return boost::report_errors();
}

View File

@@ -1,40 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/future.hpp>
// class future<R>
// future& operator=(const future&) = delete;
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
int main()
{
{
typedef int T;
boost::promise<T> p;
boost::future<T> f0 = p.get_future();
boost::future<T> f;
f = f0;
}
return boost::report_errors();
}
#include "../../../remove_error_code_unused_warning.hpp"

View File

@@ -1,38 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/future.hpp>
// class future<R>
// future(const future&) = delete;
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
int main()
{
{
typedef int T;
boost::promise<T> p;
boost::future<T> f0 = p.get_future();
boost::future<T> f = f0;
}
return boost::report_errors();
}
#include "../../../remove_error_code_unused_warning.hpp"

View File

@@ -1,109 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/future.hpp>
// class promise<R>
// ~promise();
#define BOOST_THREAD_VERSION 3
#include <boost/exception/exception.hpp>
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include "../test_allocator.hpp"
#endif
int main()
{
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
BOOST_TEST(test_alloc_base::count == 0);
{
typedef int T;
boost::future<T> f;
{
boost::promise<T> p(boost::allocator_arg, test_allocator<T>());
BOOST_TEST(test_alloc_base::count == 1);
f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
BOOST_TEST(test_alloc_base::count == 1);
BOOST_TEST(f.valid());
}
BOOST_TEST(test_alloc_base::count == 1);
BOOST_TEST(f.valid());
}
BOOST_TEST(test_alloc_base::count == 0);
{
typedef int& T;
boost::future<T> f;
{
boost::promise<T> p(boost::allocator_arg, test_allocator<int>());
BOOST_TEST(test_alloc_base::count == 1);
f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
BOOST_TEST(test_alloc_base::count == 1);
BOOST_TEST(f.valid());
}
BOOST_TEST(test_alloc_base::count == 1);
BOOST_TEST(f.valid());
}
BOOST_TEST(test_alloc_base::count == 0);
{
typedef void T;
boost::future<T> f;
{
boost::promise<T> p(boost::allocator_arg, test_allocator<T>());
BOOST_TEST(test_alloc_base::count == 1);
f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
BOOST_TEST(test_alloc_base::count == 1);
BOOST_TEST(f.valid());
}
BOOST_TEST(test_alloc_base::count == 1);
BOOST_TEST(f.valid());
}
BOOST_TEST(test_alloc_base::count == 0);
#endif
{
typedef int T;
boost::future<T> f;
{
boost::promise<T> p;
f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
BOOST_TEST(f.valid());
}
BOOST_TEST(f.valid());
}
{
typedef int& T;
boost::future<T> f;
{
boost::promise<T> p;
f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
BOOST_TEST(f.valid());
}
BOOST_TEST(f.valid());
}
{
typedef void T;
boost::future<T> f;
{
boost::promise<T> p;
f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
BOOST_TEST(f.valid());
}
BOOST_TEST(f.valid());
}
return boost::report_errors();
}

View File

@@ -1,171 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/future.hpp>
// class promise<R>
// future<R> get_future();
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/thread/thread.hpp>
#include <boost/detail/lightweight_test.hpp>
namespace boost
{
template <typename T>
struct wrap
{
wrap(T const& v) : value(v){}
T value;
};
template <typename T>
exception_ptr make_exception_ptr(T v) {
return copy_exception(wrap<T>(v));
}
}
void func1(boost::promise<int> p)
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
p.set_value(3);
}
void func2(boost::promise<int> p)
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
p.set_exception(boost::make_exception_ptr(3));
}
int j = 0;
void func3(boost::promise<int&> p)
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
j = 5;
p.set_value(j);
}
void func4(boost::promise<int&> p)
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
p.set_exception(boost::make_exception_ptr(3.5));
}
void func5(boost::promise<void> p)
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
p.set_value();
}
void func6(boost::promise<void> p)
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
p.set_exception(boost::make_exception_ptr('c'));
}
int main()
{
{
typedef int T;
{
boost::promise<T> p;
boost::future<T> f = p.get_future();
boost::thread(func1, boost::move(p)).detach();
BOOST_TEST(f.valid());
BOOST_TEST(f.get() == 3);
BOOST_TEST(!f.valid());
}
{
boost::promise<T> p;
boost::future<T> f = p.get_future();
boost::thread(func2, boost::move(p)).detach();
try
{
BOOST_TEST(f.valid());
BOOST_TEST(f.get() == 3);
BOOST_TEST(false);
}
catch (int i)
{
BOOST_TEST(i == 3);
}
BOOST_TEST(!f.valid());
}
}
// {
// typedef int& T;
// {
// boost::promise<T> p;
// boost::future<T> f = p.get_future();
// boost::thread(func3, boost::move(p)).detach();
// BOOST_TEST(f.valid());
// BOOST_TEST(f.get() == 5);
// BOOST_TEST(!f.valid());
// }
// {
// boost::promise<T> p;
// boost::future<T> f = p.get_future();
// boost::thread(func4, boost::move(p)).detach();
// try
// {
// BOOST_TEST(f.valid());
// BOOST_TEST(f.get() == 3);
// BOOST_TEST(false);
// }
// catch (double i)
// {
// BOOST_TEST(i == 3.5);
// }
// BOOST_TEST(!f.valid());
// }
// }
// {
// typedef void T;
// {
// boost::promise<T> p;
// boost::future<T> f = p.get_future();
// boost::thread(func5, boost::move(p)).detach();
// BOOST_TEST(f.valid());
// f.get();
// BOOST_TEST(!f.valid());
// }
// {
// boost::promise<T> p;
// boost::future<T> f = p.get_future();
// boost::thread(func6, boost::move(p)).detach();
// try
// {
// BOOST_TEST(f.valid());
// f.get();
// BOOST_TEST(false);
// }
// catch (char i)
// {
// BOOST_TEST(i == 'c');
// }
// BOOST_TEST(!f.valid());
// }
// }
return boost::report_errors();
}

View File

@@ -1,87 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <future>
// class promise<R>
// promise& operator=(promise&& rhs);
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
boost::mutex m0;
boost::mutex m1;
int main()
{
{
typedef int T;
boost::promise<T> p;
boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future());
boost::future<T> f;
f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(f.valid());
}
{
typedef int T;
boost::future<T> f0;
boost::future<T> f;
f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(!f.valid());
}
{
typedef int& T;
boost::promise<T> p;
boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future());
boost::future<T> f;
f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(f.valid());
}
{
typedef int& T;
boost::future<T> f0;
boost::future<T> f;
f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(!f.valid());
}
{
typedef void T;
boost::promise<T> p;
boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future());
boost::future<T> f;
f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(f.valid());
}
{
typedef void T;
boost::future<T> f0;
boost::future<T> f;
f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(!f.valid());
}
return boost::report_errors();
}

View File

@@ -1,78 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <future>
// class promise<R>
// promise(promise&& rhs);
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
boost::mutex m;
int main()
{
{
typedef int T;
boost::promise<T> p;
boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future());
boost::future<T> f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(f.valid());
}
{
typedef int T;
boost::future<T> f0;
boost::future<T> f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(!f.valid());
}
{
typedef int& T;
boost::promise<T> p;
boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future());
boost::future<T> f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(f.valid());
}
{
typedef int& T;
boost::future<T> f0;
boost::future<T> f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(!f.valid());
}
{
typedef void T;
boost::promise<T> p;
boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future());
boost::future<T> f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(f.valid());
}
{
typedef void T;
boost::future<T> f0;
boost::future<T> f = boost::move(f0);
BOOST_TEST(!f0.valid());
BOOST_TEST(!f.valid());
}
return boost::report_errors();
}

View File

@@ -1,84 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/future.hpp>
// class future<R>
// shared_future<R> share() &&;
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
int main()
{
{
typedef int T;
boost::promise<T> p;
boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future());
boost::shared_future<T> sf = f0.share();
boost::shared_future<T> f = sf;
BOOST_TEST(!f0.valid());
BOOST_TEST(f.valid());
}
{
typedef int T;
boost::future<T> f0;
boost::shared_future<T> sf = f0.share();
boost::shared_future<T> f = sf;
BOOST_TEST(!f0.valid());
BOOST_TEST(!f.valid());
}
{
typedef int& T;
boost::promise<T> p;
boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future());
boost::shared_future<T> sf = f0.share();
boost::shared_future<T> f = sf;
BOOST_TEST(!f0.valid());
BOOST_TEST(f.valid());
}
{
typedef int& T;
boost::future<T> f0;
boost::shared_future<T> sf = f0.share();
boost::shared_future<T> f = sf;
BOOST_TEST(!f0.valid());
BOOST_TEST(!f.valid());
}
{
typedef void T;
boost::promise<T> p;
boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future());
boost::shared_future<T> sf = f0.share();
boost::shared_future<T> f = sf;
BOOST_TEST(!f0.valid());
BOOST_TEST(f.valid());
}
{
typedef void T;
boost::future<T> f0;
boost::shared_future<T> sf = f0.share();
boost::shared_future<T> f = sf;
BOOST_TEST(!f0.valid());
BOOST_TEST(!f.valid());
}
return boost::report_errors();
}

View File

@@ -1,160 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/future.hpp>
// class packaged_task<R>
// template <class F, class Allocator>
// explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include "../test_allocator.hpp"
double fct()
{
return 5.0;
}
long lfct()
{
return 5;
}
class A
{
long data_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(A)
static int n_moves;
static int n_copies;
static int n_instances;
static int n_destroy;
explicit A(long i) : data_(i)
{
++n_instances;
}
A(BOOST_THREAD_RV_REF(A) a) : data_(BOOST_THREAD_RV(a).data_)
{
++n_instances;
++n_moves; BOOST_THREAD_RV(a).data_ = -1;
}
A(const A& a) : data_(a.data_)
{
++n_instances;
++n_copies;
}
~A()
{
--n_instances;
++n_destroy;
}
long operator()() const
{ return data_;}
long operator()(long i, long j) const
{ return data_ + i + j;}
};
int A::n_moves = 0;
int A::n_copies = 0;
int A::n_instances = 0;
int A::n_destroy = 0;
int main()
{
{
boost::packaged_task<double> p(boost::allocator_arg,
test_allocator<A>(), BOOST_THREAD_MAKE_RV_REF(A(5)));
BOOST_TEST(test_alloc_base::count > 0);
BOOST_TEST(p.valid());
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
//p(3, 'a');
p();
BOOST_TEST(f.get() == 5.0);
}
BOOST_TEST(A::n_copies == 0);
BOOST_TEST(A::n_moves > 0);
BOOST_TEST(A::n_instances == 0);
BOOST_TEST(A::n_destroy > 0);
BOOST_TEST(test_alloc_base::count == 0);
A::n_copies = 0;
A::n_copies = 0;
{
A a(5);
boost::packaged_task<double> p(boost::allocator_arg,
test_allocator<A>(), a);
BOOST_TEST(test_alloc_base::count > 0);
BOOST_TEST(p.valid());
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
//p(3, 'a');
p();
BOOST_TEST(f.get() == 5.0);
}
BOOST_TEST(A::n_copies > 0);
BOOST_TEST(A::n_moves > 0);
BOOST_TEST(test_alloc_base::count == 0);
A::n_copies = 0;
A::n_copies = 0;
{
const A a(5);
boost::packaged_task<double> p(boost::allocator_arg,
test_allocator<A>(), a);
BOOST_TEST(test_alloc_base::count > 0);
BOOST_TEST(p.valid());
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
//p(3, 'a');
p();
BOOST_TEST(f.get() == 5.0);
}
BOOST_TEST(A::n_copies > 0);
BOOST_TEST(A::n_moves > 0);
BOOST_TEST(test_alloc_base::count == 0);
{
boost::packaged_task<double> p(boost::allocator_arg,
test_allocator<A>(), fct);
BOOST_TEST(test_alloc_base::count > 0);
BOOST_TEST(p.valid());
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
//p(3, 'a');
p();
BOOST_TEST(f.get() == 5.0);
}
{
boost::packaged_task<double> p(boost::allocator_arg,
test_allocator<A>(), &lfct);
BOOST_TEST(test_alloc_base::count > 0);
BOOST_TEST(p.valid());
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
//p(3, 'a');
p();
BOOST_TEST(f.get() == 5.0);
}
return boost::report_errors();
}
#else
int main()
{
return boost::report_errors();
}
#endif

View File

@@ -1,49 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/future.hpp>
// class packaged_task<R>
// packaged_task& operator=(packaged_task&) = delete;
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
class A
{
long data_;
public:
explicit A(long i) : data_(i) {}
long operator()() const {return data_;}
long operator()(long i, long j) const {return data_ + i + j;}
};
int main()
{
{
boost::packaged_task<double> p0(A(5));
boost::packaged_task<double> p;
p = p0;
}
return boost::report_errors();
}
#include "../../../remove_error_code_unused_warning.hpp"

View File

@@ -1,49 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/future.hpp>
// class packaged_task<R>
// packaged_task(packaged_task&) = delete;
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
class A
{
long data_;
public:
explicit A(long i) : data_(i) {}
long operator()() const {return data_;}
long operator()(long i, long j) const {return data_ + i + j;}
};
int main()
{
{
boost::packaged_task<double> p0(A(5));
boost::packaged_task<double> p(p0);
}
return boost::report_errors();
}
#include "../../../remove_error_code_unused_warning.hpp"

View File

@@ -1,36 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/future.hpp>
// class packaged_task<R>
// packaged_task();
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
int main()
{
{
boost::packaged_task<int> p;
BOOST_TEST(!p.valid());
}
return boost::report_errors();
}

View File

@@ -1,75 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/future.hpp>
// class packaged_task<R>
// ~packaged_task();
;
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/thread/thread.hpp>
#include <boost/detail/lightweight_test.hpp>
class A
{
long data_;
public:
explicit A(long i) : data_(i) {}
long operator()() const {return data_;}
long operator()(long i, long j) const {return data_ + i + j;}
};
void func(boost::packaged_task<double> p)
{
}
void func2(boost::packaged_task<double> p)
{
//p(3, 'a');
p();
}
int main()
{
{
boost::packaged_task<double> p(A(5));
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
boost::thread(func, boost::move(p)).detach();
try
{
double i = f.get();
BOOST_TEST(false);
}
catch (const boost::future_error& e)
{
BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::broken_promise));
}
}
{
boost::packaged_task<double> p(A(5));
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
boost::thread(func2, boost::move(p)).detach();
BOOST_TEST(f.get() == 5.0);
}
return boost::report_errors();
}

View File

@@ -1,127 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Copyright (C) 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)
// <boost/thread/future.hpp>
// class packaged_task<R>
// template <class F>
// explicit packaged_task(F&& f);
#define BOOST_THREAD_VERSION 3
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
double fct()
{
return 5.0;
}
long lfct()
{
return 5;
}
class A
{
long data_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(A)
static int n_moves;
static int n_copies;
explicit A(long i) : data_(i)
{
}
A(BOOST_THREAD_RV_REF(A) a) : data_(BOOST_THREAD_RV(a).data_)
{
++n_moves; BOOST_THREAD_RV(a).data_ = -1;
}
A(const A& a) : data_(a.data_)
{
++n_copies;
}
~A()
{
}
long operator()() const
{ return data_;}
long operator()(long i, long j) const
{ return data_ + i + j;}
};
int A::n_moves = 0;
int A::n_copies = 0;
int main()
{
{
boost::packaged_task<double> p(BOOST_THREAD_MAKE_RV_REF(A(5)));
BOOST_TEST(p.valid());
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
//p(3, 'a');
p();
BOOST_TEST(f.get() == 5.0);
BOOST_TEST(A::n_copies == 0);
BOOST_TEST(A::n_moves > 0);
}
A::n_copies = 0;
A::n_copies = 0;
{
A a(5);
boost::packaged_task<double> p(a);
BOOST_TEST(p.valid());
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
//p(3, 'a');
p();
BOOST_TEST(f.get() == 5.0);
BOOST_TEST(A::n_copies > 0);
BOOST_TEST(A::n_moves > 0);
}
A::n_copies = 0;
A::n_copies = 0;
{
const A a(5);
boost::packaged_task<double> p(a);
BOOST_TEST(p.valid());
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
//p(3, 'a');
p();
BOOST_TEST(f.get() == 5.0);
BOOST_TEST(A::n_copies > 0);
BOOST_TEST(A::n_moves > 0);
}
{
boost::packaged_task<double> p(fct);
BOOST_TEST(p.valid());
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
//p(3, 'a');
p();
BOOST_TEST(f.get() == 5.0);
}
{
boost::packaged_task<double> p(&lfct);
BOOST_TEST(p.valid());
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
//p(3, 'a');
p();
BOOST_TEST(f.get() == 5.0);
}
return boost::report_errors();
}

Some files were not shown because too many files have changed in this diff Show More