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

Compare commits

..

11 Commits

Author SHA1 Message Date
Marshall Clow
7648e33c18 Release 1.52.0
[SVN r81201]
2012-11-05 15:31:58 +00:00
Vicente J. Botet Escriba
0ae81b8d4c Thread: merge [81032][81034]
[SVN r81035]
2012-10-21 11:56:52 +00:00
Vicente J. Botet Escriba
05f02e1476 Thread: merge 80986
[SVN r81024]
2012-10-20 15:19:13 +00:00
Vicente J. Botet Escriba
23ea174056 Thread: update doc fixes
[SVN r80999]
2012-10-16 17:48:12 +00:00
Vicente J. Botet Escriba
ce19b13c43 Thread: merged 80966
[SVN r80985]
2012-10-14 15:26:00 +00:00
Vicente J. Botet Escriba
8262d61ff5 Thread: Merge 80757
[SVN r80955]
2012-10-11 15:56:21 +00:00
Vicente J. Botet Escriba
4d013af927 Thread: merge from trunk
[SVN r80801]
2012-10-01 00:24:05 +00:00
Vicente J. Botet Escriba
2d8852199b Thread: Merge from trunk
[SVN r80668]
2012-09-23 12:38:00 +00:00
Vicente J. Botet Escriba
12a1c7c71c Thread: merge from trunk
[SVN r80516]
2012-09-13 18:57:04 +00:00
Vicente J. Botet Escriba
89e944914b Thread: Merged from trunk : 1.52
[SVN r80476]
2012-09-09 19:39:44 +00:00
Vicente J. Botet Escriba
7bc8c437ab Thread: merge from trunk: 1.52
[SVN r80450]
2012-09-08 14:59:26 +00:00
122 changed files with 2473 additions and 1065 deletions

View File

@@ -47,6 +47,7 @@ project boost/thread
-<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
@@ -98,6 +99,7 @@ project boost/thread
#<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
;
@@ -236,10 +238,7 @@ rule requirements ( properties * )
}
}
}
if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties)
{
result += <library>/boost/chrono//boost_chrono ;
}
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
return $(result) ;
}

View File

