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

Compare commits

...

477 Commits

Author SHA1 Message Date
Beman Dawes
ce7cca611d Release 1.50.0
[SVN r79156]
2012-06-28 12:37:29 +00:00
Vicente J. Botet Escriba
bca4c3d5fa Thread: Added other fixed tickets in history
[SVN r79031]
2012-06-21 21:26:35 +00:00
Vicente J. Botet Escriba
9e6384bf79 Thread: merge from trunk to fix some minor bugs
[SVN r78973]
2012-06-16 21:10:08 +00:00
Anthony Williams
dcd544082e Merged boost.thread from trunk
[SVN r78543]
2012-05-22 17:03:15 +00:00
Dave Abrahams
1013ce68c1 Replace all uses of boost/utility.hpp with more-granular includes. Solves modularization dependency nightmare.
[SVN r78502]
2012-05-18 04:44:04 +00:00
Vicente J. Botet Escriba
aea84b03fc Thread: link with Boost.Chrono for vacpp-11.1
[SVN r78451]
2012-05-13 08:46:43 +00:00
Anthony Williams
7608db4b0e Combine scoped enum emulation from thread library into detail/scoped_enum_emulation.hpp
[SVN r78407]
2012-05-10 17:06:15 +00:00
Anthony Williams
62f1c4b086 Reinstate abi prefix/suffix headers
[SVN r78399]
2012-05-10 07:30:41 +00:00
Vicente J. Botet Escriba
ab6864f3b4 Thread: try to fix ticket 6130 for linux systems
[SVN r78285]
2012-04-30 20:23:56 +00:00
Vicente J. Botet Escriba
b8bd80a5f4 Thread: Use NO_COPYABLE macro
[SVN r78280]
2012-04-30 16:06:04 +00:00
Vicente J. Botet Escriba
fffc5ddd1f Thread: Added some traces to catch spourious issue
[SVN r78279]
2012-04-30 16:05:24 +00:00
Vicente J. Botet Escriba
cd4c858048 Thread: Added some traces to catch spourious issue
[SVN r78278]
2012-04-30 16:04:22 +00:00
Vicente J. Botet Escriba
3fb1bd3d1d Thread: warning removal
[SVN r78277]
2012-04-30 16:03:30 +00:00
Vicente J. Botet Escriba
75aff7f1a6 Thread: Try to fix spourious issue
[SVN r78276]
2012-04-30 16:01:19 +00:00
Vicente J. Botet Escriba
3f3c5c8ac5 Thread: warning removal
[SVN r78275]
2012-04-30 16:00:29 +00:00
Vicente J. Botet Escriba
40b66a83f7 Thread: removed warning
[SVN r78254]
2012-04-29 14:27:43 +00:00
Vicente J. Botet Escriba
0b15d66dc0 Thread: Added use of macro BOOST_THREAD_MAKE_RV_REF and some traces to try to solve PGI regression test
[SVN r78243]
2012-04-28 16:11:03 +00:00
Vicente J. Botet Escriba
ceacda6c6a Thread: Refactor the no-copyable classes using the macro BOOST_THREAD_NO_COPYABLE
[SVN r78240]
2012-04-28 12:25:28 +00:00
Vicente J. Botet Escriba
0a22ac9209 Thread: Add a workaround for the bug identified in ticket 6130 by adding some microseconds to the time to wait
[SVN r78239]
2012-04-28 12:24:08 +00:00
Vicente J. Botet Escriba
ba1d54d672 Thread: inhibit allocators on wince as there is a bug on Boost.Intrusive
[SVN r78226]
2012-04-28 00:08:53 +00:00
Vicente J. Botet Escriba
b5a18dc71a Thread: Boost.Chrono seems to work on vacpp 11.1
[SVN r78225]
2012-04-27 23:29:01 +00:00
Vicente J. Botet Escriba
4a0141511d Thread: Boost.Chrono seems to work on vacpp 11.1
[SVN r78224]
2012-04-27 23:08:24 +00:00
Vicente J. Botet Escriba
f0a6e49984 Thread: Try to fix some errors with vacpp
[SVN r78222]
2012-04-27 22:24:17 +00:00
Vicente J. Botet Escriba
f60e1d1230 Thread: Try to fix some spourious error
[SVN r78197]
2012-04-25 21:55:07 +00:00
Vicente J. Botet Escriba
625db78abf Thread: more move semantics refactoring cleanup
[SVN r78139]
2012-04-22 16:33:46 +00:00
Vicente J. Botet Escriba
b470ffdb56 Thread: Added macro BOOST_THREAD_DCL_MOVABLE to mask has_move_emulation_enabled_aux specialization
[SVN r78123]
2012-04-22 08:12:27 +00:00
Vicente J. Botet Escriba
78095afdbc Thread: Fix issue with macro BOOST_THREAD_RV_REF and the use of templates as arguments, see with Sun compiler
[SVN r78086]
2012-04-19 22:19:52 +00:00
Vicente J. Botet Escriba
e83cdc6721 Thread: Change to version 3 and don't deprecate legacy time related functions, even if they are not part of the concepts since version 3
[SVN r78029]
2012-04-16 20:49:18 +00:00
Vicente J. Botet Escriba
7ba000fe45 Thread: Set by default to don't use Boost.Move
[SVN r77994]
2012-04-15 12:29:33 +00:00
Vicente J. Botet Escriba
cae6a36c19 Thread: fix some macros using old move emilation
[SVN r77985]
2012-04-15 09:55:25 +00:00
Vicente J. Botet Escriba
8549895373 Thread: Make use of the new macros to reduce the code duplication-IV
[SVN r77946]
2012-04-13 09:39:17 +00:00
Vicente J. Botet Escriba
efa907881e Thread: Make use of the new macros to reduce the code duplication-III
[SVN r77941]
2012-04-12 22:59:23 +00:00
Vicente J. Botet Escriba
744cae8270 Thread: Make use of the new macros to reduce the code duplication
[SVN r77939]
2012-04-12 20:32:20 +00:00
Vicente J. Botet Escriba
28899243b1 Thread: symplify additonaly the conditional code + fix some spurious regression errors
[SVN r77933]
2012-04-12 11:12:23 +00:00
Vicente J. Botet Escriba
267288ba19 Thread! remove unused param warning
[SVN r77930]
2012-04-12 08:07:00 +00:00
Vicente J. Botet Escriba
3487d05fac Thread: Fix typo
[SVN r77929]
2012-04-12 08:06:13 +00:00
Vicente J. Botet Escriba
031186a8e6 Thread: Add some macros to simplify the conditional code in particular the one related to mmove semantics+ fix some minor regression issues
[SVN r77928]
2012-04-11 23:42:26 +00:00
Vicente J. Botet Escriba
f970c9fddc Thread: remove some warnings + rename BOOST_EXPLICIT_MOVE by BOOST_THREAD_MAKE_RV_REF
[SVN r77918]
2012-04-11 17:16:45 +00:00
Vicente J. Botet Escriba
e9ceaaa2bb Thread: Set examples exmplcit
[SVN r77888]
2012-04-10 16:22:51 +00:00
Vicente J. Botet Escriba
0e7c436df5 Thread: Added container tests
[SVN r77887]
2012-04-10 16:21:43 +00:00
Vicente J. Botet Escriba
745e23f2c3 Thread: move specialization of uses_allocator
[SVN r77885]
2012-04-10 13:29:36 +00:00
Vicente J. Botet Escriba
1f7b8a6583 Thread: Added -ansi -permissive on some compilers
[SVN r77884]
2012-04-10 12:33:51 +00:00
Vicente J. Botet Escriba
b2790c6df5 Thread: Added pt test constructor from const functor + pt allocator ctor free fct+ cleanup of other tests
[SVN r77877]
2012-04-10 01:37:18 +00:00
Vicente J. Botet Escriba
f5e3c1c348 Thread: Added pt func_ctor test + update some test to pass Sun compiler regression
[SVN r77876]
2012-04-10 00:24:07 +00:00
Vicente J. Botet Escriba
ba955f003e Thread: Fix packaged_task callable copy
[SVN r77875]
2012-04-10 00:14:12 +00:00
Vicente J. Botet Escriba
75e0ffbbce Thread: rollback the last changes in packaged_task
[SVN r77870]
2012-04-09 23:21:16 +00:00
Vicente J. Botet Escriba
9168dd7d1d Thread: fix commit error
[SVN r77860]
2012-04-09 19:23:37 +00:00
Vicente J. Botet Escriba
ee5f871f1a Thread: fix commit error
[SVN r77857]
2012-04-09 18:56:39 +00:00
Vicente J. Botet Escriba
c896c8fda4 Thread: fix commit error
[SVN r77853]
2012-04-09 17:52:46 +00:00
Vicente J. Botet Escriba
0e895a1e28 Thread: Added packaged_task::reste() + more tests
[SVN r77852]
2012-04-09 17:18:39 +00:00
Vicente J. Botet Escriba
d95081094f Thread: remove some warnings
[SVN r77849]
2012-04-09 15:26:40 +00:00
Vicente J. Botet Escriba
011dda9816 Thread: Added packaged_task ctor allocator + result_type + Fix issue signaled on the ML with task_object(task_object const&) in presence of task_object(task_object &&)
[SVN r77845]
2012-04-08 23:51:07 +00:00
Vicente J. Botet Escriba
34c377328f Thread: Added some packaged_task tests
[SVN r77844]
2012-04-08 23:24:19 +00:00
Vicente J. Botet Escriba
382204f702 Thread: Make use of the boost version of use_allocator
[SVN r77843]
2012-04-08 22:40:37 +00:00
Vicente J. Botet Escriba
19aed55e52 Thread: Fix type
[SVN r77841]
2012-04-08 20:56:34 +00:00
Vicente J. Botet Escriba
9d1e1fb64a Thread: Activate share mutex upwards conversions tests
[SVN r77839]
2012-04-08 19:23:34 +00:00
Vicente J. Botet Escriba
d75cda0cc3 Thread: Provided an alternative implementation for thread::id using pthread_t and Windows Thread Id
[SVN r77838]
2012-04-08 19:22:38 +00:00
Vicente J. Botet Escriba
a4c7f68320 Thread: Added needed header
[SVN r77836]
2012-04-08 18:57:07 +00:00
Vicente J. Botet Escriba
547431da0b Thread: fix typo
[SVN r77825]
2012-04-08 07:57:32 +00:00
Vicente J. Botet Escriba
c3fdc098fe Thread: Try to fix some failing tests on sun
[SVN r77806]
2012-04-07 07:59:23 +00:00
Vicente J. Botet Escriba
6ed276190d Thread: rename macros and try to fix some failing sun test
[SVN r77789]
2012-04-05 22:39:22 +00:00
Vicente J. Botet Escriba
59265265d9 Thread: 6342: Adapt the one_flag and call_once to the c++11 interface
[SVN r77767]
2012-04-04 20:01:11 +00:00
Vicente J. Botet Escriba
8d9370b005 Thread: Try to pass these tests on VACPP
[SVN r77766]
2012-04-04 19:56:56 +00:00
Vicente J. Botet Escriba
fd97c6e7a7 Thread: Try to pass these test on Sun using BOOST_EXPLICIT_MOVE
[SVN r77754]
2012-04-04 15:15:11 +00:00
Vicente J. Botet Escriba
297da0745f Thread: Try to pass these test on Sun using BOOST_EXPLICIT_MOVE
[SVN r77753]
2012-04-04 15:14:05 +00:00
Vicente J. Botet Escriba
cb231e02a6 Thread: Try to pass these test on Sun using BOOST_EXPLICIT_MOVE
[SVN r77751]
2012-04-03 20:57:24 +00:00
Vicente J. Botet Escriba
298b51fefa Thread: Check if adding BOOST_EXPLICIT_MOVE helps on Sun
[SVN r77729]
2012-04-02 22:49:11 +00:00
Vicente J. Botet Escriba
80befa1c94 Thread: rollback 76581 partialy so that no link with boost chrono is done on vaccp
[SVN r77728]
2012-04-02 22:33:05 +00:00
Vicente J. Botet Escriba
11dce20534 Thread: Remove duplicated file #3160
[SVN r77719]
2012-04-02 16:37:53 +00:00
Vicente J. Botet Escriba
56bd079f96 Thread: Added call to terminate if joinable for #6266 and #6269
[SVN r77718]
2012-04-02 16:32:33 +00:00
Vicente J. Botet Escriba
733b49ae42 Thread: Fix Jamfile removing not needed source shared_mutex.cpp
[SVN r77705]
2012-04-01 22:14:06 +00:00
Vicente J. Botet Escriba
08ed4c4201 Thread: Added shared mutex upwards conversion + configuration macros
[SVN r77704]
2012-04-01 21:52:47 +00:00
Vicente J. Botet Escriba
09d5125278 Thread: Fix typos due to copy/paste
[SVN r77701]
2012-04-01 20:38:31 +00:00
Vicente J. Botet Escriba
6e1a3f3c27 Thread: Added specific macros for futures and importing container specific into boost
[SVN r77687]
2012-04-01 15:51:18 +00:00
Vicente J. Botet Escriba
5b3743d9a6 Thread: Split test with and wothout args
[SVN r77686]
2012-04-01 15:48:56 +00:00
Vicente J. Botet Escriba
ec135b1b8e Thread: Added missing file
[SVN r77684]
2012-04-01 09:14:50 +00:00
Vicente J. Botet Escriba
60e34cff11 Thread: Make use of the generic shared implementation for the missing features in windows.
[SVN r77668]
2012-03-31 15:38:56 +00:00
Vicente J. Botet Escriba
da8dc9f5aa Thread: Add the possibility to use the more complete and generic implementation of shared_mutex in windows.
[SVN r77667]
2012-03-31 15:37:44 +00:00
Vicente J. Botet Escriba
27aa44acb5 Thread: Added promise allocator ctor + more tests
[SVN r77666]
2012-03-31 15:19:22 +00:00
Vicente J. Botet Escriba
ff1d051359 Thread: Added reverse_lock
[SVN r77662]
2012-03-31 08:39:21 +00:00
Vicente J. Botet Escriba
85e32534fa Thread: Added shared_lock_guard
[SVN r77661]
2012-03-31 08:06:57 +00:00
Vicente J. Botet Escriba
bc49b7d03a Thread: Update doc with a lot of changes to follow the updated code
[SVN r77660]
2012-03-31 07:37:59 +00:00
Vicente J. Botet Escriba
ee97068208 Thread Fix incoherent BOOST_NOEXCEPT prototype
[SVN r77659]
2012-03-31 07:16:20 +00:00
Vicente J. Botet Escriba
0f7e069dd9 Thread: Added explicit int conversion from lock should fail
[SVN r77658]
2012-03-31 06:52:55 +00:00
Vicente J. Botet Escriba
3c3c6d5efe Thread: Fix warning + added DEPRECATED tag
[SVN r77655]
2012-03-30 19:16:51 +00:00
Vicente J. Botet Escriba
f163054557 Thread: Added more noexcept
[SVN r77640]
2012-03-30 04:46:47 +00:00
Vicente J. Botet Escriba
fb80bea056 Thread: Disable The use of Boost.Thread for SunPro compiler
[SVN r77612]
2012-03-28 20:40:31 +00:00
Vicente J. Botet Escriba
abad5c3028 Thread: Added BOOST_EXPLICIT_MOVE
[SVN r77588]
2012-03-27 18:22:30 +00:00
Vicente J. Botet Escriba
d0c164220d Thread: DOn't use Boost.Test when not needed to avoid issues on Sun
[SVN r77586]
2012-03-27 17:26:10 +00:00
Vicente J. Botet Escriba
34b1a86a68 Thread: Update F_pass and Frvalue tests for compilers that doesn't support rvalue references or delete constructors.
[SVN r77551]
2012-03-25 22:31:11 +00:00
Vicente J. Botet Escriba
06f5da7f5b Thread: cleanup
[SVN r77550]
2012-03-25 21:25:20 +00:00
Vicente J. Botet Escriba
1e80ccb8d3 Thread: Protect uses of Boost.Chrono for compilers don't providing support for
[SVN r77460]
2012-03-21 21:05:26 +00:00
Vicente J. Botet Escriba
8ad34a689a Thread: Fixed error on promise v2 + added tests (share)
[SVN r77443]
2012-03-20 23:49:31 +00:00
Vicente J. Botet Escriba
a421e10e3b Thread: Comment not yet commited tests
[SVN r77427]
2012-03-20 07:48:36 +00:00
Vicente J. Botet Escriba
1c4b42bb95 Thread: Make test names shorter
[SVN r77401]
2012-03-19 12:12:21 +00:00
Vicente J. Botet Escriba
bba3be457b Thread: Fix missing include
[SVN r77399]
2012-03-19 06:49:13 +00:00
Vicente J. Botet Escriba
3abfbb8ba1 Thread: Added upgrade_mutex on windows
[SVN r77396]
2012-03-18 23:42:23 +00:00
Vicente J. Botet Escriba
331a35070c Thread: comment not yet committed examples
[SVN r77394]
2012-03-18 22:55:13 +00:00
Vicente J. Botet Escriba
99ad690382 Thread: Added Chrono related functions to exclusive lock+ upgrade_mutex typedef
[SVN r77393]
2012-03-18 22:49:24 +00:00
Vicente J. Botet Escriba
4301b21702 Thread: Added LOCK::move() member function when no RVALUE is available (Useful for Sun compiler to force move semantics) + possibility to have explicit lock conversions+chrono timed related unique_lock constructor from upgrade_lock
[SVN r77392]
2012-03-18 22:35:11 +00:00
Vicente J. Botet Escriba
fceab582fe Thread: Added future/shared/future/promise/packaged_task::move() member function when no RVALUE is available (Useful for Sun compiler to force move semantics)
[SVN r77391]
2012-03-18 22:06:44 +00:00
Vicente J. Botet Escriba
e8a4ed40a5 Thread: Make test names shorter + Added more tests on locks
[SVN r77388]
2012-03-18 21:27:30 +00:00
Vicente J. Botet Escriba
b698c1437b Thread: Update test to run
[SVN r77384]
2012-03-18 19:54:39 +00:00
Vicente J. Botet Escriba
14cea92e06 Thread: Added thread::move member function when BOOST_THREAD_USES_MOVE is defined (Useful for Sun compiler)
[SVN r77379]
2012-03-18 18:35:20 +00:00
Vicente J. Botet Escriba
3a8e04cac6 Thread: Make test names shorter + Added some examples of shared mutex and tests
[SVN r77378]
2012-03-18 18:21:45 +00:00
Vicente J. Botet Escriba
5b01721440 Thread: Add time chrono related functions to shared_mutex(win) + activate tests
[SVN r77376]
2012-03-18 17:29:33 +00:00
Vicente J. Botet Escriba
aad2b35ac9 Thread: Fix bug on time related functions that should base the _for functions on the until_ ones
[SVN r77375]
2012-03-18 17:26:30 +00:00
Vicente J. Botet Escriba
f8371daeb8 Thread: Avoid some warnings as unused variable it and warning C4275: non dll-interface class 'std::logic_error' used as base for dll-interface class 'boost::future_error'
[SVN r77360]
2012-03-17 14:42:36 +00:00
Vicente J. Botet Escriba
74519977fd Thread: Avoid warning boost/bind/bind.hpp(392) : warning C4244: 'argument' : conversion from 'double' to 'int', possible loss of data
[SVN r77356]
2012-03-17 12:47:54 +00:00
Vicente J. Botet Escriba
c0bea158d4 Thread: Use of BOOST_ASSERT_MSG
[SVN r77330]
2012-03-14 06:39:07 +00:00
Vicente J. Botet Escriba
70686b4913 Thread: Comment not yet committed test
[SVN r77294]
2012-03-10 17:27:10 +00:00
Vicente J. Botet Escriba
14502dd715 Thread: Added test for upgrade_lock
[SVN r77293]
2012-03-10 17:17:14 +00:00
Vicente J. Botet Escriba
8ee986536b Thread: Added test for shared_lock move from other locks
[SVN r77292]
2012-03-10 17:07:39 +00:00
Vicente J. Botet Escriba
8ed82798d2 Thread: Fix #6673 and partial fix for 6671, 6672, 6675 which need to add the documentation and test
[SVN r77291]
2012-03-10 17:05:34 +00:00
Vicente J. Botet Escriba
ebfe10b7df Thread: Fix error on pthread/shared_mutex.hpp try_lock_xxx_for, which should use the try_lock_xxx_until+fix #6674
[SVN r77290]
2012-03-10 17:01:27 +00:00
Vicente J. Botet Escriba
4aa26180ca Thread: removed output to cout to fix 6612
[SVN r77224]
2012-03-04 20:56:42 +00:00
Vicente J. Botet Escriba
89496448d9 Thread: Update doc removing thread_move_t
[SVN r77136]
2012-02-28 18:49:22 +00:00
Vicente J. Botet Escriba
dfa0a3979a Thread: Add explicit #error when the test is not applicable
[SVN r77041]
2012-02-16 18:12:03 +00:00
Vicente J. Botet Escriba
396cd7db4f Thread: Added traces to try to catch some issues
[SVN r77038]
2012-02-16 17:40:47 +00:00
Vicente J. Botet Escriba
0351d59060 Thread: Added chrono i/f and improve move semantics for shared_mutex and shared_lock (pthread)
[SVN r77011]
2012-02-13 23:20:42 +00:00
Vicente J. Botet Escriba
6f0b0e976d Thread: uncomment Frvalue_pass test
[SVN r77004]
2012-02-13 07:48:23 +00:00
Vicente J. Botet Escriba
dd5d687014 Thread: Added chrono i/f for shared_mutex pthread
[SVN r77003]
2012-02-12 22:38:59 +00:00
Vicente J. Botet Escriba
5d8b0891bd Thread: Don't fail when native_handle is not defined
[SVN r76996]
2012-02-12 16:47:19 +00:00
Vicente J. Botet Escriba
7dc95f63d3 Thread: Move semantics cleanup
[SVN r76995]
2012-02-12 16:44:43 +00:00
Jürgen Hunold
a7adc5865b Fix: correct logic for enabling c++11 explicit conversion operators
[SVN r76959]
2012-02-09 20:21:43 +00:00
Vicente J. Botet Escriba
cdbe5766fa Thread: try to fix 6456 - trunk compilation errors converting future_errc to int
[SVN r76952]
2012-02-08 21:34:29 +00:00
Vicente J. Botet Escriba
b1cac0731c Thread: Added explicit to operator bool for locks
[SVN r76951]
2012-02-08 21:32:05 +00:00
Vicente J. Botet Escriba
fc8de511c6 Thread: Added detail/scoped_enumm.hpp file and adaptat enum classes to the new interface
[SVN r76777]
2012-01-29 18:27:26 +00:00
Vicente J. Botet Escriba
defdb8ff1c Thread: Try to fix 4885 - Access violation in set_tss_data at process exit due to invalid assumption about TlsAlloc
[SVN r76752]
2012-01-28 16:02:01 +00:00
Vicente J. Botet Escriba
9a08a8478f Thread: Try to fix 6431 - MinGW: Cannot export (anonymous namespace)::thread_binder
[SVN r76598]
2012-01-20 18:53:55 +00:00
Vicente J. Botet Escriba
a6f7a0180b Thread: Try to fix min stack size
[SVN r76597]
2012-01-20 18:52:21 +00:00
Vicente J. Botet Escriba
5a59df4476 Thread: Try to fix min stack size
[SVN r76596]
2012-01-20 18:51:24 +00:00
Vicente J. Botet Escriba
1df9d7c575 Thread: avoid the use of Boost.Chrono for vacpp toolset
[SVN r76581]
2012-01-18 21:07:13 +00:00
Vicente J. Botet Escriba
65008b11f7 Thread: Try to fix some checks that fails depending on the way the threads are switched (the time constraint is too high)
[SVN r76580]
2012-01-18 21:04:47 +00:00
Vicente J. Botet Escriba
b18314878a Thread: try to make it possible to avoid the use of Boost.Chrono
[SVN r76570]
2012-01-18 00:13:17 +00:00
Vicente J. Botet Escriba
11a951c679 Thread: Try to fix some checks that fails depending on the way the threads are switched (the time constraint is too high)
[SVN r76565]
2012-01-17 22:24:06 +00:00
Vicente J. Botet Escriba
c67e3ff7b9 Thread: try to fix #6420 - Call to forward ambiguous
[SVN r76561]
2012-01-17 18:51:36 +00:00
Vicente J. Botet Escriba
e5a633cc41 Thread: Try to fix #6418 - error: 'X(X&&)' cannot be defaulted
[SVN r76558]
2012-01-17 18:31:03 +00:00
Vicente J. Botet Escriba
3724d847cf Thread: Try to fix #6419 - Error: PTHREAD_STACK_MIN is not always defined when PTHREADS are used
[SVN r76557]
2012-01-17 18:28:46 +00:00
Vicente J. Botet Escriba
b6063b5c60 * [@http://svn.boost.org/trac/boost/ticket/2741 #2741] Proposal to manage portable and non portable thread attributes.
* [@http://svn.boost.org/trac/boost/ticket/6195 #6195] c++11 compliance: Provide the standard time related interface using Boost.Chrono. 
* [@http://svn.boost.org/trac/boost/ticket/6224 #6224] c++11 compliance: Add the use of standard noexcept on compilers supporting them. 
* [@http://svn.boost.org/trac/boost/ticket/6226 #6226] c++11 compliance: Add explicit bool conversion from locks. 
* [@http://svn.boost.org/trac/boost/ticket/6230 #6230] c++11 compliance: Follows the exception reporting mechanism as defined in the c++11. 
* [@http://svn.boost.org/trac/boost/ticket/6272 #6272] c++11 compliance: Add thread::id hash specialization.
* [@http://svn.boost.org/trac/boost/ticket/6273 #6273] c++11 compliance: Add cv_status enum class and use it on the conditions wait functions. 
* [@http://svn.boost.org/trac/boost/ticket/6194 #6194] Adapt to Boost.Move. 
 	
Fixed Bugs:

* [@http://svn.boost.org/trac/boost/ticket/2575 #2575] Bug- Boost 1.36.0 on Itanium platform.
* [@http://svn.boost.org/trac/boost/ticket/4921 #4921] BOOST_THREAD_USE_DLL and BOOST_THREAD_USE_LIB are crucial and need to be documented.
* [@http://svn.boost.org/trac/boost/ticket/5013 #5013] documentation: boost:🧵 pthreas_exit causes terminate().

* [@http://svn.boost.org/trac/boost/ticket/5351 #5351] interrupt a future get boost::unknown_exception.
* [@http://svn.boost.org/trac/boost/ticket/5516 #5516] Upgrade lock is not acquired when previous upgrade lock releases if another read lock is present. 
* [@http://svn.boost.org/trac/boost/ticket/5990 #5990] shared_future<T>::get() has wrong return type. 
* [@http://svn.boost.org/trac/boost/ticket/6174 #6174] packaged_task doesn't correctly handle moving results.



[SVN r76543]
2012-01-16 17:32:08 +00:00
Vicente J. Botet Escriba
09362f0eac Thread: merge from trunk to fix #6141, #5594, #5040 and #5502.
[SVN r76346]
2012-01-07 20:52:57 +00:00
Vicente J. Botet Escriba
32b3f3f569 Thread: Fix typo on auto_ptr
[SVN r76345]
2012-01-07 20:15:14 +00:00
Vicente J. Botet Escriba
0d08362291 Thread: Added new v2 files
[SVN r76300]
2012-01-03 22:31:11 +00:00
Vicente J. Botet Escriba
9f120a80a7 Thread: Updated Jamfiles to take care of Boost.Chrono, Boost.System and the new tests
[SVN r76298]
2012-01-03 21:50:37 +00:00
Vicente J. Botet Escriba
2eb6fd754e Thread: Added doc related to a lot of tickets mainly the time related #6195, noexcept #6224, exceptions #6230, cv_status #6273
[SVN r76297]
2012-01-03 21:45:31 +00:00
Vicente J. Botet Escriba
9f4a8973d0 Thread: Added test related to tickets
[SVN r76296]
2012-01-03 21:25:58 +00:00
Vicente J. Botet Escriba
a4d9355060 Threads: Added a lot of unit tests
[SVN r76295]
2012-01-03 21:23:11 +00:00
Vicente J. Botet Escriba
5a7545afbd Thread Towards #6273 - Add cv_status enum class and use it on the conditions wait functions
[SVN r76294]
2012-01-03 21:12:59 +00:00
Vicente J. Botet Escriba
8affa33718 Thread fixed Bugs:
* [@http://svn.boost.org/trac/boost/ticket/2309 #2309] Lack of g++ symbol visibility support in Boost.Thread. 
* [@http://svn.boost.org/trac/boost/ticket/2639 #2639] documentation should be extended(defer_lock, try_to_lock, ...).

* [@http://svn.boost.org/trac/boost/ticket/3639 #3639] Boost.Thread doesn't build with Sun-5.9 on Linux.
* [@http://svn.boost.org/trac/boost/ticket/3762 #3762] Thread can't be compiled with winscw (Codewarrior by Nokia).
* [@http://svn.boost.org/trac/boost/ticket/3885 #3885] document about mix usage of boost.thread and native thread api.
* [@http://svn.boost.org/trac/boost/ticket/3975 #3975] Incorrect precondition for promise::set_wait_callback().

* [@http://svn.boost.org/trac/boost/ticket/4048 #4048] thread::id formatting involves locale
* [@http://svn.boost.org/trac/boost/ticket/4315 #4315] gcc 4.4 Warning: inline ... declared as dllimport: attribute ignored. 
* [@http://svn.boost.org/trac/boost/ticket/4480 #4480] OpenVMS patches for compiler issues workarounds.
* [@http://svn.boost.org/trac/boost/ticket/4819 #4819] boost.thread's documentation misprints.

* [@http://svn.boost.org/trac/boost/ticket/5423 #5423] thread issues with C++0x.
* [@http://svn.boost.org/trac/boost/ticket/5617 #5617] boost::thread::id copy ctor.
* [@http://svn.boost.org/trac/boost/ticket/5739 #5739] set-but-not-used warnings with gcc-4.6.
* [@http://svn.boost.org/trac/boost/ticket/5826 #5826] threads.cpp: resource leak on threads creation failure.
* [@http://svn.boost.org/trac/boost/ticket/5839 #5839] thread.cpp: ThreadProxy leaks on exceptions.
* [@http://svn.boost.org/trac/boost/ticket/5859 #5859] win32 shared_mutex constructor leaks on exceptions. 

* [@http://svn.boost.org/trac/boost/ticket/6100 #6100] Compute hardware_concurrency() using get_nprocs() on GLIBC systems.
* [@http://svn.boost.org/trac/boost/ticket/6168 #6168] recursive_mutex is using wrong config symbol (possible typo).
* [@http://svn.boost.org/trac/boost/ticket/6175 #6175] Compile error with SunStudio.
* [@http://svn.boost.org/trac/boost/ticket/6200 #6200] patch to have condition_variable and mutex error better handle EINTR. 
* [@http://svn.boost.org/trac/boost/ticket/6207 #6207] shared_lock swap compiler error on clang 3.0 c++11. 
* [@http://svn.boost.org/trac/boost/ticket/6208 #6208] try_lock_wrapper swap compiler error on clang 3.0 c++11. 




[SVN r76291]
2012-01-03 17:31:50 +00:00
Vicente J. Botet Escriba
4d25ea1760 Thread: protect of threading=single by forcing threading=multi
[SVN r76283]
2012-01-02 22:08:02 +00:00
Vicente J. Botet Escriba
6ec8e2ccec Thread: Fix error following last commit 76277 for #6141
[SVN r76280]
2012-01-02 17:48:18 +00:00
Vicente J. Botet Escriba
97d0ae6527 Thread: #6141 - Compilation error when boost.thread and boost.move are used together
[SVN r76277]
2012-01-02 17:12:01 +00:00
Vicente J. Botet Escriba
50a74d0eda Thread: Try to solve #6341 Boost.Thread defines boost::move which conflicts with Boost.Move
[SVN r76268]
2012-01-02 00:33:32 +00:00
Vicente J. Botet Escriba
f9e03b5eaa Thread: Notify shread_cond when state.exclusive_waiting_blocked=false in shared_mutex::timed_lock to resolve #5502
[SVN r76084]
2011-12-20 21:13:22 +00:00
Vicente J. Botet Escriba
ad571bd898 Thread: Fix error returning in constructor
[SVN r76078]
2011-12-20 12:42:45 +00:00
Vicente J. Botet Escriba
de8ef9aee4 Thread: reverse part of commit r76040 which breaks msvc-10.0
[SVN r76075]
2011-12-19 23:50:03 +00:00
Vicente J. Botet Escriba
21f75da2f6 Thread: don't overload move when BOOST_NO_RVALUE_REFERENCES is not defined
[SVN r76074]
2011-12-19 23:22:08 +00:00
Vicente J. Botet Escriba
233dbf8075 Thread: dont use thread_move_t when BOOST_NO_RVALUE_REFERENCES is not defined
[SVN r76073]
2011-12-19 23:20:31 +00:00
Vicente J. Botet Escriba
d8f1ba9b3d Thread: added move definition when BOOST_NO_RVALUE_REFERENCES is not defined
[SVN r76040]
2011-12-18 14:34:09 +00:00
Vicente J. Botet Escriba
1241f18215 Thread: replace BOOST_HAS_RVALUE_REFS by BOOST_NO_RVALUE_REFERENCES and protect uses of thread_move_t
[SVN r76039]
2011-12-18 14:31:36 +00:00
Vicente J. Botet Escriba
b6604882eb Thread: Added BOOST_THREAD_VERSION so that we can add backward incompatible features
[SVN r76037]
2011-12-18 13:37:37 +00:00
Vicente J. Botet Escriba
a9c9d5c499 Thread: #4048 thread::id formatting: use ios_flags_saver
[SVN r76011]
2011-12-17 09:02:10 +00:00
Vicente J. Botet Escriba
9a827d937e Thread: #4921 BOOST_THREAD_USE_DLL and BOOST_THREAD_USE_LIB are crucial and need to be documented
[SVN r75905]
2011-12-11 18:16:07 +00:00
Vicente J. Botet Escriba
38594f889a Thread: #5013 - documentation: boost:🧵 pthreas_exit causes terminate()
[SVN r75904]
2011-12-11 18:12:55 +00:00
Vicente J. Botet Escriba
04c17e45b3 Thread: #5594 boost::shared_mutex not fully compatible with Windows CE.
[SVN r75903]
2011-12-11 15:43:13 +00:00
Vicente J. Botet Escriba
730a8de024 Thread: #5040 future.hpp in boost::thread does not compile with /clr
[SVN r75901]
2011-12-11 13:32:41 +00:00
Vicente J. Botet Escriba
7eac2fe3e4 Thread: Fix auto_ptr error
[SVN r75886]
2011-12-10 14:59:43 +00:00
Vicente J. Botet Escriba
267243d959 Thread: Fix typo
[SVN r75885]
2011-12-10 14:51:16 +00:00
Vicente J. Botet Escriba
f587262c8e Thread: Added compliance matrix
[SVN r75884]
2011-12-10 11:56:45 +00:00
Vicente J. Botet Escriba
ebf458dbd0 Thread: update fixed tickets for 1.49
[SVN r75883]
2011-12-10 11:54:36 +00:00
Vicente J. Botet Escriba
f64b5559dd Thread: #6200-mutex error better handle EINTR
[SVN r75882]
2011-12-10 10:55:53 +00:00
Vicente J. Botet Escriba
2ddcd5f678 Thread: #6200-mutex error better handle EINTR
[SVN r75860]
2011-12-07 23:15:20 +00:00
Vicente J. Botet Escriba
cac715937a Thread: boost thread unit test module bug on Microsoft Visual Studio debug mode
[SVN r75858]
2011-12-07 21:08:52 +00:00
Vicente J. Botet Escriba
39f43feb11 Thread: Added more fixed tickets
[SVN r75807]
2011-12-05 00:27:46 +00:00
Vicente J. Botet Escriba
58d65b17ea Thread: #5859 win32 shared_mutex constructor leaks on exceptions
[SVN r75806]
2011-12-04 23:06:24 +00:00
Vicente J. Botet Escriba
4314f0cac3 Thread: #3762 Thread can't be compiled with winscw (Codewarrior by Nokia) (win part)
[SVN r75802]
2011-12-04 15:18:32 +00:00
Vicente J. Botet Escriba
d4da369930 Thread: 6207/6208 shared_lock/try_lock_wrapper swap compiler error on clang 3.0 c++11
[SVN r75801]
2011-12-04 14:58:08 +00:00
Vicente J. Botet Escriba
6f1876b618 Thread: #6100 Compute hardware_concurrency() using get_nprocs() on GLIBC systems
[SVN r75800]
2011-12-04 14:33:08 +00:00
Vicente J. Botet Escriba
c6e872ceb0 Thread: #2309 - Lack of g++ symbol visibility support in Boost.Thread
[SVN r75799]
2011-12-04 10:36:34 +00:00
Vicente J. Botet Escriba
72d809819f Thread: #3639 Boost.Thread doesn't build with Sun-5.9 on Linux
[SVN r75798]
2011-12-04 09:35:34 +00:00
Vicente J. Botet Escriba
dd09ef3362 Thread: 4315 gcc 4.4 Warning: inline ... declared as dllimport: attribute ignored
[SVN r75791]
2011-12-03 17:56:38 +00:00
Vicente J. Botet Escriba
aa7941fae2 Thread: 2639 documentation should be extended(defer_lock, try_to_lock, ...) + 3885 document about mix usage of boost.thread and native thread api. + 3975 Incorrect precondition for promise::set_wait_callback() + 4819 boost.thread's documentation misprints.
[SVN r75790]
2011-12-03 14:28:17 +00:00
Vicente J. Botet Escriba
35af4a8f35 Thread: 3762 Thread can't be compiled with winscw (Codewarrior by Nokia) (pthread part)
[SVN r75789]
2011-12-03 14:11:02 +00:00
Vicente J. Botet Escriba
a01fd3dd76 Thread: 4480 (move part) + 6175 Compile error with SunStudio
[SVN r75788]
2011-12-03 14:06:32 +00:00
Vicente J. Botet Escriba
d220da89d1 Thread: 4480 OpenVMS patches for compiler issues workarounds (only sleep part)
[SVN r75787]
2011-12-03 13:57:06 +00:00
Vicente J. Botet Escriba
55c75e9299 Thread: 5423 thread issues with C++0x
[SVN r75786]
2011-12-03 13:50:40 +00:00
Vicente J. Botet Escriba
616ea87a0a Thread: 5739 set-but-not-used warnings with gcc-4.6
[SVN r75785]
2011-12-03 13:25:55 +00:00
Vicente J. Botet Escriba
319ba2fe75 Thread: 6200 patch to have condition_variable and mutex error better handle EINTR
[SVN r75781]
2011-12-03 10:09:11 +00:00
Vicente J. Botet Escriba
d79eeff779 Thread:6168 recursive_mutex is using wrong config symbol (possible typo)
[SVN r75780]
2011-12-03 10:02:37 +00:00
Gennadiy Rozental
26d38748db eliminated test_case_template.hpp
[SVN r74735]
2011-10-05 10:28:08 +00:00
Gennadiy Rozental
5c124234bb eliminated unit_test_framework and BOOST_MESSAGE
[SVN r74731]
2011-10-05 09:52:10 +00:00
Anthony Williams
b991c9a8a0 Merged thread changes from trunk
[SVN r72431]
2011-06-06 08:28:31 +00:00
Anthony Williams
681af396b8 Change pin_to_zero and interruptible_wait to use (u)intmax_t rather than (unsigned) long, to avoid warnings about truncation
[SVN r72303]
2011-05-31 12:28:11 +00:00
Anthony Williams
cac0eaa6c3 Put static functions inside extern "C" block rather than trying to declare each as extern "C"
[SVN r72176]
2011-05-26 09:00:58 +00:00
Anthony Williams
a64fa2c18f extern "C" functions are static
[SVN r72166]
2011-05-25 21:18:59 +00:00
Neil Groves
f07640850b [boost][thread] - Resolved Ticket 5170 by making the extern "C" functions static.
[SVN r72120]
2011-05-23 13:24:16 +00:00
Marshall Clow
ab665c8c56 Merge fixes to release; Fixes #1988
[SVN r71676]
2011-05-02 20:56:53 +00:00
Marshall Clow
e43586ffac Renamed BOOST_NO_THREADEX -> BOOST_HAS_THREADEX and BOOST_NO_GETSYSTEMTIMEASFILETIME --> BOOST_HAS_GETSYSTEMTIMEASFILETIME - Refs #1988
[SVN r71533]
2011-04-27 15:51:07 +00:00
Anthony Williams
9cc243837d Fixed typo
[SVN r70470]
2011-03-23 08:17:45 +00:00
Anthony Williams
de7e3baabc Applied patch from issue #4849
[SVN r70383]
2011-03-21 23:09:07 +00:00
Anthony Williams
7ec9804540 Merged Boost.Thread changes from trunk
[SVN r70382]
2011-03-21 22:59:40 +00:00
Anthony Williams
5e29afcb57 Remove inner definition of cond_res from timed_wait so outer variable
is set correctly


[SVN r69621]
2011-03-07 08:39:37 +00:00
Anthony Williams
0a1085d9be Patch condition variables to ensure that the cond mutex is unlocked before we try and check for interruption
[SVN r69547]
2011-03-04 15:44:53 +00:00
David Deakins
0439d53704 Minor patch to fix support for Windows CE (use 0xFFFFFFFF in place of TLS_OUT_OF_INDEXES on Windows CE since Windows CE does not define this constant).
[SVN r69115]
2011-02-21 04:07:13 +00:00
Hartmut Kaiser
7c9116af2e Spirit: merge from trunk
[SVN r68078]
2011-01-13 02:11:19 +00:00
Hartmut Kaiser
5ac2ff4521 Reverted accidental commit, sorry...
[SVN r67895]
2011-01-09 22:21:03 +00:00
Hartmut Kaiser
8565a3e472 Spirit: replaced proto::lit with spirit::lit
[SVN r67754]
2011-01-07 17:50:06 +00:00
Anthony Williams
3648bc8cb0 Throw condition_error if pthread_cond_wait fails, rather than asserting
[SVN r67734]
2011-01-06 22:49:41 +00:00
Anthony Williams
70584af9c0 Merged fix for issue #4736 from trunk
[SVN r66588]
2010-11-15 10:13:12 +00:00
Anthony Williams
73121eda9d Better fix for #4736 --- ensure we have tried to allocate TLS value
before complaining that it's not there, especially in native threads


[SVN r66518]
2010-11-12 09:11:22 +00:00
Anthony Williams
381554f8bc Merged fix for issue #4736 from trunk
[SVN r66482]
2010-11-10 11:24:52 +00:00
Anthony Williams
768e92b0e9 Added comment about lack of cleanup on native threads on some platforms
[SVN r66480]
2010-11-10 10:02:42 +00:00
Anthony Williams
98333b7dcf fix for issue #4736 --- avoid setting tls data after the key has been destroyed
[SVN r66471]
2010-11-09 12:54:23 +00:00
Anthony Williams
4dc1cb1ba1 Merged Boost.Thread from trunk
[SVN r66259]
2010-10-29 23:27:00 +00:00
Anthony Williams
4e0007780c Fix for issue #2330 - remove race condition in condition_variable::wait wrt interruption checking
[SVN r66228]
2010-10-28 14:18:00 +00:00
Vladimir Prus
506019dd62 Remove debug print
[SVN r66171]
2010-10-25 07:52:02 +00:00
Anthony Williams
10f0c3e08e Fix for issue #4531 --- promise::lazy_init uses shared_ptr atomic access functions to avoid race
[SVN r66146]
2010-10-22 14:01:12 +00:00
Anthony Williams
fa2950a04b Fix for #4650 --- put tss_cleanup_implemented in the boost namespace
[SVN r66142]
2010-10-22 09:58:33 +00:00
Anthony Williams
ebfb62ca49 Fixed issue #4727 --- only use microsec clock if available
[SVN r66141]
2010-10-22 09:26:15 +00:00
Anthony Williams
96023e81af Fix for issue #4258 --- static linking now works with recent versions of the mingw runtime
[SVN r66140]
2010-10-22 08:57:19 +00:00
Vladimir Prus
e30be60bc4 Merge r64010, wherein jam has been moved.
[SVN r65233]
2010-09-04 11:02:21 +00:00
Andrey Semashev
7bfafec128 Fixed compilation with MSVC and, probably, other compilers.
[SVN r64999]
2010-08-25 16:41:08 +00:00
Andrey Semashev
9c07d0ff5d Fixed compilation with MSVC and, probably, other compilers.
[SVN r64996]
2010-08-25 15:25:16 +00:00
Anthony Williams
e12d2bc486 Marged changes to Boost.Thread from trunk
[SVN r63915]
2010-07-12 07:47:39 +00:00
Anthony Williams
72a85b396c Fix for issue #4368 --- ensure mutex is destroyed if setattr call fails
[SVN r63799]
2010-07-09 22:00:51 +00:00
Anthony Williams
87786091bb Tidied up call_once to remove unused throw_count stuff
[SVN r63796]
2010-07-09 21:21:48 +00:00
Anthony Williams
784494274b Fix for issue #4225 to allow static initialization of boost::once_flag
[SVN r63795]
2010-07-09 21:15:57 +00:00
Anthony Williams
68012dd92c Fix for issue #4413 --- allow wait_for_any to work with empty ranges
[SVN r63790]
2010-07-09 19:18:16 +00:00
Anthony Williams
a37d2a1364 Merged boost.thread changes over from trunk
[SVN r63789]
2010-07-09 19:13:09 +00:00
Anthony Williams
e40be775fe Ensure futures and shared_mutex work on MSVC-10; fix for issue #2501
[SVN r63750]
2010-07-08 15:25:45 +00:00
Anthony Williams
64e6924132 Moved the test for _GNU_SOURCE to last to try and fix issue #4395
[SVN r63701]
2010-07-06 15:12:21 +00:00
Anthony Williams
4bbf47086d Added missing "typename"
[SVN r63651]
2010-07-05 14:37:13 +00:00
Anthony Williams
7c674bc255 Added overload for swap member function that takes an lvalue reference
in all cases


[SVN r63650]
2010-07-05 14:35:45 +00:00
Daniel James
cc662c102c Merge documentation fixes.
* Use `doc/src/*.css` instead of `doc/html/*.css`.
* Remove wiki and people directories.
* Some documentation fixes.
* Left out `minimal.css` changes and boostbook changes because of clashes.


[SVN r63347]
2010-06-26 12:30:09 +00:00
Steven Watanabe
6b9a2d791b Protect get_thread_info from macro expansion to prevent errors on Haiku. Fixes #4341.
[SVN r63295]
2010-06-24 19:38:16 +00:00
Steven Watanabe
4551e8759b Use __SUNPRO_CC instead of SUNPRO_CC. Fixes #4363.
[SVN r63216]
2010-06-22 01:59:23 +00:00
Daniel James
9442976bdb Update various libraries' documentation build.
Mostly to use the images and css files under doc/src instead of
doc/html, usually be deleting the settings in order to use the defaults.
Also add 'boost.root' to some builds in order to fix links which rely on
it.

[SVN r63146]
2010-06-20 18:00:48 +00:00
Steven Watanabe
8d07df176f Fix non-friend stream operator of thread::id
[SVN r62804]
2010-06-11 14:49:07 +00:00
Steven Watanabe
4b22aff33e Add old auto-link macro for backwards compatibility.
[SVN r62802]
2010-06-11 14:38:28 +00:00
Anthony Williams
93dee254d0 Don't use windows threads if BOOST_DISABLE_WIN32 defined. Fix for
issue #3760


[SVN r62723]
2010-06-10 08:43:10 +00:00
Anthony Williams
a29b598205 Fix for issue #3761 --- if define operator<< for thread::id outside
the class if not supported inside.


[SVN r62722]
2010-06-10 08:34:52 +00:00
Anthony Williams
e3b20eaae9 Remove warnings. Fix for issue #3611
[SVN r62721]
2010-06-10 08:22:39 +00:00
Anthony Williams
d369fb0f94 Emulate recursive mutex if pthread_mutexattr_settype not
available. Fix for issue #2955


[SVN r62720]
2010-06-10 08:10:26 +00:00
Anthony Williams
d816bca42f Only apply Sunpro workarounds for older compilers. Fix for issue #4071
[SVN r62719]
2010-06-10 07:43:17 +00:00
Anthony Williams
d6bb11c4e9 Added __cdecl to PVAPI. Fix for issue #1470
[SVN r62718]
2010-06-10 07:40:12 +00:00
Anthony Williams
2fdcefac05 Added static cast in move of upgrade_lock to work with MSVC10 and g++4.5
[SVN r62717]
2010-06-10 07:38:23 +00:00
Anthony Williams
044c3cc11e Explicitly cast to rvalue reference in cast_to_rval so it works with
MSVC10 and g++4.5


[SVN r62715]
2010-06-10 07:36:57 +00:00
Anthony Williams
bd9223b525 Don't warn about long long usage with gcc. Fix for issue #3680
[SVN r62654]
2010-06-09 13:04:06 +00:00
Anthony Williams
347703dab2 Changed while(true) to for(;;) to avoid warnings. Fix for issue #3195
[SVN r62652]
2010-06-09 12:36:11 +00:00
Anthony Williams
f9a0e450e1 Removed thread_info_mutex as unnecessary and cause of potentially-throwing destructor. Fix for issue #3097
[SVN r62650]
2010-06-09 11:35:41 +00:00
Anthony Williams
f6b8cdd1f5 Use BOOST_THREAD_DYN_LINK instead of BOOST_THREAD_DYN_DLL for
compatibility with the rest of boost. Fix for issue #2874


[SVN r62643]
2010-06-09 08:55:09 +00:00
Anthony Williams
6727013302 Use time_duration::tick_type rather than long when calculating due
time to fix issue #4318


[SVN r62642]
2010-06-09 08:19:47 +00:00
Anthony Williams
cda12a2660 Added BOOST_THREAD_DECL to friend declaration of
this_thread::get_id. Fix for issue #4316


[SVN r62641]
2010-06-09 07:59:31 +00:00
Anthony Williams
c3c2072472 Added unimplemented default constructor to derived to avoid complaints
about the constructors of T in some compilers. Fix for issue #4317


[SVN r62639]
2010-06-09 07:52:25 +00:00
Anthony Williams
bfc226fdc0 Add extra braces to fix issue #4321
[SVN r62638]
2010-06-09 07:46:29 +00:00
Anthony Williams
fd28e1a7fb Added missing #includes. Fix for issue #4322
[SVN r62637]
2010-06-09 07:40:09 +00:00
Anthony Williams
b11911f5e5 Moved thread startup and shutdown hooks to namespace boost
[SVN r62636]
2010-06-09 07:37:44 +00:00
Anthony Williams
a1587d070f Replace use of noncopyable with private copy operations, issue #3244
[SVN r62633]
2010-06-09 06:58:35 +00:00
Anthony Williams
df2f43bc61 Added documentation for this_thread::sleep overload that takes a
system_time. see issue #3179


[SVN r62632]
2010-06-09 06:48:37 +00:00
Anthony Williams
895e8eea52 Added "inline" on system_time overload of timed_wait to fix issue #2747
[SVN r62631]
2010-06-09 06:42:57 +00:00
Anthony Williams
97d6249f3b Added patch from issue #4305 --- limit SunCC workarounds to older versions
[SVN r62601]
2010-06-08 21:39:56 +00:00
Anthony Williams
7a8ed98eb5 Removed commented out code
[SVN r62564]
2010-06-08 13:06:58 +00:00
Anthony Williams
d611eece19 Updated tests for mutex members to handle range-based lock() and try_lock(), and fix issue #2704
[SVN r62562]
2010-06-08 12:06:03 +00:00
Anthony Williams
a99320f5a4 Updated get_due_time to handle the case where a "tick" is less than
100ns, trac issue #2447


[SVN r62555]
2010-06-08 08:40:46 +00:00
Anthony Williams
c97484943a Check limits when attempting to lock shared_mutex --- trac issue #2293
[SVN r62553]
2010-06-08 07:28:53 +00:00
Anthony Williams
547d9bd844 Fix for issue #868 --- provide element_type typedef
[SVN r62552]
2010-06-08 07:11:28 +00:00
Anthony Williams
1a65aab05a Applied patch from ticket 2918
[SVN r62505]
2010-06-07 09:08:09 +00:00
Anthony Williams
2e869aeb86 Added documentation for thread move assignment
[SVN r62504]
2010-06-07 09:04:54 +00:00
Anthony Williams
d729776575 Added documentation of thread move constructor
[SVN r62503]
2010-06-07 08:59:27 +00:00
Anthony Williams
895c436405 Fix for issue #4238: timed_lock_upgrade should not call timed_lock
[SVN r62502]
2010-06-07 08:43:15 +00:00
Anthony Williams
4ae2932792 Fix copy constructor and copy-assignment operator for condition_variable_any
[SVN r62501]
2010-06-07 08:28:42 +00:00
Anthony Williams
a52be2bdbb Consistently use count_type rather than unsigned for indexes into
future waiters vector


[SVN r62500]
2010-06-07 08:25:43 +00:00
Anthony Williams
31c4792216 Added missing inline
[SVN r62229]
2010-05-26 06:48:58 +00:00
Anthony Williams
39fd9c0b47 Fix for trac issue #3269
[SVN r62123]
2010-05-21 17:14:23 +00:00
Anthony Williams
9c25df3402 Sleeping for a negative time is same as sleeping for 0ms, fix for
issue #3178


[SVN r62122]
2010-05-21 16:59:56 +00:00
Anthony Williams
fb150b5038 Added support for BOOST_NO_IOSTREAM
[SVN r62119]
2010-05-21 15:19:06 +00:00
Anthony Williams
8cff3a167e Added documentation for boost::move on thread objects
[SVN r62079]
2010-05-18 08:25:02 +00:00
Anthony Williams
2be1431f60 Test for __APPLE__ before _GNU_SOURCE so we can compile on Intel/Darwin
[SVN r62053]
2010-05-17 08:22:14 +00:00
Anthony Williams
255b7ed7f6 Fix for compile error win Sun CC 5.9
[SVN r61618]
2010-04-27 13:23:00 +00:00
Anthony Williams
58fd27399e Added patch to fix issue #2501
[SVN r61429]
2010-04-20 15:02:47 +00:00
Anthony Williams
65d2898ff0 Merged changes to boost.thread over from trunk
[SVN r60991]
2010-04-01 15:04:15 +00:00
Anthony Williams
5f88ba1e47 Fix use of rvalue ref in futures
[SVN r60990]
2010-04-01 12:56:44 +00:00
Anthony Williams
ab569461d8 Modified boost::thread to work with MSVC10 RC
[SVN r59856]
2010-02-23 13:46:13 +00:00
Anthony Williams
7093fc670b Disable templated rvalue ref constructor for MSVC10
[SVN r59758]
2010-02-19 09:54:00 +00:00
Anthony Williams
6f2b030253 Fixes to some uses of rvalue references; patch to avoid var size warnings on 64-bit platforms in future.hpp
[SVN r59752]
2010-02-18 21:54:46 +00:00
Anthony Williams
0e61e679af Overload boost::move for thread& and thread&&
[SVN r59727]
2010-02-17 08:34:09 +00:00
Anthony Williams
b40998e1b5 Changed boost.thread to use BOOST_NO_RVALUE_REFERENCES rather than BOOST_HAS_RVALUE_REFS
[SVN r59699]
2010-02-16 14:57:30 +00:00
Anthony Williams
174d701bc3 Using BOOST_ASSERT rather than assert
[SVN r57940]
2009-11-26 09:35:31 +00:00
Anthony Williams
f2143d08b9 Added missing BOOST_THREAD_DECL for at_thread_exit_function
[SVN r57937]
2009-11-26 08:13:44 +00:00
Anthony Williams
1273e2620d Don't use timed_lock to do a lock
[SVN r57936]
2009-11-26 08:13:01 +00:00
Anthony Williams
c719f6e37e Added test and fix for issue 2742
[SVN r57925]
2009-11-25 11:05:55 +00:00
Anthony Williams
37922d8ce0 Added a wait call to new call_once
[SVN r57924]
2009-11-25 09:42:29 +00:00
Anthony Williams
7b79a31f40 A partial fix for issue #2100: use boost::throw_exception for all exceptions except thread_interrupted
[SVN r57912]
2009-11-24 21:49:27 +00:00
Anthony Williams
9a09406f77 Ensure call_once event is correctly cleaned up
[SVN r57889]
2009-11-24 11:52:09 +00:00
Anthony Williams
9bdb778478 Only allocate an event if there is contention in call_once
[SVN r57882]
2009-11-24 09:59:21 +00:00
Anthony Williams
9621dafe46 Clarify note on call_once
[SVN r57862]
2009-11-23 11:31:08 +00:00
Anthony Williams
d7c9837844 Added a note highlighting that recursive use of call_once will cause deadlock.
[SVN r57861]
2009-11-23 11:24:53 +00:00
Anthony Williams
9087fd904d Merged documentation changes to boost.thread (re at_thread_exit) from trunk
[SVN r57381]
2009-11-04 21:48:18 +00:00
Anthony Williams
27bb7803ae Update docs for at_thread_exit
[SVN r57380]
2009-11-04 21:38:45 +00:00
Anthony Williams
66ac6942b6 Merged boost.thread changes from trunk
[SVN r57243]
2009-10-30 09:50:13 +00:00
Anthony Williams
c0e1086f2c More fixes for compilers with rvalue ref support
[SVN r57173]
2009-10-27 13:22:08 +00:00
Anthony Williams
ffa751c617 Fix for move assignment of unique_lock if rvalue refs supported
[SVN r57171]
2009-10-27 10:40:57 +00:00
Anthony Williams
b8ad60a2d6 Fix for bug #2067 --- use shared_mutex for thread_group rather than a simple mutex
[SVN r57169]
2009-10-27 09:45:53 +00:00
Anthony Williams
5db0aac816 Added futures to boost.thread
[SVN r57064]
2009-10-22 09:33:21 +00:00
Anthony Williams
20980fe54d Merged thread changes from trunk
[SVN r56992]
2009-10-19 09:18:13 +00:00
Troy D. Straszheim
3fae7c5184 rm cmake from trunk. I'm not entirely sure this is necessary to satisfy the inspect script, but I'm not taking any chances, and it is easy to put back
[SVN r56942]
2009-10-17 02:07:38 +00:00
Troy D. Straszheim
fb54acfe69 rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release.
[SVN r56941]
2009-10-17 01:10:45 +00:00
Anthony Williams
47889a8f22 boost.thread exception types are now header-only so some uses of boost.thread can be header only
[SVN r56019]
2009-09-04 19:55:31 +00:00
Troy D. Straszheim
8d22c3869b Copyrights on CMakeLists.txt to keep them from clogging up the inspect
reports.  This is essentially the same commit as r55095 on the release
branch.



[SVN r55159]
2009-07-26 00:49:56 +00:00
Vladimir Prus
235ed4afe0 Check _GNU_SOURCE before using get_nprocs.
The latter function is not POSIX, but a GNU extension and therefore
not available universally.


[SVN r54408]
2009-06-27 09:22:41 +00:00
Anthony Williams
627cb7f774 Fixed typo
[SVN r53412]
2009-05-29 20:48:07 +00:00
Anthony Williams
09021af350 Changed thread_specific_ptr to use a map for faster lookup, and erase empty nodes
[SVN r53389]
2009-05-29 11:34:25 +00:00
Anthony Williams
31c280d1fa TSS cleanup not called for NULL data
[SVN r53388]
2009-05-29 11:05:01 +00:00
Anthony Williams
629f344f34 Test and fix for first part of issue #2797
[SVN r53387]
2009-05-29 10:57:39 +00:00
Anthony Williams
db5f924e24 Remove commented-out thread_group code
[SVN r53386]
2009-05-29 10:45:06 +00:00
Anthony Williams
9be3eb282a Attempts to improve the boost::thread move semantics; separated tests to give clearer ID; incorporated patch to fix issue #2062
[SVN r53385]
2009-05-29 09:57:15 +00:00
John Maddock
effd891a16 Remove options that are no longer required and get the PDF docs building.
[SVN r51142]
2009-02-09 16:26:26 +00:00
Anthony Williams
13db35cbf5 Undo commit from r49977 which added extraneous throw to thread example
[SVN r49978]
2008-11-28 11:01:21 +00:00
Anthony Williams
0f2d480e3c Added test for making std::thread work with std::vector
[SVN r49977]
2008-11-28 10:57:12 +00:00
Anthony Williams
9edc61e37b Removed controversial catch(...) clauses from thread class
[SVN r49969]
2008-11-27 21:15:37 +00:00
Michael A. Jackson
f4dab6aac5 Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use.
[SVN r49627]
2008-11-07 17:02:56 +00:00
Michael A. Jackson
9e0550d140 Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor
[SVN r49510]
2008-11-01 13:15:41 +00:00
Anthony Williams
0d1701c509 Enhanced thread move tests
[SVN r49124]
2008-10-03 07:02:57 +00:00
Anthony Williams
f2f62f93ea Test and fix for trac issue #2380: return boost::move(some_thread) now works
[SVN r49112]
2008-10-02 16:39:03 +00:00
Anthony Williams
8a329f66fb Renamed lock variables to lk to avoid name shadow warnings
[SVN r49013]
2008-09-29 16:32:24 +00:00
Anthony Williams
05d4c52918 fixed check on return code from pthread_mutex_timedlock
[SVN r48997]
2008-09-29 09:04:13 +00:00
Anthony Williams
8fd0dd0cc0 Define a raw DLL main which is called by the C runtime if we're statically linked into a DLL --- fix for issue #2199
[SVN r48537]
2008-09-02 16:56:57 +00:00
Anthony Williams
8eea5811ba Don't allocate TLS Key unless we need it; deallocate it on process exit --- partial fix for bug #2199
[SVN r48536]
2008-09-02 16:54:56 +00:00
Anthony Williams
a154c2adab Removed locked and get_active_count
[SVN r48531]
2008-09-02 10:38:17 +00:00
Anthony Williams
10bf4ed576 Removed locked and get_active_count
[SVN r48530]
2008-09-02 10:38:04 +00:00
Anthony Williams
60d12dd395 Added recursive_mutex/condition::wait() change to list of breaking changes
[SVN r48528]
2008-09-02 10:22:06 +00:00
Anthony Williams
b4e9be3c52 Added missing relative time constructor to unique_lock
[SVN r48213]
2008-08-19 10:26:53 +00:00
Anthony Williams
dcebae6d4a Renamed internal bind stuff to invoker, as more expressive
[SVN r48209]
2008-08-19 07:03:22 +00:00
Anthony Williams
0d776bcd26 Updated changes list
[SVN r48037]
2008-08-08 20:37:30 +00:00
Anthony Williams
2d6ed47cf2 Updated signature of create_thread
[SVN r48036]
2008-08-08 20:21:29 +00:00
Anthony Williams
ea06434425 Doc updates missed by previous checkin
[SVN r47826]
2008-07-26 08:37:55 +00:00
Anthony Williams
6508eff95e Added note about max number of arguments
[SVN r47818]
2008-07-25 22:22:58 +00:00
Anthony Williams
69930684a9 Added a description for the new thread constructors that allow functions with arguments.
[SVN r47817]
2008-07-25 22:21:05 +00:00
Anthony Williams
b1931a3eda Fix for trac issue #2118
[SVN r47816]
2008-07-25 22:01:04 +00:00
Anthony Williams
63b44d4e32 Added documentation for the lock and try_lock free functions
[SVN r47815]
2008-07-25 21:57:33 +00:00
Anthony Williams
f7cb8d8141 Added a description for the scoped_try_lock typedefs
[SVN r47814]
2008-07-25 21:30:37 +00:00
Anthony Williams
48c857e02c Fix for issue #2105: specify which header to include for each class or function
[SVN r47810]
2008-07-25 21:12:29 +00:00
Anthony Williams
442dc58e0f Use sysconf(_SC_NPROCESSORS_ONLN) where it is available, as a fallback
[SVN r47654]
2008-07-21 10:39:50 +00:00
Anthony Williams
25460c652c Use sysconf to detect number of processors on AIX too
[SVN r47653]
2008-07-21 10:25:08 +00:00
Anthony Williams
31a98f0a1e BOOST_NO_SFINAE isn't enough to identify compilers that can't auto-detect mutexes, so create a new macro for that, and add IBM and Sun compilers to list
[SVN r47652]
2008-07-21 10:04:26 +00:00
Anthony Williams
36c44b6f45 Borland-specific fixes should apply to all compilers for which enable_if is broken: check for BOOST_NO_SFINAE instead
[SVN r47554]
2008-07-18 13:42:10 +00:00
Anthony Williams
27426b18d1 Split lock and try_lock into mutex and range overloads without using enable_if, so it works on Borland compilers
[SVN r47472]
2008-07-16 14:41:09 +00:00
Anthony Williams
3ea9ce1c8c Fixes to make basic thread functionality work with Borland compilers again
[SVN r47471]
2008-07-16 13:19:43 +00:00
Anthony Williams
4dfc636c84 test and fix for issue #2080
[SVN r47199]
2008-07-07 22:19:28 +00:00
Anthony Williams
5fe4312c6c test and fix for issue #2081
[SVN r47197]
2008-07-07 22:04:10 +00:00
Anthony Williams
63e675a6bb Corrected description to avoid reference to arguments
[SVN r47172]
2008-07-07 07:30:27 +00:00
Anthony Williams
e92aeac7d7 Added notify functions to class synopsis
[SVN r47171]
2008-07-07 07:28:32 +00:00
Anthony Williams
f1f7eac1f2 Backwards compatibility with xtime --- test and fix for issue #2052
[SVN r47149]
2008-07-06 21:58:11 +00:00
Anthony Williams
eff0c84553 Test and fix for issue #2076
[SVN r47120]
2008-07-05 21:55:36 +00:00
Anthony Williams
58c8ce61c7 Fix for issue #2065
[SVN r47077]
2008-07-04 15:45:52 +00:00
Anthony Williams
6ac5e6953a Qualify everything with boost:: to try and avoid name clashes on AIX
[SVN r47070]
2008-07-04 07:30:35 +00:00
Anthony Williams
5d9ad59af2 Use rvalue refs for move semantics of unique_lock where available
[SVN r47033]
2008-07-03 09:16:49 +00:00
Anthony Williams
3c48a05437 Added try_lock_upgrade to shared_mutex: second half of #1867 fix
[SVN r46961]
2008-07-01 16:28:06 +00:00
Anthony Williams
4462124ff2 Added try_lock_upgrade to shared_mutex: second half of #1867 fix
[SVN r46960]
2008-07-01 16:27:59 +00:00
Anthony Williams
373f557ef7 Reduced thread counts to make tests run faster
[SVN r46958]
2008-07-01 16:22:47 +00:00
Anthony Williams
495e561398 Partial fix for issue #1867 - ensure boost::shared_mutex supports try_lock
[SVN r46956]
2008-07-01 16:04:51 +00:00
Anthony Williams
d24a579033 Partial fix for issue #1867 - ensure boost::shared_mutex supports try_lock
[SVN r46955]
2008-07-01 16:04:43 +00:00
Anthony Williams
77130424b4 Removed tabs from source files
[SVN r46706]
2008-06-26 06:43:30 +00:00
Anthony Williams
eb30688937 Added license and copyright to docs
[SVN r46705]
2008-06-26 06:41:00 +00:00
Anthony Williams
880bac0633 Added missing include of detail/config.hpp
[SVN r46624]
2008-06-23 12:14:58 +00:00
Anthony Williams
851d6a987f Correctly remove the reference type when copying the thread function into the thread data area so we don't end up with a dangling reference
[SVN r46295]
2008-06-10 15:29:35 +00:00
Anthony Williams
9bebd7b35f Disable general templated thread constructor for movable types, in order to prevent it trying to act as a thread copy constructor for EDG based compilers
[SVN r46273]
2008-06-09 14:00:03 +00:00
Anthony Williams
309acb9597 Don't try and use _interlockedbittestandset primitives if we don't know they're present
[SVN r46219]
2008-06-07 20:54:19 +00:00
Anthony Williams
a56887167e Added swap for try_lock_wrapper
[SVN r46164]
2008-06-05 12:25:58 +00:00
Anthony Williams
e984dff4e4 Combined TSS header for pthread and win32, #1958 now fixed for pthread too
[SVN r46162]
2008-06-05 11:19:06 +00:00
Anthony Williams
685e4d446b Test and fix for bug #1958 on Win32
[SVN r46161]
2008-06-05 11:16:05 +00:00
Anthony Williams
8af680f307 Added swap for unique_lock
[SVN r46160]
2008-06-05 10:39:08 +00:00
Anthony Williams
6c60cce60d Removed partial initializer for res: both values will be assigned later, so no need to initialize either
[SVN r46124]
2008-06-04 16:05:29 +00:00
Anthony Williams
5882a675bb Added extra initializer to timeout to try and eliminate warnings with some compilers
[SVN r46123]
2008-06-04 16:03:51 +00:00
Anthony Williams
a5e95845b3 Added documentation for swap()
[SVN r46122]
2008-06-04 16:00:13 +00:00
Anthony Williams
5b83d81e40 Added free function swap() for threads
[SVN r46121]
2008-06-04 15:50:34 +00:00
Anthony Williams
c8e5ad564d basic_condition_variable::lock_entry extracted to basic_cv_lock_entry in order to try and eliminate problems on Borland compiler
[SVN r46094]
2008-06-03 20:56:39 +00:00
Anthony Williams
5edfa273ff removed unused header
[SVN r46093]
2008-06-03 20:55:40 +00:00
Anthony Williams
4db57bcb10 Move thread_data to detail namespace rather than have it as a nested type of boost::thread, to try and help compilers that have problems with the partial specializations for reference_wrapper
[SVN r45912]
2008-05-29 15:38:08 +00:00
Anthony Williams
3f13340903 Don't construct function objects directly in boost::thread constructor as some compilers can't handle that.
[SVN r45911]
2008-05-29 15:36:52 +00:00
Anthony Williams
6abb53c9d3 Move definition of constructor and destructor of condition_variable into condition_variable_fwd.hpp, so they are always available
[SVN r45909]
2008-05-29 15:16:55 +00:00
Anthony Williams
fdd20a519e Use wrapper functions in try_lock_wrapper rather than using declarations, as the latter confuse some compilers
[SVN r45908]
2008-05-29 15:16:04 +00:00
Anthony Williams
67cc49f333 More tests for generic locks, and a new range version
[SVN r45897]
2008-05-29 09:02:05 +00:00
Anthony Williams
31a34cd0b5 Added missing "no"
[SVN r45870]
2008-05-28 14:50:25 +00:00
Anthony Williams
ef8c08ba99 Removed surplus "the"
[SVN r45869]
2008-05-28 12:55:30 +00:00
Anthony Williams
2991ca6c6f Added abi prefix and suffix headers
[SVN r45865]
2008-05-28 11:02:06 +00:00
Anthony Williams
52bace18b2 hardware_concurrency works for CYGWIN
[SVN r45860]
2008-05-28 09:38:14 +00:00
Anthony Williams
767d14ae4f Added documentation for time support in the thread library
[SVN r45859]
2008-05-28 09:00:32 +00:00
Anthony Williams
1a5c911e36 Added documentation for time support in the thread library
[SVN r45858]
2008-05-28 09:00:23 +00:00
Anthony Williams
6e42a04e43 Added note about move support
[SVN r45856]
2008-05-28 08:09:07 +00:00
Anthony Williams
28be2cfeef intrusive_ptr_add_ref and intrusive_ptr_release need to be inline if defined in the header
[SVN r45809]
2008-05-27 06:32:05 +00:00
Anthony Williams
8be168fd87 Basic tests for lock() when other thread is acquiring locks in same or opposite order
[SVN r45767]
2008-05-26 08:59:48 +00:00
Anthony Williams
eee95fef57 Initial test for generic lock functions
[SVN r45766]
2008-05-26 08:40:21 +00:00
Anthony Williams
9ea179b052 Initial test for generic lock functions
[SVN r45765]
2008-05-26 08:40:13 +00:00
Anthony Williams
6868280409 Try and avoid compile errors in test_thread_callable_object_one_argument
[SVN r45764]
2008-05-26 07:36:16 +00:00
Anthony Williams
e00b764454 The signature of _interlockedbittestandset changes between MSVC 2005 and MSVC 2008
[SVN r45689]
2008-05-23 19:53:06 +00:00
Anthony Williams
999613c686 Added note about mutex not being recursive
[SVN r45688]
2008-05-23 19:33:18 +00:00
Anthony Williams
c2661d7eb5 define intrusive_ptr_add_ref and intrusive_ptr_release at namespace scope rather than inline as friends in order to try and avoid compiler problems
[SVN r45682]
2008-05-23 15:18:19 +00:00
Anthony Williams
4d21dd1f47 try_lock_wrapper implements operator! in order to try and avoid compiler problems
[SVN r45681]
2008-05-23 15:17:14 +00:00
Anthony Williams
a0a0e57527 Fixed #ifdef to actually use BTS primitives on MSVC 9
[SVN r45676]
2008-05-23 13:16:01 +00:00
Anthony Williams
d8af0d0b4e Reset thread_info on move rather than assigning 0
[SVN r45672]
2008-05-23 10:48:07 +00:00
Anthony Williams
113288e3b0 tidying up move
[SVN r45661]
2008-05-22 16:33:34 +00:00
Anthony Williams
afecfd7c2d Refactored boost::thread code to try and remove duplication
[SVN r45647]
2008-05-22 11:49:48 +00:00
Anthony Williams
94d89aac5f more rvalue reference stuff
[SVN r45626]
2008-05-21 21:11:30 +00:00
Anthony Williams
8831b13efc Use lock_guard<> instead of unique_lock<> internally. Clear out generations after notify_all, as they're all notified
[SVN r45625]
2008-05-21 21:10:45 +00:00
Peter Dimov
01f99da03a Extended boost::thread to 9 arguments, hopefully fixed member function ambiguity.
[SVN r45621]
2008-05-21 20:44:08 +00:00
Anthony Williams
080654e3ef New tests for a normal function with one argument, and a member function with 0 or 1 arguments
[SVN r45607]
2008-05-21 13:38:04 +00:00
Anthony Williams
2ac2eb2a61 try_lock_wrapper has its own operator bool_type to avoid problems with a using declaration
[SVN r45602]
2008-05-21 10:39:47 +00:00
Anthony Williams
61b940b705 Renamed namespace user to user_test_ns to try and avoid a name clash on some platforms
[SVN r45601]
2008-05-21 09:51:53 +00:00
Anthony Williams
4a4f87e017 support for a generic lock() function
[SVN r45481]
2008-05-18 09:10:20 +00:00
Anthony Williams
6d5e7f63a7 Added beginnings of real rvalue-reference support
[SVN r45479]
2008-05-18 08:45:44 +00:00
Anthony Williams
f77285f375 Updated docs to make it explicit that terminate is called if a thread function throws an exception
[SVN r45294]
2008-05-12 09:04:02 +00:00
Anthony Williams
dc5d03a6dc Cleaned up to remove warnings
[SVN r45244]
2008-05-09 07:59:57 +00:00
Anthony Williams
ea0961b7f6 Fixed type truncation warning
[SVN r45243]
2008-05-09 07:49:22 +00:00
Anthony Williams
33d9f9774c Test and fix for bug #1905
[SVN r45242]
2008-05-09 07:48:44 +00:00
Anthony Williams
86097fa038 Use _WIN32 rather than WIN32 to prevent include of <unistd.h>
[SVN r45241]
2008-05-09 07:47:14 +00:00
Anthony Williams
70d9dbc45a Added default constructor to lock types
[SVN r45212]
2008-05-08 14:34:40 +00:00
Anthony Williams
3926fd3a20 Added docs for native_handle
[SVN r45211]
2008-05-08 12:59:59 +00:00
Anthony Williams
7861cf1146 Added native_handle to mutex types where possible
[SVN r45210]
2008-05-08 12:59:10 +00:00
Anthony Williams
0516b86a6e new BTS-based mutex implementation on win32
[SVN r45119]
2008-05-04 22:39:52 +00:00
Anthony Williams
ec735d3e9b Simplified move support
[SVN r45108]
2008-05-04 09:52:54 +00:00
Anthony Williams
1c5c070983 Updated locks.hpp to work with gcc as well as msvc
[SVN r44846]
2008-04-28 12:26:27 +00:00
Anthony Williams
a5c02b73dc Added entry to breaking changes about default-constructed threads and the current thread: issue #1835
[SVN r44840]
2008-04-28 09:10:38 +00:00
Anthony Williams
918b920670 Added detail::try_lock_wrapper for use as scoped_try_lock typedefs, to fix issue #1873
[SVN r44838]
2008-04-28 09:00:58 +00:00
Anthony Williams
de67d2e27e Fixed g++ compile error
[SVN r44773]
2008-04-26 07:34:46 +00:00
Anthony Williams
bc89df04cb Revamped condition variable to try and fix swallowed-notify problems (trac issue #1834)
[SVN r44699]
2008-04-21 16:22:16 +00:00
Anthony Williams
c26a4cf082 added private copy assignment operator and copy constructor to remove warnings
[SVN r44698]
2008-04-21 16:20:31 +00:00
Anthony Williams
6e1a866b13 Fix for issue #1657
[SVN r44424]
2008-04-14 21:04:33 +00:00
Anthony Williams
f91986ad0d Added extended adopt/defer/try constructors to upgrade_lock
[SVN r44370]
2008-04-13 15:50:08 +00:00
Anthony Williams
795cc23f3e Added test and fix for win32 condition_variable broadcast bug similar to #1803
[SVN r44168]
2008-04-11 08:52:09 +00:00
Anthony Williams
a3695bd4a0 Updated thread.hpp as catch-all header
[SVN r44153]
2008-04-10 18:34:42 +00:00
Anthony Williams
08dc521daf Added native_handle to condition_variable on pthreads
[SVN r44152]
2008-04-10 15:52:01 +00:00
Anthony Williams
8b916d21b1 added tests for plain timed_lock on shared_mutex
[SVN r44150]
2008-04-10 14:15:26 +00:00
Anthony Williams
c40f47a78a added overloads of timed_lock_shared with a relative timeout to shared_mutex
[SVN r44149]
2008-04-10 14:07:39 +00:00
Anthony Williams
e9fb470b06 Added native_handle to thread on posix platforms
[SVN r44148]
2008-04-10 13:35:07 +00:00
Anthony Williams
343d049772 fix for trac ticket #1804
[SVN r44147]
2008-04-10 13:27:44 +00:00
Anthony Williams
86f9480da4 fix for notify problem in trac ticket #1803
[SVN r44146]
2008-04-10 13:14:43 +00:00
Anthony Williams
8696b610ca Added test for trac ticket #1803: condition_variable::notify_one may fail to wake a waiting thread on win32
[SVN r44136]
2008-04-09 19:33:06 +00:00
Anthony Williams
6f13227eda Added locked-> owns_lock change to breaking changes
[SVN r44089]
2008-04-07 13:09:36 +00:00
Anthony Williams
58d5110e61 removed forward declaration for undefined type exclusive_lock
[SVN r43847]
2008-03-24 21:44:36 +00:00
Anthony Williams
76e53c7bc5 Removed some warnings: those from issue #1640 and others
[SVN r43730]
2008-03-19 17:25:13 +00:00
Anthony Williams
cfb08be1a8 New documentation for new thread library
[SVN r43671]
2008-03-17 10:29:27 +00:00
Anthony Williams
b5bbb7fb1c Test and fix for bug #1693 to ensure thread_specific_ptr works as desired
[SVN r43666]
2008-03-17 08:36:09 +00:00
Anthony Williams
a76c33f8cc made the callable_no_args function object a named object rather than a temporary, in order to avoid gratuitous breakage on some compilers
[SVN r43528]
2008-03-06 07:59:16 +00:00
Anthony Williams
810306b8f3 thread constructor now accepts up to three additional arguments to pass to thread function
[SVN r43464]
2008-03-03 10:52:44 +00:00
Anthony Williams
6c22bdb3bd Test and fix for issue #1665
[SVN r43461]
2008-03-03 08:44:42 +00:00
Daniel James
6a0d3e98bc Fix broken copyright urls. Fixes #1573.
[SVN r43422]
2008-02-27 18:51:14 +00:00
Anthony Williams
3809321037 added test for duration overloads of timed_lock, and added missing implementation to win32 version
[SVN r43094]
2008-02-04 13:16:32 +00:00
Anthony Williams
eef695bdf0 Provide tss_cleanup_implemented as a dummy function on Windows CE to allow tests to run
[SVN r42818]
2008-01-16 15:23:36 +00:00
Anthony Williams
ab01ab1e4d removed references to NULL
[SVN r42657]
2008-01-10 14:19:36 +00:00
Anthony Williams
c8d8a108a7 Updated thread ID test
[SVN r42228]
2007-12-21 10:54:59 +00:00
Anthony Williams
7afd9efcc5 added hardware_concurrency support for apple, freebsd and sun platforms
[SVN r42195]
2007-12-20 08:37:02 +00:00
Anthony Williams
56ded87ad2 added missing parentheses
[SVN r42194]
2007-12-20 07:46:00 +00:00
Anthony Williams
82e503339b Implement hardware_concurrency for pthread
[SVN r42168]
2007-12-19 10:45:01 +00:00
Anthony Williams
713d0c7ace Updated thread ID, and added tests
[SVN r42166]
2007-12-19 10:39:45 +00:00
Anthony Williams
25ad6e3f8f boost::move support for locks
[SVN r42118]
2007-12-17 12:52:50 +00:00
Anthony Williams
df0197b617 Updated move function test to be fair to Borland
[SVN r42117]
2007-12-17 11:24:13 +00:00
Anthony Williams
a89c4f01ad explicit move functions for threads, with a test
[SVN r42087]
2007-12-15 22:36:43 +00:00
Anthony Williams
ae67099633 added timed_wait overloads that take a duration
[SVN r42086]
2007-12-15 22:34:30 +00:00
Anthony Williams
57542d3a5c fixed order of comparison in timeout check
[SVN r41819]
2007-12-07 08:11:11 +00:00
Anthony Williams
9a1da14116 improved timeout checks
[SVN r41741]
2007-12-05 10:58:45 +00:00
Anthony Williams
ed050d753d added missing include of detail/config.hpp
[SVN r41738]
2007-12-05 08:27:44 +00:00
Anthony Williams
8bec363710 changed order of declaration to eliminate warnings
[SVN r41687]
2007-12-04 14:07:01 +00:00
Anthony Williams
7c68e190a9 Added test for thread move constructor; implemented move on pthreads
[SVN r41686]
2007-12-04 13:02:58 +00:00
Anthony Williams
7ebf5ea3d1 add explicit casts to remove warnings
[SVN r41684]
2007-12-04 12:08:38 +00:00
Anthony Williams
11e0435a4b don't dllexport/dllimport inline functions
[SVN r41683]
2007-12-04 11:44:25 +00:00
Anthony Williams
d15ee57cd1 split shared mutex tests in two to take less time
[SVN r41682]
2007-12-04 10:04:30 +00:00
Anthony Williams
56d660b7fd changed boost::move to boost::detail::thread_move to fix issue #1492
[SVN r41681]
2007-12-04 09:15:37 +00:00
Anthony Williams
792958e693 fixed typo in condition_variable_any::timed_wait
[SVN r41679]
2007-12-04 07:57:23 +00:00
Anthony Williams
914e67dc04 check predicate before returning if we time out on a predicated version of timed_wait
[SVN r41668]
2007-12-03 22:00:26 +00:00
Anthony Williams
b50a7ccb61 interruptible_wait (and hence condition timed_wait) now uses a WaitableTimer where possible, to be robust in the face of clock changes
[SVN r41505]
2007-11-30 18:38:21 +00:00
Anthony Williams
f827709d42 add support for relative timeouts to condition timed_wait
[SVN r41413]
2007-11-27 14:24:29 +00:00
Anthony Williams
36abb42175 reverted accidental checkin of new timed_wait functions on condition_variable
[SVN r41405]
2007-11-26 21:15:04 +00:00
Anthony Williams
40f3b1b4c8 once_flag uses zero-initialization on POSIX as well as windows
[SVN r41401]
2007-11-26 17:01:08 +00:00
Anthony Williams
4f35e25688 fixed import/export declarations so new once code works with pthread-win32
[SVN r41398]
2007-11-26 15:44:07 +00:00
Anthony Williams
270e88edd7 Don't compare native_handle_t against 0 --- do appropriate checks in create_native_thread for platforms where pthread_t is not comparable
[SVN r41396]
2007-11-26 13:29:15 +00:00
Anthony Williams
5ded171247 workaround for Borland compiler
[SVN r41395]
2007-11-26 12:17:45 +00:00
343 changed files with 29797 additions and 2621 deletions

View File

@@ -1,28 +0,0 @@
#
# Copyright Troy D. Straszheim
#
# Distributed under the Boost Software License, Version 1.0.
# See http://www.boost.org/LICENSE_1_0.txt
#
#----------------------------------------------------------------------------
# This file was automatically generated from the original CMakeLists.txt file
# Add a variable to hold the headers for the library
set (lib_headers
thread.hpp
thread
)
# Add a library target to the build system
boost_library_project(
thread
SRCDIRS src
TESTDIRS test
HEADERS ${lib_headers}
# DOCDIRS
# DESCRIPTION
MODULARIZED
# AUTHORS
# MAINTAINERS
)

View File

@@ -1,6 +1,7 @@
# $Id$
# Copyright 2006-2007 Roland Schwarz.
# Copyright 2007 Anthony Williams
# Copyright 2011-2012 Vicente J.Botet Escriba.
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
@@ -43,7 +44,58 @@ project boost/thread
<link>shared:<define>BOOST_THREAD_BUILD_DLL=1
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@$(__name__).tag
: default-build <threading>multi
<toolset>gcc:<cxxflags>-Wno-long-long
<define>BOOST_SYSTEM_NO_DEPRECATED
<library>/boost/system//boost_system
#-pedantic -ansi -std=gnu++0x -Wextra -fpermissive
<warnings>all
<toolset>gcc:<cxxflags>-Wextra
<toolset>gcc:<cxxflags>-pedantic
<toolset>gcc:<cxxflags>-Wno-long-long
#<toolset>gcc:<cxxflags>-ansi
#<toolset>gcc:<cxxflags>-fpermissive
<toolset>darwin:<cxxflags>-Wextra
<toolset>darwin:<cxxflags>-pedantic
<toolset>darwin:<cxxflags>-ansi
<toolset>darwin:<cxxflags>-fpermissive
<toolset>darwin:<cxxflags>-Wno-long-long
#<toolset>pathscale:<cxxflags>-Wextra
<toolset>pathscale:<cxxflags>-Wno-long-long
<toolset>pathscale:<cxxflags>-pedantic
<toolset>clang:<cxxflags>-Wextra
<toolset>clang:<cxxflags>-pedantic
<toolset>clang:<cxxflags>-ansi
#<toolset>clang:<cxxflags>-fpermissive
<toolset>clang:<cxxflags>-Wno-long-long
<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.6.3:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.7.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.8.0:<cxxflags>-fdiagnostics-show-option
<toolset>darwin-4.6.2:<cxxflags>-Wno-delete-non-virtual-dtor
<toolset>darwin-4.7.0:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.8:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.8:<cxxflags>-Wno-unused-function
#<toolset>clang-2.9:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.9:<cxxflags>-Wno-unused-function
<toolset>clang-3.0:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-3.0:<cxxflags>-Wno-unused-function
#<toolset>clang-3.0:<cxxflags>-Wno-unused-variable
# : default-build <threading>multi
: usage-requirements # pass these requirement to dependents (i.e. users)
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
<link>shared:<define>BOOST_THREAD_BUILD_DLL=1
<define>BOOST_SYSTEM_NO_DEPRECATED
<library>/boost/system//boost_system
;
local rule default_threadapi ( )
@@ -59,19 +111,19 @@ feature.set-default threadapi : [ default_threadapi ] ;
rule tag ( name : type ? : property-set )
{
local result = $(name) ;
if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB
{
local api = [ $(property-set).get <threadapi> ] ;
# non native api gets additional tag
if $(api) != [ default_threadapi ] {
result = $(result)_$(api) ;
}
}
# forward to the boost tagging rule
return [ indirect.call $(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
return [ indirect.call $(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
$(result) : $(type) : $(property-set) ] ;
}
@@ -129,7 +181,7 @@ rule win32_pthread_paths ( properties * )
.notified = true ;
}
}
else
else
{
result += <include>$(include_path) ;
result += <library>$(lib_path) ;
@@ -151,6 +203,12 @@ rule usage-requirements ( properties * )
# in that case?
}
}
if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties)
{
result += <library>/boost/chrono//boost_chrono ;
}
return $(result) ;
}
@@ -161,7 +219,7 @@ rule requirements ( properties * )
if <threadapi>pthread in $(properties)
{
result += <define>BOOST_THREAD_POSIX ;
if <target-os>windows in $(properties)
if <target-os>windows in $(properties)
{
local paths = [ win32_pthread_paths $(properties) ] ;
if $(paths)
@@ -174,13 +232,17 @@ rule requirements ( properties * )
}
}
}
if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties)
{
result += <library>/boost/chrono//boost_chrono ;
}
return $(result) ;
}
alias thread_sources
: ## win32 sources ##
win32/thread.cpp
win32/exceptions.cpp
win32/tss_dll.cpp
win32/tss_pe.cpp
: ## requirements ##
@@ -190,7 +252,6 @@ alias thread_sources
alias thread_sources
: ## pthread sources ##
pthread/thread.cpp
pthread/exceptions.cpp
pthread/once.cpp
: ## requirements ##
<threadapi>pthread
@@ -199,7 +260,7 @@ alias thread_sources
explicit thread_sources ;
lib boost_thread
: thread_sources
: thread_sources future.cpp
: <conditional>@requirements
:
: <link>shared:<define>BOOST_THREAD_USE_DLL=1

View File

@@ -1,4 +1,5 @@
# (C) Copyright 2008 Anthony Williams
# (C) Copyright 2008-11 Anthony Williams
# (C) Copyright 2011-12 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)
@@ -15,22 +16,17 @@ boostbook standalone
# Use graphics not text for navigation:
<xsl:param>navig.graphics=1
# How far down we chunk nested sections, basically all of them:
<xsl:param>chunk.section.depth=3
<xsl:param>chunk.section.depth=2
# Don't put the first section on the same page as the TOC:
<xsl:param>chunk.first.sections=1
# How far down sections get TOC's
<xsl:param>toc.section.depth=10
<xsl:param>toc.section.depth=4
# Max depth in each TOC:
<xsl:param>toc.max.depth=3
<xsl:param>toc.max.depth=2
# How far down we go with TOC's
<xsl:param>generate.section.toc.level=10
# Path for links to Boost:
<xsl:param>boost.root=../../../..
# Path for libraries index:
<xsl:param>boost.libraries=../../../../libs/libraries.htm
# Use the main Boost stylesheet:
<xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
;

View File

@@ -1,11 +1,120 @@
[/
(C) Copyright 2007-8 Anthony Williams.
(C) Copyright 2007-11 Anthony Williams.
(C) Copyright 2011-12 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
]
[section:changes Changes since boost 1.35]
[section:changes History]
[heading Version 3.0.0 - boost 1.50]
New Features:
* [@http://svn.boost.org/trac/boost/ticket/1850 #1850] Request for unlock_guard to compliment lock_guard.
* [@http://svn.boost.org/trac/boost/ticket/2637 #2637] Request for shared_mutex duration timed_lock and timed_lock_shared.
* [@http://svn.boost.org/trac/boost/ticket/2741 #2741] Proposal to manage portable and non portable thread attributes.
* [@http://svn.boost.org/trac/boost/ticket/3567 #3567] Request for shared_lock_guard.
* [@http://svn.boost.org/trac/boost/ticket/6194 #6194] Adapt to Boost.Move.
* [@http://svn.boost.org/trac/boost/ticket/6195 #6195] c++11 compliance: Provide the standard time related interface using Boost.Chrono.
* [@http://svn.boost.org/trac/boost/ticket/6217 #6217] Enhance Boost.Thread shared mutex interface following Howard Hinnant proposal.
* [@http://svn.boost.org/trac/boost/ticket/6224 #6224] c++11 compliance: Add the use of standard noexcept on compilers supporting them.
* [@http://svn.boost.org/trac/boost/ticket/6225 #6225] Add the use of standard =delete defaulted operations on compilers supporting them.
* [@http://svn.boost.org/trac/boost/ticket/6226 #6226] c++11 compliance: Add explicit bool conversion from locks.
* [@http://svn.boost.org/trac/boost/ticket/6228 #6228] Add promise constructor with allocator following the standard c++11.
* [@http://svn.boost.org/trac/boost/ticket/6229 #6229] Rename the unique_future to future following the c++11.
* [@http://svn.boost.org/trac/boost/ticket/6230 #6230] c++11 compliance: Follows the exception reporting mechanism as defined in the c++11.
* [@http://svn.boost.org/trac/boost/ticket/6231 #6231] Add BasicLockable requirements in the documentation to follow c++11.
* [@http://svn.boost.org/trac/boost/ticket/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.
* [@http://svn.boost.org/trac/boost/ticket/6272 #6272] c++11 compliance: Add thread::id hash specialization.
* [@http://svn.boost.org/trac/boost/ticket/6273 #6273] c++11 compliance: Add cv_status enum class and use it on the conditions wait functions.
* [@http://svn.boost.org/trac/boost/ticket/6342 #6342] c++11 compliance: Adapt the one_flag to the c++11 interface.
* [@http://svn.boost.org/trac/boost/ticket/6671 #6671] upgrade_lock: missing mutex and release functions.
* [@http://svn.boost.org/trac/boost/ticket/6672 #6672] upgrade_lock:: missing constructors from time related types.
* [@http://svn.boost.org/trac/boost/ticket/6675 #6675] upgrade_lock:: missing non-member swap.
* [@http://svn.boost.org/trac/boost/ticket/6676 #6676] lock conversion should be explicit.
* Added missing packaged_task::result_type and packaged_task:: constructor with allocator.
* Added packaged_task::reset()
Fixed Bugs:
* [@http://svn.boost.org/trac/boost/ticket/2380 #2380] boost::move from lvalue does not work with gcc.
* [@http://svn.boost.org/trac/boost/ticket/2430 #2430] shared_mutex for win32 doesn't have timed_lock_upgrade.
* [@http://svn.boost.org/trac/boost/ticket/2575 #2575] Bug- Boost 1.36.0 on Itanium platform.
* [@http://svn.boost.org/trac/boost/ticket/3160 #3160] Duplicate tutorial code in boost::thread.
* [@http://svn.boost.org/trac/boost/ticket/4345 #4345] thread::id and joining problem with cascade of threads.
* [@http://svn.boost.org/trac/boost/ticket/4521 #4521] Error using boost::move on packaged_task (MSVC 10).
* [@http://svn.boost.org/trac/boost/ticket/4711 #4711] Must use implementation details to return move-only types.
* [@http://svn.boost.org/trac/boost/ticket/4921 #4921] BOOST_THREAD_USE_DLL and BOOST_THREAD_USE_LIB are crucial and need to be documented.
* [@http://svn.boost.org/trac/boost/ticket/5013 #5013] documentation: boost::thread: pthreas_exit causes terminate().
* [@http://svn.boost.org/trac/boost/ticket/5173 #5173] boost::this_thread::get_id is very slow.
* [@http://svn.boost.org/trac/boost/ticket/5351 #5351] interrupt a future get boost::unknown_exception.
* [@http://svn.boost.org/trac/boost/ticket/5516 #5516] Upgrade lock is not acquired when previous upgrade lock releases if another read lock is present.
* [@http://svn.boost.org/trac/boost/ticket/5990 #5990] shared_future<T>::get() has wrong return type.
* [@http://svn.boost.org/trac/boost/ticket/6174 #6174] packaged_task doesn't correctly handle moving results.
* [@http://svn.boost.org/trac/boost/ticket/6222 #6222] Compile error with SunStudio: unique_future move.
* [@http://svn.boost.org/trac/boost/ticket/6354 #6354] PGI: Compiler threading support is not turned on.
* [@http://svn.boost.org/trac/boost/ticket/6673 #6673] shared_lock: move assign doesn't works with c++11.
* [@http://svn.boost.org/trac/boost/ticket/6674 #6674] shared_mutex: try_lock_upgrade_until doesn't works.
* [@http://svn.boost.org/trac/boost/ticket/6908 #6908] Compile error due to unprotected definitions of _WIN32_WINNT and WINVER.
* [@http://svn.boost.org/trac/boost/ticket/6940 #6940] TIME_UTC is a macro in C11.
* [@http://svn.boost.org/trac/boost/ticket/6959 #6959] call of abs is ambiguous.
* Fix issue signaled on the ML with task_object(task_object const&) in presence of task_object(task_object &&)
[/
Deprecated features since boost 1.50 available only until boost 1.55:
These deprecated features will be provided by default up to boost 1.52. If you don't want to include the deprecated features you could define BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0. Since 1.53 these features will not be included any more by default. Since this version, if you want to include the deprecated features yet you could define BOOST_THREAD_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0. These deprecated features will be only available until boost 1.55, that is you have 1 year and a half to move to the new features.
* Time related functions don't using the Boost.Chrono library, use the chrono overloads instead.
Breaking changes:
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 2, but the user can however choose the version 1 behavior by defining the corresponding macro. As for the deprecated features, these broken features will be only available until boost 1.55.
* #6266 c++11 compliance: thread destructor should call terminate if joinable
* #6269 c++11 compliance: thread move assignment should call terminate if joinable
]
[heading Version 2.1.1 - boost 1.49]
Fixed Bugs:
* [@http://svn.boost.org/trac/boost/ticket/2309 #2309] Lack of g++ symbol visibility support in Boost.Thread.
* [@http://svn.boost.org/trac/boost/ticket/2639 #2639] documentation should be extended(defer_lock, try_to_lock, ...).
* [@http://svn.boost.org/trac/boost/ticket/3639 #3639] Boost.Thread doesn't build with Sun-5.9 on Linux.
* [@http://svn.boost.org/trac/boost/ticket/3762 #3762] Thread can't be compiled with winscw (Codewarrior by Nokia).
* [@http://svn.boost.org/trac/boost/ticket/3885 #3885] document about mix usage of boost.thread and native thread api.
* [@http://svn.boost.org/trac/boost/ticket/3975 #3975] Incorrect precondition for promise::set_wait_callback().
* [@http://svn.boost.org/trac/boost/ticket/4048 #4048] thread::id formatting involves locale
* [@http://svn.boost.org/trac/boost/ticket/4315 #4315] gcc 4.4 Warning: inline ... declared as dllimport: attribute ignored.
* [@http://svn.boost.org/trac/boost/ticket/4480 #4480] OpenVMS patches for compiler issues workarounds.
* [@http://svn.boost.org/trac/boost/ticket/4819 #4819] boost.thread's documentation misprints.
* [@http://svn.boost.org/trac/boost/ticket/5423 #5423] thread issues with C++0x.
* [@http://svn.boost.org/trac/boost/ticket/5617 #5617] boost::thread::id copy ctor.
* [@http://svn.boost.org/trac/boost/ticket/5739 #5739] set-but-not-used warnings with gcc-4.6.
* [@http://svn.boost.org/trac/boost/ticket/5826 #5826] threads.cpp: resource leak on threads creation failure.
* [@http://svn.boost.org/trac/boost/ticket/5839 #5839] thread.cpp: ThreadProxy leaks on exceptions.
* [@http://svn.boost.org/trac/boost/ticket/5859 #5859] win32 shared_mutex constructor leaks on exceptions.
* [@http://svn.boost.org/trac/boost/ticket/6100 #6100] Compute hardware_concurrency() using get_nprocs() on GLIBC systems.
* [@http://svn.boost.org/trac/boost/ticket/6168 #6168] recursive_mutex is using wrong config symbol (possible typo).
* [@http://svn.boost.org/trac/boost/ticket/6175 #6175] Compile error with SunStudio.
* [@http://svn.boost.org/trac/boost/ticket/6200 #6200] patch to have condition_variable and mutex error better handle EINTR.
* [@http://svn.boost.org/trac/boost/ticket/6207 #6207] shared_lock swap compiler error on clang 3.0 c++11.
* [@http://svn.boost.org/trac/boost/ticket/6208 #6208] try_lock_wrapper swap compiler error on clang 3.0 c++11.
[heading Version 2.1.0 - Changes since boost 1.40]
The 1.41.0 release of Boost adds futures to the thread library. There are also a few minor changes.
[heading Changes since boost 1.35]
The 1.36.0 release of Boost includes a few new features in the thread library:
@@ -21,7 +130,7 @@ The 1.36.0 release of Boost includes a few new features in the thread library:
* Backwards-compatibility overloads added for `timed_lock` and `timed_wait` functions to allow use of `xtime` for timeouts.
[heading Changes since boost 1.34]
[heading Version 2.0.0 - Changes since boost 1.34]
Almost every line of code in __boost_thread__ has been changed since the 1.34 release of boost. However, most of the interface
changes have been extensions, so the new code is largely backwards-compatible with the old code. The new features and breaking
@@ -81,3 +190,18 @@ been moved to __thread_id__.
unlocked one level, and not completely. This prior behaviour was not guaranteed and did not feature in the tests.
[endsect]
[section:future Future]
The following features will be included in next releases.
# Complete the C++11 missing features, in particular
* [@http://svn.boost.org/trac/boost/ticket/4710 #4710] Missing async().
* [@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.
[endsect]

110
doc/compliance.qbk Normal file
View File

@@ -0,0 +1,110 @@
[/
(C) Copyright 2011-12 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
]
[section:compliance Conformace and Extension]
[section:cpp11 C++11 standard Thread library]
[table C++11 standard Conformace
[[Section] [Description] [Status] [Comments] [Ticket]]
[[30] [Thread support library] [Partial] [-] [-]]
[[30.1] [General] [-] [-] [-]]
[[30.2] [Requirements] [-] [-] [-]]
[[30.2.1] [Template parameter names] [-] [-] [-]]
[[30.2.2] [Exceptions] [Yes] [-] [-]]
[[30.2.3] [Native handles] [Yes] [-] [-]]
[[30.2.4] [Timing specifications] [Yes] [-] [-]]
[[30.2.5] [Requirements for Lockable types] [Yes] [-] [-]]
[[30.2.5.1] [In general] [-] [-] [-]]
[[30.2.5.2] [BasicLockable requirements] [Yes] [-] [-]]
[[30.2.5.3] [Lockable requirements] [yes] [-] [-]]
[[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.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.5] [thread members] [Yes] [-] [-]]
[[30.3.1.6] [thread static members] [Yes] [-] [-]]
[[30.3.1.7] [thread specialized algorithms] [Yes] [-] [-]]
[[30.3.2] [Namespace this_thread] [Yes] [-] [-]]
[[30.4] [Mutual exclusion] [Partial] [-] [-]]
[[30.4.1] [Mutex requirements] [Yes] [-] [-]]
[[30.4.1.1] [In general] [Yes] [-] [-]]
[[30.4.1.2] [Mutex types] [Yes] [-] [-]]
[[30.4.1.2.1] [Class mutex] [Yes] [-] [-]]
[[30.4.1.2.2] [Class recursive_mutex] [Yes] [-] [-]]
[[30.4.1.3] [Timed mutex types] [Yes] [-] [-]]
[[30.4.1.3.1] [Class timed_mutex] [Yes] [-] [-]]
[[30.4.1.3.1] [Class recursive_timed_mutex] [Yes] [-] [-]]
[[30.4.2] [Locks] [Partial] [variadic] [#6227]]
[[30.4.2.1] [Class template lock_guard] [Yes] [-] [-]]
[[30.4.2.2] [Class template unique_lock] [Yes] [-] [-]]
[[30.4.2.2.1] [unique_lock constructors, destructor, and assignment] [Yes] [-] [-]]
[[30.4.2.2.2] [unique_lock locking] [Yes] [-] [-]]
[[30.4.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.5.1] [Class condition_variable] [Yes] [-] [-]]
[[30.5.2] [Class condition_variable_any] [Yes] [-] [-]]
[[30.6] [Futures] [Partial] [-] [-]]
[[30.6.1] [Overview] [Partial] [-] [-]]
[[30.6.2] [Error handling] [Yes] [-] [-]]
[[30.6.3] [Class future_error] [Yes] [-] [-]]
[[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]]
]
[/
[table Extension
[[Section] [Description] [Comments]]
[[30.3.1.5.x] [interrupt] [-]]
[[30.3.2.x] [Interruption] [-]]
[[30.3.2.y] [at_thread_exit] [-]]
[[30.4.3.x] [Generic locking algorithms begin/end] [-]]
[[30.x] [Barriers] [-]]
[[30.y] [Thread Local Storage] [-]]
[[30.z] [Class thread_group] [-]]
]
]
[endsect]
[section:shared Shared Locking extensions]
[table Howard's Shared Locking Proposal Conformace
[[Section] [Description] [Status] [Comments]]
[[X] [Shared Locking] [Yes] [Needs `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION]]
[[X.1] [Shared Lockables Concepts] [Yes] [ - ]]
[[X.1.1] [SharedLockable concept] [Yes] [ - ]]
[[X.1.2] [UpgradeLockable concept] [Yes] [ - ]]
[[X.2] [Shared Mutex Types] [Yes] [ - ]]
[[X.2.1] [shared_mutex class] [Yes] [ - ]]
[[X.2.2] [upgrade_mutex class] [Yes] [ - ]]
[[X.3] [Locks] [Yes] [-]]
[[X.3.1] [unique_lock class adaptations] [Yes] [-]]
[[X.3.2] [shared_lock class] [Yes] [ - ]]
[[X.3.3] [upgrade_lock class] [Yes] [-]]
]
[endsect]
[endsect]

View File

@@ -1,5 +1,6 @@
[/
(C) Copyright 2007-8 Anthony Williams.
(C) Copyright 2007-11 Anthony Williams.
(C) Copyright 2011-12 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).
@@ -9,6 +10,17 @@
[heading Synopsis]
namespace boost
{
enum class cv_status;
{
no_timeout,
timeout
};
class condition_variable;
class condition_variable_any;
}
The classes `condition_variable` and `condition_variable_any` provide a
mechanism for one thread to wait for notification from another thread that a
particular condition has become true. The general usage pattern is that one
@@ -84,31 +96,54 @@ optimizations in some cases, based on the knowledge of the mutex type;
condition_variable();
~condition_variable();
void notify_one();
void notify_all();
void notify_one() noexcept;
void notify_all() noexcept;
void wait(boost::unique_lock<boost::mutex>& lock);
template<typename predicate_type>
void wait(boost::unique_lock<boost::mutex>& lock,predicate_type predicate);
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time);
template <class Clock, class Duration>
typename cv_status::type
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t);
template <class Clock, class Duration, class Predicate>
bool
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred);
template <class Rep, class Period>
typename cv_status::type
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d);
template <class Rep, class Period, class Predicate>
bool
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred);
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time);
template<typename duration_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time);
template<typename predicate_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time,predicate_type predicate);
template<typename duration_type,typename predicate_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time,predicate_type predicate);
// backwards compatibility
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time);
template<typename predicate_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time,predicate_type predicate);
#endif
};
}
@@ -292,6 +327,114 @@ return true;
[endsect]
[section:wait_until `template <class Clock, class Duration> cv_status wait_until(boost::unique_lock<boost::mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time)`]
[variablelist
[[Precondition:] [`lock` is locked by the current thread, and either no other
thread is currently waiting on `*this`, or the execution of the `mutex()` member
function on the `lock` objects supplied in the calls to `wait` or `wait_for` or `wait_until`
in all the threads currently waiting on `*this` would return the same value as
`lock->mutex()` for this call to `wait`.]]
[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
thread will unblock when notified by a call to `this->notify_one()` or
`this->notify_all()`, when the time as reported by `Clock::now()`
would be equal to or later than the specified `abs_time`, or spuriously. When
the thread is unblocked (for whatever reason), the lock is reacquired by
invoking `lock.lock()` before the call to `wait` returns. The lock is also
reacquired by invoking `lock.lock()` if the function exits with an exception.]]
[[Returns:] [`cv_status::no_timeout` if the call is returning because the time specified by
`abs_time` was reached, `cv_status::timeout` otherwise.]]
[[Postcondition:] [`lock` is locked by the current thread.]]
[[Throws:] [__thread_resource_error__ if an error
occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
]
[endsect]
[section:wait_for `template <class Rep, class Period> cv_status wait_for(boost::unique_lock<boost::mutex>& lock, const chrono::duration<Rep, Period>& rel_time)`]
[variablelist
[[Precondition:] [`lock` is locked by the current thread, and either no other
thread is currently waiting on `*this`, or the execution of the `mutex()` member
function on the `lock` objects supplied in the calls to `wait` or `wait_until` or `wait_for`
in all the threads currently waiting on `*this` would return the same value as
`lock->mutex()` for this call to `wait`.]]
[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
thread will unblock when notified by a call to `this->notify_one()` or
`this->notify_all()`, after the period of time indicated by the `rel_time`
argument has elapsed, or spuriously. When the thread is unblocked (for whatever
reason), the lock is reacquired by invoking `lock.lock()` before the call to
`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
function exits with an exception.]]
[[Returns:] [`cv_status::no_timeout ` if the call is returning because the time period specified
by `rel_time` has elapsed, `cv_status::timeout ` otherwise.]]
[[Postcondition:] [`lock` is locked by the current thread.]]
[[Throws:] [__thread_resource_error__ if an error
occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
]
[note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
[endsect]
[section:wait_until_predicate `template <class Clock, class Duration, class Predicate> bool wait_until(boost::unique_lock<boost::mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred)`]
[variablelist
[[Effects:] [As-if ``
while(!pred())
{
if(!wait_until(lock,abs_time))
{
return pred();
}
}
return true;
``]]
]
[endsect]
[section:wait_for_predicate `template <class Rep, class Period, class Predicate> bool wait_for(boost::unique_lock<boost::mutex>& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred)`]
[variablelist
[[Effects:] [As-if ``
while(!pred())
{
if(!wait_for(lock,rel_time))
{
return pred();
}
}
return true;
``]]
]
[endsect]
[endsect]
[section:condition_variable_any Class `condition_variable_any`]
@@ -315,25 +458,43 @@ return true;
template<typename lock_type,typename predicate_type>
void wait(lock_type& lock,predicate_type predicate);
template <class lock_type, class Clock, class Duration>
cv_status wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t);
template <class lock_type, class Clock, class Duration, class Predicate>
bool wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred);
template <class lock_type, class Rep, class Period>
cv_status wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d);
template <class lock_type, class Rep, class Period, class Predicate>
bool wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred);
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
template<typename lock_type>
bool timed_wait(lock_type& lock,boost::system_time const& abs_time);
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& lock,duration_type const& rel_time);
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& lock,boost::system_time const& abs_time,predicate_type predicate);
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& lock,duration_type const& rel_time,predicate_type predicate);
// backwards compatibility
template<typename lock_type>
bool timed_wait(lock_type>& lock,boost::xtime const& abs_time);
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& lock,boost::xtime const& abs_time,predicate_type predicate);
#endif
};
}
@@ -498,6 +659,96 @@ return true;
[endsect]
[section:wait_until `template <class lock_type, class Clock, class Duration> cv_status wait_until(lock_type& lock, const chrono::time_point<Clock, Duration>& abs_time)`]
[variablelist
[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
thread will unblock when notified by a call to `this->notify_one()` or
`this->notify_all()`, when the time as reported by `Clock::now()`
would be equal to or later than the specified `abs_time`, or spuriously. When
the thread is unblocked (for whatever reason), the lock is reacquired by
invoking `lock.lock()` before the call to `wait` returns. The lock is also
reacquired by invoking `lock.lock()` if the function exits with an exception.]]
[[Returns:] [`cv_status::timeout` if the call is returning because the time specified by
`abs_time` was reached, `cv_status::no_timeout` otherwise.]]
[[Postcondition:] [`lock` is locked by the current thread.]]
[[Throws:] [__thread_resource_error__ if an error
occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
]
[endsect]
[section:wait_for `template <class lock_type, class Rep, class Period> cv_status wait_for(lock_type& lock, const chrono::duration<Rep, Period>& rel_time)`]
[variablelist
[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
thread will unblock when notified by a call to `this->notify_one()` or
`this->notify_all()`, after the period of time indicated by the `rel_time`
argument has elapsed, or spuriously. When the thread is unblocked (for whatever
reason), the lock is reacquired by invoking `lock.lock()` before the call to
`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
function exits with an exception.]]
[[Returns:] [`cv_status::timeout` if the call is returning because the time specified by
`abs_time` was reached, `cv_status::no_timeout` otherwise.]]
[[Postcondition:] [`lock` is locked by the current thread.]]
[[Throws:] [__thread_resource_error__ if an error
occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
]
[note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
[endsect]
[section:wait_until_predicate `template <class lock_type, class Clock, class Duration, class Predicate> bool wait_until(lock_type& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred)`]
[variablelist
[[Effects:] [As-if ``
while(!pred())
{
if(!__cvany_wait_until(lock,abs_time))
{
return pred();
}
}
return true;
``]]
]
[endsect]
[section:wait_for_predicate `template <class lock_type, class Rep, class Period, class Predicate> bool wait_until(lock_type& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred)`]
[variablelist
[[Effects:] [As-if ``
while(!pred())
{
if(!__cvany_wait_for(lock,rel_time))
{
return pred();
}
}
return true;
``]]
]
[endsect]
[endsect]
[section:condition Typedef `condition`]

215
doc/configuration.qbk Normal file
View File

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

365
doc/emulations.qbk Normal file
View File

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

1202
doc/future_ref.qbk Normal file

File diff suppressed because it is too large Load Diff

187
doc/futures.qbk Executable file
View File

@@ -0,0 +1,187 @@
[/
(C) Copyright 2008-11 Anthony Williams.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
]
[section:futures Futures]
[template future_state_link[link_text] [link thread.synchronization.futures.reference.future_state [link_text]]]
[def __uninitialized__ [future_state_link `boost::future_state::uninitialized`]]
[def __ready__ [future_state_link `boost::future_state::ready`]]
[def __waiting__ [future_state_link `boost::future_state::waiting`]]
[def __future_uninitialized__ `boost::future_uninitialized`]
[def __broken_promise__ `boost::broken_promise`]
[def __future_already_retrieved__ `boost::future_already_retrieved`]
[def __task_moved__ `boost::task_moved`]
[def __task_already_started__ `boost::task_already_started`]
[def __promise_already_satisfied__ `boost::promise_already_satisfied`]
[def __thread_interrupted__ `boost::thread_interrupted`]
[template unique_future_link[link_text] [link thread.synchronization.futures.reference.unique_future [link_text]]]
[def __unique_future__ [unique_future_link `boost::unique_future`]]
[template unique_future_get_link[link_text] [link thread.synchronization.futures.reference.unique_future.get [link_text]]]
[def __unique_future_get__ [unique_future_get_link `boost::unique_future<R>::get()`]]
[template unique_future_wait_link[link_text] [link thread.synchronization.futures.reference.unique_future.wait [link_text]]]
[def __unique_future_wait__ [unique_future_wait_link `boost::unique_future<R>::wait()`]]
[template unique_future_is_ready_link[link_text] [link thread.synchronization.futures.reference.unique_future.is_ready [link_text]]]
[def __unique_future_is_ready__ [unique_future_is_ready_link `boost::unique_future<R>::is_ready()`]]
[template unique_future_has_value_link[link_text] [link thread.synchronization.futures.reference.unique_future.has_value [link_text]]]
[def __unique_future_has_value__ [unique_future_has_value_link `boost::unique_future<R>::has_value()`]]
[template unique_future_has_exception_link[link_text] [link thread.synchronization.futures.reference.unique_future.has_exception [link_text]]]
[def __unique_future_has_exception__ [unique_future_has_exception_link `boost::unique_future<R>::has_exception()`]]
[template unique_future_get_state_link[link_text] [link thread.synchronization.futures.reference.unique_future.get_state [link_text]]]
[def __unique_future_get_state__ [unique_future_get_state_link `boost::unique_future<R>::get_state()`]]
[template shared_future_link[link_text] [link thread.synchronization.futures.reference.shared_future [link_text]]]
[def __shared_future__ [shared_future_link `boost::shared_future`]]
[template shared_future_get_link[link_text] [link thread.synchronization.futures.reference.shared_future.get [link_text]]]
[def __shared_future_get__ [shared_future_get_link `boost::shared_future<R>::get()`]]
[template shared_future_wait_link[link_text] [link thread.synchronization.futures.reference.shared_future.wait [link_text]]]
[def __shared_future_wait__ [shared_future_wait_link `boost::shared_future<R>::wait()`]]
[template shared_future_is_ready_link[link_text] [link thread.synchronization.futures.reference.shared_future.is_ready [link_text]]]
[def __shared_future_is_ready__ [shared_future_is_ready_link `boost::shared_future<R>::is_ready()`]]
[template shared_future_has_value_link[link_text] [link thread.synchronization.futures.reference.shared_future.has_value [link_text]]]
[def __shared_future_has_value__ [shared_future_has_value_link `boost::shared_future<R>::has_value()`]]
[template shared_future_has_exception_link[link_text] [link thread.synchronization.futures.reference.shared_future.has_exception [link_text]]]
[def __shared_future_has_exception__ [shared_future_has_exception_link `boost::shared_future<R>::has_exception()`]]
[template shared_future_get_state_link[link_text] [link thread.synchronization.futures.reference.shared_future.get_state [link_text]]]
[def __shared_future_get_state__ [shared_future_get_state_link `boost::shared_future<R>::get_state()`]]
[template promise_link[link_text] [link thread.synchronization.futures.reference.promise [link_text]]]
[def __promise__ [promise_link `boost::promise`]]
[template packaged_task_link[link_text] [link thread.synchronization.futures.reference.packaged_task [link_text]]]
[def __packaged_task__ [packaged_task_link `boost::packaged_task`]]
[template wait_for_any_link[link_text] [link thread.synchronization.futures.reference.wait_for_any [link_text]]]
[def __wait_for_any__ [wait_for_any_link `boost::wait_for_any()`]]
[template wait_for_all_link[link_text] [link thread.synchronization.futures.reference.wait_for_all [link_text]]]
[def __wait_for_all__ [wait_for_all_link `boost::wait_for_all()`]]
[section:overview Overview]
The futures library provides a means of handling synchronous future values, whether those values are generated by another thread, or
on a single thread in response to external stimuli, or on-demand.
This is done through the provision of four class templates: __unique_future__ and __shared_future__ which are used to retrieve the
asynchronous results, and __promise__ and __packaged_task__ which are used to generate the asynchronous results.
An instance of __unique_future__ holds the one and only reference to a result. Ownership can be transferred between instances using
the move constructor or move-assignment operator, but at most one instance holds a reference to a given asynchronous result. When
the result is ready, it is returned from __unique_future_get__ by rvalue-reference to allow the result to be moved or copied as
appropriate for the type.
On the other hand, many instances of __shared_future__ may reference the same result. Instances can be freely copied and assigned,
and __shared_future_get__ returns a `const` reference so that multiple calls to __shared_future_get__ are safe. You can move an
instance of __unique_future__ into an instance of __shared_future__, thus transferring ownership of the associated asynchronous
result, but not vice-versa.
You can wait for futures either individually or with one of the __wait_for_any__ and __wait_for_all__ functions.
[endsect]
[section:creating Creating asynchronous values]
You can set the value in a future with either a __promise__ or a __packaged_task__. A __packaged_task__ is a callable object that
wraps a function or callable object. When the packaged task is invoked, it invokes the contained function in turn, and populates a
future with the return value. This is an answer to the perennial question: "how do I return a value from a thread?": package the
function you wish to run as a __packaged_task__ and pass the packaged task to the thread constructor. The future retrieved from the
packaged task can then be used to obtain the return value. If the function throws an exception, that is stored in the future in
place of the return value.
int calculate_the_answer_to_life_the_universe_and_everything()
{
return 42;
}
boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything);
boost::unique_future<int> fi=pt.get_future();
boost::thread task(boost::move(pt)); // launch task on a thread
fi.wait(); // wait for it to finish
assert(fi.is_ready());
assert(fi.has_value());
assert(!fi.has_exception());
assert(fi.get_state()==boost::future_state::ready);
assert(fi.get()==42);
A __promise__ is a bit more low level: it just provides explicit functions to store a value or an exception in the associated
future. A promise can therefore be used where the value may come from more than one possible source, or where a single operation may
produce multiple values.
boost::promise<int> pi;
boost::unique_future<int> fi;
fi=pi.get_future();
pi.set_value(42);
assert(fi.is_ready());
assert(fi.has_value());
assert(!fi.has_exception());
assert(fi.get_state()==boost::future_state::ready);
assert(fi.get()==42);
[endsect]
[section:lazy_futures Wait Callbacks and Lazy Futures]
Both __promise__ and __packaged_task__ support ['wait callbacks] that are invoked when a thread blocks in a call to `wait()` or
`timed_wait()` on a future that is waiting for the result from the __promise__ or __packaged_task__, in the thread that is doing the
waiting. These can be set using the `set_wait_callback()` member function on the __promise__ or __packaged_task__ in question.
This allows ['lazy futures] where the result is not actually computed until it is needed by some thread. In the example below, the
call to `f.get()` invokes the callback `invoke_lazy_task`, which runs the task to set the value. If you remove the call to
`f.get()`, the task is not ever run.
int calculate_the_answer_to_life_the_universe_and_everything()
{
return 42;
}
void invoke_lazy_task(boost::packaged_task<int>& task)
{
try
{
task();
}
catch(boost::task_already_started&)
{}
}
int main()
{
boost::packaged_task<int> task(calculate_the_answer_to_life_the_universe_and_everything);
task.set_wait_callback(invoke_lazy_task);
boost::unique_future<int> f(task.get_future());
assert(f.get()==42);
}
[endsect]
[include future_ref.qbk]
[endsect]

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
[/
(C) Copyright 2007-8 Anthony Williams.
(C) Copyright 2007-11 Anthony Williams
(C) Copyright 2011-12 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).
@@ -75,10 +76,11 @@ __try_mutex__ is a `typedef` to __mutex__, provided for backwards compatibility
void lock();
void unlock();
bool try_lock();
bool timed_lock(system_time const & abs_time);
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time);
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t);
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
@@ -86,6 +88,13 @@ __try_mutex__ is a `typedef` to __mutex__, provided for backwards compatibility
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef unspecified-type scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
bool timed_lock(system_time const & abs_time);
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time);
#endif
};
__timed_mutex__ implements the __timed_lockable_concept__ to provide an exclusive-ownership mutex. At most one thread can own the
@@ -181,10 +190,11 @@ __recursive_try_mutex__ is a `typedef` to __recursive_mutex__, provided for back
bool try_lock();
void unlock();
bool timed_lock(system_time const & abs_time);
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time);
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t);
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
@@ -192,6 +202,13 @@ __recursive_try_mutex__ is a `typedef` to __recursive_mutex__, provided for back
typedef unique_lock<recursive_timed_mutex> scoped_lock;
typedef unspecified-type scoped_try_lock;
typedef scoped_lock scoped_timed_lock;
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
bool timed_lock(system_time const & abs_time);
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time);
#endif
};
__recursive_timed_mutex__ implements the __timed_lockable_concept__ to provide an exclusive-ownership recursive mutex. At most one

View File

@@ -7,16 +7,37 @@
[section:once One-time Initialization]
#include <boost/thread/once.hpp>
namespace boost
{
struct once_flag;
template<typename Callable>
void call_once(once_flag& flag,Callable func);
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
void call_once(void (*func)(),once_flag& flag);
#endif
}
`boost::call_once` provides a mechanism for ensuring that an initialization routine is run exactly once without data races or deadlocks.
[section:once_flag Typedef `once_flag`]
#include <boost/thread/once.hpp>
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
struct once_flag
{
constexprr once_flag() noexcept;
once_flag(const once_flag&) = delete;
once_flag& operator=(const once_flag&) = delete;
};
#else
typedef platform-specific-type once_flag;
#define BOOST_ONCE_INIT platform-specific-initializer
#endif
Objects of type `boost::once_flag` shall be initialized with `BOOST_ONCE_INIT`:
Objects of type `boost::once_flag` shall be initialized with `BOOST_ONCE_INIT` if BOOST_THREAD_PROVIDES_ONCE_CXX11 is not defined
boost::once_flag f=BOOST_ONCE_INIT;
@@ -24,8 +45,6 @@ Objects of type `boost::once_flag` shall be initialized with `BOOST_ONCE_INIT`:
[section:call_once Non-member function `call_once`]
#include <boost/thread/once.hpp>
template<typename Callable>
void call_once(once_flag& flag,Callable func);
@@ -45,6 +64,15 @@ all subsequent `call_once` invocations on the same `once_flag` object. ]]
[[Throws:] [`thread_resource_error` when the effects cannot be achieved. or any exception propagated from `func`.]]
[[Note:] [The function passed to `call_once` must not also call
`call_once` passing the same `once_flag` object. This may cause
deadlock, or invoking the passed function a second time. The
alternative is to allow the second call to return immediately, but
that assumes the code knows it has been called recursively, and can
proceed even though the call to `call_once` didn't actually call the
function, in which case it could also avoid calling `call_once`
recursively.]]
]
void call_once(void (*func)(),once_flag& flag);

View File

@@ -1,5 +1,6 @@
[/
(C) Copyright 2007-8 Anthony Williams.
(C) Copyright 2007-12 Anthony Williams.
(C) Copyright 20012 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
@@ -11,7 +12,7 @@ __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. This version is a major rewrite designed to
The __boost_thread__ library was originally written and designed by William E. Kempf (version 0). Anthony Williams version (version 1) was a major rewrite designed to
closely follow the proposals presented to the C++ Standards Committee, in particular
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html N2497],
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2320.html N2320],
@@ -19,6 +20,9 @@ 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.
In order to use the classes and functions described here, you can
either include the specific headers specified by the descriptions of
each class or function, or include the master thread library header:
@@ -28,3 +32,20 @@ each class or function, or include the master thread library header:
which includes all the other headers in turn.
[endsect]
[section:build Using and building the library]
Boost.Thread is configured following the conventions used to build [@http://www.boost.org/doc/libs/1_48_0/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_for_libraries_with_separate_source_code libraries with separate source code]. Boost.Thread will import/export the code only if the user has specifically asked for it, by defining either BOOST_ALL_DYN_LINK if they want all boost libraries to be dynamically linked, or BOOST_THREAD_DYN_LINK if they want just this one to be dynamically liked.
The definition of these macros determines whether BOOST_THREAD_USE_DLL is defined. If BOOST_THREAD_USE_DLL is not defined, the library will define BOOST_THREAD_USE_DLL or BOOST_THREAD_USE_LIB depending on whether the platform. On non windows platforms BOOST_THREAD_USE_LIB is defined if is not defined. In windows platforms, BOOST_THREAD_USE_LIB is defined if BOOST_THREAD_USE_DLL and the compiler supports auto-tss cleanup with Boost.Threads (for the time been Msvc and Intel)
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.
The following section describes all the macros used to configure Boost.Thread.
[include configuration.qbk]
[endsect]

View File

@@ -12,19 +12,30 @@
class shared_mutex
{
public:
shared_mutex(shared_mutex const&) = delete;
shared_mutex& operator=(shared_mutex const&) = delete;
shared_mutex();
~shared_mutex();
void lock_shared();
bool try_lock_shared();
bool timed_lock_shared(system_time const& timeout);
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock_shared();
void lock();
bool try_lock();
bool timed_lock(system_time const& timeout);
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock();
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
// use upgrade_mutex instead.
void lock_upgrade();
void unlock_upgrade();
@@ -32,13 +43,101 @@
void unlock_and_lock_upgrade();
void unlock_and_lock_shared();
void unlock_upgrade_and_lock_shared();
#endif
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
bool timed_lock_shared(system_time const& timeout);
bool timed_lock(system_time const& timeout);
#endif
};
The class `boost::shared_mutex` provides an implementation of a multiple-reader / single-writer mutex. It implements the
__upgrade_lockable_concept__.
__shared_lockable_concept__.
Multiple concurrent calls to __lock_ref__, __try_lock_ref__, __timed_lock_ref__, __lock_shared_ref__, __try_lock_shared_ref__ and
__timed_lock_shared_ref__ shall be permitted.
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.
[endsect]
[section:upgrade_mutex Class `upgrade_mutex`]
#include <boost/thread/shared_mutex.hpp>
class upgrade_mutex
{
public:
upgrade_mutex(upgrade_mutex const&) = delete;
upgrade_mutex& operator=(upgrade_mutex const&) = delete;
upgrade_mutex();
~upgrade_mutex();
void lock_shared();
bool try_lock_shared();
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock_shared();
void lock();
bool try_lock();
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock();
void lock_upgrade();
template <class Rep, class Period>
bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock_upgrade();
// Shared <-> Exclusive
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock();
template <class Rep, class Period>
bool try_unlock_shared_and_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_unlock_shared_and_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
#endif
void unlock_and_lock_shared();
// Shared <-> Upgrade
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock_upgrade();
template <class Rep, class Period>
bool try_unlock_shared_and_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_unlock_shared_and_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time);
#endif
void unlock_upgrade_and_lock_shared();
// Upgrade <-> Exclusive
void unlock_upgrade_and_lock();
#if defined(BOOST_THREAD_PLATFORM_PTHREAD)
|| defined(BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN)
bool try_unlock_upgrade_and_lock();
template <class Rep, class Period>
bool try_unlock_upgrade_and_lock_for(const chrono::duration<Rep, Period>& rel_time);
template <class Clock, class Duration>
bool try_unlock_upgrade_and_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
#endif
void unlock_and_lock_upgrade();
};
The class `boost::upgrade_mutex` provides an implementation of a multiple-reader / single-writer mutex. It implements the
__upgrade_lockable_concept__.
Multiple concurrent calls to __lock_ref__, __try_lock_ref__, `__try_lock_for()`, `__try_lock_until()`, __timed_lock_ref__, __lock_shared_ref__,
`__try_lock_shared_for()`, `__try_lock_shared_until()`, __try_lock_shared_ref__ and __timed_lock_shared_ref__ are permitted.
[endsect]

14
doc/sync_tutorial.qbk Normal file
View File

@@ -0,0 +1,14 @@
[/
(C) Copyright 2012 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
]
[section:tutorial Tutorial]
[@http://home.roadrunner.com/~hinnant/mutexes/locking.html Handling mutexes in C++] is an excellent tutorial. You need just replace std and ting by boost.
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html Mutex, Lock, Condition Variable Rationale] adds rationale for the design decisions made for mutexes, locks and condition variables.
[endsect]

View File

@@ -1,14 +1,17 @@
[/
(C) Copyright 2007-8 Anthony Williams.
(C) Copyright 2008-11 Anthony Williams
(C) Copyright 2011-12 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).
]
[article Thread
[quickbook 1.4]
[authors [Williams, Anthony]]
[copyright 2007-8 Anthony Williams]
[library Thread
[quickbook 1.5]
[version 3.0.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
[copyright 2011-12 Vicente J. Botet Escriba]
[purpose C++ Library for launching threads and synchronizing data between them]
[category text]
[license
@@ -21,6 +24,11 @@
[template lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.lockable [link_text]]]
[def __lockable_concept__ [lockable_concept_link `Lockable` concept]]
[def __lockable_concept_type__ [lockable_concept_link `Lockable`]]
[def __BasicLockable [link thread.synchronization.mutex_concepts.basic_lockable `BasicLockable`]]
[def __Lockable [link thread.synchronization.mutex_concepts.lockable `Lockable`]]
[def __TimedLockable [link thread.synchronization.mutex_concepts.timed_lockable `TimedLockable `]]
[def __SharedLockable [link thread.synchronization.mutex_concepts.shared_lockable `SharedLockable `]]
[def __UpgradeLockable [link thread.synchronization.mutex_concepts.upgrade_lockable `UpgradeLockable `]]
[template timed_lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable [link_text]]]
[def __timed_lockable_concept__ [timed_lockable_concept_link `TimedLockable` concept]]
@@ -35,8 +43,9 @@
[def __upgrade_lockable_concept_type__ [upgrade_lockable_concept_link `UpgradeLockable`]]
[template lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.lock [link_text]]]
[template lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.basic_lockable.lock [link_text]]]
[def __lock_ref__ [lock_ref_link `lock()`]]
[def __lock [link thread.synchronization.mutex_concepts.basic_lockable.lock `lock`]]
[template lock_multiple_ref_link[link_text] [link thread.synchronization.lock_functions.lock_multiple [link_text]]]
[def __lock_multiple_ref__ [lock_multiple_ref_link `lock()`]]
@@ -44,47 +53,85 @@
[template try_lock_multiple_ref_link[link_text] [link thread.synchronization.lock_functions.try_lock_multiple [link_text]]]
[def __try_lock_multiple_ref__ [try_lock_multiple_ref_link `try_lock()`]]
[template unlock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.unlock [link_text]]]
[template unlock_ref_link[link_text] [link thread.synchronization.mutex_concepts.basic_lockable.unlock [link_text]]]
[def __unlock_ref__ [unlock_ref_link `unlock()`]]
[def __unlock [link thread.synchronization.mutex_concepts.basic_lockable.unlock `unlock`]]
[template try_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.try_lock [link_text]]]
[def __try_lock_ref__ [try_lock_ref_link `try_lock()`]]
[def __try_lock [link thread.synchronization.mutex_concepts.lockable.try_lock `try_lock`]]
[template timed_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock [link_text]]]
[def __timed_lock_ref__ [timed_lock_ref_link `timed_lock()`]]
[def __timed_lock [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock `timed_lock`]]
[def __try_lock_for [link thread.synchronization.mutex_concepts.timed_lockable.try_lock_for `try_lock_for`]]
[def __try_lock_until [link thread.synchronization.mutex_concepts.timed_lockable.try_lock_until `try_lock_until`]]
[template timed_lock_duration_ref_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock_duration [link_text]]]
[def __timed_lock_duration_ref__ [timed_lock_duration_ref_link `timed_lock()`]]
[def __timed_lock_duration [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock_duration `timed_lock`]]
[template lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.lock_shared [link_text]]]
[def __lock_shared_ref__ [lock_shared_ref_link `lock_shared()`]]
[def __lock_shared [link thread.synchronization.mutex_concepts.shared_lockable.lock_shared `lock_shared()`]]
[template unlock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.unlock_shared [link_text]]]
[def __unlock_shared_ref__ [unlock_shared_ref_link `unlock_shared()`]]
[def __unlock_shared [link thread.synchronization.mutex_concepts.shared_lockable.unlock_shared `unlock_shared()`]]
[template try_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared [link_text]]]
[def __try_lock_shared_ref__ [try_lock_shared_ref_link `try_lock_shared()`]]
[def __try_lock_shared [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared `try_lock_shared`]]
[template timed_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.timed_lock_shared [link_text]]]
[def __timed_lock_shared_ref__ [timed_lock_shared_ref_link `timed_lock_shared()`]]
[def __try_lock_shared_for [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared_for `try_lock_shared_for`]]
[def __try_lock_shared_for [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared_until `try_lock_shared_until`]]
[template timed_lock_shared_duration_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.timed_lock_shared_duration [link_text]]]
[def __timed_lock_shared_duration_ref__ [timed_lock_shared_duration_ref_link `timed_lock_shared()`]]
[def __try_lock_shared_for [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared_for `try_lock_shared_for`]]
[def __try_lock_shared_until [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared_until `try_lock_shared_until`]]
[template lock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.lock_upgrade [link_text]]]
[def __lock_upgrade_ref__ [lock_upgrade_ref_link `lock_upgrade()`]]
[def __lock_upgrade [link thread.synchronization.mutex_concepts.upgrade_lockable.lock_upgrade `lock_upgrade`]]
[def __try_lock_upgrade [link thread.synchronization.mutex_concepts.upgrade_lockable.try_lock_upgrade `try_lock_upgrade`]]
[def __try_lock_upgrade_for [link thread.synchronization.mutex_concepts.upgrade_lockable.try_lock_upgrade_for `try_lock_upgrade_for`]]
[def __try_lock_upgrade_until [link thread.synchronization.mutex_concepts.upgrade_lockable.try_lock_upgrade_until `try_lock_upgrade_until`]]
[template unlock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade [link_text]]]
[def __unlock_upgrade_ref__ [unlock_upgrade_ref_link `unlock_upgrade()`]]
[def __unlock_upgrade [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade `unlock_upgrade`]]
[template unlock_upgrade_and_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock [link_text]]]
[def __unlock_upgrade_and_lock_ref__ [unlock_upgrade_and_lock_ref_link `unlock_upgrade_and_lock()`]]
[def __unlock_upgrade_and_lock [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock `unlock_upgrade_and_lock`]]
[template unlock_and_lock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_and_lock_upgrade [link_text]]]
[def __unlock_and_lock_upgrade_ref__ [unlock_and_lock_upgrade_ref_link `unlock_and_lock_upgrade()`]]
[def __unlock_and_lock_upgrade [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_and_lock_upgrade `unlock_and_lock_upgrade`]]
[template unlock_upgrade_and_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock_shared [link_text]]]
[def __unlock_upgrade_and_lock_shared_ref__ [unlock_upgrade_and_lock_shared_ref_link `unlock_upgrade_and_lock_shared()`]]
[def __unlock_upgrade_and_lock_shared [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock_shared `unlock_upgrade_and_lock_shared`]]
[def __try_unlock_shared_and_lock [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock `try_unlock_shared_and_lock`]]
[def __try_unlock_shared_and_lock_for [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock_for `try_unlock_shared_and_lock_for`]]
[def __try_unlock_shared_and_lock_until [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock_until `try_unlock_shared_and_lock_until`]]
[def __unlock_and_lock_shared [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_and_lock_shared `unlock_and_lock_shared`]]
[def __try_unlock_shared_and_lock_upgrade [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock_upgrade `try_unlock_shared_and_lock_upgrade`]]
[def __try_unlock_shared_and_lock_upgrade_for [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock_upgrade_for `try_unlock_shared_and_lock_upgrade_for`]]
[def __try_unlock_shared_and_lock_upgrade_until [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_shared_and_lock_upgrade_until `try_unlock_shared_and_lock_upgrade_until`]]
[def __try_unlock_upgrade_and_lock [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_upgrade_and_lock `try_unlock_upgrade_and_lock`]]
[def __try_unlock_upgrade_and_lock_for [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_upgrade_and_lock_for `try_unlock_upgrade_and_lock_for`]]
[def __try_unlock_upgrade_and_lock_until [link thread.synchronization.mutex_concepts.upgrade_lockable.try_unlock_upgrade_and_lock_until `try_unlock_upgrade_and_lock_until`]]
[template owns_lock_ref_link[link_text] [link thread.synchronization.locks.unique_lock.owns_lock [link_text]]]
[def __owns_lock_ref__ [owns_lock_ref_link `owns_lock()`]]
@@ -114,17 +161,29 @@
[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 __thread__ [link thread.thread_management.thread `boost::thread`]]
[def __thread [link thread.thread_management.thread `boost::thread`]]
[def __thread_id__ [link thread.thread_management.thread.id `boost::thread::id`]]
[template join_link[link_text] [link thread.thread_management.thread.join [link_text]]]
[def __join__ [join_link `join()`]]
[def __try_join_for [link thread.thread_management.thread.try_join_for `try_join_for`]]
[def __try_join_until [link thread.thread_management.thread.try_join_until `try_join_until`]]
[template timed_join_link[link_text] [link thread.thread_management.thread.timed_join [link_text]]]
[def __timed_join__ [timed_join_link `timed_join()`]]
[def __detach__ [link thread.thread_management.thread.detach `detach()`]]
[def __interrupt__ [link thread.thread_management.thread.interrupt `interrupt()`]]
[def __sleep__ [link thread.thread_management.this_thread.sleep `boost::this_thread::sleep()`]]
[def __sleep_for [link thread.thread_management.this_thread.sleep_for `sleep_for`]]
[def __sleep_until [link thread.thread_management.this_thread.sleep_until `sleep_until`]]
[def __yield [link thread.thread_management.this_thread.yield `yield`]]
[def __get_id [link thread.thread_management.thread.get_id `get_id`]]
[def __interruption_enabled__ [link thread.thread_management.this_thread.interruption_enabled `boost::this_thread::interruption_enabled()`]]
[def __interruption_requested__ [link thread.thread_management.this_thread.interruption_requested `boost::this_thread::interruption_requested()`]]
@@ -140,11 +199,21 @@
[def __cond_wait__ [cond_wait_link `wait()`]]
[template cond_timed_wait_link[link_text] [link thread.synchronization.condvar_ref.condition_variable.timed_wait [link_text]]]
[def __cond_timed_wait__ [cond_timed_wait_link `timed_wait()`]]
[def __condition_variable [link thread.synchronization.condvar_ref.condition_variable `condition_variable`]]
[def __wait_for [link thread.synchronization.condvar_ref.condition_variable.wait_for `wait_for`]]
[def __wait_until [link thread.synchronization.condvar_ref.condition_variable.wait_until `wait_until`]]
[template cond_any_wait_link[link_text] [link thread.synchronization.condvar_ref.condition_variable_any.wait [link_text]]]
[def __cond_any_wait__ [cond_any_wait_link `wait()`]]
[template cond_any_timed_wait_link[link_text] [link thread.synchronization.condvar_ref.condition_variable_any.timed_wait [link_text]]]
[def __cond_any_timed_wait__ [cond_any_timed_wait_link `timed_wait()`]]
[def __condition_variable_any [link thread.synchronization.condvar_ref.condition_variable_any `condition_variable_any`]]
[def __cvany_wait_for [link thread.synchronization.condvar_ref.condition_variable_any.wait_for `wait_for`]]
[def __cvany_wait_until [link thread.synchronization.condvar_ref.condition_variable_any.wait_until `wait_until`]]
[def __blocked__ ['blocked]]
[include overview.qbk]
@@ -153,15 +222,21 @@
[include thread_ref.qbk]
[section:synchronization Synchronization]
[include sync_tutorial.qbk]
[include mutex_concepts.qbk]
[include mutexes.qbk]
[include condition_variables.qbk]
[include once.qbk]
[include barrier.qbk]
[include futures.qbk]
[endsect]
[include tss.qbk]
[include time.qbk]
[include emulations.qbk]
[include acknowledgements.qbk]
[include compliance.qbk]

File diff suppressed because it is too large Load Diff

View File

@@ -5,19 +5,31 @@
http://www.boost.org/LICENSE_1_0.txt).
]
[section:time Date and Time Requirements]
[section:time Time Requirements]
As of Boost 1.35.0, the __boost_thread__ library uses the [link date_time Boost.Date_Time] library for all operations that require a
time out. These include (but are not limited to):
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
[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):
* __sleep__
* __timed_join__
* __cond_timed_wait__
* __timed_lock_ref__
For the overloads that accept an absolute time parameter, an object of type [link thread.time.system_time `boost::system_time`] is
For the overloads that accept an absolute time parameter, an object of type [link thread.time.deprecated.system_time `boost::system_time`] is
required. Typically, this will be obtained by adding a duration to the current time, obtained with a call to [link
thread.time.get_system_time `boost::get_system_time()`]. e.g.
thread.time.deprecated.get_system_time `boost::get_system_time()`]. e.g.
boost::system_time const timeout=boost::get_system_time() + boost::posix_time::milliseconds(500);
@@ -70,6 +82,7 @@ See the documentation for [link date_time.posix_time.ptime_class `boost::posix_t
]
[endsect]
[endsect]
[endsect]

View File

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

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <iostream>
@@ -50,8 +50,9 @@ boost::mutex io_mutex;
void sender() {
int n = 0;
while (n < 100) {
while (n < 1000000) {
buf.send(n);
if(!(n%10000))
{
boost::mutex::scoped_lock io_lock(io_mutex);
std::cout << "sent: " << n << std::endl;
@@ -65,18 +66,24 @@ void receiver() {
int n;
do {
n = buf.receive();
if(!(n%10000))
{
boost::mutex::scoped_lock io_lock(io_mutex);
std::cout << "received: " << n << std::endl;
}
} while (n != -1); // -1 indicates end of buffer
buf.send(-1);
}
int main(int, char*[])
{
boost::thread thrd1(&sender);
boost::thread thrd2(&receiver);
boost::thread thrd3(&receiver);
boost::thread thrd4(&receiver);
thrd1.join();
thrd2.join();
thrd3.join();
thrd4.join();
return 0;
}

View File

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

View File

@@ -1,15 +1,22 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_PROVIDES_ONCE_CXX11
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
#include <cassert>
int value=0;
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
boost::once_flag once;
#else
boost::once_flag once = BOOST_ONCE_INIT;
boost::once_flag once2 = once;
#endif
void init()
{
@@ -21,7 +28,7 @@ void thread_proc()
boost::call_once(&init, once);
}
int main(int argc, char* argv[])
int main()
{
boost::thread_group threads;
for (int i=0; i<5; ++i)

143
example/shared_monitor.cpp Normal file
View File

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

744
example/shared_mutex.cpp Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
// (C) Copyright 2008 Anthony Williams
// (C) Copyright 2008-9 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -21,5 +21,6 @@
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/barrier.hpp>
#include <boost/thread/future.hpp>
#endif

View File

@@ -2,13 +2,14 @@
// David Moore, William E. Kempf
// Copyright (C) 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_BARRIER_JDM030602_HPP
#define BOOST_BARRIER_JDM030602_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/throw_exception.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
@@ -27,14 +28,14 @@ namespace boost
: m_threshold(count), m_count(count), m_generation(0)
{
if (count == 0)
throw std::invalid_argument("count cannot be zero.");
boost::throw_exception(thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
}
bool wait()
{
boost::mutex::scoped_lock lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;

View File

@@ -0,0 +1,26 @@
// cv_status.hpp
//
// 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)
#ifndef BOOST_THREAD_CV_STATUS_HPP
#define BOOST_THREAD_CV_STATUS_HPP
#include <boost/detail/scoped_enum_emulation.hpp>
namespace boost
{
// enum class cv_status;
BOOST_SCOPED_ENUM_DECLARE_BEGIN(cv_status)
{
no_timeout,
timeout
}
BOOST_SCOPED_ENUM_DECLARE_END(cv_status)
}
#endif // header

View File

@@ -1,7 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP
@@ -10,6 +11,119 @@
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
// This compiler doesn't support Boost.Chrono
#if defined __IBMCPP__ && (__IBMCPP__ < 1100)
#define BOOST_THREAD_DONT_USE_CHRONO
#endif
// This compiler doesn't support Boost.Move
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
#define BOOST_THREAD_DONT_USE_MOVE
#endif
// This compiler doesn't support Boost.Container Allocators files
#if defined __SUNPRO_CC
#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#endif
#if defined _WIN32_WCE && _WIN32_WCE==0x501
#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_BASIC_THREAD_ID
#define BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#endif
// Default version is 2
#if !defined BOOST_THREAD_VERSION
#define BOOST_THREAD_VERSION 2
#else
#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3
#error "BOOST_THREAD_VERSION must be 2 or 3"
#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
#define BOOST_THREAD_USES_CHRONO
#endif
// Don't provided by default in version 1.
#if defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION explicit
#else
#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION
#endif
// 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
#define BOOST_THREAD_PROMISE_LAZY
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0
#define BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
#endif
#endif
#if BOOST_THREAD_VERSION==3
#if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11
#define BOOST_THREAD_PROVIDES_ONCE_CXX11
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_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
#define BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE
#define BOOST_THREAD_PROVIDES_FUTURE
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#define BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSIONS
#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION
#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#endif
#if ! defined BOOST_THREAD_DONT_PROVIDE_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
#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
#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
#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
#define BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
#endif
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
# pragma warn -8008 // Condition always true/false
# pragma warn -8080 // Identifier declared but never used
@@ -17,10 +131,16 @@
# pragma warn -8066 // Unreachable code
#endif
#include "platform.hpp"
#include <boost/thread/detail/platform.hpp>
// provided for backwards compatibility, since this
// macro was used for several releases by mistake.
#if defined(BOOST_THREAD_DYN_DLL)
# define BOOST_THREAD_DYN_LINK
#endif
// compatibility with the rest of Boost's auto-linking code:
#if defined(BOOST_THREAD_DYN_DLL) || defined(BOOST_ALL_DYN_LINK)
#if defined(BOOST_THREAD_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
# undef BOOST_THREAD_USE_LIB
# define BOOST_THREAD_USE_DLL
#endif
@@ -47,12 +167,18 @@
#if defined(BOOST_HAS_DECLSPEC)
# if defined(BOOST_THREAD_BUILD_DLL) //Build dll
# define BOOST_THREAD_DECL __declspec(dllexport)
# define BOOST_THREAD_DECL BOOST_SYMBOL_EXPORT
//# define BOOST_THREAD_DECL __declspec(dllexport)
# elif defined(BOOST_THREAD_USE_DLL) //Use dll
# define BOOST_THREAD_DECL __declspec(dllimport)
# define BOOST_THREAD_DECL BOOST_SYMBOL_IMPORT
//# define BOOST_THREAD_DECL __declspec(dllimport)
# else
# define BOOST_THREAD_DECL
# endif
#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
# define BOOST_THREAD_DECL BOOST_SYMBOL_VISIBLE
#else
# define BOOST_THREAD_DECL
#endif // BOOST_HAS_DECLSPEC
@@ -63,7 +189,7 @@
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB)
//
// Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp
// once it's done with it:
// once it's done with it:
//
#if defined(BOOST_THREAD_USE_DLL)
# define BOOST_DYN_LINK

View File

@@ -0,0 +1,45 @@
// Copyright (C) 2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_DETAIL_DELETE_HPP
#define BOOST_THREAD_DETAIL_DELETE_HPP
#include <boost/config.hpp>
/**
* BOOST_THREAD_DELETE_COPY_CTOR deletes the copy constructor when the compiler supports it or
* makes it private.
*
* BOOST_THREAD_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or
* makes it private.
*/
#ifndef BOOST_NO_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
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
private: \
CLASS(CLASS&); \
public:
#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \
private: \
CLASS& operator=(CLASS&); \
public:
#endif // BOOST_NO_DELETED_FUNCTIONS
/**
* BOOST_THREAD_NO_COPYABLE deletes the copy constructor and assignment when the compiler supports it or
* makes them private.
*/
#define BOOST_THREAD_NO_COPYABLE(CLASS) \
BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS)
#endif // BOOST_THREAD_DETAIL_DELETE_HPP

View File

@@ -0,0 +1,54 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_THREAD_DETAIL_MEMORY_HPP
#define BOOST_THREAD_DETAIL_MEMORY_HPP
#include <boost/container/allocator_traits.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/config.hpp>
namespace boost
{
namespace thread_detail
{
template <class _Alloc>
class allocator_destructor
{
typedef container::allocator_traits<_Alloc> alloc_traits;
public:
typedef typename alloc_traits::pointer pointer;
typedef typename alloc_traits::size_type size_type;
private:
_Alloc& alloc_;
size_type s_;
public:
allocator_destructor(_Alloc& a, size_type s)BOOST_NOEXCEPT
: alloc_(a), s_(s)
{}
void operator()(pointer p)BOOST_NOEXCEPT
{
alloc_traits::deallocate(alloc_, p, s_);
}
};
} //namespace thread_detail
typedef container::allocator_arg_t allocator_arg_t;
BOOST_CONSTEXPR allocator_arg_t allocator_arg = {};
template <class T, class Alloc>
struct uses_allocator: public container::uses_allocator<T, Alloc>
{
};
} // namespace boost
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP

View File

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

View File

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

View File

@@ -3,15 +3,18 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2007-10 Anthony Williams
// (C) Copyright 20011-12 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#ifndef BOOST_NO_IOSTREAM
#include <ostream>
#endif
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/detail/thread_heap_alloc.hpp>
#include <boost/utility.hpp>
#include <boost/assert.hpp>
#include <list>
#include <algorithm>
@@ -22,6 +25,14 @@
#include <memory>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/io/ios_state.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/functional/hash.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
@@ -32,6 +43,7 @@
namespace boost
{
namespace detail
{
template<typename F>
@@ -39,27 +51,30 @@ namespace boost
public detail::thread_data_base
{
public:
#ifdef BOOST_HAS_RVALUE_REFS
thread_data(F&& f_):
f(static_cast<F&&>(f_))
{}
BOOST_THREAD_NO_COPYABLE(thread_data)
#ifndef BOOST_NO_RVALUE_REFERENCES
thread_data(BOOST_THREAD_RV_REF(F) f_):
f(boost::forward<F>(f_))
{}
// This overloading must be removed if we want the packaged_task's tests to pass.
// thread_data(F& f_):
// f(f_)
// {}
#else
thread_data(BOOST_THREAD_RV_REF(F) f_):
f(f_)
{}
thread_data(F f_):
f(f_)
{}
thread_data(detail::thread_move_t<F> f_):
f(f_)
{}
#endif
#endif
void run()
{
f();
}
private:
F f;
void operator=(thread_data&);
thread_data(thread_data&);
};
template<typename F>
@@ -68,14 +83,11 @@ namespace boost
{
private:
F& f;
void operator=(thread_data&);
thread_data(thread_data&);
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
thread_data(boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
@@ -88,46 +100,48 @@ namespace boost
{
private:
F& f;
void operator=(thread_data&);
thread_data(thread_data&);
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
thread_data(const boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
}
};
}
class BOOST_THREAD_DECL thread
{
public:
typedef thread_attributes attributes;
BOOST_THREAD_MOVABLE_ONLY(thread)
private:
thread(thread&);
thread& operator=(thread&);
void release_handle();
mutable boost::mutex thread_info_mutex;
detail::thread_data_ptr thread_info;
void start_thread();
void start_thread(const attributes& attr);
explicit thread(detail::thread_data_ptr data);
detail::thread_data_ptr get_thread_info() const;
detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const;
#ifdef BOOST_HAS_RVALUE_REFS
#ifndef BOOST_NO_RVALUE_REFERENCES
template<typename F>
static inline detail::thread_data_ptr make_thread_info(F&& f)
static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(static_cast<F&&>(f)));
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(
boost::forward<F>(f)));
}
static inline detail::thread_data_ptr make_thread_info(void (*f)())
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(f));
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(
boost::forward<void(*)()>(f)));
}
#else
template<typename F>
@@ -136,42 +150,50 @@ namespace boost
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
template<typename F>
static inline detail::thread_data_ptr make_thread_info(boost::detail::thread_move_t<F> f)
static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
struct dummy;
#endif
struct dummy;
public:
thread();
~thread();
#ifdef BOOST_HAS_RVALUE_REFS
template <class F>
thread(F&& f):
thread_info(make_thread_info(static_cast<F&&>(f)))
#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
thread(const volatile thread&);
#endif
#endif
thread() BOOST_NOEXCEPT;
~thread()
{
#if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
if (joinable()) {
std::terminate();
}
#else
detach();
#endif
}
#ifndef BOOST_NO_RVALUE_REFERENCES
template <
class F
>
explicit thread(BOOST_THREAD_RV_REF(F) f
, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
):
thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
{
start_thread();
}
thread(thread&& other)
template <
class F
>
thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f):
thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
{
thread_info.swap(other.thread_info);
}
thread& operator=(thread&& other)
{
thread_info=other.thread_info;
other.thread_info.reset();
return *this;
start_thread(attrs);
}
thread&& move()
{
return static_cast<thread&&>(*this);
}
#else
#ifdef BOOST_NO_SFINAE
template <class F>
@@ -180,50 +202,73 @@ namespace boost
{
start_thread();
}
template <class F>
thread(attributes& attrs, F f):
thread_info(make_thread_info(f))
{
start_thread(attrs);
}
#else
template <class F>
explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0):
explicit thread(F f
// todo Disable also if Or is_same<typename decay<F>::type, thread>
, typename disable_if<boost::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0):
thread_info(make_thread_info(f))
{
start_thread();
}
#endif
template <class F>
explicit thread(detail::thread_move_t<F> f):
thread(attributes& attrs, F f
, typename disable_if<boost::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0):
thread_info(make_thread_info(f))
{
start_thread(attrs);
}
#endif
template <class F>
explicit thread(BOOST_THREAD_RV_REF(F) f
, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
):
thread_info(make_thread_info(f))
{
start_thread();
}
thread(detail::thread_move_t<thread> x)
template <class F>
thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f):
thread_info(make_thread_info(f))
{
thread_info=x->thread_info;
x->thread_info.reset();
start_thread(attrs);
}
thread& operator=(detail::thread_move_t<thread> x)
#endif
thread(BOOST_THREAD_RV_REF(thread) x)
{
thread new_thread(x);
swap(new_thread);
thread_info=BOOST_THREAD_RV(x).thread_info;
BOOST_THREAD_RV(x).thread_info.reset();
}
#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
thread& operator=(thread x)
{
swap(x);
return *this;
}
operator detail::thread_move_t<thread>()
{
return move();
}
detail::thread_move_t<thread> move()
{
detail::thread_move_t<thread> x(*this);
return x;
}
#endif
#endif
thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT
{
#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
if (joinable()) std::terminate();
#endif
thread_info=BOOST_THREAD_RV(other).thread_info;
BOOST_THREAD_RV(other).thread_info.reset();
return *this;
}
template <class F,class A1>
thread(F f,A1 a1):
thread(F f,A1 a1,typename disable_if<boost::is_convertible<F&,thread_attributes >, dummy* >::type=0):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
{
start_thread();
@@ -284,40 +329,96 @@ namespace boost
start_thread();
}
void swap(thread& x)
void swap(thread& x) BOOST_NOEXCEPT
{
thread_info.swap(x.thread_info);
}
class id;
id get_id() const;
class BOOST_SYMBOL_VISIBLE id;
id get_id() const BOOST_NOEXCEPT;
bool joinable() const;
bool joinable() const BOOST_NOEXCEPT;
void join();
bool timed_join(const system_time& wait_until);
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_join_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_join_until(s_now + ceil<nanoseconds>(t - c_now));
}
template <class Duration>
bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
#endif
#if defined(BOOST_THREAD_PLATFORM_WIN32)
bool timed_join(const system_time& abs_time);
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp);
#endif
public:
#else
bool timed_join(const system_time& abs_time)
{
struct timespec const ts=detail::get_timespec(abs_time);
return do_try_join_until(ts);
}
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts;
seconds s = duration_cast<seconds>(d);
ts.tv_sec = static_cast<long>(s.count());
ts.tv_nsec = static_cast<long>((d - s).count());
return do_try_join_until(ts);
}
#endif
private:
bool do_try_join_until(struct timespec const &timeout);
public:
#endif
template<typename TimeDuration>
inline bool timed_join(TimeDuration const& rel_time)
{
return timed_join(get_system_time()+rel_time);
}
void detach();
static unsigned hardware_concurrency();
void detach() BOOST_NOEXCEPT;
static unsigned hardware_concurrency() BOOST_NOEXCEPT;
#define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
typedef detail::thread_data_base::native_handle_type native_handle_type;
native_handle_type native_handle();
#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
// Use thread::id when comparisions are needed
// backwards compatibility
bool operator==(const thread& other) const;
bool operator!=(const thread& other) const;
static inline void yield()
#endif
static inline void yield() BOOST_NOEXCEPT
{
this_thread::yield();
}
static inline void sleep(const system_time& xt)
{
this_thread::sleep(xt);
@@ -325,159 +426,200 @@ namespace boost
// extensions
void interrupt();
bool interruption_requested() const;
bool interruption_requested() const BOOST_NOEXCEPT;
};
inline void swap(thread& lhs,thread& rhs)
inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT
{
return lhs.swap(rhs);
}
#ifdef BOOST_HAS_RVALUE_REFS
inline thread&& move(thread&& t)
#ifndef BOOST_NO_RVALUE_REFERENCES
inline thread&& move(thread& t) BOOST_NOEXCEPT
{
return t;
}
#else
inline thread move(detail::thread_move_t<thread> t)
{
return thread(t);
return static_cast<thread&&>(t);
}
#endif
BOOST_THREAD_DCL_MOVABLE(thread)
namespace this_thread
{
class BOOST_THREAD_DECL disable_interruption
{
disable_interruption(const disable_interruption&);
disable_interruption& operator=(const disable_interruption&);
bool interruption_was_enabled;
friend class restore_interruption;
public:
disable_interruption();
~disable_interruption();
};
class BOOST_THREAD_DECL restore_interruption
{
restore_interruption(const restore_interruption&);
restore_interruption& operator=(const restore_interruption&);
public:
explicit restore_interruption(disable_interruption& d);
~restore_interruption();
};
thread::id BOOST_THREAD_DECL get_id();
thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT;
void BOOST_THREAD_DECL interruption_point();
bool BOOST_THREAD_DECL interruption_enabled();
bool BOOST_THREAD_DECL interruption_requested();
bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
inline void sleep(xtime const& abs_time)
inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time)
{
sleep(system_time(abs_time));
}
}
class thread::id
class BOOST_SYMBOL_VISIBLE thread::id
{
private:
detail::thread_data_ptr thread_data;
id(detail::thread_data_ptr thread_data_):
friend inline
std::size_t
hash_value(const thread::id &v)
{
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
return hash_value(v.thread_data);
#else
return hash_value(v.thread_data.get());
#endif
}
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#if defined(BOOST_THREAD_PLATFORM_WIN32)
typedef unsigned int data;
#else
typedef thread::native_handle_type data;
#endif
#else
typedef detail::thread_data_ptr data;
#endif
data thread_data;
id(data thread_data_):
thread_data(thread_data_)
{}
friend class thread;
friend id this_thread::get_id();
friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT;
public:
id():
thread_data()
id() BOOST_NOEXCEPT:
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#if defined(BOOST_THREAD_PLATFORM_WIN32)
thread_data(0)
#else
thread_data(0)
#endif
#else
thread_data()
#endif
{}
bool operator==(const id& y) const
id(const id& other) BOOST_NOEXCEPT :
thread_data(other.thread_data)
{}
bool operator==(const id& y) const BOOST_NOEXCEPT
{
return thread_data==y.thread_data;
}
bool operator!=(const id& y) const
bool operator!=(const id& y) const BOOST_NOEXCEPT
{
return thread_data!=y.thread_data;
}
bool operator<(const id& y) const
bool operator<(const id& y) const BOOST_NOEXCEPT
{
return thread_data<y.thread_data;
}
bool operator>(const id& y) const
bool operator>(const id& y) const BOOST_NOEXCEPT
{
return y.thread_data<thread_data;
}
bool operator<=(const id& y) const
bool operator<=(const id& y) const BOOST_NOEXCEPT
{
return !(y.thread_data<thread_data);
}
bool operator>=(const id& y) const
bool operator>=(const id& y) const BOOST_NOEXCEPT
{
return !(thread_data<y.thread_data);
}
#ifndef BOOST_NO_IOSTREAM
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
template<class charT, class traits>
friend std::basic_ostream<charT, traits>&
friend BOOST_SYMBOL_VISIBLE
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
{
if(x.thread_data)
{
return os<<x.thread_data;
io::ios_flags_saver ifs( os );
return os<< std::hex << x.thread_data;
}
else
{
return os<<"{Not-any-thread}";
}
}
#else
template<class charT, class traits>
BOOST_SYMBOL_VISIBLE
std::basic_ostream<charT, traits>&
print(std::basic_ostream<charT, traits>& os) const
{
if(thread_data)
{
io::ios_flags_saver ifs( os );
return os<< std::hex << thread_data;
}
else
{
return os<<"{Not-any-thread}";
}
}
#endif
#endif
};
#if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<class charT, class traits>
BOOST_SYMBOL_VISIBLE
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x)
{
return x.print(os);
}
#endif
inline bool thread::operator==(const thread& other) const
{
return get_id()==other.get_id();
}
inline bool thread::operator!=(const thread& other) const
{
return get_id()!=other.get_id();
}
namespace detail
{
struct thread_exit_function_base
{
virtual ~thread_exit_function_base()
{}
virtual void operator()() const=0;
virtual void operator()()=0;
};
template<typename F>
struct thread_exit_function:
thread_exit_function_base
{
F f;
thread_exit_function(F f_):
f(f_)
{}
void operator()() const
void operator()()
{
f();
}
};
void add_thread_exit_function(thread_exit_function_base*);
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
}
namespace this_thread
{
template<typename F>
@@ -487,83 +629,6 @@ namespace boost
detail::add_thread_exit_function(thread_exit_func);
}
}
class thread_group:
private noncopyable
{
public:
~thread_group()
{
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
delete *it;
}
}
template<typename F>
thread* create_thread(F threadfunc)
{
boost::lock_guard<mutex> guard(m);
std::auto_ptr<thread> new_thread(new thread(threadfunc));
threads.push_back(new_thread.get());
return new_thread.release();
}
void add_thread(thread* thrd)
{
if(thrd)
{
boost::lock_guard<mutex> guard(m);
threads.push_back(thrd);
}
}
void remove_thread(thread* thrd)
{
boost::lock_guard<mutex> guard(m);
std::list<thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd);
if(it!=threads.end())
{
threads.erase(it);
}
}
void join_all()
{
boost::lock_guard<mutex> guard(m);
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
(*it)->join();
}
}
void interrupt_all()
{
boost::lock_guard<mutex> guard(m);
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
(*it)->interrupt();
}
}
size_t size() const
{
boost::lock_guard<mutex> guard(m);
return threads.size();
}
private:
std::list<thread*> threads;
mutable mutex m;
};
}
#ifdef BOOST_MSVC

View File

@@ -0,0 +1,108 @@
#ifndef BOOST_THREAD_DETAIL_THREAD_GROUP_HPP
#define BOOST_THREAD_DETAIL_THREAD_GROUP_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-9 Anthony Williams
#include <list>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/config/abi_prefix.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4251)
#endif
namespace boost
{
class thread_group
{
private:
thread_group(thread_group const&);
thread_group& operator=(thread_group const&);
public:
thread_group() {}
~thread_group()
{
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
delete *it;
}
}
template<typename F>
thread* create_thread(F threadfunc)
{
boost::lock_guard<shared_mutex> guard(m);
std::auto_ptr<thread> new_thread(new thread(threadfunc));
threads.push_back(new_thread.get());
return new_thread.release();
}
void add_thread(thread* thrd)
{
if(thrd)
{
boost::lock_guard<shared_mutex> guard(m);
threads.push_back(thrd);
}
}
void remove_thread(thread* thrd)
{
boost::lock_guard<shared_mutex> guard(m);
std::list<thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd);
if(it!=threads.end())
{
threads.erase(it);
}
}
void join_all()
{
boost::shared_lock<shared_mutex> guard(m);
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
(*it)->join();
}
}
void interrupt_all()
{
boost::shared_lock<shared_mutex> guard(m);
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
(*it)->interrupt();
}
}
size_t size() const
{
boost::shared_lock<shared_mutex> guard(m);
return threads.size();
}
private:
std::list<thread*> threads;
mutable shared_mutex m;
};
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,36 @@
#ifndef BOOST_THREAD_DETAIL_THREAD_INTERRUPTION_HPP
#define BOOST_THREAD_DETAIL_THREAD_INTERRUPTION_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-9 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
namespace boost
{
namespace this_thread
{
class BOOST_THREAD_DECL disable_interruption
{
bool interruption_was_enabled;
friend class restore_interruption;
public:
BOOST_THREAD_NO_COPYABLE(disable_interruption)
disable_interruption() BOOST_NOEXCEPT;
~disable_interruption() BOOST_NOEXCEPT;
};
class BOOST_THREAD_DECL restore_interruption
{
public:
BOOST_THREAD_NO_COPYABLE(restore_interruption)
explicit restore_interruption(disable_interruption& d) BOOST_NOEXCEPT;
~restore_interruption() BOOST_NOEXCEPT;
};
}
}
#endif

View File

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

View File

@@ -1,8 +1,9 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007-8 Anthony Williams
// Copyright (C) 2007-9 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_EXCEPTIONS_PDM070801_H
@@ -18,97 +19,205 @@
#include <string>
#include <stdexcept>
#include <boost/system/system_error.hpp>
#include <boost/system/error_code.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class BOOST_THREAD_DECL thread_interrupted
class BOOST_SYMBOL_VISIBLE thread_interrupted
{};
class BOOST_THREAD_DECL thread_exception : public std::exception
{
protected:
thread_exception();
thread_exception(int sys_err_code);
public:
~thread_exception() throw();
int native_error() const;
private:
int m_sys_err;
};
class condition_error:
public std::exception
class BOOST_SYMBOL_VISIBLE thread_exception:
public system::system_error
//public std::exception
{
typedef system::system_error base_type;
public:
const char* what() const throw()
thread_exception()
: base_type(0,system::system_category())
{}
thread_exception(int sys_error_code)
: base_type(sys_error_code, system::system_category())
{}
thread_exception( int ev, const char * what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
{
return "Condition error";
}
thread_exception( int ev, const std::string & what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
{
}
~thread_exception() throw()
{}
int native_error() const
{
return code().value();
}
};
class BOOST_THREAD_DECL lock_error : public thread_exception
{
public:
lock_error();
lock_error(int sys_err_code);
~lock_error() throw();
class BOOST_SYMBOL_VISIBLE condition_error:
public system::system_error
//public std::exception
{
typedef system::system_error base_type;
public:
condition_error()
: base_type(system::error_code(0, system::system_category()), "Condition error")
{}
condition_error( int ev )
: base_type(system::error_code(ev, system::system_category()), "Condition error")
{
}
condition_error( int ev, const char * what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
{
}
condition_error( int ev, const std::string & what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
{
}
};
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL thread_resource_error : public thread_exception
{
public:
thread_resource_error();
thread_resource_error(int sys_err_code);
~thread_resource_error() throw();
class BOOST_SYMBOL_VISIBLE lock_error:
public thread_exception
{
typedef thread_exception base_type;
public:
lock_error()
: base_type(0, "boost::lock_error")
{}
virtual const char* what() const throw();
};
lock_error( int ev )
: base_type(ev, "boost::lock_error")
{
}
lock_error( int ev, const char * what_arg )
: base_type(ev, what_arg)
{
}
lock_error( int ev, const std::string & what_arg )
: base_type(ev, what_arg)
{
}
class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception
{
public:
unsupported_thread_option();
unsupported_thread_option(int sys_err_code);
~unsupported_thread_option() throw();
~lock_error() throw()
{}
virtual const char* what() const throw();
};
};
class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception
{
public:
invalid_thread_argument();
invalid_thread_argument(int sys_err_code);
~invalid_thread_argument() throw();
class BOOST_SYMBOL_VISIBLE thread_resource_error:
public thread_exception
{
typedef thread_exception base_type;
public:
thread_resource_error()
: base_type(system::errc::resource_unavailable_try_again, "boost::thread_resource_error")
{}
virtual const char* what() const throw();
};
thread_resource_error( int ev )
: base_type(ev, "boost::thread_resource_error")
{
}
thread_resource_error( int ev, const char * what_arg )
: base_type(ev, what_arg)
{
}
thread_resource_error( int ev, const std::string & what_arg )
: base_type(ev, what_arg)
{
}
class BOOST_THREAD_DECL thread_permission_error : public thread_exception
{
public:
thread_permission_error();
thread_permission_error(int sys_err_code);
~thread_permission_error() throw();
virtual const char* what() const throw();
};
~thread_resource_error() throw()
{}
};
class BOOST_SYMBOL_VISIBLE unsupported_thread_option:
public thread_exception
{
typedef thread_exception base_type;
public:
unsupported_thread_option()
: base_type(system::errc::invalid_argument, "boost::unsupported_thread_option")
{}
unsupported_thread_option( int ev )
: base_type(ev, "boost::unsupported_thread_option")
{
}
unsupported_thread_option( int ev, const char * what_arg )
: base_type(ev, what_arg)
{
}
unsupported_thread_option( int ev, const std::string & what_arg )
: base_type(ev, what_arg)
{
}
};
class BOOST_SYMBOL_VISIBLE invalid_thread_argument:
public thread_exception
{
typedef thread_exception base_type;
public:
invalid_thread_argument()
: base_type(system::errc::invalid_argument, "boost::invalid_thread_argument")
{}
invalid_thread_argument( int ev )
: base_type(ev, "boost::invalid_thread_argument")
{
}
invalid_thread_argument( int ev, const char * what_arg )
: base_type(ev, what_arg)
{
}
invalid_thread_argument( int ev, const std::string & what_arg )
: base_type(ev, what_arg)
{
}
};
class BOOST_SYMBOL_VISIBLE thread_permission_error:
public thread_exception
{
typedef thread_exception base_type;
public:
thread_permission_error()
: base_type(system::errc::permission_denied, "boost::thread_permission_error")
{}
thread_permission_error( int ev )
: base_type(ev, "boost::thread_permission_error")
{
}
thread_permission_error( int ev, const char * what_arg )
: base_type(ev, what_arg)
{
}
thread_permission_error( int ev, const std::string & what_arg )
: base_type(ev, what_arg)
{
}
};
} // namespace boost
#include <boost/config/abi_suffix.hpp>
#endif // BOOST_THREAD_CONFIG_PDM070801_H
// Change log:
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
// once.hpp
//
// (C) Copyright 2006-7 Anthony Williams
// (C) Copyright 2006-7 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -22,6 +22,8 @@
namespace boost
{
// template<class Callable, class ...Args> void
// call_once(once_flag& flag, Callable&& func, Args&&... args);
inline void call_once(void (*func)(),once_flag& flag)
{
call_once(flag,func);

View File

@@ -3,67 +3,129 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2007-10 Anthony Williams
// (C) Copyright 2011 Vicente J. Botet Escriba
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#include "thread_data.hpp"
#include "condition_variable_fwd.hpp"
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/thread/pthread/thread_data.hpp>
#include <boost/thread/pthread/condition_variable_fwd.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
inline void condition_variable::wait(unique_lock<mutex>& m)
namespace this_thread
{
detail::interruption_checker check_for_interruption(&cond);
BOOST_VERIFY(!pthread_cond_wait(&cond,m.mutex()->native_handle()));
void BOOST_THREAD_DECL interruption_point();
}
inline bool condition_variable::timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
namespace thread_cv_detail
{
detail::interruption_checker check_for_interruption(&cond);
struct timespec const timeout=detail::get_timespec(wait_until);
int const cond_res=pthread_cond_timedwait(&cond,m.mutex()->native_handle(),&timeout);
template<typename MutexType>
struct lock_on_exit
{
MutexType* m;
lock_on_exit():
m(0)
{}
void activate(MutexType& m_)
{
m_.unlock();
m=&m_;
}
~lock_on_exit()
{
if(m)
{
m->lock();
}
}
};
}
inline void condition_variable::wait(unique_lock<mutex>& m)
{
int res=0;
{
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
do {
res = pthread_cond_wait(&cond,&internal_mutex);
} while (res == EINTR);
}
this_thread::interruption_point();
if(res)
{
boost::throw_exception(condition_error(res, "boost:: condition_variable constructor failed in pthread_cond_wait"));
}
}
inline bool condition_variable::do_timed_wait(
unique_lock<mutex>& m,
struct timespec const &timeout)
{
if (!m.owns_lock())
boost::throw_exception(condition_error(EPERM, "condition_variable do_timed_wait: mutex not locked"));
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
int cond_res;
{
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
}
this_thread::interruption_point();
if(cond_res==ETIMEDOUT)
{
return false;
}
BOOST_ASSERT(!cond_res);
if(cond_res)
{
boost::throw_exception(condition_error(cond_res, "condition_variable failed in pthread_cond_timedwait"));
}
return true;
}
inline void condition_variable::notify_one()
inline void condition_variable::notify_one() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
inline void condition_variable::notify_all()
inline void condition_variable::notify_all() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
}
class condition_variable_any
{
pthread_mutex_t internal_mutex;
pthread_cond_t cond;
condition_variable_any(condition_variable&);
condition_variable_any& operator=(condition_variable&);
public:
BOOST_THREAD_NO_COPYABLE(condition_variable_any)
condition_variable_any()
{
int const res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
throw thread_resource_error();
boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
throw thread_resource_error();
boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_cond_init"));
}
}
~condition_variable_any()
@@ -71,23 +133,21 @@ namespace boost
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
BOOST_VERIFY(!pthread_cond_destroy(&cond));
}
template<typename lock_type>
void wait(lock_type& m)
{
int res=0;
{
detail::interruption_checker check_for_interruption(&cond);
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
m.unlock();
res=pthread_cond_wait(&cond,&internal_mutex);
}
m.lock();
thread_cv_detail::lock_on_exit<lock_type> guard;
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
res=pthread_cond_wait(&cond,&internal_mutex);
}
this_thread::interruption_point();
if(res)
{
throw condition_error();
boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_wait"));
}
}
@@ -96,30 +156,12 @@ namespace boost
{
while(!pred()) wait(m);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{
struct timespec const timeout=detail::get_timespec(wait_until);
int res=0;
{
detail::interruption_checker check_for_interruption(&cond);
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
m.unlock();
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
}
m.lock();
}
if(res==ETIMEDOUT)
{
return false;
}
if(res)
{
throw condition_error();
}
return true;
return do_timed_wait(m, timeout);
}
template<typename lock_type>
bool timed_wait(lock_type& m,xtime const& wait_until)
@@ -156,17 +198,134 @@ namespace boost
return timed_wait(m,get_system_time()+wait_duration,pred);
}
void notify_one()
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type,class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return system_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
template <class lock_type, class Clock, class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class lock_type, class Clock, class Duration, class Predicate>
bool
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class lock_type, class Rep, class Period>
cv_status
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(d));
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
template <class lock_type, class Rep, class Period, class Predicate>
bool
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
while (!pred())
{
if (wait_for(lock, d) == cv_status::timeout)
return pred();
}
return true;
}
template <class lock_type>
inline void wait_until(
lock_type& lk,
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts;
seconds s = duration_cast<seconds>(d);
ts.tv_sec = static_cast<long>(s.count());
ts.tv_nsec = static_cast<long>((d - s).count());
do_timed_wait(lk, ts);
}
#endif
void notify_one() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
void notify_all()
void notify_all() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
}
private: // used by boost::thread::try_join_until
template <class lock_type>
inline bool do_timed_wait(
lock_type& m,
struct timespec const &timeout)
{
int res=0;
{
thread_cv_detail::lock_on_exit<lock_type> guard;
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
}
this_thread::interruption_point();
if(res==ETIMEDOUT)
{
return false;
}
if(res)
{
boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_timedwait"));
}
return true;
}
};
}

View File

@@ -4,38 +4,57 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011 Vicente J. Botet Escriba
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
#include <pthread.h>
#include <boost/thread/cv_status.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/date_time/posix_time/posix_time_duration.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class condition_variable
{
private:
pthread_mutex_t internal_mutex;
pthread_cond_t cond;
condition_variable(condition_variable&);
condition_variable& operator=(condition_variable&);
public:
BOOST_THREAD_NO_COPYABLE(condition_variable)
condition_variable()
{
int const res=pthread_cond_init(&cond,NULL);
int const res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
throw thread_resource_error();
boost::throw_exception(thread_resource_error(res, "boost:: condition_variable constructor failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
boost::throw_exception(thread_resource_error(res2, "boost:: condition_variable constructor failed in pthread_cond_init"));
}
}
~condition_variable()
{
BOOST_VERIFY(!pthread_cond_destroy(&cond));
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
int ret;
do {
ret = pthread_cond_destroy(&cond);
} while (ret == EINTR);
BOOST_VERIFY(!ret);
}
void wait(unique_lock<mutex>& m);
@@ -46,20 +65,38 @@ namespace boost
while(!pred()) wait(m);
}
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until);
bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until)
inline bool timed_wait(
unique_lock<mutex>& m,
boost::system_time const& wait_until)
{
#if defined BOOST_THREAD_WAIT_BUG
struct timespec const timeout=detail::get_timespec(wait_until + BOOST_THREAD_WAIT_BUG);
return do_timed_wait(m, timeout);
#else
struct timespec const timeout=detail::get_timespec(wait_until);
return do_timed_wait(m, timeout);
#endif
}
bool timed_wait(
unique_lock<mutex>& m,
xtime const& wait_until)
{
return timed_wait(m,system_time(wait_until));
}
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
bool timed_wait(
unique_lock<mutex>& m,
duration_type const& wait_duration)
{
return timed_wait(m,get_system_time()+wait_duration);
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
bool timed_wait(
unique_lock<mutex>& m,
boost::system_time const& wait_until,predicate_type pred)
{
while (!pred())
{
@@ -70,25 +107,127 @@ namespace boost
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until,predicate_type pred)
bool timed_wait(
unique_lock<mutex>& m,
xtime const& wait_until,predicate_type pred)
{
return timed_wait(m,system_time(wait_until),pred);
}
template<typename duration_type,typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
bool timed_wait(
unique_lock<mutex>& m,
duration_type const& wait_duration,predicate_type pred)
{
return timed_wait(m,get_system_time()+wait_duration,pred);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return system_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
template <class Clock, class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class Clock, class Duration, class Predicate>
bool
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class Rep, class Period>
cv_status
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(d));
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
template <class Rep, class Period, class Predicate>
bool
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
while (!pred())
{
if (wait_for(lock, d) == cv_status::timeout)
return pred();
}
return true;
}
#endif
#define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
typedef pthread_cond_t* native_handle_type;
native_handle_type native_handle()
{
return &cond;
}
void notify_one();
void notify_all();
void notify_one() BOOST_NOEXCEPT;
void notify_all() BOOST_NOEXCEPT;
#ifdef BOOST_THREAD_USES_CHRONO
inline void wait_until(
unique_lock<mutex>& lk,
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts;
seconds s = duration_cast<seconds>(d);
ts.tv_sec = static_cast<long>(s.count());
ts.tv_nsec = static_cast<long>((d - s).count());
do_timed_wait(lk, ts);
}
#endif
//private: // used by boost::thread::try_join_until
inline bool do_timed_wait(
unique_lock<mutex>& lock,
struct timespec const &timeout);
};
}

View File

@@ -1,23 +1,29 @@
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <pthread.h>
#include <boost/utility.hpp>
#include <boost/throw_exception.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/assert.hpp>
#include <errno.h>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0
#if _POSIX_TIMEOUTS >= 0 && _POSIX_C_SOURCE>=200112L
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
@@ -26,42 +32,73 @@
namespace boost
{
class mutex:
boost::noncopyable
class mutex
{
private:
pthread_mutex_t m;
public:
BOOST_THREAD_NO_COPYABLE(mutex)
mutex()
{
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
throw thread_resource_error();
boost::throw_exception(thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init"));
}
}
~mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
int ret;
do
{
ret = pthread_mutex_destroy(&m);
} while (ret == EINTR);
}
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
int res;
do
{
res = pthread_mutex_lock(&m);
} while (res == EINTR);
if (res)
{
boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
}
}
void unlock()
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
int ret;
do
{
ret = pthread_mutex_unlock(&m);
} while (ret == EINTR);
BOOST_VERIFY(!ret);
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
int res;
do
{
res = pthread_mutex_trylock(&m);
} while (res == EINTR);
if(res && (res!=EBUSY))
{
// The following throw_exception has been replaced by an assertion and just return false,
// as this is an internal error and the user can do nothing with the exception.
//boost::throw_exception(lock_error(res,"boost: mutex try_lock failed in pthread_mutex_trylock"));
BOOST_ASSERT_MSG(false ,"boost: mutex try_lock failed in pthread_mutex_trylock");
return false;
}
return !res;
}
#define BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
@@ -74,8 +111,7 @@ namespace boost
typedef mutex try_mutex;
class timed_mutex:
boost::noncopyable
class timed_mutex
{
private:
pthread_mutex_t m;
@@ -84,19 +120,20 @@ namespace boost
bool is_locked;
#endif
public:
BOOST_THREAD_NO_COPYABLE(timed_mutex)
timed_mutex()
{
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
throw thread_resource_error();
boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init"));
}
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
throw thread_resource_error();
boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init"));
}
is_locked=false;
#endif
@@ -129,26 +166,23 @@ namespace boost
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
bool timed_lock(system_time const & abs_time)
{
struct timespec const timeout=detail::get_timespec(abs_time);
int const res=pthread_mutex_timedlock(&m,&timeout);
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
private:
bool do_try_lock_until(struct timespec const &timeout)
{
return &m;
int const res=pthread_mutex_timedlock(&m,&timeout);
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
public:
#else
void lock()
@@ -167,7 +201,7 @@ namespace boost
is_locked=false;
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
bool try_lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
@@ -179,9 +213,9 @@ namespace boost
return true;
}
bool timed_lock(system_time const & abs_time)
private:
bool do_try_lock_until(struct timespec const &timeout)
{
struct timespec const timeout=detail::get_timespec(abs_time);
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
while(is_locked)
{
@@ -195,8 +229,55 @@ namespace boost
is_locked=true;
return true;
}
public:
#endif
bool timed_lock(system_time const & abs_time)
{
struct timespec const ts=detail::get_timespec(abs_time);
return do_try_lock_until(ts);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<nanoseconds>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts;
seconds s = duration_cast<seconds>(d);
ts.tv_sec = static_cast<long>(s.count());
ts.tv_nsec = static_cast<long>((d - s).count());
return do_try_lock_until(ts);
}
#endif
#define BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;

View File

@@ -3,7 +3,8 @@
// once.hpp
//
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -13,20 +14,42 @@
#include <pthread.h>
#include <boost/assert.hpp>
#include "pthread_mutex_scoped_lock.hpp"
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/cstdint.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
struct once_flag
{
BOOST_THREAD_NO_COPYABLE(once_flag)
BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
: epoch(BOOST_ONCE_INITIAL_FLAG_VALUE)
{}
private:
boost::uintmax_t epoch;
template<typename Function>
friend
void call_once(once_flag& flag,Function f);
};
#else // BOOST_THREAD_PROVIDES_ONCE_CXX11
struct once_flag
{
boost::uintmax_t epoch;
};
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
namespace detail
{
BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
@@ -34,10 +57,6 @@ namespace boost
BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
}
#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
// Based on Mike Burrows fast_pthread_once algorithm as described in
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
@@ -48,7 +67,7 @@ namespace boost
static boost::uintmax_t const being_initialized=uninitialized_flag+1;
boost::uintmax_t const epoch=flag.epoch;
boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
if(epoch<this_thread_epoch)
{
pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
@@ -58,10 +77,13 @@ namespace boost
if(flag.epoch==uninitialized_flag)
{
flag.epoch=being_initialized;
#ifndef BOOST_NO_EXCEPTIONS
try
{
#endif
pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
f();
#ifndef BOOST_NO_EXCEPTIONS
}
catch(...)
{
@@ -69,6 +91,7 @@ namespace boost
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
throw;
}
#endif
flag.epoch=--detail::once_global_epoch;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
}

View File

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

View File

@@ -1,12 +1,13 @@
#ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <pthread.h>
#include <boost/utility.hpp>
#include <boost/throw_exception.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
@@ -16,8 +17,13 @@
#endif
#include <boost/date_time/posix_time/conversion.hpp>
#include <errno.h>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0
@@ -25,138 +31,75 @@
#endif
#endif
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK)
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class recursive_mutex:
boost::noncopyable
class recursive_mutex
{
private:
pthread_mutex_t m;
public:
recursive_mutex()
{
pthread_mutexattr_t attr;
int const init_attr_res=pthread_mutexattr_init(&attr);
if(init_attr_res)
{
throw thread_resource_error();
}
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
if(set_attr_res)
{
throw thread_resource_error();
}
int const res=pthread_mutex_init(&m,&attr);
if(res)
{
throw thread_resource_error();
}
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
}
~recursive_mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
}
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
}
void unlock()
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
typedef unique_lock<recursive_mutex> scoped_lock;
typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
};
typedef recursive_mutex recursive_try_mutex;
class recursive_timed_mutex:
boost::noncopyable
{
private:
pthread_mutex_t m;
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_cond_t cond;
bool is_locked;
pthread_t owner;
unsigned count;
#endif
public:
recursive_timed_mutex()
BOOST_THREAD_NO_COPYABLE(recursive_mutex)
recursive_mutex()
{
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_mutexattr_t attr;
int const init_attr_res=pthread_mutexattr_init(&attr);
if(init_attr_res)
{
throw thread_resource_error();
boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_init"));
}
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
if(set_attr_res)
{
throw thread_resource_error();
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_settype"));
}
int const res=pthread_mutex_init(&m,&attr);
if(res)
{
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
throw thread_resource_error();
boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
}
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
#else
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
throw thread_resource_error();
boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
throw thread_resource_error();
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init"));
}
is_locked=false;
count=0;
#endif
}
~recursive_timed_mutex()
~recursive_mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
@@ -166,21 +109,14 @@ namespace boost
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
bool timed_lock(system_time const & abs_time)
{
struct timespec const timeout=detail::get_timespec(abs_time);
int const res=pthread_mutex_timedlock(&m,&timeout);
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
#define BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
@@ -196,7 +132,7 @@ namespace boost
++count;
return;
}
while(is_locked)
{
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
@@ -215,7 +151,7 @@ namespace boost
}
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
bool try_lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
@@ -229,9 +165,151 @@ namespace boost
return true;
}
bool timed_lock(system_time const & abs_time)
#endif
typedef unique_lock<recursive_mutex> scoped_lock;
typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
};
typedef recursive_mutex recursive_try_mutex;
class recursive_timed_mutex
{
private:
pthread_mutex_t m;
#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
pthread_cond_t cond;
bool is_locked;
pthread_t owner;
unsigned count;
#endif
public:
BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex)
recursive_timed_mutex()
{
#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
pthread_mutexattr_t attr;
int const init_attr_res=pthread_mutexattr_init(&attr);
if(init_attr_res)
{
boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_init"));
}
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
if(set_attr_res)
{
boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_settype"));
}
int const res=pthread_mutex_init(&m,&attr);
if(res)
{
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
}
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
#else
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init"));
}
is_locked=false;
count=0;
#endif
}
~recursive_timed_mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
}
void unlock()
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
private:
bool do_try_lock_until(struct timespec const &timeout)
{
int const res=pthread_mutex_timedlock(&m,&timeout);
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
public:
#else
void lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && pthread_equal(owner,pthread_self()))
{
++count;
return;
}
while(is_locked)
{
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
}
is_locked=true;
++count;
owner=pthread_self();
}
void unlock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(!--count)
{
is_locked=false;
}
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
bool try_lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && !pthread_equal(owner,pthread_self()))
{
return false;
}
is_locked=true;
++count;
owner=pthread_self();
return true;
}
private:
bool do_try_lock_until(struct timespec const &timeout)
{
struct timespec const timeout=detail::get_timespec(abs_time);
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && pthread_equal(owner,pthread_self()))
{
@@ -252,8 +330,56 @@ namespace boost
owner=pthread_self();
return true;
}
public:
#endif
bool timed_lock(system_time const & abs_time)
{
struct timespec const ts=detail::get_timespec(abs_time);
return do_try_lock_until(ts);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<nanoseconds>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts;
seconds s = duration_cast<seconds>(d);
ts.tv_sec = static_cast<long>(s.count());
ts.tv_nsec = static_cast<long>((d - s).count());
return do_try_lock_until(ts);
}
#endif
#define BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;

View File

@@ -2,6 +2,7 @@
#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -10,8 +11,13 @@
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/detail/thread_interruption.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -27,7 +33,7 @@ namespace boost
bool upgrade;
bool exclusive_waiting_blocked;
};
state_data state;
@@ -41,9 +47,10 @@ namespace boost
exclusive_cond.notify_one();
shared_cond.notify_all();
}
public:
BOOST_THREAD_NO_COPYABLE(shared_mutex)
shared_mutex()
{
state_data state_={0,0,0,0};
@@ -58,7 +65,7 @@ namespace boost
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
shared_cond.wait(lk);
@@ -69,7 +76,7 @@ namespace boost
bool try_lock_shared()
{
boost::mutex::scoped_lock lk(state_change);
if(state.exclusive || state.exclusive_waiting_blocked)
{
return false;
@@ -85,7 +92,7 @@ namespace boost
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
if(!shared_cond.timed_wait(lk,timeout))
@@ -102,12 +109,34 @@ namespace boost
{
return timed_lock_shared(get_system_time()+relative_time);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
{
return false;
}
}
++state.shared_count;
return true;
}
#endif
void unlock_shared()
{
boost::mutex::scoped_lock lk(state_change);
bool const last_reader=!--state.shared_count;
if(last_reader)
{
if(state.upgrade)
@@ -128,7 +157,7 @@ namespace boost
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
@@ -150,7 +179,7 @@ namespace boost
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=false;
exclusive_cond.notify_one();
release_waiters();
return false;
}
break;
@@ -166,10 +195,41 @@ namespace boost
return timed_lock(get_system_time()+relative_time);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time))
{
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=false;
release_waiters();
return false;
}
break;
}
}
state.exclusive=true;
return true;
}
#endif
bool try_lock()
{
boost::mutex::scoped_lock lk(state_change);
if(state.shared_count || state.exclusive)
{
return false;
@@ -179,7 +239,7 @@ namespace boost
state.exclusive=true;
return true;
}
}
void unlock()
@@ -225,9 +285,36 @@ namespace boost
template<typename TimeDuration>
bool timed_lock_upgrade(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
return timed_lock_upgrade(get_system_time()+relative_time);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
{
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
break;
}
}
++state.shared_count;
state.upgrade=true;
return true;
}
#endif
bool try_lock_upgrade()
{
boost::mutex::scoped_lock lk(state_change);
@@ -248,14 +335,17 @@ namespace boost
boost::mutex::scoped_lock lk(state_change);
state.upgrade=false;
bool const last_reader=!--state.shared_count;
if(last_reader)
{
state.exclusive_waiting_blocked=false;
release_waiters();
} else {
shared_cond.notify_all();
}
}
// Upgrade <-> Exclusive
void unlock_upgrade_and_lock()
{
boost::this_thread::disable_interruption do_not_disturb;
@@ -278,7 +368,58 @@ namespace boost
state.exclusive_waiting_blocked=false;
release_waiters();
}
bool try_unlock_upgrade_and_lock()
{
boost::mutex::scoped_lock lk(state_change);
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& state.upgrade
&& state.shared_count==1)
{
state.shared_count=0;
state.exclusive=true;
state.upgrade=false;
return true;
}
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool
try_unlock_upgrade_and_lock_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_upgrade_and_lock_until(
chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool
try_unlock_upgrade_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
if (state.shared_count != 1)
{
for (;;)
{
cv_status status = shared_cond.wait_until(lk,abs_time);
if (state.shared_count == 1)
break;
if(status == cv_status::timeout)
return false;
}
}
state.upgrade=false;
state.exclusive=true;
state.exclusive_waiting_blocked=false;
state.shared_count=0;
return true;
}
#endif
// Shared <-> Exclusive
void unlock_and_lock_shared()
{
boost::mutex::scoped_lock lk(state_change);
@@ -287,7 +428,59 @@ namespace boost
state.exclusive_waiting_blocked=false;
release_waiters();
}
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock()
{
boost::mutex::scoped_lock lk(state_change);
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& !state.upgrade
&& state.shared_count==1)
{
state.shared_count=0;
state.exclusive=true;
return true;
}
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool
try_unlock_shared_and_lock_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_shared_and_lock_until(
chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool
try_unlock_shared_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
if (state.shared_count != 1)
{
for (;;)
{
cv_status status = shared_cond.wait_until(lk,abs_time);
if (state.shared_count == 1)
break;
if(status == cv_status::timeout)
return false;
}
}
state.upgrade=false;
state.exclusive=true;
state.exclusive_waiting_blocked=false;
state.shared_count=0;
return true;
}
#endif
#endif
// Shared <-> Upgrade
void unlock_upgrade_and_lock_shared()
{
boost::mutex::scoped_lock lk(state_change);
@@ -295,7 +488,62 @@ namespace boost
state.exclusive_waiting_blocked=false;
release_waiters();
}
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock_upgrade()
{
boost::mutex::scoped_lock lk(state_change);
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& !state.upgrade
)
{
state.upgrade=true;
return true;
}
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool
try_unlock_shared_and_lock_upgrade_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_shared_and_lock_upgrade_until(
chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool
try_unlock_shared_and_lock_upgrade_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
if( state.exclusive
|| state.exclusive_waiting_blocked
|| state.upgrade
)
{
for (;;)
{
cv_status status = exclusive_cond.wait_until(lk,abs_time);
if( ! state.exclusive
&& ! state.exclusive_waiting_blocked
&& ! state.upgrade
)
break;
if(status == cv_status::timeout)
return false;
}
}
state.upgrade=true;
return true;
}
#endif
#endif
};
typedef shared_mutex upgrade_mutex;
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -4,6 +4,7 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
@@ -12,22 +13,79 @@
#include <boost/thread/mutex.hpp>
#include <boost/optional.hpp>
#include <pthread.h>
#include "condition_variable_fwd.hpp"
#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 <boost/config/abi_prefix.hpp>
namespace boost
{
class thread_attributes {
public:
thread_attributes() BOOST_NOEXCEPT {
int res = pthread_attr_init(&val_);
BOOST_VERIFY(!res && "pthread_attr_init failed");
}
~thread_attributes() {
int res = pthread_attr_destroy(&val_);
BOOST_VERIFY(!res && "pthread_attr_destroy failed");
}
// stack
void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
if (size==0) return;
std::size_t page_size = getpagesize();
#ifdef PTHREAD_STACK_MIN
if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN;
#endif
size = ((size+page_size-1)/page_size)*page_size;
int res = pthread_attr_setstacksize(&val_, size);
BOOST_VERIFY(!res && "pthread_attr_setstacksize failed");
}
std::size_t get_stack_size() const BOOST_NOEXCEPT {
std::size_t size;
int res = pthread_attr_getstacksize(&val_, &size);
BOOST_VERIFY(!res && "pthread_attr_getstacksize failed");
return size;
}
#define BOOST_THREAD_DEFINES_THREAD_ATTRIBUTES_NATIVE_HANDLE
typedef pthread_attr_t native_handle_type;
native_handle_type* native_handle() BOOST_NOEXCEPT {
return &val_;
}
const native_handle_type* native_handle() const BOOST_NOEXCEPT {
return &val_;
}
private:
pthread_attr_t val_;
};
class thread;
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;
typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
struct BOOST_THREAD_DECL thread_data_base:
enable_shared_from_this<thread_data_base>
{
@@ -41,14 +99,15 @@ namespace boost
bool join_started;
bool joined;
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 interrupt_enabled;
bool interrupt_requested;
pthread_mutex_t* cond_mutex;
pthread_cond_t* current_cond;
thread_data_base():
done(false),join_started(false),joined(false),
thread_exit_callbacks(0),tss_data(0),
thread_exit_callbacks(0),
interrupt_enabled(true),
interrupt_requested(false),
current_cond(0)
@@ -65,6 +124,8 @@ namespace boost
class interruption_checker
{
thread_data_base* const thread_info;
pthread_mutex_t* m;
bool set;
void check_for_interruption()
{
@@ -74,26 +135,38 @@ namespace boost
throw thread_interrupted();
}
}
void operator=(interruption_checker&);
public:
explicit interruption_checker(pthread_cond_t* cond):
thread_info(detail::get_current_thread_data())
explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond):
thread_info(detail::get_current_thread_data()),m(cond_mutex),
set(thread_info && thread_info->interrupt_enabled)
{
if(thread_info && thread_info->interrupt_enabled)
if(set)
{
lock_guard<mutex> guard(thread_info->data_mutex);
check_for_interruption();
thread_info->cond_mutex=cond_mutex;
thread_info->current_cond=cond;
BOOST_VERIFY(!pthread_mutex_lock(m));
}
else
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
}
~interruption_checker()
{
if(thread_info && thread_info->interrupt_enabled)
if(set)
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
lock_guard<mutex> guard(thread_info->data_mutex);
thread_info->cond_mutex=NULL;
thread_info->current_cond=NULL;
check_for_interruption();
}
else
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
}
}
};
@@ -101,15 +174,30 @@ namespace boost
namespace this_thread
{
void BOOST_THREAD_DECL yield();
void BOOST_THREAD_DECL sleep(system_time const& abs_time);
#ifdef BOOST_THREAD_USES_CHRONO
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns);
#endif
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
#ifdef __DECXXX
/// Workaround of DECCXX issue of incorrect template substitution
template<typename TimeDuration>
inline void sleep(TimeDuration const& rel_time)
{
this_thread::sleep(get_system_time()+rel_time);
}
template<>
void BOOST_THREAD_DECL sleep(system_time const& abs_time);
#else
void BOOST_THREAD_DECL sleep(system_time const& abs_time);
template<typename TimeDuration>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
this_thread::sleep(get_system_time()+rel_time);
}
#endif
}
}

View File

@@ -17,7 +17,7 @@ namespace boost
return new T();
}
#ifdef BOOST_HAS_RVALUE_REFS
#ifndef BOOST_NO_RVALUE_REFERENCES
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{

View File

@@ -0,0 +1,58 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2012 Vicente J. Botet Escriba
#ifndef BOOST_THREAD_REVERSE_LOCK_HPP
#define BOOST_THREAD_REVERSE_LOCK_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/detail/delete.hpp>
namespace boost
{
template<typename Lock>
class reverse_lock
{
public:
typedef typename Lock::mutex_type mutex_type;
BOOST_THREAD_NO_COPYABLE(reverse_lock)
explicit reverse_lock(Lock& m_)
: m(m_), mtx(0)
{
if (m.owns_lock())
{
m.unlock();
}
mtx=m.release();
}
~reverse_lock()
{
if (mtx) {
mtx->lock();
m = BOOST_THREAD_MAKE_RV_REF(Lock(*mtx, adopt_lock));
}
}
private:
Lock& m;
mutex_type* mtx;
};
#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
template<typename T>
struct is_mutex_type<reverse_lock<T> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
#endif
}
#endif // header

View File

@@ -0,0 +1,52 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2012 Vicente J. Botet Escriba
#ifndef BOOST_THREAD_SHARED_LOCK_GUARD_HPP
#define BOOST_THREAD_SHARED_LOCK_GUARD_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/detail/delete.hpp>
namespace boost
{
template<typename SharedMutex>
class shared_lock_guard
{
private:
SharedMutex& m;
public:
typedef SharedMutex mutex_type;
BOOST_THREAD_NO_COPYABLE(shared_lock_guard)
explicit shared_lock_guard(SharedMutex& m_):
m(m_)
{
m.lock_shared();
}
shared_lock_guard(SharedMutex& m_,adopt_lock_t):
m(m_)
{}
~shared_lock_guard()
{
m.unlock_shared();
}
};
#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
template<typename T>
struct is_mutex_type<shared_lock_guard<T> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
#endif
}
#endif // header

View File

@@ -3,15 +3,20 @@
// shared_mutex.hpp
//
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/platform.hpp>
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#if defined(BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN)
#include <boost/thread/pthread/shared_mutex.hpp>
#else
#include <boost/thread/win32/shared_mutex.hpp>
#endif
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/shared_mutex.hpp>
#else

View File

@@ -3,7 +3,7 @@
// thread.hpp
//
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -20,6 +20,9 @@
#endif
#include <boost/thread/detail/thread.hpp>
#include <boost/thread/detail/thread_interruption.hpp>
#include <boost/thread/detail/thread_group.hpp>
#include <boost/thread/v2/thread.hpp>
#endif

View File

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

View File

@@ -1,111 +1,113 @@
#ifndef BOOST_THREAD_TSS_HPP
#define BOOST_THREAD_TSS_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
#include <boost/thread/detail/config.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/detail/thread_heap_alloc.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
struct tss_cleanup_function
{
virtual ~tss_cleanup_function()
{}
virtual void operator()(void* data)=0;
};
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
BOOST_THREAD_DECL void* get_tss_data(void const* key);
}
template <typename T>
class thread_specific_ptr
{
private:
thread_specific_ptr(thread_specific_ptr&);
thread_specific_ptr& operator=(thread_specific_ptr&);
struct delete_data:
detail::tss_cleanup_function
{
void operator()(void* data)
{
delete static_cast<T*>(data);
}
};
struct run_custom_cleanup_function:
detail::tss_cleanup_function
{
void (*cleanup_function)(T*);
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
cleanup_function(cleanup_function_)
{}
void operator()(void* data)
{
cleanup_function(static_cast<T*>(data));
}
};
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
public:
thread_specific_ptr():
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
{}
explicit thread_specific_ptr(void (*func_)(T*))
{
if(func_)
{
cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
}
}
~thread_specific_ptr()
{
reset();
}
T* get() const
{
return static_cast<T*>(detail::get_tss_data(this));
}
T* operator->() const
{
return get();
}
T& operator*() const
{
return *get();
}
T* release()
{
T* const temp=get();
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
return temp;
}
void reset(T* new_value=0)
{
T* const current_value=get();
if(current_value!=new_value)
{
detail::set_tss_data(this,cleanup,new_value,true);
}
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif
#ifndef BOOST_THREAD_TSS_HPP
#define BOOST_THREAD_TSS_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
#include <boost/thread/detail/config.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/detail/thread_heap_alloc.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
struct tss_cleanup_function
{
virtual ~tss_cleanup_function()
{}
virtual void operator()(void* data)=0;
};
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
BOOST_THREAD_DECL void* get_tss_data(void const* key);
}
template <typename T>
class thread_specific_ptr
{
private:
thread_specific_ptr(thread_specific_ptr&);
thread_specific_ptr& operator=(thread_specific_ptr&);
struct delete_data:
detail::tss_cleanup_function
{
void operator()(void* data)
{
delete static_cast<T*>(data);
}
};
struct run_custom_cleanup_function:
detail::tss_cleanup_function
{
void (*cleanup_function)(T*);
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
cleanup_function(cleanup_function_)
{}
void operator()(void* data)
{
cleanup_function(static_cast<T*>(data));
}
};
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
public:
typedef T element_type;
thread_specific_ptr():
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
{}
explicit thread_specific_ptr(void (*func_)(T*))
{
if(func_)
{
cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
}
}
~thread_specific_ptr()
{
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,true);
}
T* get() const
{
return static_cast<T*>(detail::get_tss_data(this));
}
T* operator->() const
{
return get();
}
T& operator*() const
{
return *get();
}
T* release()
{
T* const temp=get();
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
return temp;
}
void reset(T* new_value=0)
{
T* const current_value=get();
if(current_value!=new_value)
{
detail::set_tss_data(this,cleanup,new_value,true);
}
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,56 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2011 Vicente J. Botet Escriba
#ifndef BOOST_THREAD_V2_THREAD_HPP
#define BOOST_THREAD_V2_THREAD_HPP
#include <boost/thread/detail/config.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#endif
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/locks.hpp>
namespace boost
{
namespace this_thread
{
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
nanoseconds ns = duration_cast<nanoseconds> (d);
if (ns < d) ++ns;
sleep_for(ns);
}
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
mutex mut;
condition_variable cv;
unique_lock<mutex> lk(mut);
while (Clock::now() < t)
cv.wait_until(lk, t);
}
template <class Duration>
inline BOOST_SYMBOL_VISIBLE
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
{
using namespace chrono;
sleep_for(t - steady_clock::now());
}
#endif
}
}
#endif

View File

@@ -3,14 +3,19 @@
// basic_recursive_mutex.hpp
//
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "thread_primitives.hpp"
#include "basic_timed_mutex.hpp"
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/basic_timed_mutex.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
@@ -42,7 +47,7 @@ namespace boost
long const current_thread_id=win32::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
}
void lock()
{
long const current_thread_id=win32::GetCurrentThreadId();
@@ -64,6 +69,20 @@ namespace boost
return timed_lock(get_system_time()+timeout);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
long const current_thread_id=win32::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_timed_lock_for(current_thread_id,rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
long const current_thread_id=win32::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_timed_lock_until(current_thread_id,t);
}
#endif
void unlock()
{
if(!--recursion_count)
@@ -83,7 +102,7 @@ namespace boost
}
return false;
}
bool try_basic_lock(long current_thread_id)
{
if(mutex.try_lock())
@@ -94,7 +113,7 @@ namespace boost
}
return false;
}
bool try_timed_lock(long current_thread_id,::boost::system_time const& target)
{
if(mutex.timed_lock(target))
@@ -105,7 +124,28 @@ namespace boost
}
return false;
}
template <typename TP>
bool try_timed_lock_until(long current_thread_id,TP const& target)
{
if(mutex.try_lock_until(target))
{
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
recursion_count=1;
return true;
}
return false;
}
template <typename D>
bool try_timed_lock_for(long current_thread_id,D const& target)
{
if(mutex.try_lock_for(target))
{
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
recursion_count=1;
return true;
}
return false;
}
};
typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_mutex;

View File

@@ -3,19 +3,23 @@
// basic_timed_mutex_win32.hpp
//
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include "thread_primitives.hpp"
#include "interlocked_read.hpp"
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/detail/interlocked.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
@@ -52,24 +56,39 @@ namespace boost
win32::CloseHandle(old_event);
}
}
bool try_lock()
{
return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
}
void lock()
{
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
}
bool timed_lock(::boost::system_time const& wait_until)
{
if(!win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit))
if(try_lock())
{
return true;
return;
}
long old_count=active_count;
mark_waiting_and_try_lock(old_count);
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
do
{
BOOST_VERIFY(win32::WaitForSingleObject(
sem,::boost::detail::win32::infinite)==0);
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
}
}
void mark_waiting_and_try_lock(long& old_count)
{
for(;;)
{
long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
@@ -80,6 +99,33 @@ namespace boost
}
old_count=current;
}
}
void clear_waiting_and_try_lock(long& old_count)
{
old_count&=~lock_flag_value;
old_count|=event_set_flag_value;
for(;;)
{
long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
if(current==old_count)
{
break;
}
old_count=current;
}
}
bool timed_lock(::boost::system_time const& wait_until)
{
if(try_lock())
{
return true;
}
long old_count=active_count;
mark_waiting_and_try_lock(old_count);
if(old_count&lock_flag_value)
{
@@ -93,18 +139,7 @@ namespace boost
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
old_count&=~lock_flag_value;
old_count|=event_set_flag_value;
for(;;)
{
long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
if(current==old_count)
{
break;
}
old_count=current;
}
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
@@ -112,6 +147,7 @@ namespace boost
return true;
}
template<typename Duration>
bool timed_lock(Duration const& timeout)
{
@@ -123,6 +159,57 @@ namespace boost
return timed_lock(system_time(timeout));
}
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
if(try_lock())
{
return true;
}
long old_count=active_count;
mark_waiting_and_try_lock(old_count);
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
do
{
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
if(win32::WaitForSingleObject(sem,static_cast<unsigned long>(rel_time.count()))!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
}
return true;
}
void unlock()
{
long const offset=lock_flag_value;
@@ -140,7 +227,7 @@ namespace boost
void* get_event()
{
void* current_event=::boost::detail::interlocked_read_acquire(&event);
if(!current_event)
{
void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset);
@@ -165,9 +252,9 @@ namespace boost
}
return current_event;
}
};
}
}

View File

@@ -4,18 +4,24 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/mutex.hpp>
#include "thread_primitives.hpp"
#include <boost/thread/win32/thread_primitives.hpp>
#include <limits.h>
#include <boost/assert.hpp>
#include <algorithm>
#include <boost/thread/thread.hpp>
#include <boost/thread/cv_status.hpp>
#include <boost/thread/win32/thread_data.hpp>
#include <boost/thread/thread_time.hpp>
#include "interlocked_read.hpp"
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/thread/xtime.hpp>
#include <vector>
#include <boost/intrusive_ptr.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
@@ -26,7 +32,7 @@ namespace boost
class basic_cv_list_entry;
void intrusive_ptr_add_ref(basic_cv_list_entry * p);
void intrusive_ptr_release(basic_cv_list_entry * p);
class basic_cv_list_entry
{
private:
@@ -36,10 +42,8 @@ namespace boost
bool notified;
long references;
basic_cv_list_entry(basic_cv_list_entry&);
void operator=(basic_cv_list_entry&);
public:
BOOST_THREAD_NO_COPYABLE(basic_cv_list_entry)
explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_):
semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)),
wake_sem(wake_sem_.duplicate()),
@@ -55,7 +59,7 @@ namespace boost
{
BOOST_INTERLOCKED_INCREMENT(&waiters);
}
void remove_waiter()
{
BOOST_INTERLOCKED_DECREMENT(&waiters);
@@ -97,7 +101,7 @@ namespace boost
{
BOOST_INTERLOCKED_INCREMENT(&p->references);
}
inline void intrusive_ptr_release(basic_cv_list_entry * p)
{
if(!BOOST_INTERLOCKED_DECREMENT(&p->references))
@@ -125,13 +129,14 @@ namespace boost
detail::interlocked_write_release(&total_count,total_count-count_to_wake);
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
}
template<typename lock_type>
struct relocker
{
BOOST_THREAD_NO_COPYABLE(relocker)
lock_type& lock;
bool unlocked;
relocker(lock_type& lock_):
lock(lock_),unlocked(false)
{}
@@ -146,13 +151,10 @@ namespace boost
{
lock.lock();
}
}
private:
relocker(relocker&);
void operator=(relocker&);
};
entry_ptr get_wait_entry()
{
@@ -177,15 +179,16 @@ namespace boost
return generations.back();
}
}
struct entry_manager
{
entry_ptr const entry;
BOOST_THREAD_NO_COPYABLE(entry_manager)
entry_manager(entry_ptr const& entry_):
entry(entry_)
{}
~entry_manager()
{
entry->remove_waiter();
@@ -195,19 +198,15 @@ namespace boost
{
return entry.get();
}
private:
void operator=(entry_manager&);
entry_manager(entry_manager&);
};
protected:
template<typename lock_type>
bool do_wait(lock_type& lock,timeout wait_until)
{
relocker<lock_type> locker(lock);
entry_manager entry(get_wait_entry());
locker.unlock();
@@ -219,7 +218,7 @@ namespace boost
{
return false;
}
woken=entry->woken();
}
return woken;
@@ -235,7 +234,7 @@ namespace boost
}
return true;
}
basic_condition_variable(const basic_condition_variable& other);
basic_condition_variable& operator=(const basic_condition_variable& other);
@@ -243,11 +242,11 @@ namespace boost
basic_condition_variable():
total_count(0),active_generation_count(0),wake_sem(0)
{}
~basic_condition_variable()
{}
void notify_one()
void notify_one() BOOST_NOEXCEPT
{
if(detail::interlocked_read_acquire(&total_count))
{
@@ -267,8 +266,8 @@ namespace boost
generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end());
}
}
void notify_all()
void notify_all() BOOST_NOEXCEPT
{
if(detail::interlocked_read_acquire(&total_count))
{
@@ -288,23 +287,21 @@ namespace boost
wake_sem=detail::win32::handle(0);
}
}
};
}
class condition_variable:
private detail::basic_condition_variable
{
private:
condition_variable(condition_variable&);
void operator=(condition_variable&);
public:
BOOST_THREAD_NO_COPYABLE(condition_variable)
condition_variable()
{}
using detail::basic_condition_variable::notify_one;
using detail::basic_condition_variable::notify_all;
void wait(unique_lock<mutex>& m)
{
do_wait(m,detail::timeout::sentinel());
@@ -315,7 +312,7 @@ namespace boost
{
while(!pred()) wait(m);
}
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
{
@@ -347,21 +344,71 @@ namespace boost
{
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
do_wait(lock, ceil<milliseconds>(t-Clock::now()).count());
return Clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
template <class Rep, class Period>
cv_status
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
steady_clock::time_point c_now = steady_clock::now();
do_wait(lock, ceil<milliseconds>(d).count());
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
template <class Clock, class Duration, class Predicate>
bool
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class Rep, class Period, class Predicate>
bool
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
return wait_until(lock, chrono::steady_clock::now() + d, pred);
}
#endif
};
class condition_variable_any:
private detail::basic_condition_variable
{
private:
condition_variable_any(condition_variable_any&);
void operator=(condition_variable_any&);
public:
BOOST_THREAD_NO_COPYABLE(condition_variable_any)
condition_variable_any()
{}
using detail::basic_condition_variable::notify_one;
using detail::basic_condition_variable::notify_all;
template<typename lock_type>
void wait(lock_type& m)
{
@@ -373,7 +420,7 @@ namespace boost
{
while(!pred()) wait(m);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{
@@ -409,6 +456,58 @@ namespace boost
{
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type, class Clock, class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
do_wait(lock, ceil<milliseconds>(t-Clock::now()).count());
return Clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
template <class lock_type, class Rep, class Period>
cv_status
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
steady_clock::time_point c_now = steady_clock::now();
do_wait(lock, ceil<milliseconds>(d).count());
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
template <class lock_type, class Clock, class Duration, class Predicate>
bool
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class lock_type, class Rep, class Period, class Predicate>
bool
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
return wait_until(lock, chrono::steady_clock::now() + d, pred);
}
#endif
};
}

View File

@@ -1,12 +1,12 @@
#ifndef BOOST_THREAD_WIN32_MUTEX_HPP
#define BOOST_THREAD_WIN32_MUTEX_HPP
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "basic_timed_mutex.hpp"
#include <boost/utility.hpp>
#include <boost/thread/win32/basic_timed_mutex.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
@@ -20,10 +20,10 @@ namespace boost
}
class mutex:
boost::noncopyable,
public ::boost::detail::underlying_mutex
{
public:
BOOST_THREAD_NO_COPYABLE(mutex)
mutex()
{
initialize();
@@ -40,10 +40,10 @@ namespace boost
typedef mutex try_mutex;
class timed_mutex:
boost::noncopyable,
public ::boost::detail::basic_timed_mutex
{
public:
BOOST_THREAD_NO_COPYABLE(timed_mutex)
timed_mutex()
{
initialize();

View File

@@ -3,8 +3,9 @@
// once.hpp
//
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2005 John Maddock
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -30,83 +31,112 @@ namespace std
namespace boost
{
typedef long once_flag;
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
#define BOOST_ONCE_INIT 0
struct once_flag
{
BOOST_THREAD_NO_COPYABLE(once_flag)
BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
: status(0), count(0)
{}
private:
long status;
long count;
template<typename Function>
friend
void call_once(once_flag& flag,Function f);
};
#define BOOST_ONCE_INIT once_flag()
#else // BOOST_THREAD_PROVIDES_ONCE_CXX11
struct once_flag
{
long status;
long count;
};
#define BOOST_ONCE_INIT {0,0}
#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
namespace detail
{
struct win32_mutex_scoped_lock
{
void* const mutex_handle;
explicit win32_mutex_scoped_lock(void* mutex_handle_):
mutex_handle(mutex_handle_)
{
BOOST_VERIFY(!win32::WaitForSingleObject(mutex_handle,win32::infinite));
}
~win32_mutex_scoped_lock()
{
BOOST_VERIFY(win32::ReleaseMutex(mutex_handle)!=0);
}
private:
void operator=(win32_mutex_scoped_lock&);
};
#ifdef BOOST_NO_ANSI_APIS
typedef wchar_t once_char_type;
#else
typedef char once_char_type;
#endif
unsigned const once_mutex_name_fixed_length=54;
unsigned const once_mutex_name_length=once_mutex_name_fixed_length+
sizeof(void*)*2+sizeof(unsigned long)*2+1;
template <class I>
void int_to_string(I p, wchar_t* buf)
void int_to_string(I p, once_char_type* buf)
{
for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
{
*buf = L'A' + static_cast<wchar_t>((p >> (i*4)) & 0x0f);
}
*buf = 0;
}
#else
template <class I>
void int_to_string(I p, char* buf)
{
for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
{
*buf = 'A' + static_cast<char>((p >> (i*4)) & 0x0f);
}
*buf = 0;
}
#endif
// create a named mutex. It doesn't really matter what this name is
// as long as it is unique both to this process, and to the address of "flag":
inline void* create_once_mutex(void* flag_address)
{
#ifdef BOOST_NO_ANSI_APIS
typedef wchar_t char_type;
static const char_type fixed_mutex_name[]=L"{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
once_char_type const a=L'A';
#else
typedef char char_type;
static const char_type fixed_mutex_name[]="{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
once_char_type const a='A';
#endif
unsigned const once_mutex_name_fixed_buffer_size=sizeof(fixed_mutex_name)/sizeof(char_type);
unsigned const once_mutex_name_fixed_length=once_mutex_name_fixed_buffer_size-1;
unsigned const once_mutex_name_length=once_mutex_name_fixed_buffer_size+sizeof(void*)*2+sizeof(unsigned long)*2;
char_type mutex_name[once_mutex_name_length];
*buf = a + static_cast<once_char_type>((p >> (i*4)) & 0x0f);
}
*buf = 0;
}
inline void name_once_mutex(once_char_type* mutex_name,void* flag_address)
{
#ifdef BOOST_NO_ANSI_APIS
static const once_char_type fixed_mutex_name[]=L"Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
#else
static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
#endif
BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) ==
(sizeof(once_char_type)*(once_mutex_name_fixed_length+1)));
std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
BOOST_STATIC_ASSERT(sizeof(void*) == sizeof(std::ptrdiff_t));
detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), mutex_name + once_mutex_name_fixed_length);
detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
#ifdef BOOST_NO_ANSI_APIS
return win32::CreateMutexW(0, 0, mutex_name);
#else
return win32::CreateMutexA(0, 0, mutex_name);
#endif
detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address),
mutex_name + once_mutex_name_fixed_length);
detail::int_to_string(win32::GetCurrentProcessId(),
mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
}
inline void* open_once_event(once_char_type* mutex_name,void* flag_address)
{
if(!*mutex_name)
{
name_once_mutex(mutex_name,flag_address);
}
#ifdef BOOST_NO_ANSI_APIS
return ::boost::detail::win32::OpenEventW(
#else
return ::boost::detail::win32::OpenEventA(
#endif
::boost::detail::win32::synchronize |
::boost::detail::win32::event_modify_state,
false,
mutex_name);
}
inline void* create_once_event(once_char_type* mutex_name,void* flag_address)
{
if(!*mutex_name)
{
name_once_mutex(mutex_name,flag_address);
}
#ifdef BOOST_NO_ANSI_APIS
return ::boost::detail::win32::CreateEventW(
#else
return ::boost::detail::win32::CreateEventA(
#endif
0,::boost::detail::win32::manual_reset_event,
::boost::detail::win32::event_initially_reset,
mutex_name);
}
}
template<typename Function>
void call_once(once_flag& flag,Function f)
@@ -114,19 +144,79 @@ namespace boost
// Try for a quick win: if the procedure has already been called
// just skip through:
long const function_complete_flag_value=0xc15730e2;
long const running_value=0x7f0725e3;
long status;
bool counted=false;
detail::win32::handle_manager event_handle;
detail::once_char_type mutex_name[detail::once_mutex_name_length];
mutex_name[0]=0;
if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value)
while((status=::boost::detail::interlocked_read_acquire(&flag.status))
!=function_complete_flag_value)
{
void* const mutex_handle(::boost::detail::create_once_mutex(&flag));
BOOST_ASSERT(mutex_handle);
detail::win32::handle_manager const closer(mutex_handle);
detail::win32_mutex_scoped_lock const lock(mutex_handle);
if(flag!=function_complete_flag_value)
status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0);
if(!status)
{
f();
BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value);
try
{
if(!event_handle)
{
event_handle=detail::open_once_event(mutex_name,&flag);
}
if(event_handle)
{
::boost::detail::win32::ResetEvent(event_handle);
}
f();
if(!counted)
{
BOOST_INTERLOCKED_INCREMENT(&flag.count);
counted=true;
}
BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value);
if(!event_handle &&
(::boost::detail::interlocked_read_acquire(&flag.count)>1))
{
event_handle=detail::create_once_event(mutex_name,&flag);
}
if(event_handle)
{
::boost::detail::win32::SetEvent(event_handle);
}
break;
}
catch(...)
{
BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
if(!event_handle)
{
event_handle=detail::open_once_event(mutex_name,&flag);
}
if(event_handle)
{
::boost::detail::win32::SetEvent(event_handle);
}
throw;
}
}
if(!counted)
{
BOOST_INTERLOCKED_INCREMENT(&flag.count);
counted=true;
status=::boost::detail::interlocked_read_acquire(&flag.status);
if(status==function_complete_flag_value)
{
break;
}
if(!event_handle)
{
event_handle=detail::create_once_event(mutex_name,&flag);
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
event_handle,::boost::detail::win32::infinite));
}
}
}

View File

@@ -3,15 +3,14 @@
// recursive_mutex.hpp
//
// (C) Copyright 2006-7 Anthony Williams
// (C) Copyright 2006-7 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/utility.hpp>
#include "basic_recursive_mutex.hpp"
#include <boost/thread/win32/basic_recursive_mutex.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
@@ -20,10 +19,10 @@
namespace boost
{
class recursive_mutex:
boost::noncopyable,
public ::boost::detail::basic_recursive_mutex
{
public:
BOOST_THREAD_NO_COPYABLE(recursive_mutex)
recursive_mutex()
{
::boost::detail::basic_recursive_mutex::initialize();
@@ -40,10 +39,10 @@ namespace boost
typedef recursive_mutex recursive_try_mutex;
class recursive_timed_mutex:
boost::noncopyable,
public ::boost::detail::basic_recursive_timed_mutex
{
public:
BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex)
recursive_timed_mutex()
{
::boost::detail::basic_recursive_timed_mutex::initialize();

View File

@@ -2,6 +2,7 @@
#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -12,15 +13,18 @@
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/static_assert.hpp>
#include <limits.h>
#include <boost/utility.hpp>
#include <boost/thread/thread_time.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class shared_mutex:
private boost::noncopyable
class shared_mutex
{
private:
struct state_data
@@ -37,7 +41,7 @@ namespace boost
return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
}
};
template<typename T>
T interlocked_compare_exchange(T* target,T new_value,T comparand)
@@ -49,34 +53,48 @@ namespace boost
return *reinterpret_cast<T const*>(&res);
}
enum
{
unlock_sem = 0,
exclusive_sem = 1
};
state_data state;
detail::win32::handle semaphores[2];
detail::win32::handle &unlock_sem;
detail::win32::handle &exclusive_sem;
detail::win32::handle upgrade_sem;
void release_waiters(state_data old_state)
{
if(old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,0)!=0);
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
}
if(old_state.shared_waiting || old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
}
}
public:
shared_mutex():
unlock_sem(semaphores[0]),
exclusive_sem(semaphores[1])
BOOST_THREAD_NO_COPYABLE(shared_mutex)
shared_mutex()
{
unlock_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
exclusive_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX);
if (!semaphores[exclusive_sem])
{
detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX);
boost::throw_exception(thread_resource_error());
}
upgrade_sem=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX);
if (!upgrade_sem)
{
detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX);
detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX);
boost::throw_exception(thread_resource_error());
}
state_data state_={0};
state=state_;
}
@@ -84,8 +102,8 @@ namespace boost
~shared_mutex()
{
detail::win32::CloseHandle(upgrade_sem);
detail::win32::CloseHandle(unlock_sem);
detail::win32::CloseHandle(exclusive_sem);
detail::win32::CloseHandle(semaphores[unlock_sem]);
detail::win32::CloseHandle(semaphores[exclusive_sem]);
}
bool try_lock_shared()
@@ -97,8 +115,12 @@ namespace boost
if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
@@ -131,10 +153,18 @@ namespace boost
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
++new_state.shared_waiting;
if(!new_state.shared_waiting)
{
boost::throw_exception(boost::lock_error());
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
boost::throw_exception(boost::lock_error());
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
@@ -149,8 +179,8 @@ namespace boost
{
return true;
}
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,::boost::detail::get_milliseconds_until(wait_until));
unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until));
if(res==detail::win32::timeout)
{
for(;;)
@@ -166,6 +196,10 @@ namespace boost
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
@@ -182,11 +216,118 @@ namespace boost
}
return false;
}
BOOST_ASSERT(res==0);
}
}
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_shared_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_shared_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
++new_state.shared_waiting;
if(!new_state.shared_waiting)
{
boost::throw_exception(boost::lock_error());
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
boost::throw_exception(boost::lock_error());
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
chrono::system_clock::time_point n = chrono::system_clock::now();
unsigned long res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n);
res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],
static_cast<unsigned long>(rel_time.count()));
} else {
res=detail::win32::timeout;
}
if(res==detail::win32::timeout)
{
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
if(new_state.shared_waiting)
{
--new_state.shared_waiting;
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
return false;
}
BOOST_ASSERT(res==0);
}
}
void unlock_shared()
{
state_data old_state=state;
@@ -194,7 +335,7 @@ namespace boost
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
if(new_state.upgrade)
@@ -212,7 +353,7 @@ namespace boost
new_state.shared_waiting=0;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
@@ -258,7 +399,7 @@ namespace boost
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
@@ -282,6 +423,11 @@ namespace boost
if(new_state.shared_count || new_state.exclusive)
{
++new_state.exclusive_waiting;
if(!new_state.exclusive_waiting)
{
boost::throw_exception(boost::lock_error());
}
new_state.exclusive_waiting_blocked=true;
}
else
@@ -301,7 +447,12 @@ namespace boost
{
return true;
}
unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,true,::boost::detail::get_milliseconds_until(wait_until));
#ifndef UNDER_CE
const bool wait_all = true;
#else
const bool wait_all = false;
#endif
unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until));
if(wait_res==detail::win32::timeout)
{
for(;;)
@@ -339,6 +490,115 @@ namespace boost
}
}
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
++new_state.exclusive_waiting;
if(!new_state.exclusive_waiting)
{
boost::throw_exception(boost::lock_error());
}
new_state.exclusive_waiting_blocked=true;
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
#ifndef UNDER_CE
const bool wait_all = true;
#else
const bool wait_all = false;
#endif
chrono::system_clock::time_point n = chrono::system_clock::now();
unsigned long wait_res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,
static_cast<unsigned long>(rel_time.count()));
} else {
wait_res=detail::win32::timeout;
}
if(wait_res==detail::win32::timeout)
{
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
if(new_state.exclusive_waiting)
{
if(!--new_state.exclusive_waiting)
{
new_state.exclusive_waiting_blocked=false;
}
}
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
return false;
}
BOOST_ASSERT(wait_res<2);
}
}
void unlock()
{
state_data old_state=state;
@@ -374,10 +634,18 @@ namespace boost
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
{
++new_state.shared_waiting;
if(!new_state.shared_waiting)
{
boost::throw_exception(boost::lock_error());
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
boost::throw_exception(boost::lock_error());
}
new_state.upgrade=true;
}
@@ -393,8 +661,8 @@ namespace boost
{
return;
}
BOOST_VERIFY(!detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite));
BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite));
}
}
@@ -411,9 +679,13 @@ namespace boost
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
new_state.upgrade=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
@@ -432,7 +704,7 @@ namespace boost
state_data new_state=old_state;
new_state.upgrade=false;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
if(new_state.exclusive_waiting)
@@ -442,13 +714,15 @@ namespace boost
}
new_state.shared_waiting=0;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
if(last_reader)
{
release_waiters(old_state);
} else {
release_waiters(old_state);
}
break;
}
@@ -463,13 +737,13 @@ namespace boost
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
new_state.upgrade=false;
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
@@ -508,7 +782,28 @@ namespace boost
}
release_waiters(old_state);
}
// bool try_unlock_upgrade_and_lock()
// {
// return false;
// }
//#ifdef BOOST_THREAD_USES_CHRONO
// template <class Rep, class Period>
// bool
// try_unlock_upgrade_and_lock_for(
// const chrono::duration<Rep, Period>& rel_time)
// {
// return try_unlock_upgrade_and_lock_until(
// chrono::steady_clock::now() + rel_time);
// }
// template <class Clock, class Duration>
// bool
// try_unlock_upgrade_and_lock_until(
// const chrono::time_point<Clock, Duration>& abs_time)
// {
// return false;
// }
//#endif
void unlock_and_lock_shared()
{
state_data old_state=state;
@@ -533,7 +828,6 @@ namespace boost
}
release_waiters(old_state);
}
void unlock_upgrade_and_lock_shared()
{
state_data old_state=state;
@@ -557,8 +851,10 @@ namespace boost
}
release_waiters(old_state);
}
};
typedef shared_mutex upgrade_mutex;
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -4,17 +4,58 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2008 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/thread/thread_time.hpp>
#include "thread_primitives.hpp"
#include "thread_heap_alloc.hpp"
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/thread_heap_alloc.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class thread_attributes {
public:
thread_attributes() BOOST_NOEXCEPT {
val_.stack_size = 0;
//val_.lpThreadAttributes=0;
}
~thread_attributes() {
}
// stack size
void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
val_.stack_size = size;
}
std::size_t get_stack_size() const BOOST_NOEXCEPT {
return val_.stack_size;
}
//void set_security(LPSECURITY_ATTRIBUTES lpThreadAttributes)
//{
// val_.lpThreadAttributes=lpThreadAttributes;
//}
//LPSECURITY_ATTRIBUTES get_security()
//{
// return val_.lpThreadAttributes;
//}
struct win_attrs {
std::size_t stack_size;
//LPSECURITY_ATTRIBUTES lpThreadAttributes;
};
typedef win_attrs native_handle_type;
native_handle_type* native_handle() {return &val_;}
const native_handle_type* native_handle() const {return &val_;}
private:
win_attrs val_;
};
namespace detail
{
struct thread_exit_callback_node;
@@ -23,8 +64,8 @@ namespace boost
struct thread_data_base;
void intrusive_ptr_add_ref(thread_data_base * p);
void intrusive_ptr_release(thread_data_base * p);
struct thread_data_base
struct BOOST_SYMBOL_VISIBLE thread_data_base
{
long count;
detail::win32::handle_manager thread_handle;
@@ -48,7 +89,7 @@ namespace boost
{
BOOST_INTERLOCKED_INCREMENT(&p->count);
}
friend void intrusive_ptr_release(thread_data_base * p)
{
if(!BOOST_INTERLOCKED_DECREMENT(&p->count))
@@ -61,7 +102,7 @@ namespace boost
{
BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
}
typedef detail::win32::handle native_handle_type;
virtual void run()=0;
@@ -69,7 +110,7 @@ namespace boost
typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
struct timeout
struct BOOST_SYMBOL_VISIBLE timeout
{
unsigned long start;
uintmax_t milliseconds;
@@ -92,7 +133,7 @@ namespace boost
abs_time(abs_time_)
{}
struct remaining_time
struct BOOST_SYMBOL_VISIBLE remaining_time
{
bool more;
unsigned long milliseconds;
@@ -130,7 +171,7 @@ namespace boost
{
return milliseconds==~uintmax_t(0);
}
static timeout sentinel()
{
@@ -139,38 +180,49 @@ namespace boost
private:
struct sentinel_type
{};
explicit timeout(sentinel_type):
start(0),milliseconds(~uintmax_t(0)),relative(true)
{}
};
inline uintmax_t pin_to_zero(intmax_t value)
{
return (value<0)?0u:(uintmax_t)value;
}
}
namespace this_thread
{
void BOOST_THREAD_DECL yield();
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
inline void interruptible_wait(unsigned long milliseconds)
inline void interruptible_wait(uintmax_t milliseconds)
{
interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
}
inline void interruptible_wait(system_time const& abs_time)
inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time)
{
interruptible_wait(detail::win32::invalid_handle_value,abs_time);
}
template<typename TimeDuration>
inline void sleep(TimeDuration const& rel_time)
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
interruptible_wait(static_cast<unsigned long>(rel_time.total_milliseconds()));
interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
}
inline void sleep(system_time const& abs_time)
inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
{
interruptible_wait(abs_time);
}
#ifdef BOOST_THREAD_USES_CHRONO
inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
{
interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
}
#endif
}
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -5,9 +5,10 @@
#ifndef THREAD_HEAP_ALLOC_HPP
#define THREAD_HEAP_ALLOC_HPP
#include <new>
#include "thread_primitives.hpp"
#include <boost/thread/win32/thread_primitives.hpp>
#include <stdexcept>
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
@@ -55,21 +56,21 @@ namespace boost
{
namespace detail
{
inline BOOST_THREAD_DECL void* allocate_raw_heap_memory(unsigned size)
inline void* allocate_raw_heap_memory(unsigned size)
{
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
if(!heap_memory)
{
throw std::bad_alloc();
boost::throw_exception(std::bad_alloc());
}
return heap_memory;
}
inline BOOST_THREAD_DECL void free_raw_heap_memory(void* heap_memory)
inline void free_raw_heap_memory(void* heap_memory)
{
BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0);
}
template<typename T>
inline T* heap_new()
{
@@ -86,7 +87,7 @@ namespace boost
}
}
#ifdef BOOST_HAS_RVALUE_REFS
#ifndef BOOST_NO_RVALUE_REFERENCES
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
@@ -225,7 +226,7 @@ namespace boost
{
return heap_new_impl<T,A1&>(a1);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2 const& a2)
{
@@ -371,8 +372,8 @@ namespace boost
{
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
#endif
#endif
template<typename T>
inline void heap_delete(T* data)
{

View File

@@ -3,14 +3,15 @@
// win32_thread_primitives.hpp
//
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2007 David Deakins
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2007 David Deakins
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#include <boost/throw_exception.hpp>
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/detail/interlocked.hpp>
@@ -30,14 +31,18 @@ namespace boost
unsigned const infinite=INFINITE;
unsigned const timeout=WAIT_TIMEOUT;
handle const invalid_handle_value=INVALID_HANDLE_VALUE;
unsigned const event_modify_state=EVENT_MODIFY_STATE;
unsigned const synchronize=SYNCHRONIZE;
# ifdef BOOST_NO_ANSI_APIS
using ::CreateMutexW;
using ::CreateEventW;
using ::OpenEventW;
using ::CreateSemaphoreW;
# else
using ::CreateMutexA;
using ::CreateEventA;
using ::OpenEventA;
using ::CreateSemaphoreA;
# endif
using ::CloseHandle;
@@ -89,7 +94,7 @@ namespace boost
{
namespace win32
{
# ifdef _WIN64
typedef unsigned __int64 ulong_ptr;
# else
@@ -99,6 +104,8 @@ namespace boost
unsigned const infinite=~0U;
unsigned const timeout=258U;
handle const invalid_handle_value=(handle)(-1);
unsigned const event_modify_state=2;
unsigned const synchronize=0x100000u;
extern "C"
{
@@ -107,10 +114,12 @@ namespace boost
__declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
__declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
# else
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
__declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
# endif
__declspec(dllimport) int __stdcall CloseHandle(void*);
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
@@ -161,40 +170,49 @@ namespace boost
auto_reset_event=false,
manual_reset_event=true
};
enum initial_event_state
{
event_initially_reset=false,
event_initially_set=true
};
inline handle create_anonymous_event(event_type type,initial_event_state state)
{
#if !defined(BOOST_NO_ANSI_APIS)
#if !defined(BOOST_NO_ANSI_APIS)
handle const res=win32::CreateEventA(0,type,state,0);
#else
handle const res=win32::CreateEventW(0,type,state,0);
#endif
#endif
if(!res)
{
throw thread_resource_error();
boost::throw_exception(thread_resource_error());
}
return res;
}
inline handle create_anonymous_semaphore(long initial_count,long max_count)
{
#if !defined(BOOST_NO_ANSI_APIS)
#if !defined(BOOST_NO_ANSI_APIS)
handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
#else
handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
#endif
#endif
if(!res)
{
throw thread_resource_error();
boost::throw_exception(thread_resource_error());
}
return res;
}
inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
{
#if !defined(BOOST_NO_ANSI_APIS)
handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
#else
handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
#endif
return res;
}
inline handle duplicate_handle(handle source)
{
@@ -204,7 +222,7 @@ namespace boost
bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
if(!success)
{
throw thread_resource_error();
boost::throw_exception(thread_resource_error());
}
return new_handle;
}
@@ -228,7 +246,7 @@ namespace boost
BOOST_VERIFY(CloseHandle(handle_to_manage));
}
}
public:
explicit handle_manager(handle handle_to_manage_):
handle_to_manage(handle_to_manage_)
@@ -236,7 +254,7 @@ namespace boost
handle_manager():
handle_to_manage(0)
{}
handle_manager& operator=(handle new_handle)
{
cleanup();
@@ -270,13 +288,13 @@ namespace boost
{
return !handle_to_manage;
}
~handle_manager()
{
cleanup();
}
};
}
}
}
@@ -309,7 +327,7 @@ namespace boost
{
return _interlockedbittestandreset(x,bit)!=0;
}
}
}
}
@@ -328,7 +346,7 @@ namespace boost
mov edx,x;
lock bts [edx],eax;
setc al;
};
};
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
@@ -338,9 +356,9 @@ namespace boost
mov edx,x;
lock btr [edx],eax;
setc al;
};
};
}
}
}
}

View File

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

View File

@@ -1 +0,0 @@
boost_module(thread DEPENDS date_time bind optional range)

View File

@@ -1,21 +0,0 @@
#
# Copyright Troy D. Straszheim
#
# Distributed under the Boost Software License, Version 1.0.
# See http://www.boost.org/LICENSE_1_0.txt
#
if (WIN32)
set(THREAD_SOURCES win32/thread.cpp win32/exceptions.cpp win32/tss_dll.cpp
win32/tss_pe.cpp)
else (WIN32)
set(THREAD_SOURCES pthread/thread.cpp pthread/exceptions.cpp pthread/once.cpp)
endif (WIN32)
boost_add_library(
boost_thread
${THREAD_SOURCES}
SHARED_COMPILE_FLAGS "-DBOOST_THREAD_BUILD_DLL=1"
STATIC_COMPILE_FLAGS "-DBOOST_THREAD_BUILD_LIB=1"
NO_SINGLE_THREADED
)

56
src/future.cpp Executable file
View File

@@ -0,0 +1,56 @@
// (C) Copyright 2012 Vicente J. Botet Escriba
// Use, modification and distribution are subject to 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/future.hpp>
namespace boost
{
namespace thread_detail
{
class future_error_category :
public boost::system::error_category
{
public:
virtual const char* name() const; //BOOST_NOEXCEPT;
virtual std::string message(int ev) const;
};
const char*
future_error_category::name() const //BOOST_NOEXCEPT
{
return "future";
}
std::string
future_error_category::message(int ev) const
{
switch (BOOST_SCOPED_ENUM_NATIVE(future_errc)(ev))
{
case future_errc::broken_promise:
return std::string("The associated promise has been destructed prior "
"to the associated state becoming ready.");
case future_errc::future_already_retrieved:
return std::string("The future has already been retrieved from "
"the promise or packaged_task.");
case future_errc::promise_already_satisfied:
return std::string("The state of the promise has already been set.");
case future_errc::no_state:
return std::string("Operation not permitted on an object without "
"an associated state.");
}
return std::string("unspecified future_errc value\n");
}
}
const system::error_category&
future_category()
{
static thread_detail::future_error_category f;
return f;
}
}

View File

@@ -1,124 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <cstring>
#include <string>
namespace boost {
thread_exception::thread_exception()
: m_sys_err(0)
{
}
thread_exception::thread_exception(int sys_err_code)
: m_sys_err(sys_err_code)
{
}
thread_exception::~thread_exception() throw()
{
}
int thread_exception::native_error() const
{
return m_sys_err;
}
lock_error::lock_error()
{
}
lock_error::lock_error(int sys_err_code)
: thread_exception(sys_err_code)
{
}
lock_error::~lock_error() throw()
{
}
const char* lock_error::what() const throw()
{
return "boost::lock_error";
}
thread_resource_error::thread_resource_error()
{
}
thread_resource_error::thread_resource_error(int sys_err_code)
: thread_exception(sys_err_code)
{
}
thread_resource_error::~thread_resource_error() throw()
{
}
const char* thread_resource_error::what() const throw()
{
return "boost::thread_resource_error";
}
unsupported_thread_option::unsupported_thread_option()
{
}
unsupported_thread_option::unsupported_thread_option(int sys_err_code)
: thread_exception(sys_err_code)
{
}
unsupported_thread_option::~unsupported_thread_option() throw()
{
}
const char* unsupported_thread_option::what() const throw()
{
return "boost::unsupported_thread_option";
}
invalid_thread_argument::invalid_thread_argument()
{
}
invalid_thread_argument::invalid_thread_argument(int sys_err_code)
: thread_exception(sys_err_code)
{
}
invalid_thread_argument::~invalid_thread_argument() throw()
{
}
const char* invalid_thread_argument::what() const throw()
{
return "boost::invalid_thread_argument";
}
thread_permission_error::thread_permission_error()
{
}
thread_permission_error::thread_permission_error(int sys_err_code)
: thread_exception(sys_err_code)
{
}
thread_permission_error::~thread_permission_error() throw()
{
}
const char* thread_permission_error::what() const throw()
{
return "boost::thread_permission_error";
}
} // namespace boost

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

@@ -1,6 +1,6 @@
// Copyright (C) 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define __STDC_CONSTANT_MACROS
@@ -8,6 +8,7 @@
#include <boost/assert.hpp>
#include <pthread.h>
#include <stdlib.h>
#include <memory>
namespace boost
{
@@ -21,19 +22,39 @@ namespace boost
{
pthread_key_t epoch_tss_key;
pthread_once_t epoch_tss_key_flag=PTHREAD_ONCE_INIT;
extern "C" void delete_epoch_tss_data(void* data)
extern "C"
{
free(data);
static void delete_epoch_tss_data(void* data)
{
free(data);
}
static void create_epoch_tss_key()
{
BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data));
}
}
extern "C" void create_epoch_tss_key()
#if defined BOOST_THREAD_PATCH
const pthread_once_t pthread_once_init_value=PTHREAD_ONCE_INIT;
struct BOOST_THREAD_DECL delete_epoch_tss_key_on_dlclose_t
{
BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data));
}
delete_epoch_tss_key_on_dlclose_t()
{
}
~delete_epoch_tss_key_on_dlclose_t()
{
if(memcmp(&epoch_tss_key_flag, &pthread_once_init_value, sizeof(pthread_once_t)))
{
pthread_key_delete(epoch_tss_key);
}
}
};
delete_epoch_tss_key_on_dlclose_t delete_epoch_tss_key_on_dlclose;
#endif
}
boost::uintmax_t& get_once_per_thread_epoch()
{
BOOST_VERIFY(!pthread_once(&epoch_tss_key_flag,create_epoch_tss_key));
@@ -47,5 +68,5 @@ namespace boost
return *static_cast<boost::uintmax_t*>(data);
}
}
}

View File

@@ -1,8 +1,9 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007-8 Anthony Williams
// (C) Copyright 2011 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
@@ -13,7 +14,8 @@
#include <boost/thread/locks.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/tss.hpp>
#ifdef __linux__
#include <boost/throw_exception.hpp>
#ifdef __GLIBC__
#include <sys/sysinfo.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/types.h>
@@ -22,7 +24,7 @@
#include <unistd.h>
#endif
#include "timeconv.inl"
#include <libs/thread/src/pthread/timeconv.inl>
namespace boost
{
@@ -42,32 +44,23 @@ 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
{
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
boost::once_flag current_thread_tls_init_flag;
#else
boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
#endif
pthread_key_t current_thread_tls_key;
extern "C"
{
void tls_destructor(void* data)
static void tls_destructor(void* data)
{
boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
if(thread_info)
{
while(thread_info->tss_data || thread_info->thread_exit_callbacks)
while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks)
{
while(thread_info->thread_exit_callbacks)
{
@@ -80,29 +73,49 @@ namespace boost
}
delete current_node;
}
while(thread_info->tss_data)
for(std::map<void const*,tss_data_node>::iterator next=thread_info->tss_data.begin(),
current,
end=thread_info->tss_data.end();
next!=end;)
{
detail::tss_data_node* const current_node=thread_info->tss_data;
thread_info->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);
}
delete current_node;
thread_info->tss_data.erase(current);
}
}
thread_info->self.reset();
}
}
}
#if defined BOOST_THREAD_PATCH
struct delete_current_thread_tls_key_on_dlclose_t
{
delete_current_thread_tls_key_on_dlclose_t()
{
}
~delete_current_thread_tls_key_on_dlclose_t()
{
if (current_thread_tls_init_flag.epoch!=BOOST_ONCE_INITIAL_FLAG_VALUE)
{
pthread_key_delete(current_thread_tls_key);
}
}
};
delete_current_thread_tls_key_on_dlclose_t delete_current_thread_tls_key_on_dlclose;
#endif
void create_current_thread_tls_key()
{
BOOST_VERIFY(!pthread_key_create(&current_thread_tls_key,&tls_destructor));
}
}
boost::detail::thread_data_base* get_current_thread_data()
{
boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
@@ -115,12 +128,12 @@ namespace boost
BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data));
}
}
namespace
{
extern "C"
{
void* thread_proxy(void* param)
static void* thread_proxy(void* param)
{
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
thread_info->self.reset();
@@ -155,7 +168,7 @@ namespace boost
{
interrupt_enabled=false;
}
void run()
{}
@@ -186,7 +199,7 @@ namespace boost
}
thread::thread()
thread::thread() BOOST_NOEXCEPT
{}
void thread::start_thread()
@@ -196,28 +209,63 @@ namespace boost
if (res != 0)
{
thread_info->self.reset();
throw thread_resource_error();
boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create"));
}
}
thread::~thread()
void thread::start_thread(const attributes& attr)
{
detach();
thread_info->self=thread_info;
const attributes::native_handle_type* h = attr.native_handle();
int res = pthread_create(&thread_info->thread_handle, h, &thread_proxy, thread_info.get());
if (res != 0)
{
thread_info->self.reset();
throw thread_resource_error();
}
int detached_state;
res = pthread_attr_getdetachstate(h, &detached_state);
if (res != 0)
{
thread_info->self.reset();
throw thread_resource_error();
}
if (PTHREAD_CREATE_DETACHED==detached_state)
{
detail::thread_data_ptr local_thread_info;
thread_info.swap(local_thread_info);
if(local_thread_info)
{
//lock_guard<mutex> lock(local_thread_info->data_mutex);
if(!local_thread_info->join_started)
{
//BOOST_VERIFY(!pthread_detach(local_thread_info->thread_handle));
local_thread_info->join_started=true;
local_thread_info->joined=true;
}
}
}
}
detail::thread_data_ptr thread::get_thread_info() const
detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
{
lock_guard<mutex> l(thread_info_mutex);
return thread_info;
}
void thread::join()
{
detail::thread_data_ptr const local_thread_info=get_thread_info();
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 const local_thread_info=(get_thread_info)();
if(local_thread_info)
{
bool do_join=false;
{
unique_lock<mutex> lock(local_thread_info->data_mutex);
while(!local_thread_info->done)
@@ -225,7 +273,7 @@ namespace boost
local_thread_info->done_condition.wait(lock);
}
do_join=!local_thread_info->join_started;
if(do_join)
{
local_thread_info->join_started=true;
@@ -246,8 +294,7 @@ namespace boost
local_thread_info->joined=true;
local_thread_info->done_condition.notify_all();
}
lock_guard<mutex> l1(thread_info_mutex);
if(thread_info==local_thread_info)
{
thread_info.reset();
@@ -255,24 +302,28 @@ namespace boost
}
}
bool thread::timed_join(system_time const& wait_until)
bool thread::do_try_join_until(struct timespec const &timeout)
{
detail::thread_data_ptr const local_thread_info=get_thread_info();
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 const local_thread_info=(get_thread_info)();
if(local_thread_info)
{
bool do_join=false;
{
unique_lock<mutex> lock(local_thread_info->data_mutex);
while(!local_thread_info->done)
{
if(!local_thread_info->done_condition.timed_wait(lock,wait_until))
if(!local_thread_info->done_condition.do_timed_wait(lock,timeout))
{
return false;
}
}
do_join=!local_thread_info->join_started;
if(do_join)
{
local_thread_info->join_started=true;
@@ -293,8 +344,7 @@ namespace boost
local_thread_info->joined=true;
local_thread_info->done_condition.notify_all();
}
lock_guard<mutex> l1(thread_info_mutex);
if(thread_info==local_thread_info)
{
thread_info.reset();
@@ -303,20 +353,17 @@ namespace boost
return true;
}
bool thread::joinable() const
bool thread::joinable() const BOOST_NOEXCEPT
{
return get_thread_info();
return (get_thread_info)();
}
void thread::detach()
void thread::detach() BOOST_NOEXCEPT
{
detail::thread_data_ptr local_thread_info;
{
lock_guard<mutex> l1(thread_info_mutex);
thread_info.swap(local_thread_info);
}
thread_info.swap(local_thread_info);
if(local_thread_info)
{
lock_guard<mutex> lock(local_thread_info->data_mutex);
@@ -331,20 +378,24 @@ namespace boost
namespace this_thread
{
#ifdef __DECXXX
/// Workaround of DECCXX issue of incorrect template substitution
template<>
#endif
void sleep(const system_time& st)
{
detail::thread_data_base* const thread_info=detail::get_current_thread_data();
if(thread_info)
{
unique_lock<mutex> lk(thread_info->sleep_mutex);
while(thread_info->sleep_condition.timed_wait(lk,st));
while(thread_info->sleep_condition.timed_wait(lk,st)) {}
}
else
{
xtime const xt=get_xtime(st);
for (int foo=0; foo < 5; ++foo)
{
# if defined(BOOST_HAS_PTHREAD_DELAY_NP)
@@ -354,7 +405,7 @@ namespace boost
# elif defined(BOOST_HAS_NANOSLEEP)
timespec ts;
to_timespec_duration(xt, ts);
// nanosleep takes a timespec that is an offset, not
// an absolute time.
nanosleep(&ts, 0);
@@ -365,14 +416,41 @@ namespace boost
cond.timed_wait(lock, xt);
# endif
xtime cur;
xtime_get(&cur, TIME_UTC);
xtime_get(&cur, TIME_UTC_);
if (xtime_cmp(xt, cur) <= 0)
return;
}
}
}
void yield()
#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)
BOOST_VERIFY(!sched_yield());
@@ -380,18 +458,15 @@ namespace boost
BOOST_VERIFY(!pthread_yield());
# else
xtime xt;
xtime_get(&xt, TIME_UTC);
xtime_get(&xt, TIME_UTC_);
sleep(xt);
# endif
}
}
unsigned thread::hardware_concurrency()
unsigned thread::hardware_concurrency() BOOST_NOEXCEPT
{
#if defined(PTW32_VERSION) || defined(__hpux)
return pthread_num_processors_np();
#elif defined(__linux__)
return get_nprocs();
#elif defined(__APPLE__) || defined(__FreeBSD__)
int count;
size_t size=sizeof(count);
@@ -399,41 +474,49 @@ namespace boost
#elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN)
int const count=sysconf(_SC_NPROCESSORS_ONLN);
return (count>0)?count:0;
#elif defined(__GLIBC__)
return get_nprocs();
#else
return 0;
#endif
}
thread::id thread::get_id() const
thread::id thread::get_id() const BOOST_NOEXCEPT
{
detail::thread_data_ptr const local_thread_info=get_thread_info();
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
//return local_thread_info->thread_handle;
return const_cast<thread*>(this)->native_handle();
#else
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
if(local_thread_info)
{
return id(local_thread_info);
}
else
{
return id();
return id();
}
#endif
}
void thread::interrupt()
{
detail::thread_data_ptr const local_thread_info=get_thread_info();
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
if(local_thread_info)
{
lock_guard<mutex> lk(local_thread_info->data_mutex);
local_thread_info->interrupt_requested=true;
if(local_thread_info->current_cond)
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(local_thread_info->cond_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(local_thread_info->current_cond));
}
}
}
bool thread::interruption_requested() const
bool thread::interruption_requested() const BOOST_NOEXCEPT
{
detail::thread_data_ptr const local_thread_info=get_thread_info();
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
if(local_thread_info)
{
lock_guard<mutex> lk(local_thread_info->data_mutex);
@@ -447,7 +530,7 @@ namespace boost
thread::native_handle_type thread::native_handle()
{
detail::thread_data_ptr const local_thread_info=get_thread_info();
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
if(local_thread_info)
{
lock_guard<mutex> lk(local_thread_info->data_mutex);
@@ -458,15 +541,19 @@ namespace boost
return pthread_t();
}
}
namespace this_thread
{
thread::id get_id()
thread::id get_id() BOOST_NOEXCEPT
{
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
return pthread_self();
#else
boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
return thread::id(thread_info?thread_info->shared_from_this():detail::thread_data_ptr());
#endif
}
void interruption_point()
@@ -482,14 +569,14 @@ namespace boost
}
}
}
bool interruption_enabled()
bool interruption_enabled() BOOST_NOEXCEPT
{
boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
return thread_info && thread_info->interrupt_enabled;
}
bool interruption_requested()
bool interruption_requested() BOOST_NOEXCEPT
{
boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
if(!thread_info)
@@ -503,7 +590,7 @@ namespace boost
}
}
disable_interruption::disable_interruption():
disable_interruption::disable_interruption() BOOST_NOEXCEPT:
interruption_was_enabled(interruption_enabled())
{
if(interruption_was_enabled)
@@ -511,8 +598,8 @@ namespace boost
detail::get_current_thread_data()->interrupt_enabled=false;
}
}
disable_interruption::~disable_interruption()
disable_interruption::~disable_interruption() BOOST_NOEXCEPT
{
if(detail::get_current_thread_data())
{
@@ -520,15 +607,15 @@ namespace boost
}
}
restore_interruption::restore_interruption(disable_interruption& d)
restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT
{
if(d.interruption_was_enabled)
{
detail::get_current_thread_data()->interrupt_enabled=true;
}
}
restore_interruption::~restore_interruption()
restore_interruption::~restore_interruption() BOOST_NOEXCEPT
{
if(detail::get_current_thread_data())
{
@@ -552,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;
@@ -573,106 +657,47 @@ 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)
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
{
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
tss_data_node* const new_node=new tss_data_node(key,func,tss_data,current_thread_data->tss_data);
current_thread_data->tss_data=new_node;
add_new_tss_node(key,func,tss_data);
}
}
}
// thread_group::thread_group()
// {
// }
// thread_group::~thread_group()
// {
// // We shouldn't have to scoped_lock here, since referencing this object
// // from another thread while we're deleting it in the current thread is
// // going to lead to undefined behavior any way.
// for (std::list<thread*>::iterator it = m_threads.begin();
// it != m_threads.end(); ++it)
// {
// delete (*it);
// }
// }
// thread* thread_group::create_thread(const function0<void>& threadfunc)
// {
// // No scoped_lock required here since the only "shared data" that's
// // modified here occurs inside add_thread which does scoped_lock.
// std::auto_ptr<thread> thrd(new thread(threadfunc));
// add_thread(thrd.get());
// return thrd.release();
// }
// void thread_group::add_thread(thread* thrd)
// {
// mutex::scoped_lock scoped_lock(m_mutex);
// // For now we'll simply ignore requests to add a thread object multiple
// // times. Should we consider this an error and either throw or return an
// // error value?
// std::list<thread*>::iterator it = std::find(m_threads.begin(),
// m_threads.end(), thrd);
// BOOST_ASSERT(it == m_threads.end());
// if (it == m_threads.end())
// m_threads.push_back(thrd);
// }
// void thread_group::remove_thread(thread* thrd)
// {
// mutex::scoped_lock scoped_lock(m_mutex);
// // For now we'll simply ignore requests to remove a thread object that's
// // not in the group. Should we consider this an error and either throw or
// // return an error value?
// std::list<thread*>::iterator it = std::find(m_threads.begin(),
// m_threads.end(), thrd);
// BOOST_ASSERT(it != m_threads.end());
// if (it != m_threads.end())
// m_threads.erase(it);
// }
// void thread_group::join_all()
// {
// mutex::scoped_lock scoped_lock(m_mutex);
// for (std::list<thread*>::iterator it = m_threads.begin();
// it != m_threads.end(); ++it)
// {
// (*it)->join();
// }
// }
// void thread_group::interrupt_all()
// {
// boost::lock_guard<mutex> guard(m_mutex);
// for(std::list<thread*>::iterator it=m_threads.begin(),end=m_threads.end();
// it!=end;
// ++it)
// {
// (*it)->interrupt();
// }
// }
// size_t thread_group::size() const
// {
// return m_threads.size();
// }
}

View File

@@ -1,11 +1,14 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2009 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// boostinspect:nounnamed
#include <boost/assert.hpp>
namespace {
const int MILLISECONDS_PER_SECOND = 1000;
const int NANOSECONDS_PER_SECOND = 1000000000;
@@ -17,8 +20,8 @@ const int NANOSECONDS_PER_MICROSECOND = 1000;
inline void to_time(int milliseconds, boost::xtime& xt)
{
int res = 0;
res = boost::xtime_get(&xt, boost::TIME_UTC);
assert(res == boost::TIME_UTC);
res = boost::xtime_get(&xt, boost::TIME_UTC_);
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
@@ -30,7 +33,6 @@ inline void to_time(int milliseconds, boost::xtime& xt)
xt.nsec -= NANOSECONDS_PER_SECOND;
}
}
#if defined(BOOST_HAS_PTHREADS)
inline void to_timespec(const boost::xtime& xt, timespec& ts)
{
@@ -54,8 +56,8 @@ inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)
{
boost::xtime cur;
int res = 0;
res = boost::xtime_get(&cur, boost::TIME_UTC);
assert(res == boost::TIME_UTC);
res = boost::xtime_get(&cur, boost::TIME_UTC_);
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
if (boost::xtime_cmp(xt, cur) <= 0)
{
@@ -85,8 +87,8 @@ inline void to_duration(boost::xtime xt, int& milliseconds)
{
boost::xtime cur;
int res = 0;
res = boost::xtime_get(&cur, boost::TIME_UTC);
assert(res == boost::TIME_UTC);
res = boost::xtime_get(&cur, boost::TIME_UTC_);
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
if (boost::xtime_cmp(xt, cur) <= 0)
milliseconds = 0;
@@ -107,8 +109,8 @@ inline void to_microduration(boost::xtime xt, int& microseconds)
{
boost::xtime cur;
int res = 0;
res = boost::xtime_get(&cur, boost::TIME_UTC);
assert(res == boost::TIME_UTC);
res = boost::xtime_get(&cur, boost::TIME_UTC_);
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
if (boost::xtime_cmp(xt, cur) <= 0)
microseconds = 0;

328
src/shared_mutex.cpp Normal file
View File

@@ -0,0 +1,328 @@
// Copyright Howard Hinnant 2007-2010.
// Copyright Vicente J. Botet Escriba 2012.
// Use, modification and distribution are subject to 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/v2/shared_mutex.hpp>
#include <boost/thread/locks.hpp>
namespace boost
{
namespace thread_v2
{
// shared_mutex
shared_mutex::shared_mutex()
: state_(0)
{
}
shared_mutex::~shared_mutex()
{
boost::lock_guard<mutex_t> _(mut_);
}
// Exclusive ownership
void
shared_mutex::lock()
{
boost::unique_lock<mutex_t> lk(mut_);
while (state_ & write_entered_)
gate1_.wait(lk);
state_ |= write_entered_;
while (state_ & n_readers_)
gate2_.wait(lk);
}
bool
shared_mutex::try_lock()
{
boost::unique_lock<mutex_t> lk(mut_);
if (state_ == 0)
{
state_ = write_entered_;
return true;
}
return false;
}
void
shared_mutex::unlock()
{
boost::lock_guard<mutex_t> _(mut_);
state_ = 0;
gate1_.notify_all();
}
// Shared ownership
void
shared_mutex::lock_shared()
{
boost::unique_lock<mutex_t> lk(mut_);
while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
gate1_.wait(lk);
count_t num_readers = (state_ & n_readers_) + 1;
state_ &= ~n_readers_;
state_ |= num_readers;
}
bool
shared_mutex::try_lock_shared()
{
boost::unique_lock<mutex_t> lk(mut_);
count_t num_readers = state_ & n_readers_;
if (!(state_ & write_entered_) && num_readers != n_readers_)
{
++num_readers;
state_ &= ~n_readers_;
state_ |= num_readers;
return true;
}
return false;
}
void
shared_mutex::unlock_shared()
{
boost::lock_guard<mutex_t> _(mut_);
count_t num_readers = (state_ & n_readers_) - 1;
state_ &= ~n_readers_;
state_ |= num_readers;
if (state_ & write_entered_)
{
if (num_readers == 0)
gate2_.notify_one();
}
else
{
if (num_readers == n_readers_ - 1)
gate1_.notify_one();
}
}
// upgrade_mutex
upgrade_mutex::upgrade_mutex()
: gate1_(),
gate2_(),
state_(0)
{
}
upgrade_mutex::~upgrade_mutex()
{
boost::lock_guard<mutex_t> _(mut_);
}
// Exclusive ownership
void
upgrade_mutex::lock()
{
boost::unique_lock<mutex_t> lk(mut_);
while (state_ & (write_entered_ | upgradable_entered_))
gate1_.wait(lk);
state_ |= write_entered_;
while (state_ & n_readers_)
gate2_.wait(lk);
}
bool
upgrade_mutex::try_lock()
{
boost::unique_lock<mutex_t> lk(mut_);
if (state_ == 0)
{
state_ = write_entered_;
return true;
}
return false;
}
void
upgrade_mutex::unlock()
{
boost::lock_guard<mutex_t> _(mut_);
state_ = 0;
gate1_.notify_all();
}
// Shared ownership
void
upgrade_mutex::lock_shared()
{
boost::unique_lock<mutex_t> lk(mut_);
while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
gate1_.wait(lk);
count_t num_readers = (state_ & n_readers_) + 1;
state_ &= ~n_readers_;
state_ |= num_readers;
}
bool
upgrade_mutex::try_lock_shared()
{
boost::unique_lock<mutex_t> lk(mut_);
count_t num_readers = state_ & n_readers_;
if (!(state_ & write_entered_) && num_readers != n_readers_)
{
++num_readers;
state_ &= ~n_readers_;
state_ |= num_readers;
return true;
}
return false;
}
void
upgrade_mutex::unlock_shared()
{
boost::lock_guard<mutex_t> _(mut_);
count_t num_readers = (state_ & n_readers_) - 1;
state_ &= ~n_readers_;
state_ |= num_readers;
if (state_ & write_entered_)
{
if (num_readers == 0)
gate2_.notify_one();
}
else
{
if (num_readers == n_readers_ - 1)
gate1_.notify_one();
}
}
// Upgrade ownership
void
upgrade_mutex::lock_upgrade()
{
boost::unique_lock<mutex_t> lk(mut_);
while ((state_ & (write_entered_ | upgradable_entered_)) ||
(state_ & n_readers_) == n_readers_)
gate1_.wait(lk);
count_t num_readers = (state_ & n_readers_) + 1;
state_ &= ~n_readers_;
state_ |= upgradable_entered_ | num_readers;
}
bool
upgrade_mutex::try_lock_upgrade()
{
boost::unique_lock<mutex_t> lk(mut_);
count_t num_readers = state_ & n_readers_;
if (!(state_ & (write_entered_ | upgradable_entered_))
&& num_readers != n_readers_)
{
++num_readers;
state_ &= ~n_readers_;
state_ |= upgradable_entered_ | num_readers;
return true;
}
return false;
}
void
upgrade_mutex::unlock_upgrade()
{
{
boost::lock_guard<mutex_t> _(mut_);
count_t num_readers = (state_ & n_readers_) - 1;
state_ &= ~(upgradable_entered_ | n_readers_);
state_ |= num_readers;
}
gate1_.notify_all();
}
// Shared <-> Exclusive
bool
upgrade_mutex::try_unlock_shared_and_lock()
{
boost::unique_lock<mutex_t> lk(mut_);
if (state_ == 1)
{
state_ = write_entered_;
return true;
}
return false;
}
void
upgrade_mutex::unlock_and_lock_shared()
{
{
boost::lock_guard<mutex_t> _(mut_);
state_ = 1;
}
gate1_.notify_all();
}
// Shared <-> Upgrade
bool
upgrade_mutex::try_unlock_shared_and_lock_upgrade()
{
boost::unique_lock<mutex_t> lk(mut_);
if (!(state_ & (write_entered_ | upgradable_entered_)))
{
state_ |= upgradable_entered_;
return true;
}
return false;
}
void
upgrade_mutex::unlock_upgrade_and_lock_shared()
{
{
boost::lock_guard<mutex_t> _(mut_);
state_ &= ~upgradable_entered_;
}
gate1_.notify_all();
}
// Upgrade <-> Exclusive
void
upgrade_mutex::unlock_upgrade_and_lock()
{
boost::unique_lock<mutex_t> lk(mut_);
count_t num_readers = (state_ & n_readers_) - 1;
state_ &= ~(upgradable_entered_ | n_readers_);
state_ |= write_entered_ | num_readers;
while (state_ & n_readers_)
gate2_.wait(lk);
}
bool
upgrade_mutex::try_unlock_upgrade_and_lock()
{
boost::unique_lock<mutex_t> lk(mut_);
if (state_ == (upgradable_entered_ | 1))
{
state_ = write_entered_;
return true;
}
return false;
}
void
upgrade_mutex::unlock_and_lock_upgrade()
{
{
boost::lock_guard<mutex_t> _(mut_);
state_ = upgradable_entered_ | 1;
}
gate1_.notify_all();
}
} // thread_v2
} // boost

View File

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

View File

@@ -1,124 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <cstring>
#include <string>
namespace boost {
thread_exception::thread_exception()
: m_sys_err(0)
{
}
thread_exception::thread_exception(int sys_err_code)
: m_sys_err(sys_err_code)
{
}
thread_exception::~thread_exception() throw()
{
}
int thread_exception::native_error() const
{
return m_sys_err;
}
lock_error::lock_error()
{
}
lock_error::lock_error(int sys_err_code)
: thread_exception(sys_err_code)
{
}
lock_error::~lock_error() throw()
{
}
const char* lock_error::what() const throw()
{
return "boost::lock_error";
}
thread_resource_error::thread_resource_error()
{
}
thread_resource_error::thread_resource_error(int sys_err_code)
: thread_exception(sys_err_code)
{
}
thread_resource_error::~thread_resource_error() throw()
{
}
const char* thread_resource_error::what() const throw()
{
return "boost::thread_resource_error";
}
unsupported_thread_option::unsupported_thread_option()
{
}
unsupported_thread_option::unsupported_thread_option(int sys_err_code)
: thread_exception(sys_err_code)
{
}
unsupported_thread_option::~unsupported_thread_option() throw()
{
}
const char* unsupported_thread_option::what() const throw()
{
return "boost::unsupported_thread_option";
}
invalid_thread_argument::invalid_thread_argument()
{
}
invalid_thread_argument::invalid_thread_argument(int sys_err_code)
: thread_exception(sys_err_code)
{
}
invalid_thread_argument::~invalid_thread_argument() throw()
{
}
const char* invalid_thread_argument::what() const throw()
{
return "boost::invalid_thread_argument";
}
thread_permission_error::thread_permission_error()
{
}
thread_permission_error::thread_permission_error(int sys_err_code)
: thread_exception(sys_err_code)
{
}
thread_permission_error::~thread_permission_error() throw()
{
}
const char* thread_permission_error::what() const throw()
{
return "boost::thread_permission_error";
}
} // namespace boost

View File

@@ -4,12 +4,16 @@
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2007 David Deakins
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
#endif
#ifndef WINVER
#define WINVER 0x400
#endif
#include <boost/thread/thread.hpp>
#include <algorithm>
#include <windows.h>
#ifndef UNDER_CE
#include <process.h>
#endif
@@ -17,35 +21,48 @@
#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
{
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
boost::once_flag current_thread_tls_init_flag;
#else
boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
DWORD current_thread_tls_key=0;
#endif
#if defined(UNDER_CE)
// Windows CE does not define the TLS_OUT_OF_INDEXES constant.
DWORD tls_out_of_index=0xFFFFFFFF;
#else
DWORD tls_out_of_index=TLS_OUT_OF_INDEXES;
#endif
DWORD current_thread_tls_key=tls_out_of_index;
void create_current_thread_tls_key()
{
tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in
current_thread_tls_key=TlsAlloc();
BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES);
BOOST_ASSERT(current_thread_tls_key!=tls_out_of_index);
}
void cleanup_tls_key()
{
if(current_thread_tls_key)
if(current_thread_tls_key!=tls_out_of_index)
{
TlsFree(current_thread_tls_key);
current_thread_tls_key=0;
current_thread_tls_key=tls_out_of_index;
}
}
detail::thread_data_base* get_current_thread_data()
{
if(!current_thread_tls_key)
if(current_thread_tls_key==tls_out_of_index)
{
return 0;
}
@@ -55,10 +72,13 @@ namespace boost
void set_current_thread_data(detail::thread_data_base* new_data)
{
boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
if(current_thread_tls_key!=tls_out_of_index)
BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
else
boost::throw_exception(thread_resource_error());
}
#ifdef BOOST_NO_THREADEX
#ifndef BOOST_HAS_THREADEX
// Windows CE doesn't define _beginthreadex
struct ThreadProxyData
@@ -71,22 +91,25 @@ namespace boost
DWORD WINAPI ThreadProxy(LPVOID args)
{
ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args);
std::auto_ptr<ThreadProxyData> data(reinterpret_cast<ThreadProxyData*>(args));
DWORD ret=data->start_address_(data->arglist_);
delete data;
return ret;
}
typedef void* uintptr_t;
inline uintptr_t const _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
inline uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
void* arglist, unsigned initflag, unsigned* thrdaddr)
{
DWORD threadID;
ThreadProxyData* data = new ThreadProxyData(start_address,arglist);
HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy,
new ThreadProxyData(start_address,arglist),initflag,&threadID);
if (hthread!=0)
*thrdaddr=threadID;
data,initflag,&threadID);
if (hthread==0) {
delete data;
return 0;
}
*thrdaddr=threadID;
return reinterpret_cast<uintptr_t const>(hthread);
}
@@ -153,11 +176,11 @@ namespace boost
boost::detail::heap_delete(current_node);
}
}
set_current_thread_data(0);
}
}
unsigned __stdcall thread_start_function(void* param)
{
detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param));
@@ -180,7 +203,7 @@ namespace boost
}
}
thread::thread()
thread::thread() BOOST_NOEXCEPT
{}
void thread::start_thread()
@@ -188,13 +211,26 @@ namespace boost
uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
if(!new_thread)
{
throw thread_resource_error();
boost::throw_exception(thread_resource_error());
}
intrusive_ptr_add_ref(thread_info.get());
thread_info->thread_handle=(detail::win32::handle)(new_thread);
ResumeThread(thread_info->thread_handle);
}
void thread::start_thread(const attributes& attr)
{
//uintptr_t const new_thread=_beginthreadex(attr.get_security(),attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
uintptr_t const new_thread=_beginthreadex(0,attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
if(!new_thread)
{
boost::throw_exception(thread_resource_error());
}
intrusive_ptr_add_ref(thread_info.get());
thread_info->thread_handle=(detail::win32::handle)(new_thread);
ResumeThread(thread_info->thread_handle);
}
thread::thread(detail::thread_data_ptr data):
thread_info(data)
{}
@@ -209,7 +245,7 @@ namespace boost
++count;
interruption_enabled=false;
}
void run()
{}
private:
@@ -220,7 +256,15 @@ namespace boost
void make_external_thread_data()
{
externally_launched_thread* me=detail::heap_new<externally_launched_thread>();
set_current_thread_data(me);
try
{
set_current_thread_data(me);
}
catch(...)
{
detail::heap_delete(me);
throw;
}
}
detail::thread_data_base* get_or_make_current_thread_data()
@@ -233,27 +277,32 @@ namespace boost
}
return current_thread_data;
}
}
thread::~thread()
thread::id thread::get_id() const BOOST_NOEXCEPT
{
detach();
}
thread::id thread::get_id() const
{
return thread::id(get_thread_info());
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
detail::thread_data_ptr local_thread_info=(get_thread_info)();
return local_thread_info?local_thread_info->id:0;
//return const_cast<thread*>(this)->native_handle();
#else
return thread::id((get_thread_info)());
#endif
}
bool thread::joinable() const
bool thread::joinable() const BOOST_NOEXCEPT
{
return get_thread_info();
return (get_thread_info)();
}
void thread::join()
{
detail::thread_data_ptr local_thread_info=get_thread_info();
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)
{
this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel());
@@ -263,7 +312,11 @@ namespace boost
bool thread::timed_join(boost::system_time const& wait_until)
{
detail::thread_data_ptr local_thread_info=get_thread_info();
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)))
@@ -274,49 +327,70 @@ namespace boost
}
return true;
}
void thread::detach()
#ifdef BOOST_THREAD_USES_CHRONO
bool thread::try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
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)
{
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();
}
return true;
}
#endif
void thread::detach() BOOST_NOEXCEPT
{
release_handle();
}
void thread::release_handle()
{
lock_guard<mutex> l1(thread_info_mutex);
thread_info=0;
}
void thread::interrupt()
{
detail::thread_data_ptr local_thread_info=get_thread_info();
detail::thread_data_ptr local_thread_info=(get_thread_info)();
if(local_thread_info)
{
local_thread_info->interrupt();
}
}
bool thread::interruption_requested() const
bool thread::interruption_requested() const BOOST_NOEXCEPT
{
detail::thread_data_ptr local_thread_info=get_thread_info();
detail::thread_data_ptr local_thread_info=(get_thread_info)();
return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0);
}
unsigned thread::hardware_concurrency()
unsigned thread::hardware_concurrency() BOOST_NOEXCEPT
{
SYSTEM_INFO info={0};
SYSTEM_INFO info={{0}};
GetSystemInfo(&info);
return info.dwNumberOfProcessors;
}
thread::native_handle_type thread::native_handle()
{
detail::thread_data_ptr local_thread_info=get_thread_info();
detail::thread_data_ptr local_thread_info=(get_thread_info)();
return local_thread_info?(detail::win32::handle)local_thread_info->thread_handle:detail::win32::invalid_handle_value;
}
detail::thread_data_ptr thread::get_thread_info() const
detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
{
boost::mutex::scoped_lock l(thread_info_mutex);
return thread_info;
}
@@ -326,7 +400,7 @@ namespace boost
{
LARGE_INTEGER get_due_time(detail::timeout const& target_time)
{
LARGE_INTEGER due_time={0};
LARGE_INTEGER due_time={{0}};
if(target_time.relative)
{
unsigned long const elapsed_milliseconds=GetTickCount()-target_time.start;
@@ -355,13 +429,29 @@ namespace boost
else
{
long const hundred_nanoseconds_in_one_second=10000000;
due_time.QuadPart+=target_time.abs_time.time_of_day().fractional_seconds()*(hundred_nanoseconds_in_one_second/target_time.abs_time.time_of_day().ticks_per_second());
posix_time::time_duration::tick_type const ticks_per_second=
target_time.abs_time.time_of_day().ticks_per_second();
if(ticks_per_second>hundred_nanoseconds_in_one_second)
{
posix_time::time_duration::tick_type const
ticks_per_hundred_nanoseconds=
ticks_per_second/hundred_nanoseconds_in_one_second;
due_time.QuadPart+=
target_time.abs_time.time_of_day().fractional_seconds()/
ticks_per_hundred_nanoseconds;
}
else
{
due_time.QuadPart+=
target_time.abs_time.time_of_day().fractional_seconds()*
(hundred_nanoseconds_in_one_second/ticks_per_second);
}
}
}
return due_time;
}
}
bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
{
@@ -382,10 +472,10 @@ namespace boost
}
detail::win32::handle_manager timer_handle;
#ifndef UNDER_CE
unsigned const min_timer_wait_period=20;
if(!target_time.is_sentinel())
{
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
@@ -396,7 +486,7 @@ namespace boost
if(timer_handle!=0)
{
LARGE_INTEGER due_time=get_due_time(target_time);
bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
if(set_time_succeeded)
{
@@ -412,17 +502,17 @@ namespace boost
}
}
#endif
bool const using_timer=timeout_index!=~0u;
detail::timeout::remaining_time time_left(0);
do
{
if(!using_timer)
{
time_left=target_time.remaining_milliseconds();
}
if(handle_count)
{
unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds);
@@ -456,9 +546,14 @@ namespace boost
return false;
}
thread::id get_id()
thread::id get_id() BOOST_NOEXCEPT
{
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
//return detail::win32::GetCurrentThread();
return detail::win32::GetCurrentThreadId();
#else
return thread::id(get_or_make_current_thread_data());
#endif
}
void interruption_point()
@@ -469,23 +564,23 @@ namespace boost
throw thread_interrupted();
}
}
bool interruption_enabled()
bool interruption_enabled() BOOST_NOEXCEPT
{
return get_current_thread_data() && get_current_thread_data()->interruption_enabled;
}
bool interruption_requested()
bool interruption_requested() BOOST_NOEXCEPT
{
return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0);
}
void yield()
void yield() BOOST_NOEXCEPT
{
detail::win32::Sleep(0);
}
disable_interruption::disable_interruption():
disable_interruption::disable_interruption() BOOST_NOEXCEPT:
interruption_was_enabled(interruption_enabled())
{
if(interruption_was_enabled)
@@ -493,8 +588,8 @@ namespace boost
get_current_thread_data()->interruption_enabled=false;
}
}
disable_interruption::~disable_interruption()
disable_interruption::~disable_interruption() BOOST_NOEXCEPT
{
if(get_current_thread_data())
{
@@ -502,15 +597,15 @@ namespace boost
}
}
restore_interruption::restore_interruption(disable_interruption& d)
restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT
{
if(d.interruption_was_enabled)
{
get_current_thread_data()->interruption_enabled=true;
}
}
restore_interruption::~restore_interruption()
restore_interruption::~restore_interruption() BOOST_NOEXCEPT
{
if(get_current_thread_data())
{
@@ -525,8 +620,8 @@ namespace boost
{
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
thread_exit_callback_node* const new_node=
heap_new<thread_exit_callback_node>(func,
current_thread_data->thread_exit_callbacks);
heap_new<thread_exit_callback_node>(
func,current_thread_data->thread_exit_callbacks);
current_thread_data->thread_exit_callbacks=new_node;
}
@@ -556,42 +651,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)
{
if(tss_data_node* const current_node=find_tss_data(key))
{
if(cleanup_existing && current_node->func.get())
if(cleanup_existing && current_node->func.get() && current_node->value)
{
(*current_node->func)(current_node->value);
}
current_node->func=func;
current_node->value=tss_data;
}
else
else if(func && tss_data)
{
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
tss_data_node* const new_node=heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data);
tss_data_node* const new_node=
heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data);
current_thread_data->tss_data=new_node;
}
}
}
BOOST_THREAD_DECL void __cdecl on_process_enter()
{}
BOOST_THREAD_DECL void __cdecl on_thread_enter()
{}
BOOST_THREAD_DECL void __cdecl on_process_exit()
{
boost::cleanup_tls_key();
}
BOOST_THREAD_DECL void __cdecl on_thread_exit()
{
boost::run_thread_exit_callbacks();
}
}
extern "C" BOOST_THREAD_DECL void on_process_enter()
{}
extern "C" BOOST_THREAD_DECL void on_thread_enter()
{}
extern "C" BOOST_THREAD_DECL void on_process_exit()
{
boost::cleanup_tls_key();
}
extern "C" BOOST_THREAD_DECL void on_thread_exit()
{
boost::run_thread_exit_callbacks();
}

View File

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

View File

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

View File

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

View File

@@ -1,39 +0,0 @@
#
# Copyright Troy D. Straszheim
#
# Distributed under the Boost Software License, Version 1.0.
# See http://www.boost.org/LICENSE_1_0.txt
#
boost_additional_test_dependencies(thread BOOST_DEPENDS test )
set(TESTS
test_thread
test_thread_id
test_hardware_concurrency
test_thread_move
test_thread_launching
test_thread_mf
test_move_function
test_mutex
test_condition_notify_one
test_condition_timed_wait_times_out
test_condition_notify_all
test_condition
test_tss
test_once
test_xtime
test_barrier
test_shared_mutex
test_shared_mutex_part_2
test_shared_mutex_timed_locks
test_lock_concept
test_generic_locks)
foreach (TEST ${TESTS})
boost_test_run(${TEST} MULTI_THREADED DEPENDS boost_thread boost_unit_test_framework)
endforeach (TEST ${TESTS})
boost_test_compile_fail(no_implicit_move_from_lvalue_thread)
boost_test_compile_fail(no_implicit_assign_from_lvalue_thread)

View File

@@ -1,6 +1,7 @@
# (C) Copyright William E. Kempf 2001.
# (C) Copyright 2007 Anthony Williams.
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# (C) Copyright William E. Kempf 2001.
# (C) Copyright 2007 Anthony Williams.
# (C) Copyright 2011-2012 Vicente J.Botet Escriba.
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
# Boost.Threads test Jamfile
@@ -19,43 +20,516 @@
import testing ;
project
: requirements <library>/boost/test//boost_unit_test_framework/<link>static
<threading>multi
: requirements
<threading>multi
<warnings>all
<toolset>gcc:<cxxflags>-Wextra
<toolset>gcc:<cxxflags>-pedantic
<toolset>gcc:<cxxflags>-Wno-long-long
#<toolset>gcc:<cxxflags>-ansi
#<toolset>gcc:<cxxflags>-fpermissive
<toolset>darwin:<cxxflags>-Wextra
<toolset>darwin:<cxxflags>-pedantic
<toolset>darwin:<cxxflags>-Wno-long-long
#<toolset>darwin:<cxxflags>-ansi # doesn't work for 4.1.2
<toolset>darwin:<cxxflags>-fpermissive
#<toolset>pathscale:<cxxflags>-Wextra
<toolset>pathscale:<cxxflags>-Wno-long-long
<toolset>pathscale:<cxxflags>-pedantic
<toolset>clang:<cxxflags>-Wextra
<toolset>clang:<cxxflags>-pedantic
<toolset>clang:<cxxflags>-Wno-long-long
<toolset>clang:<cxxflags>-ansi
#<toolset>clang:<cxxflags>-fpermissive # doesn't work
<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.6.3:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.7.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.8.0:<cxxflags>-fdiagnostics-show-option
<toolset>darwin-4.6.2:<cxxflags>-ansi
#<toolset>darwin-4.6.2:<cxxflags>-Wno-delete-non-virtual-dtor # doesn't work
<toolset>darwin-4.7.0:<cxxflags>-ansi
<toolset>darwin-4.7.0:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.8:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.8:<cxxflags>-Wno-unused-function
#<toolset>clang-2.9:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-2.9:<cxxflags>-Wno-unused-function
<toolset>clang-3.0:<cxxflags>-Wno-delete-non-virtual-dtor
#<toolset>clang-3.0:<cxxflags>-Wno-unused-function
#<toolset>clang-3.0:<cxxflags>-Wno-unused-variable
;
rule thread-run ( sources )
{
return
return
[ run $(sources) ../build//boost_thread ]
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
: : : : $(sources[1]:B)_lib ]
;
}
}
rule thread-test ( sources )
{
test-suite "threads"
: [ thread-run test_thread.cpp ]
[ thread-run test_thread_id.cpp ]
[ thread-run test_hardware_concurrency.cpp ]
[ thread-run test_thread_move.cpp ]
[ thread-run test_thread_launching.cpp ]
[ thread-run test_thread_mf.cpp ]
[ thread-run test_move_function.cpp ]
[ thread-run test_mutex.cpp ]
[ thread-run test_condition_notify_one.cpp ]
[ thread-run test_condition_timed_wait_times_out.cpp ]
[ thread-run test_condition_notify_all.cpp ]
[ thread-run test_condition.cpp ]
[ thread-run test_tss.cpp ]
[ thread-run test_once.cpp ]
[ thread-run test_xtime.cpp ]
[ thread-run test_barrier.cpp ]
[ thread-run test_shared_mutex.cpp ]
[ thread-run test_shared_mutex_part_2.cpp ]
[ thread-run test_shared_mutex_timed_locks.cpp ]
[ thread-run test_lock_concept.cpp ]
[ thread-run test_generic_locks.cpp ]
[ compile-fail no_implicit_move_from_lvalue_thread.cpp ]
[ compile-fail no_implicit_assign_from_lvalue_thread.cpp ]
return
[ run $(sources) ../build//boost_thread : : : <library>/boost/test//boost_unit_test_framework/<link>static ]
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
: : : <library>/boost/test//boost_unit_test_framework/<link>static : $(sources[1]:B)_lib ]
;
}
rule thread-run2 ( sources : name )
{
return
[ run $(sources) ../build//boost_thread : : :
: $(name) ]
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
: : :
: $(name)_lib ]
;
}
rule thread-run-lib2 ( sources : name )
{
return
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
: : :
: $(name)_lib ]
;
}
rule thread-compile-fail ( sources : reqs * : name )
{
return
[ compile-fail $(sources)
: $(reqs)
: $(name) ]
;
}
{
test-suite t_threads
:
[ thread-test test_thread.cpp ]
[ thread-test test_thread_id.cpp ]
[ thread-test test_hardware_concurrency.cpp ]
[ thread-test test_thread_move.cpp ]
[ thread-test test_thread_return_local.cpp ]
[ thread-test test_thread_move_return.cpp ]
[ thread-test test_thread_launching.cpp ]
[ thread-test test_thread_mf.cpp ]
[ thread-test test_thread_exit.cpp ]
[ thread-test test_move_function.cpp ]
[ compile-fail no_implicit_move_from_lvalue_thread.cpp ]
[ compile-fail no_implicit_assign_from_lvalue_thread.cpp ]
[ thread-test test_tss.cpp ]
[ thread-test test_xtime.cpp ]
;
test-suite t_sync
:
[ thread-test test_mutex.cpp ]
[ thread-test test_condition_notify_one.cpp ]
[ thread-test test_condition_timed_wait_times_out.cpp ]
[ thread-test test_condition_notify_all.cpp ]
[ thread-test test_condition.cpp ]
[ thread-test test_once.cpp ]
[ thread-test test_barrier.cpp ]
[ thread-test test_lock_concept.cpp ]
[ thread-test test_generic_locks.cpp ]
;
test-suite t_shared
:
[ thread-test test_shared_mutex.cpp ]
[ thread-test test_shared_mutex_part_2.cpp ]
[ thread-test test_shared_mutex_timed_locks.cpp ]
[ thread-test test_shared_mutex_timed_locks_chrono.cpp ]
#uncomment the following once these works on windows
#[ thread-test test_vhh_shared_mutex.cpp ]
#[ thread-test test_vhh_shared_mutex_part_2.cpp ]
#[ thread-test test_vhh_shared_mutex_timed_locks.cpp ]
;
test-suite t_futures
:
[ thread-test test_futures.cpp ]
;
#explicit tickets ;
test-suite tickets
:
[ thread-test test_2309.cpp ]
[ thread-run test_2501.cpp ]
[ thread-test test_2741.cpp ]
[ thread-run test_4521.cpp ]
[ thread-run test_4648.cpp ]
[ thread-run test_4882.cpp ]
[ thread-run test_5542_1.cpp ]
[ thread-run test_5542_2.cpp ]
[ thread-run test_5542_3.cpp ]
[ thread-run test_5891.cpp ]
[ thread-run test_6130.cpp ]
[ thread-run test_6170.cpp ]
[ thread-run test_6174.cpp ]
;
explicit oth_tickets ;
test-suite oth_tickets
:
[ thread-run test_5351.cpp ]
[ thread-run test_5502.cpp ]
;
#explicit conditions ;
test-suite ts_conditions
:
[ thread-compile-fail ./sync/conditions/condition_variable/assign_fail.cpp : : condition_variable__assign_f ]
[ thread-compile-fail ./sync/conditions/condition_variable/copy_fail.cpp : : condition_variable__copy_f ]
[ thread-run2 ./sync/conditions/condition_variable/default_pass.cpp : condition_variable__default_p ]
[ thread-run2 ./sync/conditions/condition_variable/dtor_pass.cpp : condition_variable__dtor_p ]
[ thread-run2 ./sync/conditions/condition_variable/native_handle_pass.cpp : condition_variable__native_handle_p ]
[ thread-run2 ./sync/conditions/condition_variable/wait_for_pass.cpp : condition_variable__wait_for_p ]
[ thread-run2 ./sync/conditions/condition_variable/wait_for_pred_pass.cpp : condition_variable__wait_for_pred_p ]
[ thread-run2 ./sync/conditions/condition_variable/wait_until_pass.cpp : condition_variable__wait_until_p ]
[ thread-run2 ./sync/conditions/condition_variable/wait_until_pred_pass.cpp : condition_variable__wait_until_pred_p ]
[ thread-compile-fail ./sync/conditions/condition_variable_any/assign_fail.cpp : : condition_variable_any__assign_f ]
[ thread-compile-fail ./sync/conditions/condition_variable_any/copy_fail.cpp : : condition_variable_any__copy_f ]
[ thread-run2 ./sync/conditions/condition_variable_any/default_pass.cpp : condition_variable_any__default_p ]
[ thread-run2 ./sync/conditions/condition_variable_any/dtor_pass.cpp : condition_variable_any__dtor_p ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_for_pass.cpp : condition_variable_any__wait_for_p ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_for_pred_pass.cpp : condition_variable_any__wait_for_pred_p ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_until_pass.cpp : condition_variable_any__wait_until_p ]
[ thread-run2 ./sync/conditions/condition_variable_any/wait_until_pred_pass.cpp : condition_variable_any__wait_until_pred_p ]
[ thread-run2 ./sync/conditions/cv_status/cv_status_pass.cpp : cv_status__cv_status_p ]
;
#explicit async ;
test-suite ts_async
:
# [ thread-run2 ./sync/futures/async/async_pass.cpp : async__async_p ]
;
#explicit promise ;
test-suite ts_promise
:
[ thread-compile-fail ./sync/futures/promise/copy_assign_fail.cpp : : promise__copy_assign_f ]
[ thread-compile-fail ./sync/futures/promise/copy_ctor_fail.cpp : : promise__copy_ctor_f ]
[ thread-run2 ./sync/futures/promise/alloc_ctor_pass.cpp : promise__alloc_ctor_p ]
[ thread-run2 ./sync/futures/promise/default_pass.cpp : promise__default_p ]
[ thread-run2 ./sync/futures/promise/dtor_pass.cpp : promise__dtor_p ]
[ thread-run2 ./sync/futures/promise/get_future_pass.cpp : promise__get_future_p ]
[ thread-run2 ./sync/futures/promise/move_ctor_pass.cpp : promise__move_ctor_p ]
[ thread-run2 ./sync/futures/promise/move_assign_pass.cpp : promise__move_asign_p ]
[ thread-run2 ./sync/futures/promise/use_allocator_pass.cpp : promise__use_allocator_p ]
;
#explicit future ;
test-suite ts_future
:
[ thread-compile-fail ./sync/futures/future/copy_assign_fail.cpp : : future__copy_assign_f ]
[ thread-compile-fail ./sync/futures/future/copy_ctor_fail.cpp : : future__copy_ctor_f ]
[ thread-run2 ./sync/futures/future/default_pass.cpp : future__default_p ]
[ thread-run2 ./sync/futures/future/dtor_pass.cpp : future__dtor_p ]
#[ thread-run2 ./sync/futures/future/get_pass.cpp : future__get_p ]
[ thread-run2 ./sync/futures/future/move_ctor_pass.cpp : future__move_ctor_p ]
[ thread-run2 ./sync/futures/future/move_assign_pass.cpp : future__move_asign_p ]
[ thread-run2 ./sync/futures/future/share_pass.cpp : future__share_p ]
;
#explicit packaged_task ;
test-suite ts_packaged_task
:
[ thread-run2 ./sync/futures/packaged_task/alloc_ctor_pass.cpp : packaged_task__alloc_ctor_p ]
[ thread-compile-fail ./sync/futures/packaged_task/copy_assign_fail.cpp : : packaged_task__copy_assign_f ]
[ thread-compile-fail ./sync/futures/packaged_task/copy_ctor_fail.cpp : : packaged_task__copy_ctor_f ]
[ thread-run2 ./sync/futures/packaged_task/default_ctor_pass.cpp : packaged_task__default_ctor_p ]
[ thread-run2 ./sync/futures/packaged_task/func_ctor_pass.cpp : packaged_task__func_ctor_p ]
#[ thread-run2 ./sync/futures/packaged_task/dtor_pass.cpp : packaged_task__dtor_p ]
[ thread-run2 ./sync/futures/packaged_task/get_future_pass.cpp : packaged_task__get_future_p ]
[ thread-run2 ./sync/futures/packaged_task/move_ctor_pass.cpp : packaged_task__move_ctor_p ]
[ thread-run2 ./sync/futures/packaged_task/move_assign_pass.cpp : packaged_task__move_asign_p ]
#[ thread-run2 ./sync/futures/packaged_task/operator_pass.cpp : packaged_task__operator_p ]
[ thread-run2 ./sync/futures/packaged_task/reset_pass.cpp : packaged_task__reset_p ]
[ thread-run2 ./sync/futures/packaged_task/use_allocator_pass.cpp : packaged_task__use_allocator_p ]
[ thread-run2 ./sync/futures/packaged_task/types_pass.cpp : packaged_task__types_p ]
[ thread-run2 ./sync/futures/packaged_task/member_swap_pass.cpp : packaged_task__member_swap_p ]
[ thread-run2 ./sync/futures/packaged_task/non_member_swap_pass.cpp : packaged_task__non_member_swap_p ]
;
#explicit lock_guard ;
test-suite ts_lock_guard
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/lock_guard/copy_assign_fail.cpp : : lock_guard__cons__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/lock_guard/copy_ctor_fail.cpp : : lock_guard__cons__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/lock_guard/adopt_lock_pass.cpp : lock_guard__cons__adopt_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/lock_guard/default_pass.cpp : lock_guard__cons__default_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/lock_guard/types_pass.cpp : lock_guard__types_p ]
;
#explicit unique_lock ;
test-suite ts_unique_lock
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/cons/copy_assign_fail.cpp : : unique_lock__cons__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/cons/copy_ctor_fail.cpp : : unique_lock__cons__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/adopt_lock_pass.cpp : unique_lock__cons__adopt_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/default_pass.cpp : unique_lock__cons__default_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/defer_lock_pass.cpp : unique_lock__cons__defer_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp : unique_lock__cons__duration_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp : unique_lock__cons__move_assign_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp : unique_lock__cons__move_ctor_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_try_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_until_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp : unique_lock__cons__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp : unique_lock__cons__time_point_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp : unique_lock__cons__try_to_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/lock_pass.cpp : unique_lock__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_for_pass.cpp : unique_lock__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_pass.cpp : unique_lock__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_until_pass.cpp : unique_lock__try_lock_until_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/locking/unlock_pass.cpp : unique_lock__unlock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/mod/member_swap_pass.cpp : unique_lock__member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/mod/non_member_swap_pass.cpp : unique_lock__non_member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/mod/release_pass.cpp : unique_lock__release_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/obs/mutex_pass.cpp : unique_lock__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/obs/op_bool_pass.cpp : unique_lock__op_bool_p ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/obs/op_int_fail.cpp : : unique_lock__op_int_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/obs/owns_lock_pass.cpp : unique_lock__owns_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/types_pass.cpp : unique_lock__types_p ]
;
#explicit shared_lock ;
test-suite ts_shared_lock
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock/cons/copy_assign_fail.cpp : : shared_lock__cons__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock/cons/copy_ctor_fail.cpp : : shared_lock__cons__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/adopt_lock_pass.cpp : shared_lock__cons__adopt_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp : shared_lock__cons__default_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp : shared_lock__cons__defer_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp : shared_lock__cons__duration_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp : shared_lock__cons__move_assign_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp : shared_lock__cons__move_ctor_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp : shared_lock__cons__move_ctor_unique_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp : shared_lock__cons__move_ctor_upgrade_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp : shared_lock__cons__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp : shared_lock__cons__time_point_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp : shared_lock__cons__try_to_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/lock_pass.cpp : shared_lock__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_for_pass.cpp : shared_lock__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_pass.cpp : shared_lock__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_until_pass.cpp : shared_lock__try_lock_until_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/locking/unlock_pass.cpp : shared_lock__unlock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/mod/member_swap_pass.cpp : shared_lock__member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/mod/non_member_swap_pass.cpp : shared_lock__non_member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/mod/release_pass.cpp : shared_lock__release_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/obs/mutex_pass.cpp : shared_lock__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/obs/op_bool_pass.cpp : shared_lock__op_bool_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/obs/owns_lock_pass.cpp : shared_lock__owns_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock/types_pass.cpp : shared_lock__types_p ]
;
#explicit upgrade_lock ;
test-suite ts_upgrade_lock
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/upgrade_lock/cons/copy_assign_fail.cpp : : upgrade_lock__cons__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/upgrade_lock/cons/copy_ctor_fail.cpp : : upgrade_lock__cons__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/adopt_lock_pass.cpp : upgrade_lock__cons__adopt_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/default_pass.cpp : upgrade_lock__cons__default_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/defer_lock_pass.cpp : upgrade_lock__cons__defer_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp : upgrade_lock__cons__duration_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp : upgrade_lock__cons__move_assign_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp : upgrade_lock__cons__move_ctor_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp : upgrade_lock__cons__move_ctor_unique_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp : upgrade_lock__cons__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp : upgrade_lock__cons__time_point_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp : upgrade_lock__cons__try_to_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/locking/lock_pass.cpp : upgrade_lock__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_for_pass.cpp : upgrade_lock__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_pass.cpp : upgrade_lock__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_until_pass.cpp : upgrade_lock__try_lock_until_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/locking/unlock_pass.cpp : upgrade_lock__unlock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/mod/member_swap_pass.cpp : upgrade_lock__member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/mod/non_member_swap_pass.cpp : upgrade_lock__non_member_swap_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/mod/release_pass.cpp : upgrade_lock__release_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/obs/mutex_pass.cpp : upgrade_lock__mutex_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/obs/op_bool_pass.cpp : upgrade_lock__op_bool_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/obs/owns_lock_pass.cpp : upgrade_lock__owns_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/types_pass.cpp : upgrade_lock__types_p ]
;
#explicit mutexs ;
test-suite ts_mutex
:
[ thread-compile-fail ./sync/mutual_exclusion/mutex/assign_fail.cpp : : mutex__assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/mutex/copy_fail.cpp : : mutex__copy_f ]
[ thread-run2 ./sync/mutual_exclusion/mutex/default_pass.cpp : mutex__default_p ]
[ thread-run2 ./sync/mutual_exclusion/mutex/lock_pass.cpp : mutex__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/mutex/native_handle_pass.cpp : mutex__native_handle_p ]
[ thread-run2 ./sync/mutual_exclusion/mutex/try_lock_pass.cpp : mutex__try_lock_p ]
;
#explicit recursive_mutex ;
test-suite ts_recursive_mutex
:
[ thread-compile-fail ./sync/mutual_exclusion/recursive_mutex/assign_fail.cpp : : recursive_mutex__assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/recursive_mutex/copy_fail.cpp : : recursive_mutex__copy_f ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/default_pass.cpp : recursive_mutex__default_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/lock_pass.cpp : recursive_mutex__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/native_handle_pass.cpp : recursive_mutex__native_handle_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_mutex/try_lock_pass.cpp : recursive_mutex__try_lock_p ]
;
#explicit recursive_timed_mutex ;
test-suite ts_recursive_timed_mutex
:
[ thread-compile-fail ./sync/mutual_exclusion/recursive_timed_mutex/assign_fail.cpp : : recursive_timed_mutex__assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp : : recursive_timed_mutex__copy_f ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp : recursive_timed_mutex__default_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp : recursive_timed_mutex__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp : recursive_timed_mutex__native_handle_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp : recursive_timed_mutex__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp : recursive_timed_mutex__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp : recursive_timed_mutex__try_lock_until_p ]
;
#explicit timed_mutex ;
test-suite ts_timed_mutex
:
[ thread-compile-fail ./sync/mutual_exclusion/timed_mutex/assign_fail.cpp : : timed_mutex__assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/timed_mutex/copy_fail.cpp : : timed_mutex__copy_f ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/default_pass.cpp : timed_mutex__default_p ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/lock_pass.cpp : timed_mutex__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp : timed_mutex__native_handle_p ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp : timed_mutex__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp : timed_mutex__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp : timed_mutex__try_lock_until_p ]
;
#explicit shared_mutexs ;
test-suite ts_shared_mutex
:
[ thread-compile-fail ./sync/mutual_exclusion/shared_mutex/assign_fail.cpp : : shared_mutex__assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/shared_mutex/copy_fail.cpp : : shared_mutex__copy_f ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/default_pass.cpp : shared_mutex__default_p ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/lock_pass.cpp : shared_mutex__lock_p ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp : shared_mutex__try_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp : shared_mutex__try_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp : shared_mutex__try_lock_until_p ]
;
#explicit this_thread ;
test-suite ts_this_thread
:
[ thread-run2 ./threads/this_thread/get_id/get_id_pass.cpp : this_thread__get_id_p ]
[ thread-run2 ./threads/this_thread/sleep_for/sleep_for_pass.cpp : this_thread__sleep_for_p ]
[ thread-run2 ./threads/this_thread/sleep_until/sleep_until_pass.cpp : this_thread__sleep_until_p ]
;
#explicit thread ;
test-suite ts_thread
:
[ thread-compile-fail ./threads/thread/assign/copy_fail.cpp : : thread__assign__copy_f ]
[ thread-run2 ./threads/thread/assign/move_pass.cpp : thread__assign__move_p ]
[ thread-compile-fail ./threads/thread/constr/copy_fail.cpp : : thread__constr__copy_f ]
[ thread-run2 ./threads/thread/constr/default_pass.cpp : thread__constr__default_p ]
[ thread-run-lib2 ./threads/thread/constr/F_pass.cpp : thread__constr__F_p ]
[ thread-run-lib2 ./threads/thread/constr/FArgs_pass.cpp : thread__constr__FArgs_p ]
[ thread-run2 ./threads/thread/constr/Frvalue_pass.cpp : thread__constr__Frvalue_p ]
#[ thread-run2 ./threads/thread/constr/FrvalueArgs_pass.cpp : thread__constr__FrvalueArgs_p ]
[ thread-run2 ./threads/thread/constr/move_pass.cpp : thread__constr__move_p ]
[ thread-run2 ./threads/thread/destr/dtor_pass.cpp : thread__destr__dtor_p ]
[ thread-run2 ./threads/thread/id/hash_pass.cpp : thread__id__hash_p ]
[ thread-run2 ./threads/thread/members/detach_pass.cpp : thread__detach_p ]
[ thread-run2 ./threads/thread/members/get_id_pass.cpp : thread__get_id_p ]
[ thread-run2 ./threads/thread/members/join_pass.cpp : thread__join_p ]
[ thread-run2 ./threads/thread/members/joinable_pass.cpp : thread__joinable_p ]
[ thread-run2 ./threads/thread/members/native_handle_pass.cpp : thread__native_handle_p ]
[ thread-run2 ./threads/thread/members/swap_pass.cpp : thread__swap_p ]
[ thread-run2 ./threads/thread/non_members/swap_pass.cpp : swap_threads_p ]
[ thread-run2 ./threads/thread/static/hardware_concurrency_pass.cpp : thread__hardware_concurrency_p ]
;
#explicit ts_container ;
test-suite ts_container
:
[ thread-run2 ./threads/container/thread_vector_pass.cpp : container__thread_vector_p ]
[ thread-run2 ./threads/container/thread_ptr_list_pass.cpp : container__thread_ptr_list_p ]
;
#explicit examples ;
test-suite ts_examples
:
[ thread-run ../example/monitor.cpp ]
[ compile ../example/starvephil.cpp ]
#[ compile ../example/tennis.cpp ]
[ compile ../example/condition.cpp ]
[ thread-run ../example/mutex.cpp ]
[ thread-run ../example/once.cpp ]
[ thread-run ../example/recursive_mutex.cpp ]
[ thread-run2 ../example/thread.cpp : ex_thread ]
[ thread-run ../example/thread_group.cpp ]
[ thread-run ../example/tss.cpp ]
[ thread-run ../example/xtime.cpp ]
[ thread-run ../example/shared_monitor.cpp ]
[ thread-run ../example/shared_mutex.cpp ]
#[ thread-run ../example/vhh_shared_monitor.cpp ]
#[ thread-run ../example/vhh_shared_mutex.cpp ]
;
#explicit shared_upwards ;
test-suite ts_shared_upwards
:
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp : unique_lock__cons__move_ctor_shared_lock_try_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp : unique_lock__cons__move_ctor_shared_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp : unique_lock__cons__move_ctor_shared_lock_until_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_try_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_for_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_until_p ]
;
#explicit shared_lock_guard ;
test-suite ts_shared_lock_guard
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock_guard/copy_assign_fail.cpp : : shared_lock_guard__cons__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock_guard/copy_ctor_fail.cpp : : shared_lock_guard__cons__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock_guard/adopt_lock_pass.cpp : shared_lock_guard__cons__adopt_lock_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock_guard/default_pass.cpp : shared_lock_guard__cons__default_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/shared_lock_guard/types_pass.cpp : shared_lock_guard__types_p ]
;
#explicit reverse_lock ;
test-suite ts_reverse_lock
:
[ thread-compile-fail ./sync/mutual_exclusion/locks/reverse_lock/copy_assign_fail.cpp : : reverse_lock__copy_assign_f ]
[ thread-compile-fail ./sync/mutual_exclusion/locks/reverse_lock/copy_ctor_fail.cpp : : reverse_lock__copy_ctor_f ]
[ thread-run2 ./sync/mutual_exclusion/locks/reverse_lock/unique_lock_ctor_pass.cpp : reverse_lock__unique_lock_ctor_p ]
[ thread-run2 ./sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp : reverse_lock__types_p ]
;
explicit ts ;
test-suite ts
:
[ thread-run test_ml.cpp ]
;
}

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2008 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
@@ -13,3 +13,15 @@ void test()
boost::thread t2;
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;
}

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2008 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
@@ -12,3 +12,15 @@ void test()
boost::thread t1(do_nothing);
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;
}

View File

@@ -0,0 +1,39 @@
//===----------------------------------------------------------------------===//
//
// 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>
// class condition_variable;
// condition_variable& operator=(const condition_variable&) = delete;
#include <boost/thread/condition_variable.hpp>
void fail()
{
boost::condition_variable cv0;
boost::condition_variable cv1;
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]
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -0,0 +1,38 @@
//===----------------------------------------------------------------------===//
//
// 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>
// class condition_variable;
// condition_variable(const condition_variable&) = delete;
#include <boost/thread/condition_variable.hpp>
#include <boost/detail/lightweight_test.hpp>
void fail()
{
boost::condition_variable cv0;
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]
(void)boost::system::posix_category;
(void)boost::system::errno_ecat;
(void)boost::system::native_ecat;
}

View File

@@ -0,0 +1,27 @@
//===----------------------------------------------------------------------===//
//
// 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>
// class condition_variable;
// condition_variable(const condition_variable&) = delete;
#include <boost/thread/condition_variable.hpp>
#include <boost/detail/lightweight_test.hpp>
int main()
{
boost::condition_variable cv0;
return boost::report_errors();
}

View File

@@ -0,0 +1,69 @@
//===----------------------------------------------------------------------===//
//
// 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>
// class condition_variable;
// condition_variable(const condition_variable&) = delete;
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/locks.hpp>
#include <boost/detail/lightweight_test.hpp>
boost::condition_variable* cv;
boost::mutex m;
typedef boost::unique_lock<boost::mutex> Lock;
bool f_ready = false;
bool g_ready = false;
void f()
{
Lock lk(m);
f_ready = true;
cv->notify_one();
cv->wait(lk);
delete cv;
}
void g()
{
Lock lk(m);
g_ready = true;
cv->notify_one();
while (!f_ready)
{
cv->wait(lk);
}
cv->notify_one();
}
int main()
{
cv = new boost::condition_variable;
boost::thread th2(g);
Lock lk(m);
while (!g_ready)
{
cv->wait(lk);
}
lk.unlock();
boost::thread th1(f);
th1.join();
th2.join();
return boost::report_errors();
}

View File

@@ -0,0 +1,37 @@
//===----------------------------------------------------------------------===//
//
// 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>
// class condition_variable;
// condition_variable(const condition_variable&) = delete;
#include <boost/thread/condition_variable.hpp>
#include <boost/static_assert.hpp>
#include <boost/detail/lightweight_test.hpp>
int main()
{
#if defined BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
//BOOST_STATIC_ASSERT((boost::is_same<boost::condition_variable::native_handle_type, pthread_cond_t*>::value));
boost::condition_variable cv;
boost::condition_variable::native_handle_type h = cv.native_handle();
BOOST_TEST(h != 0);
#else
#error "Test not applicable: BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE not defined for this platform as not supported"
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,95 @@
//===----------------------------------------------------------------------===//
//
// 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>
// class condition_variable;
// condition_variable(const condition_variable&) = delete;
#include <iostream>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_USES_CHRONO
boost::condition_variable cv;
boost::mutex mut;
int test1 = 0;
int test2 = 0;
int runs = 0;
void f()
{
typedef boost::chrono::steady_clock Clock;
typedef boost::chrono::milliseconds milliseconds;
boost::unique_lock<boost::mutex> lk(mut);
BOOST_TEST(test2 == 0);
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
int count=0;
while (test2 == 0 && cv.wait_for(lk, milliseconds(250)) == boost::cv_status::no_timeout)
count++;
Clock::time_point t1 = Clock::now();
if (runs == 0)
{
BOOST_TEST(t1 - t0 < milliseconds(250));
BOOST_TEST(test2 != 0);
}
else
{
// This test is spurious as it depends on the time the thread system switches the threads
BOOST_TEST(t1 - t0 - milliseconds(250) < milliseconds(count*250+5+1000));
BOOST_TEST(test2 == 0);
}
++runs;
}
int main()
{
{
boost::unique_lock<boost::mutex> lk(mut);
boost::thread t(f);
BOOST_TEST(test1 == 0);
while (test1 == 0)
cv.wait(lk);
BOOST_TEST(test1 != 0);
test2 = 1;
lk.unlock();
cv.notify_one();
t.join();
}
test1 = 0;
test2 = 0;
{
boost::unique_lock<boost::mutex> lk(mut);
boost::thread t(f);
BOOST_TEST(test1 == 0);
while (test1 == 0)
cv.wait(lk);
BOOST_TEST(test1 != 0);
lk.unlock();
t.join();
}
return boost::report_errors();
}
#else
#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
#endif

View File

@@ -0,0 +1,110 @@
//===----------------------------------------------------------------------===//
//
// 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>
// class condition_variable;
// condition_variable(const condition_variable&) = delete;
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_USES_CHRONO
class Pred
{
int& i_;
public:
explicit Pred(int& i) :
i_(i)
{
}
bool operator()()
{
return i_ != 0;
}
};
boost::condition_variable cv;
boost::mutex mut;
int test1 = 0;
int test2 = 0;
int runs = 0;
void f()
{
typedef boost::chrono::system_clock Clock;
typedef boost::chrono::milliseconds milliseconds;
boost::unique_lock < boost::mutex > lk(mut);
BOOST_TEST(test2 == 0);
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
int count=0;
//bool r =
(void)cv.wait_for(lk, milliseconds(250), Pred(test2));
count++;
Clock::time_point t1 = Clock::now();
if (runs == 0)
{
// This test is spurious as it depends on the time the thread system switches the threads
BOOST_TEST(t1 - t0 < milliseconds(250+1000));
BOOST_TEST(test2 != 0);
}
else
{
BOOST_TEST(t1 - t0 - milliseconds(250) < milliseconds(count*250+2));
BOOST_TEST(test2 == 0);
}
++runs;
}
int main()
{
{
boost::unique_lock < boost::mutex > lk(mut);
boost::thread t(f);
BOOST_TEST(test1 == 0);
while (test1 == 0)
cv.wait(lk);
BOOST_TEST(test1 != 0);
test2 = 1;
lk.unlock();
cv.notify_one();
t.join();
}
test1 = 0;
test2 = 0;
{
boost::unique_lock < boost::mutex > lk(mut);
boost::thread t(f);
BOOST_TEST(test1 == 0);
while (test1 == 0)
cv.wait(lk);
BOOST_TEST(test1 != 0);
lk.unlock();
t.join();
}
return boost::report_errors();
}
#else
#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
#endif

View File

@@ -0,0 +1,108 @@
//===----------------------------------------------------------------------===//
//
// 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>
// class condition_variable;
// condition_variable(const condition_variable&) = delete;
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_USES_CHRONO
struct Clock
{
typedef boost::chrono::milliseconds duration;
typedef duration::rep rep;
typedef duration::period period;
typedef boost::chrono::time_point<Clock> time_point;
static const bool is_steady = true;
static time_point now()
{
using namespace boost::chrono;
return time_point(duration_cast<duration> (steady_clock::now().time_since_epoch()));
}
};
boost::condition_variable cv;
boost::mutex mut;
int test1 = 0;
int test2 = 0;
int runs = 0;
void f()
{
boost::unique_lock < boost::mutex > lk(mut);
BOOST_TEST(test2 == 0);
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
Clock::time_point t = t0 + Clock::duration(250);
int count=0;
while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout)
count++;
Clock::time_point t1 = Clock::now();
if (runs == 0)
{
BOOST_TEST(t1 - t0 < Clock::duration(250));
BOOST_TEST(test2 != 0);
}
else
{
// This test is spurious as it depends on the time the thread system switches the threads
BOOST_TEST(t1 - t0 - Clock::duration(250) < Clock::duration(count*250+5+1000));
BOOST_TEST(test2 == 0);
}
++runs;
}
int main()
{
{
boost::unique_lock < boost::mutex > lk(mut);
boost::thread t(f);
BOOST_TEST(test1 == 0);
while (test1 == 0)
cv.wait(lk);
BOOST_TEST(test1 != 0);
test2 = 1;
lk.unlock();
cv.notify_one();
t.join();
}
test1 = 0;
test2 = 0;
{
boost::unique_lock < boost::mutex > lk(mut);
boost::thread t(f);
BOOST_TEST(test1 == 0);
while (test1 == 0)
cv.wait(lk);
BOOST_TEST(test1 != 0);
lk.unlock();
t.join();
}
return boost::report_errors();
}
#else
#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
#endif

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