@@ -8,8 +8,61 @@
[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.
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.
@@ -38,6 +91,10 @@ Fixed Bugs:
* [@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]
@@ -218,7 +275,7 @@ The following features will be included in next releases.
# Complete the C++11 missing features, in particular
* [@http://svn.boost.org/trac/boost/ticket/4710 #4710] Missing async().
* 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.

View File

@@ -26,11 +26,11 @@
[[30.2.5.4] [TimedLockable requirements] [Yes] [-] [-]]
[[30.2.6] [decay_copy] [-] [-] [-]]
[[30.3] [Threads] [Partial] [-] [-]]
[[30.3.1] [Class thread] [Partial] [move,variadic,terminate] [#zzzz,#6270,#6269]]
[[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] [#zzzz,#6270]]
[[30.3.1.3] [thread destructor] [Partial] [terminate] [#6266]]
[[30.3.1.4] [thread assignment] [Partial] [terminate] [#6269]]
[[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.7] [thread specialized algorithms] [Yes] [-] [-]]
@@ -53,23 +53,23 @@
[[30.4.2.2.3] [unique_lock modifiers] [Yes] [-] [-]]
[[30.4.2.2.4] [unique_lock observers] [Yes] [] [-]]
[[30.4.3] [Generic locking algorithms] [Partial] [variadic] [#6227]]
[[30.4.4] [Call once] [Partial] [The interface doesn't corresponds] [#6342]]
[[30.4.4.1] [Struct once_flag] [Partial] [interface] [#6342]]
[[30.4.4.2] [Function call_once] [Partial] [interface] [#6342]]
[[30.5] [Condition variables] [Partial] [notify_all_at_thread_exit] [#xxxx]]
[[30.5 6-10] [Function notify_all_at_thread_exit] [No] [-] [#xxxx]]
[[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] [-] [-]]
[[30.6] [Futures] [Partial] [async,at_thread_exit] [#4710,#7280]]
[[30.6.1] [Overview] [Partial] [-] [-]]
[[30.6.2] [Error handling] [Yes] [-] [-]]
[[30.6.3] [Class future_error] [Yes] [-] [-]]
[[30.6.3] [Class future_error] [Partial] [noexcept] [#7279]]
[[30.6.4] [Shared state] [-] [-] [-]]
[[30.6.5] [Class template promise] [Partial] [allocator] [#6228]]
[[30.6.6] [Class template future] [Partial] [allocator,unique_future is the closest to future, renamed in V3] [#6228]]
[[30.6.7] [Class template shared_future] [Partial] [allocator] [#6228]]
[[30.6.8] [Function template async] [No] [async] [#4710]]
[[30.6.9] [Class template packaged_task] [Partial] [move] [#yyyy]]
[[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]]
]
[/

View File

@@ -19,6 +19,7 @@
};
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
@@ -86,7 +87,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
{
@@ -439,7 +440,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
{
@@ -751,14 +752,53 @@ return true;
[endsect]
[section:condition Typedef `condition`]
[section:condition Typedef `condition` DEPRECATED V3]
#include <boost/thread/condition.hpp>
// #include <boost/thread/condition.hpp>
namespace boost
{
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

@@ -8,20 +8,14 @@
[section:configuration Configuration]
[section:system Boost.System]
Boost.Thread uses by default Boost.System to define the exceptions. For backward compatibility and also for compilers that don't work well with Boost.System the user can define `BOOST_THREAD_DONT_USE_SYSTEM `.
`BOOST_THREAD_USES_SYSTEM` is defined when Boost.Thread uses Boost.Move.
[endsect]
[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`. If `BOOST_THREAD_DONT_USE_SYSTEM` is defined then `BOOST_THREAD_DONT_USE_CHRONO` is defined implicitly.
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]
@@ -29,7 +23,7 @@ Boost.Thread uses by default Boost.Chrono for the time related functions. For ba
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 want to use boost::unique_future.
When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_DONT_USE_MOVE ` if you don't want to use Boost.Move interface.
[endsect]
@@ -44,7 +38,7 @@ When `BOOST_THREAD_VERSION==3` define `BOOST_THREAD_DONT_PROVIDE_GENERIC_SHARED_
[section:shared_upwards Shared Locking Upwards Conversion]
Boost.Threads includes in version 2 the Shared Locking Upwards Conversion as defined in [@http://home.roadrunner.com/~hinnant/bloomington/shared_mutex.html Shared Locking].
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.
@@ -201,13 +195,16 @@ Some compilers don't work correctly with some of the added features.
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__ is defined the library defines
If __IBMCPP__ < 1100 the library defines
* `BOOST_THREAD_DONT_USE_CHRONO`

View File

@@ -5,16 +5,17 @@
http://www.boost.org/LICENSE_1_0.txt).
]
[section:reference Futures Reference]
//#include <boost/thread/futures.hpp>
namespace boost
namespace boost
{
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
namespace future_state
{
enum state {uninitialized, waiting, ready, moved};
enum state {uninitialized, waiting, ready, moved};
}
#endif
@@ -26,6 +27,17 @@
no_state
};
enum class launch
{
async = unspecified,
deferred = unspecified,
any = async | deferred
};
enum class future_status {
ready, timeout, deferred
};
namespace system
{
template <>
@@ -47,7 +59,7 @@
void swap(promise<R>& x, promise<R>& y) noexcept;
namespace container {
template <class R, class Alloc>
template <class R, class Alloc>
struct uses_allocator<promise<R>, Alloc>:: true_type;
}
@@ -61,14 +73,21 @@
class packaged_task;
template <class R> void swap(packaged_task<R>&, packaged_task<R>&) noexcept;
//template <class R, class Alloc>
//struct uses_allocator<packaged_task <R>, Alloc>; // NOT YET IMPLEMENTED
template <class R, class Alloc>
struct uses_allocator<packaged_task <R>, Alloc>;
// template <class F, class... Args>
// future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
template <class F>
future<typename result_of<typename decay<F>::type()>::type>
async(F f);
template <class F>
future<typename result_of<typename decay<F>::type()>::type>
async(launch policy, F f);
// template <class F, class... Args>
// future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
// async(F&& f, Args&&... args); // NOT YET IMPLEMENTED
// template <class F, class... Args>
// future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
// template <class F, class... Args>
// future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
// async(launch policy, F&& f, Args&&... args); // NOT YET IMPLEMENTED
@@ -89,7 +108,7 @@
namespace future_state
{
enum state {uninitialized, waiting, ready, moved};
enum state {uninitialized, waiting, ready, moved};
}
@@ -106,6 +125,18 @@
no_state
}
[endsect]
[section:launch Enumeration `launch `]
enum class launch
{
async = unspecified,
deferred = unspecified,
any = async | deferred
};
The enum type launch is a bitmask type with launch::async and launch::deferred denoting individual bits.
[endsect]
[section:is_error_code_enum Specialization `is_error_code_enum<future_errc>`]
@@ -124,6 +155,12 @@
error_code make_error_code(future_errc e);
}
[variablelist
[[Returns:] [`error_code(static_cast<int>(e), future_category())`.]]
]
[endsect]
[section:make_error_condition Non-member function `make_error_condition()`]
@@ -132,11 +169,26 @@
error_condition make_error_condition(future_errc e);
}
[variablelist
[[Returns:] [`error_condition(static_cast<int>(e), future_category())`.]]
]
[endsect]
[section:future_category Non-member function `future_category()`]
const system::error_category& future_category();
[variablelist
[[Returns:] [A reference to an object of a type derived from class error_category.]]
[[Notes:] [The object's `default_error_condition` and equivalent virtual functions behave as specified for the class `system::error_category`.
The object's `name` virtual function returns a pointer to the string "future".]]
]
[endsect]
[section:future_error Class `future_error`]
@@ -149,70 +201,98 @@
const system::error_code& code() const no_except;
};
[section:constructor Constructor]
future_error(system::error_code ec);
[variablelist
[[Effects:] [Constructs a future_error.]]
[[Postconditions:] [`code()==ec` ]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:code Member function `code()`]
const system::error_code& code() const no_except;
[variablelist
[[Returns:] [The value of `ec` that was passed to the object's constructor.]]
]
[endsect]
[endsect]
[section:future_status Enumeration `future_status`]
enum class future_status {
enum class future_status {
ready, timeout, deferred
};
[endsect]
[section:unique_future `unique_future` class template]
[section:unique_future __unique_future class template]
template <typename R>
class unique_future
class __unique_future__
{
public:
unique_future(unique_future & rhs);// = delete;
unique_future& operator=(unique_future& rhs);// = delete;
__unique_future__(__unique_future__ & rhs);// = delete;
__unique_future__& operator=(__unique_future__& rhs);// = delete;
unique_future() noexcept;
~unique_future();
__unique_future__() noexcept;
~__unique_future__();
// move support
unique_future(unique_future && other) noexcept;
unique_future& operator=(unique_future && other) noexcept;
shared_future<R> share();
// move support
__unique_future__(__unique_future__ && other) noexcept;
__unique_future__& operator=(__unique_future__ && other) noexcept;
shared_future<R> share();
void swap(unique_future& other) noexcept; // EXTENSION
void swap(__unique_future__& other) noexcept; // EXTENSION
// retrieving the value
R&& get();
// retrieving the value
R&& get();
// functions to check state
bool valid() const;
bool is_ready() const; // EXTENSION
bool has_exception() const; // EXTENSION
bool has_value() const; // EXTENSION
// functions to check state
bool valid() const;
bool is_ready() const; // EXTENSION
bool has_exception() const; // EXTENSION
bool has_value() const; // EXTENSION
// waiting for the result to be ready
void wait() const;
template <class Rep, class Period>
future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
template <class Clock, class Duration>
future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
// waiting for the result to be ready
void wait() const;
template <class Rep, class Period>
future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
template <class Clock, class Duration>
future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
template<typename Duration>
bool timed_wait(Duration const& rel_time) const;
bool timed_wait_until(boost::system_time const& abs_time) const;
template<typename Duration>
bool timed_wait(Duration const& rel_time) const;
bool timed_wait_until(boost::system_time const& abs_time) const;
#endif
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
typedef future_state::state state;
state get_state() const;
typedef future_state::state state;
state get_state() const;
#endif
};
[section:default_constructor Default Constructor]
unique_future();
__unique_future__();
[variablelist
[[Effects:] [Constructs an uninitialized future.]]
[[Effects:] [Constructs an uninitialized __unique_future__.]]
[[Postconditions:] [[unique_future_is_ready_link `this->is_ready`] returns `false`. [unique_future_get_state_link
`this->get_state()`] returns __uninitialized__.]]
@@ -225,7 +305,7 @@
[section:destructor Destructor]
~unique_future();
~__unique_future__();
[variablelist
@@ -239,11 +319,11 @@
[section:move_constructor Move Constructor]
unique_future(unique_future && other);
__unique_future__(__unique_future__ && other);
[variablelist
[[Effects:] [Constructs a new future, and transfers ownership of the asynchronous result associated with `other` to `*this`.]]
[[Effects:] [Constructs a new __unique_future__, and transfers ownership of the asynchronous result associated with `other` to `*this`.]]
[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
call. `other->get_state()` returns __uninitialized__. If `other` was associated with an asynchronous result, that result is now
@@ -259,7 +339,7 @@ associated with `*this`. `other` is not associated with any asynchronous result.
[section:move_assignment Move Assignment Operator]
unique_future& operator=(unique_future && other);
__unique_future__& operator=(__unique_future__ && other);
[variablelist
@@ -280,7 +360,7 @@ result prior to the call, that result no longer has an associated __unique_futur
[section:swap Member function `swap()`]
void swap(unique_future & other) no_except;
void swap(__unique_future__ & other) no_except;
[variablelist
@@ -301,8 +381,8 @@ associated with an asynchronous result, that result is now associated with `othe
[section:get Member function `get()`]
R&& get();
R& unique_future<R&>::get();
void unique_future<void>::get();
R& __unique_future__<R&>::get();
void __unique_future__<void>::get();
[variablelist
@@ -400,16 +480,96 @@ associated with `*this` is not ready at the point of the call, and the current t
[endsect]
[section:wait_for Member function `wait_for()`]
[section:is_ready Member function `is_ready()` EXTENSION]
bool is_ready();
template <class Rep, class Period>
future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
[variablelist
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set.]]
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time specified by
`wait_duration` has elapsed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is
invoked prior to waiting.]]
[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready for retrieval, `false`
[[Returns:] [
- `future_status::deferred` if the shared state contains a deferred function. (Not implemented yet)
- `future_status::ready` if the shared state is ready.
- `future_status::timeout` if the function is returning because the relative timeout specified by `rel_time` has expired.
]]
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
['wait callback] if such a callback is called.]]
[[Postconditions:] [If this call returned `true`, then [unique_future_is_ready_link `this->is_ready()`] returns `true` and
[unique_future_get_state_link `this->get_state()`] returns __ready__.]]
[[Notes:] [`wait_for()` is an ['interruption point]. `Duration` must be a type that meets the Boost.DateTime time duration requirements.]]
]
[endsect]
[section:wait_until Member function `wait_until()`]
template <class Clock, class Duration>
future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
[variablelist
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time point specified by
`wait_timeout` has passed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is invoked
prior to waiting.]]
[[Returns:] [
- `future_status::deferred` if the shared state contains a deferred function. (Not implemented yet)
- `future_status::ready` if the shared state is ready.
- `future_status::timeout` if the function is returning because the absolute timeout specified by `absl_time` has reached.
]]
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
['wait callback] if such a callback is called.]]
[[Postconditions:] [If this call returned `true`, then [unique_future_is_ready_link `this->is_ready()`] returns `true` and
[unique_future_get_state_link `this->get_state()`] returns __ready__.]]
[[Notes:] [`wait_until()` is an ['interruption point].]]
]
[endsect]
[section:valid Member function `valid()`]
bool valid() const;
[variablelist
[[Returns:] [`true` if `*this` is associated with an asynchronous result, `false`
otherwise.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:is_ready Member function `is_ready()` EXTENSION]
bool is_ready() const;
[variablelist
[[Returns:] [`true` if `*this` is associated with an asynchronous result and that result is ready for retrieval, `false`
otherwise.]]
[[Throws:] [Nothing.]]
@@ -420,12 +580,10 @@ otherwise.]]
[section:has_value Member function `has_value()` EXTENSION]
bool has_value();
bool has_value() const;
[variablelist
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with a value rather than an exception.]]
[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
stored value, `false` otherwise.]]
@@ -437,12 +595,10 @@ stored value, `false` otherwise.]]
[section:has_exception Member function `has_exception()` EXTENSION]
bool has_exception();
bool has_exception() const;
[variablelist
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with an exception rather than a value.]]
[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
stored exception, `false` otherwise.]]
@@ -478,46 +634,46 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
class shared_future
{
public:
typedef future_state::state state; // EXTENSION
typedef future_state::state state; // EXTENSION
shared_future() noexcept;
~shared_future();
shared_future() noexcept;
~shared_future();
// copy support
shared_future(shared_future const& other);
shared_future& operator=(shared_future const& other);
// copy support
shared_future(shared_future const& other);
shared_future& operator=(shared_future const& other);
// move support
shared_future(shared_future && other) noexcept;
shared_future(unique_future<R> && other) noexcept;
shared_future& operator=(shared_future && other) noexcept;
shared_future& operator=(unique_future<R> && other) noexcept;
// move support
shared_future(shared_future && other) noexcept;
shared_future(__unique_future__<R> && other) noexcept;
shared_future& operator=(shared_future && other) noexcept;
shared_future& operator=(__unique_future__<R> && other) noexcept;
void swap(shared_future& other);
void swap(shared_future& other);
// retrieving the value
R get();
// functions to check state, and wait for ready
bool valid() const noexcept;
bool is_ready() const noexcept; // EXTENSION
bool has_exception() const noexcept; // EXTENSION
bool has_value() const noexcept; // EXTENSION
// retrieving the value
R get();
// waiting for the result to be ready
void wait() const;
template <class Rep, class Period>
future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
template <class Clock, class Duration>
future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
// functions to check state, and wait for ready
bool valid() const noexcept;
bool is_ready() const noexcept; // EXTENSION
bool has_exception() const noexcept; // EXTENSION
bool has_value() const noexcept; // EXTENSION
// waiting for the result to be ready
void wait() const;
template <class Rep, class Period>
future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
template <class Clock, class Duration>
future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
template<typename Duration>
bool timed_wait(Duration const& rel_time) const;
bool timed_wait_until(boost::system_time const& abs_time) const;
template<typename Duration>
bool timed_wait(Duration const& rel_time) const;
bool timed_wait_until(boost::system_time const& abs_time) const;
#endif
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
state get_state() const noexcept;
state get_state() const noexcept;
#endif
};
@@ -527,7 +683,7 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
[variablelist
[[Effects:] [Constructs an uninitialized future.]]
[[Effects:] [Constructs an uninitialized shared_future.]]
[[Postconditions:] [[shared_future_is_ready_link `this->is_ready`] returns `false`. [shared_future_get_state_link
`this->get_state()`] returns __uninitialized__.]]
@@ -634,13 +790,95 @@ associated with `*this` is not ready at the point of the call, and the current t
[endsect]
[section:is_ready Member function `is_ready()` EXTENSION]
[section:wait_for Member function `wait_for()`]
template <class Rep, class Period>
future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
bool is_ready();
[variablelist
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set.]]
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time specified by
`wait_duration` has elapsed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is
invoked prior to waiting.]]
[[Returns:] [
- `future_status::deferred` if the shared state contains a deferred function. (Not implemented yet)
- `future_status::ready` if the shared state is ready.
- `future_status::timeout` if the function is returning because the relative timeout specified by `rel_time` has expired.
]]
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
['wait callback] if such a callback is called.]]
[[Postconditions:] [If this call returned `true`, then [shared_future_is_ready_link `this->is_ready()`] returns `true` and
[shared_future_get_state_link `this->get_state()`] returns __ready__.]]
[[Notes:] [`timed_wait()` is an ['interruption point]. `Duration` must be a type that meets the Boost.DateTime time duration requirements.]]
]
[endsect]
[section:wait_until Member function `wait_until()`]
template <class Clock, class Duration>
future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
[variablelist
[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time point specified by
`wait_timeout` has passed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is invoked
prior to waiting.]]
[[Returns:] [
- `future_status::deferred` if the shared state contains a deferred function. (Not implemented yet)
- `future_status::ready` if the shared state is ready.
- `future_status::timeout` if the function is returning because the absolute timeout specified by `absl_time` has reached.
]]
[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
['wait callback] if such a callback is called.]]
[[Postconditions:] [If this call returned `true`, then [shared_future_is_ready_link `this->is_ready()`] returns `true` and
[shared_future_get_state_link `this->get_state()`] returns __ready__.]]
[[Notes:] [`timed_wait()` is an ['interruption point].]]
]
[endsect]
[section:valid Member function `valid()`]
bool valid() const;
[variablelist
[[Returns:] [`true` if `*this` is associated with an asynchronous result, `false`
otherwise.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:is_ready Member function `is_ready()` EXTENSION]
bool is_ready() const;
[variablelist
[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready for retrieval, `false`
otherwise.]]
@@ -653,12 +891,10 @@ otherwise.]]
[section:has_value Member function `has_value()` EXTENSION]
bool has_value();
bool has_value() const;
[variablelist
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with a value rather than an exception.]]
[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
stored value, `false` otherwise.]]
@@ -670,12 +906,10 @@ stored value, `false` otherwise.]]
[section:has_exception Member function `has_exception()` EXTENSION]
bool has_exception();
bool has_exception() const;
[variablelist
[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with an exception rather than a value.]]
[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
stored exception, `false` otherwise.]]
@@ -712,33 +946,33 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
{
public:
promise();
template <class Allocator>
promise(allocator_arg_t, Allocator a);
promise & operator=(const promise & rhs);// = delete;
promise(const promise & rhs);// = delete;
~promise();
promise();
template <class Allocator>
promise(allocator_arg_t, Allocator a);
promise & operator=(const promise & rhs);// = delete;
promise(const promise & rhs);// = delete;
~promise();
// Move support
promise(promise && rhs) noexcept;;
promise & operator=(promise&& rhs) noexcept;;
void swap(promise& other) noexcept;
// Result retrieval
unique_future<R> get_future();
// Move support
promise(promise && rhs) noexcept;;
promise & operator=(promise&& rhs) noexcept;;
// Set the value
void set_value(R& r);
void set_value(R&& r);
void set_exception(boost::exception_ptr e);
void swap(promise& other) noexcept;
// Result retrieval
__unique_future__<R> get_future();
// setting the result with deferred notification
// void set_value_at_thread_exit(const R& r); // NOT YET IMPLEMENTED
// void set_value_at_thread_exit(see below); // NOT YET IMPLEMENTED
// void set_exception_at_thread_exit(exception_ptr p); // NOT YET IMPLEMENTED
// Set the value
void set_value(R& r);
void set_value(R&& r);
void set_exception(boost::exception_ptr e);
template<typename F>
void set_wait_callback(F f); // EXTENSION
// setting the result with deferred notification
// void set_value_at_thread_exit(const R& r); // NOT YET IMPLEMENTED
// void set_value_at_thread_exit(see below); // NOT YET IMPLEMENTED
// void set_exception_at_thread_exit(exception_ptr p); // NOT YET IMPLEMENTED
template<typename F>
void set_wait_callback(F f); // EXTENSION
};
[section:default_constructor Default Constructor]
@@ -757,8 +991,8 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
[section:alloc_constructor Allocator Constructor]
template <class Allocator>
promise(allocator_arg_t, Allocator a);
template <class Allocator>
promise(allocator_arg_t, Allocator a);
[variablelist
@@ -826,7 +1060,7 @@ associated with that task to ['ready] with a __broken_promise__ exception as the
[section:get_future Member Function `get_future()`]
unique_future<R> get_future();
__unique_future__<R> get_future();
[variablelist
@@ -913,43 +1147,43 @@ or __shared_future__ associated with this result, and the result is not ['ready]
class packaged_task
{
public:
typedef R result_type;
typedef R result_type;
packaged_task(packaged_task&);// = delete;
packaged_task& operator=(packaged_task&);// = delete;
packaged_task(packaged_task&);// = delete;
packaged_task& operator=(packaged_task&);// = delete;
// construction and destruction
packaged_task() noexcept;
// construction and destruction
packaged_task() noexcept;
explicit packaged_task(R(*f)());
template <class F>
explicit packaged_task(F&& f);
explicit packaged_task(R(*f)());
template <class F, class Allocator>
packaged_task(allocator_arg_t, Allocator a, F&& f);
template <class F>
explicit packaged_task(F&& f);
~packaged_task()
{}
template <class F, class Allocator>
packaged_task(allocator_arg_t, Allocator a, F&& f);
// move support
packaged_task(packaged_task&& other) noexcept;
packaged_task& operator=(packaged_task&& other) noexcept;
~packaged_task()
{}
void swap(packaged_task& other) noexcept;
// move support
packaged_task(packaged_task&& other) noexcept;
packaged_task& operator=(packaged_task&& other) noexcept;
bool valid() const noexcept;
// result retrieval
unique_future<R> get_future();
void swap(packaged_task& other) noexcept;
// execution
void operator()();
// void operator()(ArgTypes... ); // NOT YET IMPLEMENTED
// void make_ready_at_thread_exit(ArgTypes...); // NOT YET IMPLEMENTED
bool valid() const noexcept;
// result retrieval
__unique_future__<R> get_future();
void reset();
template<typename F>
void set_wait_callback(F f); // EXTENSION
// execution
void operator()();
// void operator()(ArgTypes... ); // NOT YET IMPLEMENTED
// void make_ready_at_thread_exit(ArgTypes...); // NOT YET IMPLEMENTED
void reset();
template<typename F>
void set_wait_callback(F f); // EXTENSION
};
[section:task_constructor Task Constructor]
@@ -977,10 +1211,10 @@ structures could not be allocated.]]
[section:alloc_constructor Allocator Constructor]
template <class Allocator>
packaged_task(allocator_arg_t, Allocator a, R(*f)());
template <class F, class Allocator>
packaged_task(allocator_arg_t, Allocator a, F&& f);
template <class Allocator>
packaged_task(allocator_arg_t, Allocator a, R(*f)());
template <class F, class Allocator>
packaged_task(allocator_arg_t, Allocator a, F&& f);
[variablelist
@@ -1052,7 +1286,7 @@ associated with that task to ['ready] with a __broken_promise__ exception as the
[section:get_future Member Function `get_future()`]
unique_future<R> get_future();
__unique_future__<R> get_future();
[variablelist
@@ -1086,7 +1320,7 @@ __packaged_task__. __task_already_started__ if the task has already been invoked
[section:reset Member Function `reset()`]
void reset();
void reset();
[variablelist
@@ -1123,6 +1357,129 @@ __packaged_task__.]]
[endsect]
[section:decay_copy Non-member function `decay_copy()`]
template <class T>
typename decay<T>::type decay_copy(T&& v)
{
return boost::forward<T>(v);
}
[endsect]
[section:async Non-member function `async()`]
template <class F>
__unique_future__<typename result_of<typename decay<F>::type()>::type>
async(F f);
template <class F>
__unique_future__<typename result_of<typename decay<F>::type()>::type>
async(launch policy, F f);
The function template async provides a mechanism to launch a function potentially in a new thread and
provides the result of the function in a future object with which it shares a shared state.
[warning `async(launch::deferred, F)` is NOT YET IMPLEMENTED!]
[variablelist
[[Requires:] [
``
decay_copy(boost::forward<F>(f))()
``
shall be a valid expression.
]]
[[Effects] [The first function behaves the same as a call to the second function with a policy argument of
`launch::async | launch::deferred` and the same arguments for `F`. The second function creates a shared state that is associated with the returned future object.
The further behavior of the second function depends on the policy argument as follows (if more than one of these conditions applies, the implementation may choose any of the corresponding policies):
- if `policy & launch::async` is non-zero - calls `decay_copy(boost::forward<F>(f))()` as if in a new thread of execution represented by a thread object with the calls to `decay_copy()` being evaluated in the thread that called `async`. Any return value is stored as the result in the shared state. Any exception propagated from the execution of `decay_copy(boost::forward<F>(f))()` is stored as the exceptional result in the shared state. The thread object is stored in the shared state and affects the behavior of any asynchronous return objects that reference that state.
- if `policy & launch::deferred` is non-zero - Stores `decay_copy(boost::forward<F>(f))` in the shared state. This copy of `f` constitute a deferred function. Invocation of the deferred function evaluates `boost::move(g)()` where `g` is the stored value of `decay_copy(boost::forward<F>(f))`. The shared state is not made ready until the function has completed. The first call to a non-timed waiting function on an asynchronous return object referring to this shared state shall invoke the deferred function in the thread that called the waiting function. Once evaluation of `boost::move(g)()` begins, the function is no longer considered deferred. (Note: If this policy is specified together with other policies, such as when using a policy value of `launch::async | launch::deferred`, implementations should defer invocation or the selection of the policy when no more concurrency can be effectively exploited.)
]]
[[Returns:] [An object of type `__unique_future__<typename result_of<typename decay<F>::type()>::type>` that refers to the shared state created by this call to `async`.]]
[[Synchronization:] [Regardless of the provided policy argument,
- the invocation of `async` synchronizes with the invocation of `f`. (Note: This statement applies even when the corresponding future object is moved to another thread.); and
- the completion of the function `f` is sequenced before the shared state is made ready. (Note: `f` might not be called at all, so its completion might never happen.)
If the implementation chooses the `launch::async` policy,
- a call to a waiting function on an asynchronous return object that shares the shared state created by this async call shall block until the associated thread has completed, as if joined;
- the associated thread completion synchronizes with the return from the first function that successfully detects the ready status of the shared state or with the return from the last function that releases the shared state, whichever happens first.
]]
[[Throws:][`system_error` if policy is `launch::async` and the implementation is unable to start a new thread.
]]
[[Error conditions:] [
- `resource_unavailable_try_again` - if policy is `launch::async` and the system is unable to start a new thread.
]]
[[Remarks:] [The first signature shall not participate in overload resolution if decay<F>::type is boost::launch.
]]
]
[/
[variablelist
[[Requires:] [F and each Ti in Args shall satisfy the MoveConstructible requirements. INVOKE (DECAY_- COPY (boost::forward<F>(f)), decay_copy (boost::forward<Args>(args))...) shall be a valid expression.
]]
[[Effects:] [The first function behaves the same as a call to the second function with a policy argument of launch::async | launch::deferred and the same arguments for F and Args. The second function creates a shared state that is associated with the returned future object. The further behavior of the second function depends on the policy argument as follows (if more than one of these conditions applies, the implementation may choose any of the corresponding policies):
- if policy & launch::async is non-zero - calls INVOKE (decay_copy (boost::forward<F>(f)), decay_copy (boost::forward<Args>(args))...) (20.8.2, 30.3.1.2) as if in a new thread of exe- cution represented by a thread object with the calls to decay_copy() being evaluated in the thread that called async. Any return value is stored as the result in the shared state. Any excep- tion propagated from the execution of INVOKE(decay_copy(boost::forward<F>(f)), DECAY_- COPY (boost::forward<Args>(args))...) is stored as the exceptional result in the shared state. The thread object is stored in the shared state and affects the behavior of any asynchronous return objects that reference that state.
- if policy & launch::deferred is non-zero - Stores decay_copy (boost::forward<F>(f)) and decay_copy (boost::forward<Args>(args))... in the shared state. These copies of f and args constitute a deferred function. Invocation of the deferred function evaluates INVOKE (boost::move(g), boost::move(xyz)) where g is the stored value of decay_copy (boost::forward<F>(f)) and xyz is the stored copy of decay_copy (boost::forward<Args>(args)).... The shared state is not made ready until the function has completed. The first call to a non-timed waiting function (30.6.4) on an asynchronous return object referring to this shared state shall invoke the deferred func- tion in the thread that called the waiting function. Once evaluation of INVOKE (boost::move(g), boost::move(xyz)) begins, the function is no longer considered deferred.
]]
[[Note:] [If this policy is specified together with other policies, such as when using a policy value of launch::async | launch::deferred, implementations should defer invocation or the selection of the policy when no more concurrency can be effectively exploited.]]
[[Returns:] [An object of type __unique_future__<typename result_of<typename decay<F>::type(typename de- cay<Args>::type...)>::type> that refers to the shared state created by this call to async.]]
[[Synchronization:] [Regardless of the provided policy argument,
- the invocation of async synchronizes with (1.10) the invocation of f. (Note: This statement applies even when the corresponding future object is moved to another thread.); and
- the completion of the function f is sequenced before (1.10) the shared state is made ready. (Note: f might not be called at all, so its completion might never happen.)
If the implementation chooses the launch::async policy,
- a call to a waiting function on an asynchronous return object that shares the shared state created by this async call shall block until the associated thread has completed, as if joined;
- the associated thread completion synchronizes with (1.10) the return from the first function that successfully detects the ready status of the shared state or with the return from the last function that releases the shared state, whichever happens first.
]]
[[Throws:] [system_error if policy is launch::async and the implementation is unable to start a new thread.
]]
[[Error conditions:][
- resource_unavailable_try_again - if policy is launch::async and the system is unable to start a new thread.
]]
[[Remarks:] [The first signature shall not participate in overload resolution if decay<F>::type is boost::launch.
]]
]
]
[endsect]
[section:wait_for_any Non-member function `wait_for_any()`]
template<typename Iterator>

View File

@@ -23,25 +23,26 @@
[template unique_future_link[link_text] [link thread.synchronization.futures.reference.unique_future [link_text]]]
[def __unique_future__ [unique_future_link `boost::unique_future`]]
[def __unique_future__ [unique_future_link `future`]]
[def __unique_future `future`]
[template unique_future_get_link[link_text] [link thread.synchronization.futures.reference.unique_future.get [link_text]]]
[def __unique_future_get__ [unique_future_get_link `boost::unique_future<R>::get()`]]
[def __unique_future_get__ [unique_future_get_link `boost::future<R>::get()`]]
[template unique_future_wait_link[link_text] [link thread.synchronization.futures.reference.unique_future.wait [link_text]]]
[def __unique_future_wait__ [unique_future_wait_link `boost::unique_future<R>::wait()`]]
[def __unique_future_wait__ [unique_future_wait_link `boost::future<R>::wait()`]]
[template unique_future_is_ready_link[link_text] [link thread.synchronization.futures.reference.unique_future.is_ready [link_text]]]
[def __unique_future_is_ready__ [unique_future_is_ready_link `boost::unique_future<R>::is_ready()`]]
[def __unique_future_is_ready__ [unique_future_is_ready_link `boost::future<R>::is_ready()`]]
[template unique_future_has_value_link[link_text] [link thread.synchronization.futures.reference.unique_future.has_value [link_text]]]
[def __unique_future_has_value__ [unique_future_has_value_link `boost::unique_future<R>::has_value()`]]
[def __unique_future_has_value__ [unique_future_has_value_link `boost::future<R>::has_value()`]]
[template unique_future_has_exception_link[link_text] [link thread.synchronization.futures.reference.unique_future.has_exception [link_text]]]
[def __unique_future_has_exception__ [unique_future_has_exception_link `boost::unique_future<R>::has_exception()`]]
[def __unique_future_has_exception__ [unique_future_has_exception_link `boost::future<R>::has_exception()`]]
[template unique_future_get_state_link[link_text] [link thread.synchronization.futures.reference.unique_future.get_state [link_text]]]
[def __unique_future_get_state__ [unique_future_get_state_link `boost::unique_future<R>::get_state()`]]
[def __unique_future_get_state__ [unique_future_get_state_link `boost::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`]]
@@ -69,6 +70,7 @@
[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()`]]
@@ -114,7 +116,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
@@ -132,7 +134,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);
@@ -174,7 +176,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);
}

View File

@@ -75,7 +75,7 @@ Lock ownership acquired through a call to __lock_ref__ must be released through
[endsect]
[section:lockable `Lockable` Concept]
A type `L` meets the __Lockable requirements if it meets the __BasicLocable requirements and the following expressions are well-formed and have the specified semantics (`m` denotes a value of type `L`):
A type `L` meets the __Lockable requirements if it meets the __BasicLockable requirements and the following expressions are well-formed and have the specified semantics (`m` denotes a value of type `L`):
* `m.__try_lock()`
@@ -343,7 +343,8 @@ Ownership can also be ['downgraded] as well as ['upgraded]: exclusive ownership
__upgrade_lockable_concept__ can be downgraded to upgradable ownership or shared ownership, and upgradable ownership can be
downgraded to plain shared ownership.
A type `L` meets the __SharedLockable requirements if it meets the __TimedLockable requirements and the following expressions are well-formed and have the specified semantics.
A type `L` meets the __UpgradeLockable requirements if it meets the __SharedLockable
requirements and the following expressions are well-formed and have the specified semantics.
[*Variables:]
@@ -360,7 +361,7 @@ A type `L` meets the __SharedLockable requirements if it meets the __TimedLockab
* `m.__try_lock_upgrade_until(abs_time)`
* `m.__unlock_and_lock_shared()`
* `m.__unlock_and_lock_upgrade();`
* `m.__unlock_upgrade_and_lock();`]
* `m.__unlock_upgrade_and_lock();`
* `m.__try_unlock_upgrade_and_lock()`
* `m.__try_unlock_upgrade_and_lock_for(rel_time)`
* `m.__try_unlock_upgrade_and_lock_until(abs_time)`
@@ -790,8 +791,10 @@ blocking.]]
[section:locks Lock Types]
#include <boost/thread/locks.hpp>
//#include <boost/thread/locks.hpp>
namespace boost
{
struct defer_lock_t {};
struct try_to_lock_t {};
struct adopt_lock_t {};
@@ -815,6 +818,7 @@ blocking.]]
void swap(upgrade_lock <Mutex>& lhs, upgrade_lock <Mutex>& rhs);
template <class Mutex>
class upgrade_to_unique_lock;
}
[section:lock_tags Lock option tags]
@@ -837,7 +841,7 @@ These tags are used in scoped locks constructors to specify a specific behavior.
[section:lock_guard Class template `lock_guard`]
#include <boost/thread/locks.hpp>
//#include <boost/thread/locks.hpp>
template<typename Lockable>
class lock_guard
@@ -903,7 +907,7 @@ object passed to the constructor.]]
[section:unique_lock Class template `unique_lock`]
#include <boost/thread/locks.hpp>
//#include <boost/thread/locks.hpp>
template<typename Lockable>
class unique_lock
@@ -1066,7 +1070,7 @@ returns `false`.]]
[[Requires:] [The supplied `Mutex` type must implement `__try_unlock_shared_and_lock()`.]]
[[Effects:] [Constructs an object of type __unique_lock. Let `pm` be and `owns` the ownership state. Initializes `pm` with nullptr and `owns` with false.
[[Effects:] [Constructs an object of type __unique_lock. Let `pm` be the pointer to the mutex and `owns` the ownership state. Initializes `pm` with nullptr and `owns` with false.
If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.release()`.
Else `sl.__owns_lock()` returns `true`, and in this case if `sl.mutex()->try_unlock_shared_and_lock()` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]]
@@ -1092,8 +1096,8 @@ Else `sl.__owns_lock()` returns `true`, and in this case if `sl.mutex()->try_unl
[[Requires:] [The supplied `Mutex` type shall implement `__try_unlock_shared_and_lock_until(abs_time)`.]]
[[Effects:] [Constructs an object of type `__unique_lock`, initializing `pm` with `nullptr` and `owns` with `false`.
If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.__release()`.
Else `sl.owns_lock()` returns `true`, and in this case if `sl.mutex()->__try_unlock_shared_and_lock_until(abs_time)` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]]
If `sl.__owns_lock_shared_ref__()` returns `false`, sets `pm` to the return value of `sl.release()`.
Else `sl.__owns_lock_shared_ref__()` returns `true`, and in this case if `sl.mutex()->__try_unlock_shared_and_lock_until(abs_time)` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]]
[[Note:] [If `sl.owns_lock()` returns `true` and `sl.mutex()-> __try_unlock_shared_and_lock_until(abs_time)` returns `false`, `sl` is not modified.]]
@@ -1116,7 +1120,7 @@ Else `sl.owns_lock()` returns `true`, and in this case if `sl.mutex()->__try_unl
[[Requires:] [The supplied `Mutex` type shall implement `__try_unlock_shared_and_lock_for(rel_time)`.]]
[[Effects:] [Constructs an object of type `__unique_lock`, initializing `pm` with `nullptr` and `owns` with `false`.
If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.__release()`.
If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.release()`.
Else `sl.owns_lock()` returns `true`, and in this case if `sl.mutex()-> __try_unlock_shared_and_lock_for(rel_time)` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]]
[[Note:] [If `sl.owns_lock()` returns `true` and `sl.mutex()-> __try_unlock_shared_and_lock_for(rel_time)` returns `false`, `sl` is not modified.]]
@@ -1267,7 +1271,7 @@ __owns_lock_ref__ returns `false`.]]
[section:shared_lock Class template `shared_lock`]
#include <boost/thread/locks.hpp>
//#include <boost/thread/locks.hpp>
template<typename Lockable>
class shared_lock
@@ -1508,7 +1512,7 @@ __owns_lock_shared_ref__ returns `false`.]]
[section:upgrade_lock Class template `upgrade_lock`]
#include <boost/thread/locks.hpp>
//#include <boost/thread/locks.hpp>
template<typename Lockable>
class upgrade_lock
@@ -1663,8 +1667,10 @@ call [try_lock_ref_link `m.try_lock()`] rather than `m.lock()`.
[section: reverse_mutex Class template `reverse_mutex`]
#include <boost/thread/reverse_mutex.hpp>
//#include <boost/thread/reverse_mutex.hpp>
namespace boost
{
template<typename BasicLockable>
class reverse_mutex
{
@@ -1679,6 +1685,7 @@ call [try_lock_ref_link `m.try_lock()`] rather than `m.lock()`.
void lock();
void unlock();
};
}
__reverse_mutex reverse the operations of a __BasicLockable, that unlocks the lockable when `lock()` is called and locks it when `unlock()` is called.
@@ -1692,24 +1699,29 @@ __reverse_mutex reverse the operations of a __BasicLockable, that unlocks the lo
[section:shared_lock_guard Class template `shared_lock_guard`]
#include <boost/thread/shared_lock_guard.hpp>
// #include <boost/thread/shared_lock_guard.hpp>
namespace boost
{
template<typename SharedLockable>
class shared_lock_guard
{
public:
shared_lock_guard(shared_lock_guard const&) = delete;
shared_lock_guard& operator=(shared_lock_guard const&) = delete;
explicit shared_lock_guard(SharedLockable& m_);
shared_lock_guard(SharedLockable& m_,boost::adopt_lock_t);
~shared_lock_guard();
};
}
__shared_lock_guard is very simple: on construction it
acquires shared ownership of the implementation of the __shared_lockable_concept__ supplied as
the constructor parameter. On destruction, the ownership is released. This
provides simple RAII-style locking of a __shared_lockable_concept_type__ object, to facilitate exception-safe
shared locking and unlocking.
In addition, the `__shared_lock_guard_ca(SharedLockable &m, boost::adopt_lock_t)` constructor allows the __shared_lock_guard object to
In addition, the `__shared_lock_guard_constructor_adopt(SharedLockable &m, boost::adopt_lock_t)` constructor allows the __shared_lock_guard object to
take shared ownership of a lock already held by the current thread.
[section:constructor `shared_lock_guard(SharedLockable & m)`]
@@ -1756,7 +1768,9 @@ obtained by a call to `m.__lock_shared()`.]]
[section:reverse_lock Class template `reverse_lock`]
#include <boost/thread/reverse_lock.hpp>
// #include <boost/thread/reverse_lock.hpp>
namespace boost
{
template<typename Lock>
class reverse_lock
@@ -1768,6 +1782,7 @@ obtained by a call to `m.__lock_shared()`.]]
explicit reverse_lock(Lock& m_);
~reverse_lock();
};
}
__reverse_lock reverse the operations of a lock: it provide for RAII-style, that unlocks the lock at construction time and lock it at destruction time. In addition, it transfer ownership temporarily, so that the mutex can not be locked using the Lock.
@@ -1777,9 +1792,9 @@ An instance of __reverse_lock doesn't ['own] the lock never.
[variablelist
[[Effects:] [Stores a reference to `m`. Invokes `m.__unlock()` if `m` owns his lock and then stores the mutex by calling `m.__release()`.]]
[[Effects:] [Stores a reference to `m`. Invokes `m.__unlock()` if `m` owns his lock and then stores the mutex by calling `m.release()`.]]
[[Postcondition:] [`!m.__owns_lock() && m.__mutex()==0`.]]
[[Postcondition:] [`!m.__owns_lock() && m.mutex()==0`.]]
[[Throws:] [Any exception thrown by the call to `m.__unlock()`.]]
@@ -1810,6 +1825,10 @@ An instance of __reverse_lock doesn't ['own] the lock never.
[section:lock_multiple Non-member function `lock(Lockable1,Lockable2,...)`]
// #include <boost/thread/locks.hpp>
namespace boost
{
template<typename Lockable1,typename Lockable2>
void lock(Lockable1& l1,Lockable2& l2);
@@ -1822,6 +1841,8 @@ An instance of __reverse_lock doesn't ['own] the lock never.
template<typename Lockable1,typename Lockable2,typename Lockable3,typename Lockable4,typename Lockable5>
void lock(Lockable1& l1,Lockable2& l2,Lockable3& l3,Lockable4& l4,Lockable5& l5);
}
[variablelist
[[Effects:] [Locks the __lockable_concept_type__ objects supplied as

View File

@@ -131,7 +131,7 @@ implementation. If no such instance exists, `native_handle()` and `native_handle
~recursive_mutex();
void lock();
bool try_lock();
bool try_lock() noexcept;
void unlock();
typedef platform-specific-type native_handle_type;
@@ -187,7 +187,7 @@ __recursive_try_mutex__ is a `typedef` to __recursive_mutex__, provided for back
~recursive_timed_mutex();
void lock();
bool try_lock();
bool try_lock() noexcept;
void unlock();

View File

@@ -12,7 +12,9 @@ __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 0). Anthony Williams version (version 1) was a major rewrite designed to
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
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],
@@ -20,8 +22,8 @@ closely follow the proposals presented to the C++ Standards Committee, in partic
[@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 in version 2 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 features have been added also as thread attributes, reverse_lock, shared_lock_guard.
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.
In order to use the classes and functions described here, you can
either include the specific headers specified by the descriptions of
@@ -42,6 +44,27 @@ 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]

View File

@@ -58,6 +58,7 @@ __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]

View File

@@ -8,7 +8,7 @@
[library Thread
[quickbook 1.5]
[version 3.0.1]
[version 3.1.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
[copyright 2011-12 Vicente J. Botet Escriba]
@@ -135,6 +135,7 @@
[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()`]]
@@ -158,15 +159,17 @@
[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 `boost::thread`]]
[def __thread [link thread.thread_management.thread `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()`]]

View File

@@ -338,7 +338,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::interrupt_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::interruption_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.
@@ -391,7 +391,7 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
void swap(thread& x) noexcept;
class id;
class attributes;
class attributes; // EXTENSION
id get_id() const noexcept;
@@ -470,8 +470,8 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
[variablelist
[[Effects:] [Transfers ownership of the thread managed by `other` (if
any) to `*this`. Version 1: If there was a thread previously associated with
`*this` then that thread is detached, version 2: If the thread is joinable calls to std::terminate.]]
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.]]
[[Postconditions:] [`other->get_id()==thread::id()` and `get_id()` returns the value of `other.get_id()` prior to the assignment.]]
@@ -628,7 +628,7 @@ are copied into internal storage for access by the new thread.]]]
[variablelist
[[Effects:] [Version 1: If `*this` has an associated thread of execution, calls __detach__, Version 2: If the thread is joinable calls to std::terminate. Destroys `*this`.]]
[[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`.]]
[[Throws:] [Nothing.]]
@@ -686,12 +686,14 @@ 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() == std::this_thread::get_id().
[*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.
[/
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable.
]
]]
@@ -711,7 +713,7 @@ are copied into internal storage for access by the new thread.]]]
[variablelist
[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
[[Preconditions:] [the thread is joinable.]]
[[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.]]
@@ -727,12 +729,13 @@ unchanged.]]
[[Error Conditions:] [
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == std::this_thread::get_id().
[*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.
[/
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable.
]
]]
@@ -750,7 +753,7 @@ unchanged.]]
[variablelist
[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
[[Preconditions:] [the thread is joinable.]]
[[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.]]
@@ -766,12 +769,13 @@ unchanged.]]
[[Error Conditions:] [
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == std::this_thread::get_id().
[*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.
[/
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable.
]
]]
@@ -789,7 +793,7 @@ unchanged.]]
[variablelist
[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
[[Preconditions:] [the thread is joinable.]]
[[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.]]
@@ -805,12 +809,14 @@ unchanged.]]
[[Error Conditions:] [
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == std::this_thread::get_id().
[*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.
[/
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable.
]
]]
@@ -825,7 +831,7 @@ unchanged.]]
[section:detach Member function `detach()`]
void detach() noexcept;
void detach();
[variablelist
@@ -835,7 +841,15 @@ unchanged.]]
[[Postconditions:] [`*this` no longer refers to any thread of execution.]]
[[Throws:] [Nothing]]
[[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.
]]
]

View File

@@ -10,14 +10,16 @@
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):
* __sleep_for
* __sleep_until
* __try_join_for
* __try_join_until
* __wait_for
* __wait_until
* __try_lock_for
* __try_lock_until
* `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):

View File

@@ -47,10 +47,16 @@ 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
{
@@ -66,6 +72,7 @@ from that thread.
T* release();
void reset(T* new_value=0);
};
}
[section:default_constructor `thread_specific_ptr();`]
@@ -102,10 +109,14 @@ 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

@@ -8,29 +8,40 @@
#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)
#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)
#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
#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
#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
#if ! defined BOOST_THREAD_DONT_PROVIDE_BASIC_THREAD_ID && ! defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#define BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#endif
@@ -43,13 +54,8 @@
#endif
#endif
// Uses Boost.System by default if not stated the opposite defining BOOST_THREAD_DONT_USE_SYSTEM
#if ! defined BOOST_THREAD_DONT_USE_SYSTEM
#define BOOST_THREAD_USES_SYSTEM
#endif
// Uses Boost.Chrono by default if not stated the opposite defining BOOST_THREAD_DONT_USE_CHRONO or BOOST_THREAD_DONT_USE_SYSTEM
#if ! defined BOOST_THREAD_DONT_USE_CHRONO && ! defined BOOST_THREAD_DONT_USE_SYSTEM
// 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
#define BOOST_THREAD_USES_CHRONO
#endif
@@ -61,15 +67,8 @@
#endif
// Uses Boost.Move by default if not stated the opposite defining BOOST_THREAD_DONT_USE_MOVE
#if ! defined BOOST_THREAD_DONT_USE_MOVE
#if ! defined BOOST_THREAD_USES_MOVE
//#define BOOST_THREAD_USES_MOVE
#endif
#endif
#if BOOST_THREAD_VERSION==2
#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY
#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
@@ -78,49 +77,59 @@
#endif
#if BOOST_THREAD_VERSION==3
#if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11
#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
#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
#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
#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
#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
#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
#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
#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
#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
#if ! defined BOOST_THREAD_USES_MOVE
#if ! defined BOOST_THREAD_DONT_USE_MOVE \
&& ! defined BOOST_THREAD_USES_MOVE
#define BOOST_THREAD_USES_MOVE
#endif
#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
#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
#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
@@ -135,7 +144,7 @@
// provided for backwards compatibility, since this
// macro was used for several releases by mistake.
#if defined(BOOST_THREAD_DYN_DLL)
#if defined(BOOST_THREAD_DYN_DLL) && ! defined BOOST_THREAD_DYN_LINK
# define BOOST_THREAD_DYN_LINK
#endif

View File

@@ -15,14 +15,14 @@
* BOOST_THREAD_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or
* makes it private.
*/
#ifndef BOOST_NO_DELETED_FUNCTIONS
#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_DELETED_FUNCTIONS
#else // BOOST_NO_CXX11_DELETED_FUNCTIONS
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
private: \
CLASS(CLASS&); \
@@ -32,7 +32,7 @@
private: \
CLASS& operator=(CLASS&); \
public:
#endif // BOOST_NO_DELETED_FUNCTIONS
#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
/**
* BOOST_THREAD_NO_COPYABLE deletes the copy constructor and assignment when the compiler supports it or

View File

@@ -11,9 +11,15 @@
#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/config.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
{
@@ -27,7 +33,7 @@ namespace boost
typedef typename alloc_traits::pointer pointer;
typedef typename alloc_traits::size_type size_type;
private:
_Alloc& alloc_;
_Alloc alloc_;
size_type s_;
public:
allocator_destructor(_Alloc& a, size_type s)BOOST_NOEXCEPT
@@ -35,6 +41,7 @@ namespace boost
{}
void operator()(pointer p)BOOST_NOEXCEPT
{
alloc_traits::destroy(alloc_, p);
alloc_traits::deallocate(alloc_, p, s_);
}
};
@@ -48,6 +55,101 @@ namespace boost
{
};
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

View File

@@ -65,7 +65,7 @@ namespace boost
}
}
#if ! defined BOOST_NO_RVALUE_REFERENCES
#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
@@ -84,7 +84,7 @@ namespace boost
{}; \
}
#elif ! defined BOOST_NO_RVALUE_REFERENCES && defined BOOST_MSVC
#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
@@ -176,7 +176,7 @@ namespace detail
#endif
#if ! defined BOOST_NO_RVALUE_REFERENCES
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_MOVABLE(TYPE)
@@ -227,7 +227,7 @@ namespace detail
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
namespace boost
{ namespace thread_detail
{

View File

@@ -23,6 +23,8 @@
#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>
@@ -52,7 +54,7 @@ namespace boost
{
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
thread_data(BOOST_THREAD_RV_REF(F) f_):
f(boost::forward<F>(f_))
{}
@@ -69,10 +71,13 @@ namespace boost
f(f_)
{}
#endif
//thread_data() {}
void run()
{
f();
}
private:
F f;
};
@@ -131,7 +136,7 @@ namespace boost
detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const;
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename F>
static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
{
@@ -174,7 +179,7 @@ namespace boost
detach();
#endif
}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <
class F
>
@@ -364,11 +369,17 @@ namespace boost
#endif
#if defined(BOOST_THREAD_PLATFORM_WIN32)
bool timed_join(const system_time& abs_time);
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp);
#endif
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)
@@ -400,7 +411,7 @@ namespace boost
return timed_join(get_system_time()+rel_time);
}
void detach() BOOST_NOEXCEPT;
void detach();
static unsigned hardware_concurrency() BOOST_NOEXCEPT;
@@ -434,7 +445,7 @@ namespace boost
return lhs.swap(rhs);
}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
inline thread&& move(thread& t) BOOST_NOEXCEPT
{
return static_cast<thread&&>(t);

View File

@@ -50,7 +50,7 @@
#endif
#include <boost/utility/result_of.hpp>
//#include <boost/thread.hpp>
#include <boost/thread/thread.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_FUTURE future
@@ -77,7 +77,7 @@ namespace boost
template <>
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type {};
#ifdef BOOST_NO_SCOPED_ENUMS
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
template <>
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { };
#endif
@@ -102,20 +102,20 @@ namespace boost
BOOST_SCOPED_ENUM_DECLARE_END(future_status)
BOOST_THREAD_DECL
const system::error_category& future_category();
const system::error_category& future_category() BOOST_NOEXCEPT;
namespace system
{
inline BOOST_THREAD_DECL
inline
error_code
make_error_code(future_errc e)
make_error_code(future_errc e) //BOOST_NOEXCEPT
{
return error_code(underlying_cast<int>(e), boost::future_category());
}
inline BOOST_THREAD_DECL
inline
error_condition
make_error_condition(future_errc e)
make_error_condition(future_errc e) //BOOST_NOEXCEPT
{
return error_condition(underlying_cast<int>(e), future_category());
}
@@ -136,15 +136,18 @@ namespace boost
{
return ec_;
}
const char* what() const BOOST_THREAD_NOEXCEPT_OR_THROW
{
return code().message().c_str();
}
//virtual ~future_error() BOOST_NOEXCEPT;
};
class BOOST_SYMBOL_VISIBLE future_uninitialized:
public future_error
{
public:
future_uninitialized():
future_uninitialized() :
future_error(system::make_error_code(future_errc::no_state))
{}
};
@@ -179,7 +182,6 @@ namespace boost
public:
task_already_started():
future_error(system::make_error_code(future_errc::promise_already_satisfied))
//std::logic_error("Task already started")
{}
};
@@ -189,7 +191,6 @@ namespace boost
public:
task_moved():
future_error(system::make_error_code(future_errc::no_state))
//std::logic_error("Task moved")
{}
};
@@ -199,7 +200,6 @@ namespace boost
public:
promise_moved():
future_error(system::make_error_code(future_errc::no_state))
//std::logic_error("Promise moved")
{}
};
@@ -374,7 +374,7 @@ namespace boost
struct future_traits
{
typedef boost::scoped_ptr<T> storage_type;
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef T const& source_reference_type;
struct dummy;
typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
@@ -576,7 +576,7 @@ namespace boost
class future_waiter
{
struct registered_waiter;
typedef std::vector<registered_waiter>::size_type count_type;
typedef std::vector<int>::size_type count_type;
struct registered_waiter
{
@@ -594,15 +594,20 @@ namespace boost
struct all_futures_lock
{
count_type count;
#ifdef _MANAGED
typedef std::ptrdiff_t count_type_portable;
#else
typedef count_type count_type_portable;
#endif
count_type_portable count;
boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
all_futures_lock(std::vector<registered_waiter>& futures):
count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
{
for(count_type i=0;i<count;++i)
for(count_type_portable i=0;i<count;++i)
{
#if defined __DECCXX || defined __SUNPRO_CC
#if defined __DECCXX || defined __SUNPRO_CC || defined __hpux
locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex).move();
#else
locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex);
@@ -617,7 +622,7 @@ namespace boost
void unlock()
{
for(count_type i=0;i<count;++i)
for(count_type_portable i=0;i<count;++i)
{
locks[i].unlock();
}
@@ -1219,6 +1224,11 @@ namespace boost
future_->mark_exceptional_finish_internal(p);
}
// setting the result with deferred notification
//void set_value_at_thread_exit(const R& r); // NOT YET IMPLEMENTED
//void set_value_at_thread_exit(see below); // NOT YET IMPLEMENTED
//void set_exception_at_thread_exit(exception_ptr p); // NOT YET IMPLEMENTED
template<typename F>
void set_wait_callback(F f)
{
@@ -1411,6 +1421,8 @@ namespace boost
};
template<typename R,typename F>
struct task_object:
task_base<R>
@@ -1422,7 +1434,7 @@ namespace boost
task_object(F const& f_):
f(f_)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
task_object(BOOST_THREAD_RV_REF(F) f_):
f(boost::forward<F>(f_))
{}
@@ -1448,6 +1460,34 @@ namespace boost
}
};
template<typename R>
struct task_object<R,R (*)()>:
task_base<R>
{
private:
task_object(task_object&);
public:
R (*f)();
task_object(R (*f_)()):
f(f_)
{}
void do_run()
{
try
{
this->mark_finished_with_result(f());
}
catch(thread_interrupted& )
{
this->mark_interrupted_finish();
}
catch(...)
{
this->mark_exceptional_finish();
}
}
};
template<typename F>
struct task_object<void,F>:
task_base<void>
@@ -1459,7 +1499,7 @@ namespace boost
task_object(F const& f_):
f(f_)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
task_object(BOOST_THREAD_RV_REF(F) f_):
f(boost::forward<F>(f_))
{}
@@ -1487,6 +1527,35 @@ namespace boost
}
};
template<>
struct task_object<void,void (*)()>:
task_base<void>
{
private:
task_object(task_object&);
public:
void (*f)();
task_object(void (*f_)()):
f(f_)
{}
void do_run()
{
try
{
f();
this->mark_finished_with_result();
}
catch(thread_interrupted& )
{
this->mark_interrupted_finish();
}
catch(...)
{
this->mark_exceptional_finish();
}
}
};
}
template<typename R>
@@ -1509,7 +1578,7 @@ namespace boost
explicit packaged_task(R(*f)()):
task(new detail::task_object<R,R(*)()>(f)),future_obtained(false)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class F>
explicit packaged_task(BOOST_THREAD_RV_REF(F) f):
task(new detail::task_object<R,
@@ -1539,7 +1608,7 @@ namespace boost
task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(f), D(a2, 1) );
future_obtained = false;
}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class F, class Allocator>
packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
{
@@ -1572,7 +1641,7 @@ namespace boost
task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(boost::move(f)), D(a2, 1) );
future_obtained = false;
}
#endif //BOOST_NO_RVALUE_REFERENCES
#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
#endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
~packaged_task()
@@ -1665,17 +1734,80 @@ namespace boost
BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
template <class R>
BOOST_THREAD_FUTURE<R>
async(launch policy, R(*f)())
{
if (int(policy) & int(launch::async))
{
packaged_task<R> pt( f );
BOOST_THREAD_FUTURE<R> ret = pt.get_future();
boost::thread( boost::move(pt) ).detach();
return ::boost::move(ret);
}
else if (int(policy) & int(launch::deferred))
{
packaged_task<R> pt( f );
BOOST_THREAD_FUTURE<R> ret = pt.get_future();
return ::boost::move(ret);
} else {
BOOST_THREAD_FUTURE<R> ret;
return ::boost::move(ret);
}
}
template <class R>
BOOST_THREAD_FUTURE<R>
async(R(*f)())
{
return async(launch::any, f);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class F>
BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
async(launch policy, BOOST_THREAD_FWD_REF(F) f)
{
typedef typename boost::result_of<typename decay<F>::type()>::type R;
if (int(policy) & int(launch::async))
{
packaged_task<R> pt( boost::forward<F>(f) );
BOOST_THREAD_FUTURE<R> ret = pt.get_future();
boost::thread( boost::move(pt) ).detach();
return ::boost::move(ret);
}
else if (int(policy) & int(launch::deferred))
{
packaged_task<R> pt( boost::forward<F>(f) );
BOOST_THREAD_FUTURE<R> ret = pt.get_future();
return ::boost::move(ret);
} else {
BOOST_THREAD_FUTURE<R> ret;
return ::boost::move(ret);
}
}
template <class F>
BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
async(BOOST_THREAD_RV_REF(F) f)
{
return async(launch::any, boost::forward<F>(f));
}
#else
// template <class F>
// BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
// async(launch policy, F f)
// BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
// async(launch policy, F const& f)
// {
// typedef typename boost::result_of<F()>::type R;
// typedef BOOST_THREAD_FUTURE<R> future;
// typedef typename boost::result_of<typename decay<F>::type()>::type R;
// if (int(policy) & int(launch::async))
// {
// packaged_task<R> pt( f );
//
// BOOST_THREAD_FUTURE ret = pt.get_future();
// BOOST_THREAD_FUTURE<R> ret = pt.get_future();
// boost::thread( boost::move(pt) ).detach();
// return ::boost::move(ret);
// }
@@ -1683,19 +1815,52 @@ namespace boost
// {
// packaged_task<R> pt( f );
//
// BOOST_THREAD_FUTURE ret = pt.get_future();
// BOOST_THREAD_FUTURE<R> ret = pt.get_future();
// return ::boost::move(ret);
// } else {
// BOOST_THREAD_FUTURE<R> ret;
// return ::boost::move(ret);
// }
// }
//
// template <class F>
// BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
// async(F f)
// async(F const& f)
// {
// return async(launch::any, f);
// }
template <class F>
BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
async(launch policy, BOOST_THREAD_FWD_REF(F) f)
{
typedef typename boost::result_of<typename decay<F>::type()>::type R;
if (int(policy) & int(launch::async))
{
packaged_task<R> pt( boost::forward<F>(f) );
BOOST_THREAD_FUTURE<R> ret = pt.get_future();
boost::thread( boost::move(pt) ).detach();
return ::boost::move(ret);
}
else if (int(policy) & int(launch::deferred))
{
packaged_task<R> pt( boost::forward<F>(f) );
BOOST_THREAD_FUTURE<R> ret = pt.get_future();
return ::boost::move(ret);
} else {
BOOST_THREAD_FUTURE<R> ret;
return ::boost::move(ret);
}
}
template <class F>
BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
async(BOOST_THREAD_FWD_REF(F) f)
{
return async(launch::any, boost::forward<F>(f));
}
#endif
}

View File

@@ -609,7 +609,7 @@ namespace boost
is_locked=false;
}
#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
typedef void (unique_lock::*bool_type)();
operator bool_type() const BOOST_NOEXCEPT
{
@@ -880,7 +880,7 @@ namespace boost
is_locked=false;
}
#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
typedef void (shared_lock<Mutex>::*bool_type)();
operator bool_type() const BOOST_NOEXCEPT
{
@@ -1140,7 +1140,7 @@ namespace boost
return is_locked;
}
#endif
#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
typedef void (upgrade_lock::*bool_type)();
operator bool_type() const BOOST_NOEXCEPT
{
@@ -1224,7 +1224,7 @@ namespace boost
exclusive.swap(other.exclusive);
}
#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&);
operator bool_type() const BOOST_NOEXCEPT
{
@@ -1275,7 +1275,7 @@ namespace boost
try_lock_wrapper(Mutex& m_,try_to_lock_t):
base(m_,try_to_lock)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
base(::boost::move(other))
{}
@@ -1325,7 +1325,7 @@ namespace boost
return base::release();
}
#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
typedef typename base::bool_type bool_type;
operator bool_type() const
{

View File

@@ -229,8 +229,11 @@ 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

@@ -12,19 +12,34 @@
#include <boost/thread/detail/config.hpp>
#include <pthread.h>
#include <boost/assert.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/cstdint.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>
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
struct once_flag
@@ -34,7 +49,7 @@ namespace boost
: epoch(BOOST_ONCE_INITIAL_FLAG_VALUE)
{}
private:
boost::uintmax_t epoch;
volatile thread_detail::uintmax_atomic_t epoch;
template<typename Function>
friend
void call_once(once_flag& flag,Function f);
@@ -44,7 +59,7 @@ namespace boost
struct once_flag
{
boost::uintmax_t epoch;
volatile thread_detail::uintmax_atomic_t epoch;
};
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
@@ -52,8 +67,8 @@ namespace boost
namespace detail
{
BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
BOOST_THREAD_DECL extern boost::uintmax_t once_global_epoch;
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 extern pthread_mutex_t once_epoch_mutex;
BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
}
@@ -63,10 +78,10 @@ namespace boost
template<typename Function>
void call_once(once_flag& flag,Function f)
{
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();
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();
if(epoch<this_thread_epoch)
{
@@ -77,21 +92,18 @@ namespace boost
if(flag.epoch==uninitialized_flag)
{
flag.epoch=being_initialized;
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
BOOST_TRY
{
#endif
pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
f();
#ifndef BOOST_NO_EXCEPTIONS
}
catch(...) // BOOST_NO_EXCEPTIONS protected
BOOST_CATCH (...)
{
flag.epoch=uninitialized_flag;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
throw; // BOOST_NO_EXCEPTIONS protected
BOOST_RETHROW
}
#endif
BOOST_CATCH_END
flag.epoch=--detail::once_global_epoch;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
}

View File

@@ -110,7 +110,7 @@ namespace boost
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
bool try_lock() BOOST_NOEXCEPT
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
@@ -294,7 +294,7 @@ namespace boost
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
bool try_lock()
bool try_lock() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && !pthread_equal(owner,pthread_self()))

View File

@@ -8,18 +8,25 @@
#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
@@ -104,19 +111,28 @@ 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)
current_cond(0),
notify()
{}
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();
@@ -177,7 +193,43 @@ namespace boost
namespace this_thread
{
#ifdef BOOST_THREAD_USES_CHRONO
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns);
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
}
}
}
#endif
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;

View File

@@ -17,7 +17,7 @@ namespace boost
return new T();
}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_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

@@ -42,7 +42,7 @@ namespace boost
mutex.destroy();
}
bool try_lock()
bool try_lock() BOOST_NOEXCEPT
{
long const current_thread_id=win32::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
@@ -93,7 +93,7 @@ namespace boost
}
private:
bool try_recursive_lock(long current_thread_id)
bool try_recursive_lock(long current_thread_id) BOOST_NOEXCEPT
{
if(::boost::detail::interlocked_read_acquire(&locking_thread_id)==current_thread_id)
{
@@ -103,7 +103,7 @@ namespace boost
return false;
}
bool try_basic_lock(long current_thread_id)
bool try_basic_lock(long current_thread_id) BOOST_NOEXCEPT
{
if(mutex.try_lock())
{

View File

@@ -58,7 +58,7 @@ namespace boost
}
bool try_lock()
bool try_lock() BOOST_NOEXCEPT
{
return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
}

View File

@@ -6,23 +6,27 @@
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/mutex.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/win32/thread_data.hpp>
#include <boost/thread/thread_time.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 <vector>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/assert.hpp>
#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
@@ -191,7 +195,10 @@ namespace boost
~entry_manager()
{
if(! entry->is_notified())
{
entry->remove_waiter();
}
}
list_entry* operator->()
@@ -510,6 +517,7 @@ 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,13 +3,15 @@
// interlocked_read_win32.hpp
//
// (C) Copyright 2005-8 Anthony Williams
// (C) Copyright 2005-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
// 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>
@@ -22,25 +24,25 @@ namespace boost
{
namespace detail
{
inline long interlocked_read_acquire(long volatile* x)
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
{
long const res=*x;
_ReadWriteBarrier();
return res;
}
inline void* interlocked_read_acquire(void* volatile* x)
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
{
void* const res=*x;
_ReadWriteBarrier();
return res;
}
inline void interlocked_write_release(long volatile* x,long value)
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
{
_ReadWriteBarrier();
*x=value;
}
inline void interlocked_write_release(void* volatile* x,void* value)
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
{
_ReadWriteBarrier();
*x=value;
@@ -54,19 +56,19 @@ namespace boost
{
namespace detail
{
inline long interlocked_read_acquire(long volatile* x)
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0);
}
inline void* interlocked_read_acquire(void* volatile* x)
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
}
inline void interlocked_write_release(long volatile* x,long value)
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
{
BOOST_INTERLOCKED_EXCHANGE(x,value);
}
inline void interlocked_write_release(void* volatile* x,void* value)
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
{
BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value);
}

View File

@@ -7,17 +7,26 @@
// (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 {
@@ -58,32 +67,47 @@ namespace boost
namespace detail
{
struct tss_cleanup_function;
struct thread_exit_callback_node;
struct tss_data_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 thread_data_base;
void intrusive_ptr_add_ref(thread_data_base * p);
void intrusive_ptr_release(thread_data_base * p);
struct BOOST_SYMBOL_VISIBLE thread_data_base
struct BOOST_THREAD_DECL 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;
boost::detail::tss_data_node* tss_data;
std::map<void const*,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(0),
thread_exit_callbacks(0),tss_data(),
interruption_enabled(true),
id(0)
{}
virtual ~thread_data_base()
id(0),
notify()
{}
virtual ~thread_data_base();
friend void intrusive_ptr_add_ref(thread_data_base * p)
{
@@ -106,6 +130,12 @@ 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

@@ -91,7 +91,7 @@ namespace boost
#endif
}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{

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/config.hpp>
#include <boost/thread/detail/config.hpp>
#include <boost/throw_exception.hpp>
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
@@ -341,7 +341,7 @@ namespace boost
{
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
#if 0
#ifndef BOOST_INTEL_CXX_VERSION
__asm {
mov eax,bit;
mov edx,x;
@@ -351,7 +351,11 @@ namespace boost
#else
bool ret;
__asm {
mov eax,bit; mov edx,x; lock bts [edx],eax; setc al; mov ret, al
mov eax,bit
mov edx,x
lock bts [edx],eax
setc al
mov ret, al
};
return ret;
@@ -360,7 +364,7 @@ namespace boost
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
#if 0
#ifndef BOOST_INTEL_CXX_VERSION
__asm {
mov eax,bit;
mov edx,x;
@@ -368,11 +372,13 @@ namespace boost
setc al;
};
#else
bool ret;
__asm {
mov eax,bit; mov edx,x; lock btr [edx],eax; setc al; mov ret, al
mov eax,bit
mov edx,x
lock btr [edx],eax
setc al
mov ret, al
};
return ret;

View File

@@ -51,7 +51,7 @@ namespace boost
}
const system::error_category&
future_category()
future_category() BOOST_NOEXCEPT
{
static thread_detail::future_error_category f;
return f;

View File

@@ -14,7 +14,7 @@ namespace boost
{
namespace detail
{
BOOST_THREAD_DECL boost::uintmax_t once_global_epoch=UINTMAX_C(~0);
BOOST_THREAD_DECL thread_detail::uintmax_atomic_t once_global_epoch=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C;
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
}
boost::uintmax_t& get_once_per_thread_epoch()
thread_detail::uintmax_atomic_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(boost::uintmax_t));
data=malloc(sizeof(thread_detail::uintmax_atomic_t));
BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data));
*static_cast<boost::uintmax_t*>(data)=UINTMAX_C(~0);
*static_cast<thread_detail::uintmax_atomic_t*>(data)=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C;
}
return *static_cast<boost::uintmax_t*>(data);
return *static_cast<thread_detail::uintmax_atomic_t*>(data);
}
}

View File

@@ -10,11 +10,12 @@
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/condition_variable.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__)
@@ -24,14 +25,23 @@
#include <unistd.h>
#endif
#include <libs/thread/src/pthread/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
{
@@ -138,20 +148,17 @@ 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());
#ifndef BOOST_NO_EXCEPTIONS
try // BOOST_NO_EXCEPTIONS protected
#endif
BOOST_TRY
{
thread_info->run();
}
#ifndef BOOST_NO_EXCEPTIONS
catch(thread_interrupted const&) // BOOST_NO_EXCEPTIONS protected
BOOST_CATCH (thread_interrupted const&)
{
}
#endif
BOOST_CATCH_END
// 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
// BOOST_CATCH(...)
// {
// std::terminate();
// }
@@ -175,6 +182,8 @@ namespace boost
void run()
{}
void notify_all_at_thread_exit(condition_variable*, mutex*)
{}
private:
externally_launched_thread(externally_launched_thread&);
@@ -304,6 +313,12 @@ 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)
@@ -353,8 +368,14 @@ 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
@@ -363,7 +384,7 @@ namespace boost
}
void thread::detach() BOOST_NOEXCEPT
void thread::detach()
{
detail::thread_data_ptr local_thread_info;
thread_info.swap(local_thread_info);
@@ -427,33 +448,6 @@ namespace boost
}
}
#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)
@@ -652,7 +646,7 @@ namespace boost
return &current_node->second;
}
}
return NULL;
return 0;
}
void* get_tss_data(void const* key)
@@ -661,7 +655,7 @@ namespace boost
{
return current_node->value;
}
return NULL;
return 0;
}
void add_new_tss_node(void const* key,
@@ -698,12 +692,21 @@ namespace boost
erase_tss_node(key);
}
}
else
else if(func || (tss_data!=0))
{
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

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

@@ -13,22 +13,39 @@
#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
@@ -128,19 +145,6 @@ 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
@@ -150,7 +154,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 || current_thread_data->thread_exit_callbacks)
while(! current_thread_data->tss_data.empty() || current_thread_data->thread_exit_callbacks)
{
while(current_thread_data->thread_exit_callbacks)
{
@@ -163,15 +167,18 @@ namespace boost
}
boost::detail::heap_delete(current_node);
}
while(current_thread_data->tss_data)
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;)
{
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=next;
++next;
if(current->second.func && (current->second.value!=0))
{
(*current_node->func)(current_node->value);
(*current->second.func)(current->second.value);
}
boost::detail::heap_delete(current_node);
current_thread_data->tss_data.erase(current);
}
}
@@ -250,6 +257,9 @@ 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&);
@@ -301,7 +311,6 @@ namespace boost
{
return (get_thread_info)();
}
void thread::join()
{
if (this_thread::get_id() == get_id())
@@ -314,50 +323,44 @@ 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)
{
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;
return do_try_join_until(get_milliseconds_until(wait_until));
}
#ifdef BOOST_THREAD_USES_CHRONO
bool thread::try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
bool thread::do_try_join_until(uintmax_t milli)
{
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)
{
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
if(!this_thread::interruptible_wait(local_thread_info->thread_handle,rel_time.count()))
{
return false;
}
release_handle();
if(!this_thread::interruptible_wait(local_thread_info->thread_handle,milli))
{
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() BOOST_NOEXCEPT
void thread::detach()
{
release_handle();
}
@@ -636,14 +639,11 @@ namespace boost
detail::thread_data_base* const current_thread_data(get_current_thread_data());
if(current_thread_data)
{
detail::tss_data_node* current_node=current_thread_data->tss_data;
while(current_node)
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())
{
if(current_node->key==key)
{
return current_node;
}
current_node=current_node->next;
return &current_node->second;
}
}
return NULL;
@@ -658,23 +658,43 @@ namespace boost
return NULL;
}
void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing)
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)
{
if(tss_data_node* const current_node=find_tss_data(key))
{
if(cleanup_existing && current_node->func.get() && current_node->value)
if(cleanup_existing && current_node->func && (current_node->value!=0))
{
(*current_node->func)(current_node->value);
}
current_node->func=func;
current_node->value=tss_data;
if(func || (tss_data!=0))
{
current_node->func=func;
current_node->value=tss_data;
}
else
{
erase_tss_node(key);
}
}
else if(func && tss_data)
else if(func || (tss_data!=0))
{
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;
add_new_tss_node(key,func,tss_data);
}
}
}
@@ -694,6 +714,14 @@ 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

@@ -5,6 +5,7 @@
#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

@@ -44,7 +44,7 @@ project
<toolset>clang:<cxxflags>-pedantic
<toolset>clang:<cxxflags>-Wno-long-long
<toolset>clang:<cxxflags>-ansi
#<toolset>clang:<cxxflags>-fpermissive # doesn't work
#<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
@@ -80,13 +80,13 @@ 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) ../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
: : :
<library>/boost/test//boost_unit_test_framework/<link>static
: $(sources[1]:B)_lib
]
;
}
@@ -178,6 +178,7 @@ rule thread-compile-fail ( sources : reqs * : name )
[ thread-test test_2309.cpp ]
[ thread-run test_2501.cpp ]
[ thread-test test_2741.cpp ]
[ thread-run test_3628.cpp ]
[ thread-run test_4521.cpp ]
[ thread-run test_4648.cpp ]
[ thread-run test_4882.cpp ]
@@ -188,6 +189,8 @@ 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 ]
;
@@ -222,12 +225,13 @@ rule thread-compile-fail ( sources : reqs * : name )
[ 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 ]
;
#explicit ts_async ;
explicit ts_async ;
test-suite ts_async
:
# [ thread-run2 ./sync/futures/async/async_pass.cpp : async__async_p ]
[ thread-run2 ./sync/futures/async/async_pass.cpp : async__async_p ]
;
#explicit ts_promise ;
@@ -466,6 +470,8 @@ rule thread-compile-fail ( sources : reqs * : name )
[ 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 ]
@@ -532,10 +538,4 @@ rule thread-compile-fail ( sources : reqs * : name )
[ thread-run2 ./sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp : reverse_lock__types_p ]
;
explicit ts ;
test-suite ts
:
[ thread-run test_ml.cpp ]
;
}

View File

@@ -14,14 +14,4 @@ void test()
t2=t1;
}
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;
}
#include "./remove_error_code_unused_warning.hpp"

View File

@@ -13,14 +13,4 @@ void test()
boost::thread t2(t1);
}
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;
}
#include "./remove_error_code_unused_warning.hpp"

View File

@@ -0,0 +1,17 @@
// 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

@@ -27,13 +27,5 @@ void fail()
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -26,13 +26,5 @@ void fail()
boost::condition_variable cv1(cv0);
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -26,13 +26,5 @@ void fail()
cv1 = cv0;
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -26,13 +26,5 @@ void fail()
boost::condition_variable_any cv1(cv0);
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -0,0 +1,51 @@
//===----------------------------------------------------------------------===//
//
// 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,6 +22,7 @@
// 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>
@@ -32,6 +33,41 @@
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));
@@ -51,18 +87,21 @@ void f2()
boost::this_thread::sleep_for(ms(200));
}
boost::interprocess::unique_ptr<int> f3(int i)
boost::interprocess::unique_ptr<int, boost::default_delete<int> > f3(int i)
{
boost::this_thread::sleep_for(ms(200));
return boost::interprocess::unique_ptr<int>(new int(i));
return boost::interprocess::unique_ptr<int, boost::default_delete<int> >(new int(i));
}
boost::interprocess::unique_ptr<int> f4(boost::interprocess::unique_ptr<int>&& p)
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::this_thread::sleep_for(ms(200));
return boost::move(p);
}
int main()
{
{
@@ -82,7 +121,7 @@ int main()
BOOST_TEST(t1 - t0 < ms(100));
}
{
boost::future<int> f = boost::async(boost::launch::any, f0);
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);
@@ -90,14 +129,30 @@ int main()
BOOST_TEST(t1 - t0 < ms(100));
}
{
boost::future<int> f = boost::async(boost::launch::deferred, f0);
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_TEST(t1 - t0 < ms(100));
}
{
boost::future<int> f = boost::async(boost::launch::any, 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));
@@ -122,15 +177,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));
@@ -155,32 +210,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>> 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(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>> f = boost::async(f4, boost::interprocess::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));
}
// {
// 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));
// }
return boost::report_errors();
}

View File

@@ -36,13 +36,5 @@ int main()
return boost::report_errors();
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -34,13 +34,5 @@ int main()
return boost::report_errors();
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -24,7 +24,7 @@
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include <libs/thread/test/sync/futures/test_allocator.hpp>
#include "../test_allocator.hpp"
#endif
int main()

View File

@@ -25,7 +25,7 @@
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include <libs/thread/test/sync/futures/test_allocator.hpp>
#include "../test_allocator.hpp"
double fct()
{
@@ -44,20 +44,27 @@ 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
@@ -68,6 +75,8 @@ public:
int A::n_moves = 0;
int A::n_copies = 0;
int A::n_instances = 0;
int A::n_destroy = 0;
int main()
{
@@ -83,6 +92,8 @@ int main()
}
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;

View File

@@ -45,13 +45,5 @@ int main()
return boost::report_errors();
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -45,13 +45,5 @@ int main()
return boost::report_errors();
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -28,7 +28,7 @@
#include <boost/static_assert.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include <libs/thread/test/sync/futures/test_allocator.hpp>
#include "../test_allocator.hpp"
int main()
{

View File

@@ -23,7 +23,7 @@
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include <libs/thread/test/sync/futures/test_allocator.hpp>
#include "../test_allocator.hpp"
int main()
{

View File

@@ -31,13 +31,5 @@ int main()
return boost::report_errors();
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -30,13 +30,5 @@ int main()
return boost::report_errors();
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -23,7 +23,7 @@
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include <libs/thread/test/sync/futures/test_allocator.hpp>
#include "../test_allocator.hpp"
#endif
boost::mutex m0;

View File

@@ -23,7 +23,7 @@
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include <libs/thread/test/sync/futures/test_allocator.hpp>
#include "../test_allocator.hpp"
#endif
boost::mutex m;

View File

@@ -25,7 +25,7 @@
#include <boost/static_assert.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include <libs/thread/test/sync/futures/test_allocator.hpp>
#include "../test_allocator.hpp"
int main()
{

View File

@@ -33,13 +33,5 @@ int main()
}
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]
#include "../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -32,13 +32,5 @@ int main()
boost::lock_guard<boost::mutex> lk1 = lk0;
}
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]
#include "../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -29,13 +29,5 @@ int main()
}
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]
#include "../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -28,13 +28,5 @@ int main()
}
}
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]
#include "../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -37,13 +37,5 @@ int main()
}
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]
#include "../../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -36,13 +36,5 @@ int main()
BOOST_TEST(lk0.owns_lock() == false);
}
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]
#include "../../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -33,13 +33,5 @@ int main()
}
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]
#include "../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -32,13 +32,5 @@ int main()
boost::shared_lock_guard<boost::shared_mutex> lk1 = lk0;
}
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]
#include "../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -37,13 +37,5 @@ int main()
}
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]
#include "../../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -36,13 +36,5 @@ int main()
BOOST_TEST(lk0.owns_lock() == false);
}
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]
#include "../../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -35,13 +35,5 @@ int main()
return boost::report_errors();
}
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]
#include "../../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -37,13 +37,5 @@ int main()
}
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]
#include "../../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -36,13 +36,5 @@ int main()
BOOST_TEST(lk0.owns_lock() == false);
}
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]
#include "../../../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -27,13 +27,5 @@ int main()
boost::mutex m1(m0);
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -27,13 +27,5 @@ int main()
boost::mutex m1(m0);
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -27,13 +27,5 @@ int main()
boost::recursive_mutex m1(m0);
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -27,13 +27,5 @@ int main()
boost::recursive_mutex m1(m0);
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -27,13 +27,4 @@ int main()
boost::recursive_timed_mutex m1(m0);
}
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;
}
#include "../../../remove_error_code_unused_warning.hpp"

View File

@@ -27,13 +27,5 @@ int main()
boost::recursive_timed_mutex m1(m0);
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -27,13 +27,5 @@ int main()
boost::shared_mutex m1(m0);
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -27,15 +27,6 @@ int main()
boost::shared_mutex m1(m0);
}
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]
#include "../../../remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -27,14 +27,5 @@ int main()
boost::timed_mutex m1(m0);
}
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]
#include "impl/thread/test/remove_error_code_unused_warning.hpp"
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -27,13 +27,4 @@ int main()
boost::timed_mutex m1(m0);
}
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;
}
#include "impl/thread/test/remove_error_code_unused_warning.hpp"

View File

@@ -9,54 +9,54 @@
#include <boost/thread.hpp>
using namespace std;
using namespace std;
boost::mutex mutex_;
boost::mutex mutex_;
void perform()
{
try
{
boost::this_thread::sleep(boost::posix_time::seconds(100));
}
catch (boost::thread_interrupted& interrupt)
{
boost::mutex::scoped_lock lock(mutex_);
cerr << "Thread " << boost::this_thread::get_id() << " got interrupted" << endl;
throw(interrupt);
}
catch (std::exception& e)
{
boost::mutex::scoped_lock lock(mutex_);
cerr << "Thread " << boost::this_thread::get_id() << " caught std::exception" << e.what() << endl;
}
catch (...)
{
boost::mutex::scoped_lock lock(mutex_);
cerr << "Thread " << boost::this_thread::get_id() << " caught something else" << endl;
}
}
void perform()
{
try
{
boost::this_thread::sleep(boost::posix_time::seconds(100));
}
catch (boost::thread_interrupted& interrupt)
{
boost::mutex::scoped_lock lock(mutex_);
cerr << "Thread " << boost::this_thread::get_id() << " got interrupted" << endl;
throw(interrupt);
}
catch (std::exception& e)
{
boost::mutex::scoped_lock lock(mutex_);
cerr << "Thread " << boost::this_thread::get_id() << " caught std::exception" << e.what() << endl;
}
catch (...)
{
boost::mutex::scoped_lock lock(mutex_);
cerr << "Thread " << boost::this_thread::get_id() << " caught something else" << endl;
}
}
void test()
{
void test()
{
try
{
boost::thread_group threads;
for (int i = 0; i < 2; ++i)
{
threads.create_thread(perform);
}
for (int i = 0; i < 2; ++i)
{
threads.create_thread(perform);
}
//boost::this_thread::sleep(1);
threads.interrupt_all();
threads.join_all();
//boost::this_thread::sleep(1);
threads.interrupt_all();
threads.join_all();
}
catch (...)
{
BOOST_CHECK(false && "exception raised");
}
}
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{

View File

@@ -1,3 +1,8 @@
// Copyright (C) 2010 Vicente Botet
//
// 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/shared_mutex.hpp>
#include <boost/thread/locks.hpp>

View File

@@ -15,7 +15,7 @@
#include <boost/test/unit_test.hpp>
#define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only
#include <libs/thread/test/util.inl>
#include "./util.inl"
int test_value;
#ifdef PTHREAD_STACK_MIN

89
test/test_3628.cpp Normal file
View File

@@ -0,0 +1,89 @@
// Copyright (C) 2010 Vicente Botet
//
// 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/condition.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <list>
#include <iostream>
using namespace std;
boost::recursive_mutex theMutex;
typedef std::list<boost::condition*> Conditions;
Conditions theConditions;
void ThreadFuncWaiter()
{
boost::condition con1;
//for(; ; )
for (int j = 0; j < 10; j++)
{
{
boost::recursive_mutex::scoped_lock lockMtx(theMutex);
theConditions.push_back(&con1);
cout << "Added " << boost::this_thread::get_id() << " " << &con1 << endl;
if (con1.timed_wait(lockMtx, boost::posix_time::time_duration(0, 0, 50)))
{
cout << "Woke Up " << boost::this_thread::get_id() << " " << &con1 << endl;
}
else
{
cout << "*****Timed Out " << boost::this_thread::get_id() << " " << &con1 << endl;
exit(13);
}
theConditions.remove(&con1);
cout << "Removed " << boost::this_thread::get_id() << " " << &con1 << endl;
cout << "Waiter " << j << endl;
}
//Sleep(2000);
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
}
}
void ThreadFuncNotifier()
{
for (int j = 0; j < 70; j++)
{
{
boost::recursive_mutex::scoped_lock lockMtx(theMutex);
cout << "<Notifier " << j << endl;
unsigned int i = 0;
for (Conditions::iterator it = theConditions.begin(); it != theConditions.end() && i < 2; ++it)
{
(*it)->notify_one();
//WORKAROUND_ lockMtx.unlock();
//WORKAROUND_ boost::this_thread::sleep_for(boost::chrono::milliseconds(50));
cout << "Notified One " << theConditions.size() << " " << (*it) << endl;
++i;
//WORKAROUND_ lockMtx.lock();
}
cout << "Notifier> " << j << endl;
}
boost::this_thread::sleep_for(boost::chrono::milliseconds(50));
}
}
int main()
{
boost::thread_group tg;
for (int i = 0; i < 12; ++i)
{
tg.create_thread(ThreadFuncWaiter);
}
tg.create_thread(ThreadFuncNotifier);
tg.join_all();
return 0;
}

72
test/test_3837.cpp Normal file
View File

@@ -0,0 +1,72 @@
// Copyright (C) 2010 Vicente Botet
//
// 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.hpp>
#include <boost/optional.hpp>
#include <boost/detail/lightweight_test.hpp>
using namespace boost;
using namespace boost::chrono;
struct dummy_class_tracks_deletions
{
static unsigned deletions;
dummy_class_tracks_deletions()
{
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
}
~dummy_class_tracks_deletions()
{
++deletions;
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
}
};
unsigned dummy_class_tracks_deletions::deletions=0;
optional<thread_specific_ptr<dummy_class_tracks_deletions> > optr;
//struct X
//{
// thread_specific_ptr<int> f;
//} sptr;
void other_thread()
{
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
optr = none;
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
optr = in_place();
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
BOOST_TEST(optr->get() == 0);
this_thread::sleep(posix_time::seconds(5));
BOOST_TEST(optr->get() == 0);
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
}
int main()
{
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
dummy_class_tracks_deletions * pi = new dummy_class_tracks_deletions;
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
optr = in_place();
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
optr->reset(pi);
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
BOOST_TEST(optr->get() == pi);
thread t1(bind(&other_thread));
this_thread::sleep(posix_time::seconds(5));
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
BOOST_TEST(optr->get() == pi);
std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl;
t1.join();
return boost::report_errors();
}

View File

@@ -1,3 +1,8 @@
// Copyright (C) 2010 Vicente Botet
//
// 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.hpp>
int calculate_the_answer_to_life_the_universe_and_everything()

View File

@@ -1,3 +1,8 @@
// Copyright (C) 2010 Vicente Botet
//
// 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.hpp>
#include <boost/current_function.hpp>

View File

@@ -1,5 +1,11 @@
// Copyright (C) 2010 Vicente Botet
//
// 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/shared_mutex.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <iostream>
@@ -8,9 +14,7 @@ boost::shared_mutex mutex;
void thread()
{
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
#ifndef BOOST_NO_EXCEPTIONS
try
#endif
BOOST_TRY
{
for (int i =0; i<10; ++i)
{
@@ -25,12 +29,15 @@ void thread()
}
}
}
#ifndef BOOST_NO_EXCEPTIONS
catch (boost::lock_error& le)
BOOST_CATCH (boost::lock_error& le)
{
std::cerr << "lock_error exception\n";
}
#endif
BOOST_CATCH (...)
{
std::cerr << " exception\n";
}
BOOST_CATCH_END
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
}

View File

@@ -1,3 +1,8 @@
// Copyright (C) 2010 Vicente Botet
//
// 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.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>

View File

@@ -1,3 +1,8 @@
// Copyright (C) 2010 Vicente Botet
//
// 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)
// bm.cpp
// g++ test.cpp -lboost_thread-mt && ./a.out

View File

@@ -1,3 +1,8 @@
// Copyright (C) 2010 Vicente Botet
//
// 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.hpp>

View File

@@ -1,3 +1,8 @@
// Copyright (C) 2010 Vicente Botet
//
// 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.hpp>
void run_thread() {

View File

@@ -1,3 +1,8 @@
// Copyright (C) 2010 Vicente Botet
//
// 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.hpp>
#include <boost/date_time.hpp>

View File

@@ -1,4 +1,10 @@
// Copyright (C) 2010 Vicente Botet
//
// 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.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <assert.h>
#include <iostream>
#include <stdlib.h>
@@ -29,6 +35,9 @@ int main()
std::cerr << "now_time =" << now_time << " \n";
std::cerr << "end_time =" << end_time << " \n";
std::cerr << "wait_time=" << wait_time << " \n";
std::cerr << "now_time =" << from_time_t(now_time) << " \n";
std::cerr << "end_time =" << from_time_t(end_time) << " \n";
std::cerr << "wait_time=" << from_time_t(wait_time) << " \n";
std::cerr << end_time - wait_time << " \n";
assert(end_time >= wait_time);
std::cerr << " OK\n";

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