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

Compare commits

..

160 Commits

Author SHA1 Message Date
Vicente J. Botet Escriba
0f6a3ebbe5 Merge branch 'develop' 2015-03-21 15:44:02 +01:00
Vicente J. Botet Escriba
a5c34e7be2 update version and copyright. 2015-03-21 15:43:04 +01:00
Vicente J. Botet Escriba
287100119a Merge branch 'develop' 2015-03-17 03:16:35 +01:00
Vicente J. Botet Escriba
ba2f814342 Don't lock while storing the exception_ptr list as only the task_region thread can do it. 2015-03-16 08:41:04 +01:00
Vicente J. Botet Escriba
5169a5414b mutex::unlock must not throw. 2015-03-14 16:26:35 +01:00
Vicente J. Botet Escriba
82b9a4e28c Use coherently size_type. 2015-03-12 04:09:34 +01:00
Vicente J. Botet Escriba
e989d2f626 Add comments. 2015-03-12 04:08:42 +01:00
Vicente J. Botet Escriba
331f0b9325 Added test for future<T&>::get_or. 2015-03-10 07:54:09 +01:00
Vicente J. Botet Escriba
ec6a1fcf80 try to get rid of data race. 2015-03-10 00:48:12 +01:00
Vicente J. Botet Escriba
dcebe26a11 try to get rid of possible deadlock. 2015-03-10 00:47:38 +01:00
Vicente J. Botet Escriba
d7721940f3 update history. 2015-03-09 23:17:35 +01:00
Vicente J. Botet Escriba
b678edb0d8 update history. 2015-03-08 23:31:37 +01:00
Vicente J. Botet Escriba
1371728e02 Merge pull request #50 from wmamrak/develop
Fixed some documentation bugs.
2015-03-06 00:11:52 +01:00
Wojciech Mamrak
17d802db81 Fixed documentation bugs. 2015-03-05 13:22:04 +01:00
Wojciech Mamrak
9fc06a8741 Fixed documentation bugs. 2015-03-05 12:37:10 +01:00
Wojciech Mamrak
946fac633e Fixed documentation bugs. 2015-03-04 12:22:33 +01:00
Wojciech Mamrak
af1c7d0c26 Fixed documentation bugs. 2015-03-03 19:03:18 +01:00
Vicente J. Botet Escriba
d9594e7fc8 Merge branch 'develop' 2015-03-01 18:54:42 +01:00
Vicente J. Botet Escriba
0653efff3d Added this_executor and default_executor examples. 2015-03-01 18:53:11 +01:00
Vicente J. Botet Escriba
566199e49b Added this_executor and default_executor examples. 2015-03-01 18:37:16 +01:00
Vicente J. Botet Escriba
c7bb6fa318 Allow timed and recursive mutex on ANDROID. Related to #11035. 2015-03-01 01:37:45 +01:00
Vicente J. Botet Escriba
c678b3794b Crash issue while calling run_thread_exit_callbacks. Related to #11053. 2015-03-01 01:37:35 +01:00
Vicente J. Botet Escriba
e0ce8af1d9 cleanup work.hpp 2015-02-28 12:39:03 +01:00
Vicente J. Botet Escriba
c54dbe30a2 move the work parameter. 2015-02-28 12:37:27 +01:00
Vicente J. Botet Escriba
b8763b05ad Add missing push(movable&&) and Run some failing tests that work when BOOST_NO_CXX11_RVALUE_REFERENCES is not defined. 2015-02-28 12:35:42 +01:00
Vicente J. Botet Escriba
3755af2063 Run some failing tests that work when BOOST_NO_CXX11_RVALUE_REFERENCES is not defined. 2015-02-28 12:35:23 +01:00
Vicente J. Botet Escriba
41172e4814 fix missing include in caller_context.hpp and let the possibility to dump function at compile time. 2015-02-28 12:33:46 +01:00
Vicente J. Botet Escriba
25310eaf7c make use of nullary_function<void()> as work for timed schedulers (priority_queue) on C++11. 2015-02-22 23:44:34 +01:00
Vicente J. Botet Escriba
55f9563f60 Merge branch 'fix/blocking_future' into develop 2015-02-20 16:36:18 +01:00
Vicente J. Botet Escriba
ec770eeb6a fix forwarding reference_wrapper in make_ready_future. 2015-02-20 16:34:56 +01:00
Vicente J. Botet Escriba
b9ab307912 rollback nullary_function<void()const> specialization. 2015-02-20 16:33:53 +01:00
Vicente J. Botet Escriba
83ced837fa rollback nullary_function specialization as is the cause of compile failures. 2015-02-20 15:33:26 +01:00
Vicente J. Botet Escriba
ce2b2801d6 Merge branch 'fix/blocking_future' into develop 2015-02-20 14:37:10 +01:00
Vicente J. Botet Escriba
1ae96b3820 Merge branch 'develop' into fix/blocking_future 2015-02-20 14:34:55 +01:00
Vicente J. Botet Escriba
889c178173 fix issues with fallback_to. The route cause was that the original future was locked after destruction. This was more evident when the future was already ready when future::then was called. 2015-02-20 14:34:33 +01:00
Vicente J. Botet Escriba
7ba9591015 first trial towards a work=nullary_function<void() const>. 2015-02-20 10:20:38 +01:00
Vicente J. Botet Escriba
b07f18facf remove include/boost/thread/detail/work.hpp. 2015-02-20 10:18:35 +01:00
Vicente J. Botet Escriba
7b1b1b5daa fix include guard on serial_executor_cont.hpp. 2015-02-19 18:00:29 +01:00
Vicente J. Botet Escriba
63fb28c7d4 Merge branch 'develop' into fix/blocking_future 2015-02-19 10:36:20 +01:00
Vicente J. Botet Escriba
67e18ff039 Merge branch 'feature/serial_executor_continuation' into develop 2015-02-19 10:31:39 +01:00
Vicente J. Botet Escriba
e715d74a95 use a different name for serial_executor continuation as it add more constraints. 2015-02-19 10:30:25 +01:00
Vicente J. Botet Escriba
393d214ac9 Merge branch 'develop' into feature/serial_executor_continuation 2015-02-19 10:16:27 +01:00
Vicente J. Botet Escriba
855e56076b Merge branch 'develop' 2015-02-19 08:59:18 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
0fa6038f6a Revert "Make mandatory that the Win32 API version configured is at least Windows XP or higher."
This reverts commit e0217424f3.
2015-02-18 23:40:46 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
cf1182ee99 Disable physical_concurrency() on Mingw32 alone. 2015-02-18 15:19:48 +00:00
Vicente J. Botet Escriba
a04497af24 make thread-safe serial_executor. There are yet somme synchronization limitations. 2015-02-18 10:45:10 +01:00
Vicente J. Botet Escriba
821a93ca1a first draft for serial_executor based on continuations. 2015-02-17 19:09:56 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
e0217424f3 Make mandatory that the Win32 API version configured is at least Windows XP or higher. 2015-02-17 14:42:39 +00:00
Vicente J. Botet Escriba
cf76bc666c Merge branch 'develop' into fix/blocking_future 2015-02-17 11:44:04 +01:00
Vicente J. Botet Escriba
d00e39acc7 Add traces to sporious fali on fallback_to. 2015-02-17 11:41:21 +01:00
Vicente J. Botet Escriba
90ba3ae7c6 Merge pull request #48 from wmamrak/develop
Fixed documentation bugs.
2015-02-17 11:25:58 +01:00
Vicente J. Botet Escriba
b68702b56d Merge branch 'develop' into fix/blocking_future 2015-02-17 01:50:11 +01:00
Wojciech Mamrak
3b2322db96 Fixed documentation bugs. 2015-02-17 00:52:39 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
6a427ac4b6 Fix physical_concurrency() on win32. 2015-02-16 18:03:46 +00:00
Vicente J. Botet Escriba
ffd856073f Merge branch 'develop' of github.com:boostorg/thread into develop 2015-02-16 14:28:00 +01:00
Vicente J. Botet Escriba
f1fafb117a fix typo. 2015-02-16 14:27:37 +01:00
Vicente J. Botet Escriba
e2cda49b0b cleanup. unlock before submiting to an executor as it can directly call the continuation. 2015-02-16 14:17:57 +01:00
Vicente J. Botet Escriba
d1aa2eec56 Merge pull request #47 from wmamrak/develop
Removed redundant move ctor and ass. operator of Thread class synopsis.
2015-02-15 23:56:24 +01:00
Wojciech Mamrak
1db0ba4639 Removed redundant move ctor and ass. operator of Thread class synopsis. 2015-02-15 20:49:07 +01:00
Vicente J. Botet Escriba
a4e7eba1d4 cleanup. 2015-02-11 07:05:10 +01:00
Vicente J. Botet Escriba
67778b3278 fix shared_future::then, get and get_or. 2015-02-10 00:01:28 +01:00
Vicente J. Botet Escriba
a5e6952a95 merge from develop - coamesced timers. 2015-02-09 13:08:55 +01:00
Vicente J. Botet Escriba
3c6a183aa3 Merge branch 'develop' 2015-02-08 18:19:07 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
9cc1357c95 Revert "Try to include some STL headers which Android libc++ claims have not been included."
This reverts commit b571686e5d.
2015-02-06 12:21:55 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
b571686e5d Try to include some STL headers which Android libc++ claims have not been included. 2015-02-06 12:09:52 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
9c67be287e Fix warning on mingw about casting a function pointer through a void *.
Fix warning on MSVC about GetModuleHandle potentially failing.
2015-02-06 12:04:22 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
f599783444 Fixed the MSVC10 breakage caused by coalesced timers support. 2015-02-06 11:51:37 +00:00
Vicente J. Botet Escriba
d628b8d36c Merge branch 'develop' of github.com:boostorg/thread into develop 2015-02-05 08:30:39 +01:00
Vicente J. Botet Escriba
65c519c22c Merge branch 'master' into develop 2015-02-04 22:35:29 +01:00
Vicente J. Botet Escriba
05e492c56c Merge branch 'master' of github.com:boostorg/thread 2015-02-04 22:33:22 +01:00
Vicente J. Botet Escriba
3c2321c37a Merge pull request #45 from Matulis/master
Updated namespace to call no_interruption_point sleep_for
2015-02-04 22:31:11 +01:00
Martin Matulyauskas
6c72a2527f Updated namespace to call no_interruption_point sleep_for 2015-02-04 15:00:51 -06:00
Niall Douglas
1bd09085db Merge pull request #44 from boostorg/win32_coalesced_timers_support
Win32 coalesced timers support
2015-02-04 18:14:40 +00:00
Vicente J. Botet Escriba
d6c3f15947 Merge branch 'develop' 2015-02-04 18:47:40 +01:00
Vicente J. Botet Escriba
5960985355 merge from develop: Reverted parts of c16ec42 because 45510fa was a better fix.: 2015-02-04 18:46:29 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
84e2b7869d Merge branch 'develop' of github.com:boostorg/thread into develop 2015-02-04 13:58:30 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
401f69f108 Added coalesced timer support to Windows where that API is available. Tolerable delay is set to the maximum of 5% of interval or 32 ms. 2015-02-04 13:58:11 +00:00
Vicente J. Botet Escriba
4f57e3fb61 Merge pull request #43 from vtnerd/RevertMakeReady
Reverted parts of c16ec42 because 45510fa was a better fix.
2015-02-03 08:34:53 +01:00
Vicente J. Botet Escriba
fdf20f1adc merge Allow to call shared_future::then multiple times. Related to #10972. 2015-02-02 19:40:04 +01:00
Lee Clagett
990474ff47 Reverted parts of c16ec42 because 45510fa was a better fix. 2015-02-02 12:08:38 -05:00
Vicente J. Botet Escriba
786d842ad1 update history. 2015-02-02 17:45:57 +01:00
Vicente J. Botet Escriba
441c89d304 Allow to call shared_future::then multiple times. Related to #10972. 2015-02-02 17:41:57 +01:00
Vicente J. Botet Escriba
63098e84a2 Merge branch 'develop' into fix/blocking_future 2015-02-01 19:39:43 +01:00
Vicente J. Botet Escriba
71997bd9aa Merge branch 'develop' 2015-02-01 19:38:50 +01:00
Vicente J. Botet Escriba
45510facc7 unwrapped future must forward the continuation to the wrapped future. Related to #10964. 2015-02-01 14:56:52 +01:00
Vicente J. Botet Escriba
cf539064d6 Deduce T& when the make_ready_future parameter is reference_wrapper<T>. Relates to #10979. 2015-02-01 13:44:41 +01:00
Vicente J. Botet Escriba
3431736c88 Merge branch 'develop' into fix/blocking_future 2015-01-27 22:22:37 +01:00
Vicente J. Botet Escriba
095b53b2a2 Update changes. 2015-01-27 07:14:17 +01:00
Vicente J. Botet Escriba
7a63c40a01 Merge pull request #39 from jhunold/shadow
Fix gcc/clang shadow warnings.
2015-01-26 19:48:53 +01:00
Jürgen Hunold
c1148a66cc Fix gcc/clang shadow warnings.
The variable names are re-used in the all_futures_lock() functions.
2015-01-26 12:39:27 +01:00
Vicente J. Botet Escriba
5fa0a5d4c5 make shared_future::get() const. Related to #10971. 2015-01-26 08:39:30 +01:00
Vicente J. Botet Escriba
75a8280701 Merge branch 'develop' 2015-01-25 16:00:08 +01:00
Vicente J. Botet Escriba
2891aff469 Add missing file . 2015-01-24 18:43:56 +01:00
Vicente J. Botet Escriba
e74fd82060 Merge from develop. 2015-01-24 18:02:31 +01:00
Vicente J. Botet Escriba
c16ec42941 Take care of #10964. 2015-01-24 16:48:44 +01:00
Vicente J. Botet Escriba
b77eac3e37 Take care of #10963. 2015-01-24 11:57:54 +01:00
Vicente J. Botet Escriba
5a141ccf99 Merge branch 'develop' 2015-01-24 09:07:25 +01:00
Vicente J. Botet Escriba
35d7ae0d2e add forgotten wait when shared_future::then deferred. 2015-01-23 08:36:46 +01:00
Vicente J. Botet Escriba
d9c7f95617 fix future async deferred. 2015-01-23 07:10:22 +01:00
Vicente J. Botet Escriba
06b3f6a9d7 disable async deferred on C++98 as not implemented. 2015-01-23 06:02:11 +01:00
Vicente J. Botet Escriba
895b4a0ac5 Try to fix a lot of issues, even if alldoesn't works yet. 2015-01-22 23:10:40 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
eb14d3d958 Added a test for defect #9856 where wait_for() is not always returning timedout on Windows. 2015-01-22 17:20:46 +00:00
Vicente J. Botet Escriba
9cb72849ee Go towards blocking on the last future associated to an async shared state. shared_future don't work yet. 2015-01-18 12:19:17 +01:00
Vicente J. Botet Escriba
2c028aa014 fix more erros after Boost.Test commit. 2015-01-12 00:36:55 +01:00
Vicente J. Botet Escriba
ab026e239c Fix erros after Boost.Test adding dependency to Boost.Timer. 2015-01-11 18:21:22 +01:00
Vicente J. Botet Escriba
3a48148462 Fix Boost.Test issues after meger :(. 2015-01-11 17:30:54 +01:00
Vicente J. Botet Escriba
9b9590730f Merge branch 'master' of github.com:boostorg/thread 2015-01-11 17:00:10 +01:00
Vicente J. Botet Escriba
8edc37930b Merge pull request #38 from raffienficiaud/master
Some fixes of boost.test init and link fix
2015-01-11 16:58:14 +01:00
Raffi Enficiaud
ef48908f35 Merge branch 'master' of https://github.com/boostorg/thread
# By Vicente J. Botet Escriba (274) and others
# Via Vicente J. Botet Escriba (42) and others
* 'master' of https://github.com/boostorg/thread: (318 commits)
  Added missing include.
  cleanup future.hpp.
  Updated CI dashboard with latest tests.
  Looks like timeconv.inl may be completely unnecessary, so remove.
  Could find no code anywhere in Boost which uses to_time(), to_timespec_duration(), to_duration() nor to_microduration(), so removed the code.
  Fixed MSVC static analyser warning about writing off the end of an array.
  Stop LNK4221 link warning with link=static.
  Suppressed some unimportant warnings so the CI doesn't flag them.
  Added static analysers to CI dashboard.
  Added winphone8 build test.
  Fix failure to build on Android.
  redo
  Added overall build and test status
  Added test matrix to Readme.md so a summary appears on github
  fix some typos.
  ensure that the exceptions throw by a task submitted by a serial executor are transfered to it, and so the serial_executor doesn't block forever.
  No comment after preprocessor continuation for msvc-12.0
  Added  ! defined __clang__ when tested defined __GNUC__.
  Added BOOST_THREAD_PROVIDES_INVOKE constraing for invoker.
  thread: physical_concurrency - return 0 instead of hardware_concurrency on failure
  ...

Conflicts:
	test/test_2741.cpp
2015-01-11 16:22:32 +01:00
Raffi Enficiaud
28ead512c1 some reworked test init + boost.test link fix 2015-01-11 16:21:32 +01:00
Vicente J. Botet Escriba
6b60943f3e Added csbl/queue.hpp and concurrent_queues/detail/sync_deque_base.hpp dradt. 2015-01-10 16:09:15 +01:00
Vicente J. Botet Escriba
1fcaa47efa extract future_error,future_status and launch. 2015-01-10 09:02:37 +01:00
Vicente J. Botet Escriba
aac441392a extract wait_for_any for sequences. 2015-01-09 08:09:34 +01:00
Vicente J. Botet Escriba
6a34fc9c33 moved future_error_code.hpp file. 2015-01-09 08:08:03 +01:00
Vicente J. Botet Escriba
69d01b9bfd extract wait_for_all into futures/wait_for_all.hpp. 2015-01-07 07:13:48 +01:00
Vicente J. Botet Escriba
7b91ce7b64 move future_error_code.hpp to futures. 2015-01-07 06:42:27 +01:00
Vicente J. Botet Escriba
978884ff0d extracted futures/is_future_type.hpp. 2015-01-07 06:22:20 +01:00
Vicente J. Botet Escriba
ac8ca6eb04 Added notify_when_ready/unnotify_when_ready. 2015-01-07 04:53:50 +01:00
Vicente J. Botet Escriba
1c16c52fe6 Added missing include. 2015-01-04 17:41:52 +01:00
Vicente J. Botet Escriba
9299d26acf cleanup future.hpp. 2014-12-30 11:47:15 +01:00
Niall Douglas
5577128bd8 Merge pull request #37 from ned14/develop
Remove timeconv.inl files as apparently no longer used.
2014-12-14 20:31:21 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
e62c576944 Updated CI dashboard with latest tests. 2014-12-14 19:20:11 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
ce8049f83f Looks like timeconv.inl may be completely unnecessary, so remove. 2014-12-14 02:01:13 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
035217985c Could find no code anywhere in Boost which uses to_time(), to_timespec_duration(), to_duration() nor to_microduration(), so removed the code. 2014-12-14 01:38:50 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
dfe95b3f2c Fixed MSVC static analyser warning about writing off the end of an array. 2014-12-14 01:15:49 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
e98447f974 Stop LNK4221 link warning with link=static. 2014-12-14 00:52:17 +00:00
Vicente J. Botet Escriba
deffa9aaf7 Merge pull request #36 from ned14/develop
Add static analysers to CI dashboard, and suppress unimportant warnings
2014-12-11 23:10:51 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
b87d26a900 Suppressed some unimportant warnings so the CI doesn't flag them. 2014-12-11 19:15:38 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
6c9115fe39 Added static analysers to CI dashboard. 2014-12-11 15:48:37 +00:00
Vicente J. Botet Escriba
b5b25eab1c Merge pull request #35 from ned14/develop
Added test matrix to Readme.md so a summary appears on github
2014-12-10 19:38:01 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
803ba458ce Added winphone8 build test. 2014-12-10 17:26:50 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
c0470893d4 Fix failure to build on Android. 2014-12-10 14:36:29 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
b2c445a030 redo 2014-12-10 14:32:46 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
6e37c55221 Added overall build and test status 2014-12-10 14:31:10 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
e1039e61f3 Added test matrix to Readme.md so a summary appears on github 2014-12-10 14:20:55 +00:00
Vicente J. Botet Escriba
063b59e511 fix some typos. 2014-12-07 19:03:59 +01:00
Vicente J. Botet Escriba
a342d1ccee Merge pull request #33 from jhunold/fix_comment
No comment after preprocessor continuation for msvc-12.0
2014-12-06 10:50:55 +01:00
Vicente J. Botet Escriba
811f3df98d ensure that the exceptions throw by a task submitted by a serial executor are transfered to it, and so the serial_executor doesn't block forever. 2014-12-06 10:47:43 +01:00
Jürgen Hunold
8e1be55c6d No comment after preprocessor continuation for msvc-12.0 2014-12-05 22:11:35 +01:00
Vicente J. Botet Escriba
421469686d Added ! defined __clang__ when tested defined __GNUC__. 2014-12-03 22:40:34 +01:00
Vicente J. Botet Escriba
72dfa02269 Added BOOST_THREAD_PROVIDES_INVOKE constraing for invoker. 2014-12-03 22:37:42 +01:00
Vicente J. Botet Escriba
4c48b2276c Merge pull request #32 from timblechmann/topic/physical_concurrency_fix
Topic/physical concurrency fix
2014-11-29 14:25:48 +01:00
Tim Blechmann
8c7275cb9e thread: physical_concurrency - return 0 instead of hardware_concurrency on failure 2014-11-29 11:44:04 +01:00
Tim Blechmann
14c5cff2ee thread: physical_concurrency - windows xp does not provide GetLogicalProcessorInformation 2014-11-29 11:43:36 +01:00
Vicente J. Botet Escriba
83f38ea52c fix detail::priority_queue_top. 2014-11-23 16:47:33 +01:00
Vicente J. Botet Escriba
06a9f9ab6d Added Clock parameter to scheduler and priority_timed_queue. Fix warnings in tests. 2014-11-17 07:34:43 +01:00
Vicente J. Botet Escriba
e7f140cab6 replace >> by > >. 2014-11-14 20:14:03 +01:00
Vicente J. Botet Escriba
1b99fe5587 Replace range-based for loops to make the code more portable. 2014-11-14 08:45:16 +01:00
Vicente J. Botet Escriba
b9a70f7aca don't use std::vector with msvc.a 2014-11-14 00:25:51 +01:00
Vicente J. Botet Escriba
ca87cbf57b workaround bug on Boost.Config that left the section private after using the macro BOOST_DELETED_FUNCTION. 2014-11-11 22:32:25 +01:00
Vicente J. Botet Escriba
929dc55a5a Add default Container parameter to sync_queue/sync_deque as csbl::devector. 2014-11-10 00:40:02 +01:00
Vicente J. Botet Escriba
b29d9f850c Added devector, a minimal vector providing pop_front that can be used as Container of the sync queues. 2014-11-09 20:32:58 +01:00
Vicente J. Botet Escriba
1c81d8a4b1 remove BOOST_NO_CXX11_HDR_DEQUE as it doesn't exists art all :(. 2014-11-09 17:12:54 +01:00
Vicente J. Botet Escriba
7de29f4d45 fix typo in sync_priority_queue.hpp. 2014-11-09 17:12:03 +01:00
Vicente J. Botet Escriba
9b0705cb6f Added deque_views. Make use of sync_queue and refactor to use sync_queue removing _front and _back. 2014-11-09 15:39:10 +01:00
Vicente J. Botet Escriba
3abdb869df Reduce the interface of sync_quue to the queue operations, removing the deprecated ones and removing _front and _back. 2014-11-09 14:12:28 +01:00
Vicente J. Botet Escriba
f90e76a59c Added sync_deque. 2014-11-09 13:45:05 +01:00
Vicente J. Botet Escriba
d4c8185cc9 Added priority_executor_base and refactor scheduled_executor_base. 2014-11-09 12:20:15 +01:00
Vicente J. Botet Escriba
e6501b5485 cleanup scheduled executors. 2014-11-09 11:37:18 +01:00
Vicente J. Botet Escriba
1ae3cb65f7 Make task_region more portable using Boost.Config helper macros. 2014-11-08 23:22:37 +01:00
120 changed files with 6540 additions and 3195 deletions

133
README.md
View File

@@ -6,3 +6,136 @@ Portable C++ multi-threading. C++11, C++14.
### License
Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).
### Current Jenkins CI Test Status for unstable (develop) branch
Overall build (nightly): <a href='https://ci.nedprod.com/view/All/job/Boost.Thread%20Build/'><img src='https://ci.nedprod.com/buildStatus/icon?job=Boost.Thread%20Build'></a> Overall tests (weekly, on Sundays): <a href='https://ci.nedprod.com/view/All/job/Boost.Thread%20Test/'><img src='https://ci.nedprod.com/buildStatus/icon?job=Boost.Thread%20Test'></a>
#### Build (nightly):
<table id="configuration-matrix" width="100%" border="1">
<tr>
<td class="matrix-leftcolumn" rowspan="6" valign="top">android-ndk</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="6" valign="top">winphone8</td>
</tr>
<tr>
<td/>
</tr>
<tr>
<td/>
</tr>
<tr>
<td/>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=static,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=static,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=static,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=shared,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=shared,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=shared,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="6" valign="top">arm-gcc-clang</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="6" valign="top">freebsd10-clang3.3</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=static,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=shared,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=static,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=shared,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
</tr>
<tr>
<td/>
</tr>
<tr>
<td/>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="6" valign="top">linux-gcc-clang</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.7,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.2,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.4,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.7,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.2,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.4,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.7,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.2,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.4,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.7,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.2,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.4,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
</tr>
<tr>
<td/>
</tr>
<tr>
<td/>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="6" valign="top">linux64-gcc-clang</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-analyse,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Unstable" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/yellow.png" tooltip="Unstable"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-analyse,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Unstable" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/yellow.png" tooltip="Unstable"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-analyse,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-analyse,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-analyse,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-analyse,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="6" valign="top">win8-msvc-mingw</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw32,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw64,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw32,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw64,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw32,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw64,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw32,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw64,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-10.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-10.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
</tr>
<tr>
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-analyse,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-10.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-10.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
</tr>
</table>

View File

@@ -63,6 +63,7 @@ project boost/thread
<toolset>gcc:<cxxflags>-Wno-variadic-macros
#<toolset>gcc:<cxxflags>-Wunused-local-typedefs
<toolset>gcc:<cxxflags>-Wunused-function
<toolset>gcc:<cxxflags>-Wno-unused-parameter
<toolset>darwin:<cxxflags>-Wextra
<toolset>darwin:<cxxflags>-pedantic
@@ -72,18 +73,20 @@ project boost/thread
<toolset>darwin:<cxxflags>-Wno-variadic-macros
#<toolset>darwin:<cxxflags>-Wunused-local-typedefs
<toolset>darwin:<cxxflags>-Wunused-function
<toolset>darwin:<cxxflags>-Wno-unused-parameter
#<toolset>pathscale:<cxxflags>-Wextra
<toolset>pathscale:<cxxflags>-Wno-long-long
<toolset>pathscale:<cxxflags>-pedantic
<toolset>clang:<warnings>on
<toolset>clang:<cxxflags>-Wextra
#<toolset>clang:<cxxflags>-ansi
#<toolset>clang:<cxxflags>-fpermissive
<toolset>clang:<cxxflags>-Wno-long-long
<toolset>clang:<cxxflags>-Wunused-function
<toolset>clang:<cxxflags>-Wno-variadic-macros
<toolset>clang:<warnings>on
<toolset>clang:<cxxflags>-Wno-unused-parameter
#<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
#<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
@@ -116,7 +119,9 @@ project boost/thread
<toolset>intel:<cxxflags>-wd1418
<toolset>intel:<cxxflags>-wd2415
<toolset>msvc:<cxxflags>/wd4100
<toolset>msvc:<cxxflags>/wd4512
<toolset>msvc:<cxxflags>/wd6246
# : default-build <threading>multi

View File

@@ -142,6 +142,7 @@ The third one is related to performance. They assert that "any mechanism for sto
In addition `std::function<void()>` can not be constructed by moving the closure, so e.g. `std::packaged_task` could not be a Closure.
[/
[heading Scheduled work]
The approach of this library respect to scheduled work of the N3785 proposal is quite different. Instead of adding the scheduled operations to a specific scheduled_executor polymorphic interface, we opt by adding two member template functions to a class scheduled_executor that wraps an existing executor. This has several advantages:
@@ -155,6 +156,25 @@ In order to manage with all the clocks, there are two alternatives:
* have a single instance of a `scheduled_executor<Clock>` for each `CLock`.
The library chose the first of those options, largely for simplicity.
]
[heading Scheduled work]
The approach of this library respect to scheduled work of the N3785 proposal is quite different. Instead of adding the scheduled operations to a specific scheduled_executor polymorphic interface, we opt by adding a specific `scheduler` class that is not an executor and knows how to manage with the scheduling of timed tasks `submit_at`/`submit_after`.
`scheduler` provides executor factories `at`/`after` given a specific `time_point` or a `duration`. The built executors wrap a reference to this scheduler and the time at which the submitted task will be executed.
If we want to schedule these operations on an existing executor (as `serial_executor` does), these classes provide a `on` factory taking another executor as parameter and wraps both instance on the returned executor.
sch.on(tp).after(seconds(i)).submit(boost::bind(fn,i));
This has several advantages:
* The scheduled operations are available for all the executors via wrappers.
* The template functions could accept any chrono `time_point` and `duration` respectively as we are not working with virtual functions.
In order to manage with all the clocks, this library propose generic solution. `scheduler<Clock>` know how to manage with the `submit_at`/`submit_after` `Clock::time_point`/`Clock::duration` tasks. Note that the durations on different clocks differ.
[heading Not Handled Exceptions]
As in N3785 and based on the same design decision than `std`/`boost::thread` if a user closure throws an exception, the executor must call the `std::terminate` function.
@@ -299,33 +319,23 @@ The reason is that the user can always use a thread_local variable and reset it
}
);
[
[heading Default executor]
The library authors share some of the concerns of the C++ standard committee (introduction of a new single shared resource, a singleton, could make it difficult to make it portable to all the environments) and that this library doesn't need to provide a default executor for the time been.
The user can always define his default executor himself and use the `at_thread_entry ` member function to set the default constructor.
The user can always define his default executor himself.
thread_local default_executor_state_type default_executor_state;
executor* default_executor() { return default_executor_state.default_executor(); }
// in main
MyDefaultExecutor myDefaultExecutor(
// at_thread_entry
[](MyDefaultExecutor& ex) {
default_executor_state.set_default_executor(ex);
}
);
basic_thread_pool pool(
// at_thread_entry
[&myDefaultExecutor](basic_thread_pool& pool) {
default_executor_state.set_default_executor(myDefaultExecutor);
}
);
boost::generic_executor_ref default_executor()
{
static boost::basic_thread_pool tp(4);
return generic_executor_ref(tp);
}
[endsect]
[/////////////////////]
[section:ref Reference]
@@ -401,7 +411,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
[variablelist
[[Effects:] [close the executor `e` for submissions.]]
[[Effects:] [close the scheduler/executor `e` for submissions.]]
[[Remark:] [The worker threads will work until there is no more closures to run.]]
@@ -421,7 +431,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
[[Return type:] [`bool`.]]
[[Return:] [whether the pool is closed for submissions.]]
[[Return:] [whether the scheduler/executor is closed for submissions.]]
[[Throws:] [Whatever exception that can be throw while ensuring the thread safety.]]
@@ -659,8 +669,532 @@ Executor abstract base class.
[endsect]
[//////////////////////////////////////////////////////////]
[section: scheduler Template Class `scheduler `]
Scheduler providing time related functions. Note that `scheduler` is not an Executor.
#include <boost/thread/executors/scheduler.hpp>
namespace boost {
template <class Clock=steady_clock>
class scheduler
{
public:
using work = boost::function<void()> ;
using clock = Clock;
scheduler(scheduler const&) = delete;
scheduler& operator=(scheduler const&) = delete;
scheduler();
~scheduler();
void close();
bool closed();
template <class Duration, typename Closure>
void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
template <class Rep, class Period, typename Closure>
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
template <class Duration>
at_executor<scheduler> submit_at(chrono::time_point<clock,Duration> abs_time);
template <class Rep, class Period>
at_executor<scheduler> submit_after(chrono::duration<Rep,Period> rel_time);
template <class Executor>
scheduler_executor_wrapper<scheduler, Executor> on(Executor& ex);
};
}
[/////////////////////////////////////]
[section:constructor Constructor `scheduler()`]
scheduler();
[variablelist
[[Effects:] [Constructs a `scheduler`. ]]
[[Throws:] [Nothing. ]]
]
[endsect]
[/////////////////////////////////////]
[section:destructor Destructor `~scheduler()`]
~scheduler();
[variablelist
[[Effects:] [Destroys the scheduler.]]
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_at Template Function Member `submit_at()`]
template <class Clock, class Duration, typename Closure>
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
[variablelist
[[Effects:] [Schedule a `closure` to be executed at `abs_time`. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_after Template Function Member `submit_after()`]
template <class Rep, class Period, typename Closure>
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
[variablelist
[[Effects:] [Schedule a `closure` to be executed after `rel_time`. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]
[//////////////////////////////////////////////////////////]
[section:at_executor Template Class `at_executor`]
#include <boost/thread/executors/scheduler.hpp>
namespace boost {
template <class Scheduler>
class at_executor
{
public:
using work = Scheduler::work;
using clock = Scheduler::clock;
at_executor(at_executor const&) = default;
at_executor(at_executor &&) = default;
at_executor& operator=(at_executor const&) = default;
at_executor& operator=(at_executor &&) = default;
at_executor(Scheduler& sch, clock::time_point const& tp);
~at_executor();
void close();
bool closed();
Scheduler& underlying_scheduler();
template <class Closure>
void submit(Closure&& closure);
template <class Duration, typename Work>
void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
template <class Rep, class Period, typename Work>
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
template <class Executor>
resubmit_at_executor<Scheduler, Executor> on(Executor& ex);
};
}
[/////////////////////////////////////]
[section:constructor Constructor `at_executor(Scheduler&)`]
at_executor(Scheduler& sch, clock::time_point const& tp);
[variablelist
[[Effects:] [Constructs a `at_executor`. ]]
[[Throws:] [Nothing. ]]
]
[endsect]
[/////////////////////////////////////]
[section:destructor Destructor `~at_executor()`]
~at_executor();
[variablelist
[[Effects:] [Destroys the `at_executor`.]]
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
]
[endsect]
[/////////////////////////////////////]
[section:underlying_scheduler Function member `underlying_scheduler()`]
Scheduler& underlying_scheduler() noexcept;
[variablelist
[[Return:] [The underlying scheduler instance. ]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_at Template Function Member `submit()`]
template <typename Closure>
void submit(Closure&& closure);
[variablelist
[[Effects:] [Schedule the `closure` to be executed at the `abs_time` given at construction time. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_at Template Function Member `submit_at()`]
template <class Clock, class Duration, typename Closure>
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
[variablelist
[[Effects:] [Schedule a `closure` to be executed at `abs_time`. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_after Template Function Member `submit_after()`]
template <class Rep, class Period, typename Closure>
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
[variablelist
[[Effects:] [Schedule a `closure` to be executed after `rel_time`. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]
[//////////////////////////////////////////////////////////]
[section:scheduler_executor_wrapper Template Class `scheduler_executor_wrapper`]
#include <boost/thread/executors/scheduler.hpp>
namespace boost {
template <class Scheduler, class Executor>
class scheduler_executor_wrapper
{
public:
using work = Scheduler::work;
using clock = Scheduler::clock;
scheduler_executor_wrapper(scheduler_executor_wrapper const&) = default;
scheduler_executor_wrapper(scheduler_executor_wrapper &&) = default;
scheduler_executor_wrapper& operator=(scheduler_executor_wrapper const&) = default;
scheduler_executor_wrapper& operator=(scheduler_executor_wrapper &&) = default;
scheduler_executor_wrapper(Scheduler& sch, Executor& ex);
~scheduler_executor_wrapper();
void close();
bool closed();
Executor& underlying_executor();
Scheduler& underlying_scheduler();
template <class Closure>
void submit(Closure&& closure);
template <class Duration, typename Work>
void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
template <class Rep, class Period, typename Work>
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
template <class Duration>
resubmit_at_executor<Scheduler, Executor> at(chrono::time_point<clock,Duration> abs_time);
template <class Rep, class Period>
resubmit_at_executor<Scheduler, Executor> after(chrono::duration<Rep,Period> rel_time);
};
}
[/////////////////////////////////////]
[section:constructor Constructor `scheduler_executor_wrapper(Scheduler&, Executor&)`]
scheduler_executor_wrapper(Scheduler& sch, Executor& ex);
[variablelist
[[Effects:] [Constructs a `scheduler_executor_wrapper`. ]]
[[Throws:] [Nothing. ]]
]
[endsect]
[/////////////////////////////////////]
[section:destructor Destructor `~scheduler_executor_wrapper()`]
~scheduler_executor_wrapper();
[variablelist
[[Effects:] [Destroys the `scheduler_executor_wrapper`.]]
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
]
[endsect]
[/////////////////////////////////////]
[section:underlying_scheduler Function member `underlying_scheduler()`]
Scheduler& underlying_scheduler() noexcept;
[variablelist
[[Return:] [The underlying scheduler instance. ]]
]
[endsect]
[/////////////////////////////////////]
[section:underlying_executor Function member `underlying_executor()`]
Executor& underlying_executor() noexcept;
[variablelist
[[Return:] [The underlying executor instance. ]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_at Template Function Member `submit()`]
template <typename Closure>
void submit(Closure&& closure);
[variablelist
[[Effects:] [Submit the `closure` on the underlying executor. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_at Template Function Member `submit_at()`]
template <class Clock, class Duration, typename Closure>
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
[variablelist
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor at `abs_time`. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_after Template Function Member `submit_after()`]
template <class Rep, class Period, typename Closure>
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
[variablelist
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor after `rel_time`. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]
[//////////////////////////////////////////////////////////]
[section:resubmit_at_executor Template Class `resubmit_at_executor`]
`Executor` wrapping an `Scheduler`, an `Executor` and a `time_point` providing an `Executor` interface.
#include <boost/thread/executors/scheduler.hpp>
namespace boost {
template <class Scheduler, class Executor>
class resubmit_at_executor
{
public:
using work = Scheduler::work;
using clock = Scheduler::clock;
resubmit_at_executor(resubmit_at_executor const&) = default;
resubmit_at_executor(resubmit_at_executor &&) = default;
resubmit_at_executor& operator=(resubmit_at_executor const&) = default;
resubmit_at_executor& operator=(resubmit_at_executor &&) = default;
template <class Duration>
resubmit_at_executor(Scheduler& sch, Executor& ex, clock::time_point<Duration> const& tp);
~resubmit_at_executor();
void close();
bool closed();
Executor& underlying_executor();
Scheduler& underlying_scheduler();
template <class Closure>
void submit(Closure&& closure);
template <class Duration, typename Work>
void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
template <class Rep, class Period, typename Work>
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
};
}
[/////////////////////////////////////]
[section:constructor Constructor `resubmit_at_executor(Scheduler&, Executor&, clock::time_point<Duration>)`]
template <class Duration>
resubmit_at_executor(Scheduler& sch, Executor& ex, clock::time_point<Duration> const& tp);
[variablelist
[[Effects:] [Constructs a `resubmit_at_executor`. ]]
[[Throws:] [Nothing. ]]
]
[endsect]
[/////////////////////////////////////]
[section:destructor Destructor `~resubmit_at_executor()`]
~resubmit_at_executor();
[variablelist
[[Effects:] [Destroys the executor_adaptor.]]
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
]
[endsect]
[/////////////////////////////////////]
[section:underlying_executor Function member `underlying_executor()`]
Executor& underlying_executor() noexcept;
[variablelist
[[Return:] [The underlying executor instance. ]]
]
[endsect]
[/////////////////////////////////////]
[section:underlying_scheduler Function member `underlying_scheduler()`]
Scheduler& underlying_scheduler() noexcept;
[variablelist
[[Return:] [The underlying scheduler instance. ]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_at Template Function Member `submit()`]
template <typename Closure>
void submit(Closure&& closure);
[variablelist
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor at the `abs_time` given at construction time. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_at Template Function Member `submit_at()`]
template <class Clock, class Duration, typename Closure>
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
[variablelist
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor at `abs_time`. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_after Template Function Member `submit_after()`]
template <class Rep, class Period, typename Closure>
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
[variablelist
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor after `rel_time`. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]
[//////////////////////////////////////////////////////////]
[/
[section:scheduled_executor_ref Template Class `scheduled_executor_ref`]
Executor providing time related functions.
@@ -694,10 +1228,6 @@ Executor providing time related functions.
template <typename Pred>
bool reschedule_until(Pred const& pred);
template <class Clock, class Duration>
void submit_at(chrono::time_point<Clock,Duration> abs_time, work&& closure);
template <class Rep, class Period>
void submit_after(chrono::duration<Rep,Period> rel_time, work&& closure);
template <class Clock, class Duration, typename Closure>
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
template <class Rep, class Period, typename Closure>
@@ -746,20 +1276,31 @@ Executor providing time related functions.
]
[endsect]
[/////////////////////////////////////]
[section:submit_at Template Function Member `submit()`]
template <typename Closure>
void submit(Closure&& closure);
[variablelist
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[/////////////////////////////////////]
[section:submit_at Template Function Member `submit_at()`]
template <class Clock, class Duration, typename Closure>
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
template <class Rep, class Period, typename Closure>
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
[variablelist
[[Effects:] [The underlying executor instance. ]]
[[Effects:] [Schedule a `closure` to be executed at `abs_time`. ]]
[[Throws:] [Nothing.]]
@@ -767,11 +1308,26 @@ Executor providing time related functions.
[endsect]
[/////////////////////////////////////]
[section:submit_after Template Function Member `submit_after()`]
template <class Rep, class Period, typename Closure>
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
[variablelist
[[Effects:] [Schedule a `closure` to be executed after `rel_time`. ]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]
]
[//////////////////////////////////////////////////////////]
[section:serial_executor Template Class `serial_executor`]

View File

@@ -12,35 +12,56 @@
[*Know Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/2442 #2442] Application statically linked with Boost.Thread crashes when Google Desktop is installed (Windows XP)
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
* [@http://svn.boost.org/trac/boost/ticket/4833 #4833] MinGW/test_tss_lib: Support of automatic tss cleanup for native threading API not available
* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue
* [@http://svn.boost.org/trac/boost/ticket/8600 #8600] wait_for_any hangs, if called with multiple copies of shared_future referencing same task
* [@http://svn.boost.org/trac/boost/ticket/9118 #9118] Seg fault on thread join when llvm and libc++ are used
* [@http://svn.boost.org/trac/boost/ticket/9309 #9309] test_latch fails often on clang-darwin-tot11
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
* [@http://svn.boost.org/trac/boost/ticket/10537 #10537] Application crash on throw exception
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler
* [@http://svn.boost.org/trac/boost/ticket/10942 #10942] Boost.Thread fails to build on Cygwin.
[/
* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler.
* [@http://svn.boost.org/trac/boost/ticket/10685 #10685] mfc_thread_init.hpp does not compile.
* [@http://svn.boost.org/trac/boost/ticket/10967 #10967] Timed wait points inconsistently convert relative to absolute waits.
]
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last snapshot.
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last regression test snapshot.
[*Sever limitations:]
There are some severe bugs that prevent the use of the library on concrete contexts, in particular:
* on thread specific storage that prevent the library to be used with dynamic libraries,
* on thread specific storage that prevent the library to be used with dynamic libraries ( [@http://svn.boost.org/trac/boost/ticket/3926 #3926], ),
[*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/9600 #9600] Async: Add task_region
* [@http://svn.boost.org/trac/boost/ticket/10611 #10611] Add emplace promise::set_value and emplace make_ready_future
* [@http://svn.boost.org/trac/boost/ticket/10826 #10826] Add scheduled executor operations
* [@http://svn.boost.org/trac/boost/ticket/11048 #11048] Add a serial_executor based on continuations
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
* [@http://svn.boost.org/trac/boost/ticket/10734 #10734] Submit method work differently on different executors, some throw exception and some silently ignore error (thread_executor and inline_executor)
* [@http://svn.boost.org/trac/boost/ticket/10736 #10736] Task exceptions silently ignored. I think std::terminate solution from N3785 and std::thread is better choice and more consistent.
* [@http://svn.boost.org/trac/boost/ticket/10737 #10737] In serial_executor we have infinite wait if task throw exception.
* [@http://svn.boost.org/trac/boost/ticket/10822 #10822] Boost.Thread fails to compile on Android
* [@http://svn.boost.org/trac/boost/ticket/10824 #10824] Boost.Thread 1.57 breaks Windows XP compatibility for SP2 and below.
* [@http://svn.boost.org/trac/boost/ticket/10963 #10963] future<future<T>>::then Has No Implementation
* [@http://svn.boost.org/trac/boost/ticket/10964 #10964] future<future<T>>::unwrap().then() Deadlocks
* [@http://svn.boost.org/trac/boost/ticket/10968 #10968] The futures returned by async() and future::then() are not blocking.
* [@http://svn.boost.org/trac/boost/ticket/10971 #10971] shared_future::get()/get_or() must be const
* [@http://svn.boost.org/trac/boost/ticket/10972 #10972] shared_future::then() can be called multiple times.
* [@http://svn.boost.org/trac/boost/ticket/10979 #10979] Support T& type deduction when the make_ready_future parameter is reference_wrapper<T>
* [@http://svn.boost.org/trac/boost/ticket/10996 #10996] Thread physical_concurrency() is failing on Windows
* [@http://svn.boost.org/trac/boost/ticket/11035 #11035] BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE not defined for Android
* [@http://svn.boost.org/trac/boost/ticket/11053 #11053] The attached code results in a R6025 - pure virtual function call in run_thread_exit_callbacks
[heading Version 4.4.0 - boost 1.57]
@@ -58,6 +79,7 @@ There are some severe bugs that prevent the use of the library on concrete conte
* [@http://svn.boost.org/trac/boost/ticket/10537 #10537] Application crash on throw exception
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last snapshot.

View File

@@ -98,7 +98,7 @@ or inheriting from a class which add these lockable functions.
The `basic_lockable_adapter` class helps to define the `BankAccount` class as
class BankAccount
: public basic_lockable_adapter<thread_mutex>
: public basic_lockable_adapter<boost::mutex>
{
int balance_;
public:
@@ -138,7 +138,7 @@ Notice that now acct is being locked by Withdraw after it has already been locke
As `boost::mutex` is not recursive, we need to use its recursive version `boost::recursive_mutex`.
class BankAccount
: public basic_lockable_adapter<recursive_mutex>
: public basic_lockable_adapter<boost::recursive_mutex>
{
// ...
@@ -147,7 +147,7 @@ As `boost::mutex` is not recursive, we need to use its recursive version `boost:
The caller-ensured locking approach is more flexible and the most efficient, but very dangerous. In an implementation using caller-ensured locking, BankAccount still holds a mutex, but its member functions don't manipulate it at all. Deposit and Withdraw are not thread-safe anymore. Instead, the client code is responsible for locking BankAccount properly.
class BankAccount
: public basic_lockable_adapter<boost:mutex> {
: public basic_lockable_adapter<boost::mutex> {
int balance_;
public:
void Deposit(int amount) {
@@ -271,7 +271,7 @@ Now that we have such a strict `strict_lock`, how do we harness its power in def
A little code is worth 1,000 words, a (hacked into) saying goes, so here's the new BankAccount class:
class BankAccount
: public basic_lockable_adapter<boost:recursive_mutex>
: public basic_lockable_adapter<boost::mutex>
{
int balance_;
public:
@@ -280,7 +280,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n
balance_ += amount;
}
void Deposit(int amount) {
strict_lock<boost:mutex> guard(*this); // Internally locked
strict_lock<BankAccount> guard(*this); // Internally locked
Deposit(amount, guard);
}
void Withdraw(int amount, strict_lock<BankAccount>&) {
@@ -288,7 +288,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n
balance_ -= amount;
}
void Withdraw(int amount) {
strict_lock<boost:mutex> guard(*this); // Internally locked
strict_lock<BankAccount> guard(*this); // Internally locked
Withdraw(amount, guard);
}
};
@@ -327,7 +327,7 @@ The scheme is useful because the likelihood of a programmer forgetting about any
Using `strict_lock` permits compile-time checking of the most common source of errors, and runtime checking of the less frequent problem.
Let's see how to enforce that the appropriate BankAccount object is locked. First, we need to add a member function to the `strict_lock` class template.
The `bool strict_lock<T>::owns_lock(Loclable*)` function returns a reference to the locked object.
The `bool strict_lock<T>::owns_lock(Lockable*)` function returns a reference to the locked object.
template <class Lockable> class strict_lock {
... as before ...
@@ -338,7 +338,7 @@ The `bool strict_lock<T>::owns_lock(Loclable*)` function returns a reference to
Second, BankAccount needs to use this function compare the locked object against this:
class BankAccount {
: public basic_lockable_adapter<boost::recursive_mutex>
: public basic_lockable_adapter<boost::mutex>
int balance_;
public:
void Deposit(int amount, strict_lock<BankAccount>& guard) {
@@ -403,7 +403,7 @@ The solution is to use a little bridge template `externally_locked` that control
T& get(strict_lock<Lockable>& lock) {
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
if (!lock.owns_lock(&lockable_)) throw lock_error(); run time check throw if not locks the same
if (!lock.owns_lock(&lockable_)) throw lock_error(); //run time check throw if not locks the same
#endif
return obj_;
}
@@ -421,10 +421,10 @@ The solution is to use a little bridge template `externally_locked` that control
Instead of making `checkingAcct_` and `savingsAcct_` of type `BankAccount`, `AccountManager` holds objects of type `externally_locked<BankAccount, AccountManager>`:
class AccountManager
: public basic_lockable_adapter<thread_mutex>
: public basic_lockable_adapter<boost::mutex>
{
public:
typedef basic_lockable_adapter<thread_mutex> lockable_base_type;
typedef basic_lockable_adapter<boost::mutex> lockable_base_type;
AccountManager()
: checkingAcct_(*this)
, savingsAcct_(*this)
@@ -498,7 +498,7 @@ Now we need to state that both classes are `strict_lock`s.
Well let me show what this `nested_strict_lock` class looks like and the impacts on the `externally_locked` class and the `AccountManager::AMoreComplicatedFunction` function.
First `nested_strict_lock` class will store on a temporary lock the `Locker`, and transfer the lock ownership on the constructor. On destruction it will restore the ownership. Note the use of `lock_traits` and that the `Locker` needs to have a reference to the mutex otherwise and exception is thrown.
First `nested_strict_lock` class will store on a temporary lock the `Locker`, and transfer the lock ownership on the constructor. On destruction it will restore the ownership. Note the use of `lock_traits` and that the `Locker` needs to have a reference to the mutex otherwise an exception is thrown.
template <typename Locker >
class nested_strict_lock
@@ -510,7 +510,7 @@ First `nested_strict_lock` class will store on a temporary lock the `Locker`, an
nested_strict_lock(Locker& lock)
: lock_(lock) // Store reference to locker
, tmp_lock_(lock.move()) // Move ownership to temporaty locker
, tmp_lock_(lock.move()) // Move ownership to temporary locker
{
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
if (tmp_lock_.mutex()==0) {

View File

@@ -1020,7 +1020,7 @@ There are not too much tests yet, so it is possible that you can find out some t
void swap(shared_future& other);
// retrieving the value
see below get();
see below get() const;
exception_ptr get_exception_ptr(); // EXTENSION
@@ -1066,9 +1066,9 @@ There are not too much tests yet, so it is possible that you can find out some t
[///////////////////////////////////]
[section:get Member function `get()`]
const R& get();
R& get();
void get();
const R& get() const;
R& get() const;
void get() const;
[variablelist
@@ -2362,7 +2362,7 @@ All `R` types must be the same. If any of the `future<R>` or `shared_future<R>`
[section:make_ready_future Non-member function `make_ready_future()` EXTENSION]
template <typename T>
future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
future<V> make_ready_future(T&& value); // EXTENSION
future<void> make_ready_future(); // EXTENSION
template <typename T>
future<T> make_ready_future(exception_ptr ex); // DEPRECATED
@@ -2371,11 +2371,15 @@ All `R` types must be the same. If any of the `future<R>` or `shared_future<R>`
[variablelist
[[Remark:][
where `V` is determined as follows: Let `U` be `decay_t<T>`. Then `V` is `X&`
if `U` equals `reference_wrapper<X>`, otherwise `V` is `U`.
]]
[[Effects:] [
- value prototype: The value that is passed into the function is moved to the shared state of the returned function if it is an rvalue.
Otherwise the value is copied to the shared state of the returned function.
- value prototype: The value that is passed into the function is moved to the shared state of the returned future if it is an rvalue.
Otherwise the value is copied to the shared state of the returned future.
- exception: The exception that is passed into the function is copied to the shared state of the returned function.
- exception: The exception that is passed into the function is copied to the shared state of the returned future.
.]]

View File

@@ -93,7 +93,7 @@ the result is ready, it is returned from __unique_future_get__ by rvalue-referen
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 non `const` reference so that multiple calls to __shared_future_get__ are safe. You can move an
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.

View File

@@ -2664,7 +2664,7 @@ Only the specificities respect to __Lockable are described here.
[endsect]
[///////////////////////////////]
[section:get2 `get(strict_lock<nested_strict_lock<Lock>>&)`]
[section:get2 `get(nested_strict_lock<Lock>&)`]
template <class Lock>
T& get(nested_strict_lock<Lock>& lk);
@@ -2684,7 +2684,7 @@ Only the specificities respect to __Lockable are described here.
[endsect]
[///////////////////////////////]
[section:get3 `get(strict_lock<nested_strict_lock<Lock>>&)`]
[section:get3 `get(Lock&)`]
template <class Lock>
T& get(Lock& lk);
@@ -2826,7 +2826,7 @@ Only the specificities respect to __Lockable are described here.
[endsect]
[///////////////////////////////]
[section:get2 `get(strict_lock<nested_strict_lock<Lock>>&)`]
[section:get2 `get(nested_strict_lock<Lock>&)`]
template <class Lock>
T& get(nested_strict_lock<Lock>& lk);
@@ -2846,7 +2846,7 @@ Only the specificities respect to __Lockable are described here.
[endsect]
[///////////////////////////////]
[section:get3 `get(strict_lock<nested_strict_lock<Lock>>&)`]
[section:get3 `get(Lock&)`]
template <class Lock>
T& get(Lock& lk);

View File

@@ -21,18 +21,18 @@
class scoped_thread;
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
[section:motovation Motivation]
[section:motivation Motivation]
Based on the scoped_thread class defined in C++ Concurrency in Action Boost.Thread defines a thread wrapper class that instead of calling terminate if the thread is joinable on destruction, call a specific action given as template parameter.
While the scoped_thread class defined in C++ Concurrency in Action is closer to strict_scoped_thread class that doesn't allows any change in the wrapped thread, Boost.Thread provides a class scoped_thread that provides the same non-deprecated interface than __thread.
While the scoped_thread class defined in C++ Concurrency in Action is closer to strict_scoped_thread class that doesn't allows any change in the wrapped thread, Boost.Thread provides a class scoped_thread that provides the same non-deprecated interface as __thread.
[endsect]
[section:tutorial Tutorial]
Scoped Threads are wrappers around a thread that allows the user to state what to do at destruction time. One of the common uses is to join the thread at destruction time so this is the default behavior. This is the single difference respect to a thread. While thread call std::terminate() on the destructor is the thread is joinable, strict_scoped_thread<> or scoped_thread<> join the thread if joinable.
Scoped Threads are wrappers around a thread that allows the user to state what to do at destruction time. One of the common uses is to join the thread at destruction time so this is the default behavior. This is the single difference respect to a thread. While thread call std::terminate() on the destructor if the thread is joinable, strict_scoped_thread<> or scoped_thread<> join the thread if joinable.
The difference between strict_scoped_thread and scoped_thread is that the strict_scoped_thread hides completely the owned thread and so the user can do nothing with the owned thread other than the specific action given as parameter, while scoped_thread provide the same interface than __thread and forwards all the operations.
The difference between strict_scoped_thread and scoped_thread is that the strict_scoped_thread hides completely the owned thread and so the user can do nothing with the owned thread other than the specific action given as parameter, while scoped_thread provide the same interface as __thread and forwards all the operations.
boost::strict_scoped_thread<> t1((boost::thread(f)));
//t1.detach(); // compile fails
@@ -114,15 +114,15 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
};
RAI __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
RAII __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
CallableThread: A callable `void(thread&)`.
The default is a `join_if_joinable`.
`std/boost::thread` destructor terminates the program if the __thread is not joinable.
This wrapper can be used to join the thread before destroying it seems a natural need.
Thread destructor terminates the program if the __thread is joinable.
This wrapper can be used to join the thread before destroying it.
[heading Example]
@@ -233,13 +233,13 @@ This wrapper can be used to join the thread before destroying it seems a natural
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
RAI __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
RAII __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
CallableThread: A callable void(thread&).
The default is join_if_joinable.
thread std::thread destructor terminates the program if the thread is not joinable.
Having a wrapper that can join the thread before destroying it seems a natural need.
Thread destructor terminates the program if the thread is joinable.
This wrapper can be used to join the thread before destroying it.
Remark: `scoped_thread` is not a __thread as __thread is not designed to be derived from as a polymorphic type.
@@ -312,9 +312,9 @@ any) to `*this`.
[variablelist
[[Effects:] [move the thread to own `t_`.]]
[[Effects:] [Transfers ownership of the thread managed by `other` (if any) to the newly constructed scoped_thread instance.]]
[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
[[Postconditions:] [other.get_id()==thread::id() and get_id() returns the value of other.get_id() prior to the construction.]]
[[Throws:] [Nothing]]
@@ -329,7 +329,7 @@ any) to `*this`.
[variablelist
[[Effects:] [Construct a internal thread in place.]]
[[Effects:] [Construct an internal thread in place.]]
[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]

View File

@@ -181,7 +181,7 @@ where
[variablelist
[[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety.]]
[[Requires:] [Q::value_type is no throw move constructible. This is needed to ensure the exception safety.]]
[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element.]]
@@ -206,7 +206,7 @@ where
[variablelist
[/[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety. ]]
[/[Requires:] [Q::value_type is no throw move assignable. This is needed to ensure the exception safety. ]]
[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element into a shared_ptr.]]
@@ -314,7 +314,7 @@ where
[variablelist
[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
[[Effects:] [If the queue is not empty pulls the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
@@ -393,7 +393,7 @@ where
[endsect]
[/////////////////////////////////////]
[section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve());`]
[section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve);`]
[variablelist
@@ -427,7 +427,7 @@ where
[variablelist
[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
[[Effects:] [If the queue is not empty pulls the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
@@ -636,12 +636,12 @@ Closed queues add the following valid expressions
namespace boost
{
template <typename ValueType>
template <typename ValueType, class SizeType=std::size_t>
class queue_base
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base() {};
@@ -671,7 +671,7 @@ Closed queues add the following valid expressions
virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
virtual queue_op_status wait_pull_front(value_type& elem) = 0;
};
}
@@ -685,11 +685,11 @@ Closed queues add the following valid expressions
namespace boost
{
template <typename Queue>
class queue_adaptor : public queue_base<typename Queue::value_type>
class queue_adaptor : public queue_base<typename Queue::value_type, typename Queue::size_type>
{
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
@@ -1002,13 +1002,13 @@ Closed queues add the following valid expressions
namespace boost
{
template <typename ValueType>
template <typename ValueType, class Container = csbl::devector<ValueType>>
class sync_queue
{
public:
typedef ValueType value_type;
typedef csbl::deque<ValueType> underlying_queue_type;
typedef std::size_t size_type;
typedef Container underlying_queue_type;
typedef typename Container::size_type size_type;
sync_queue(sync_queue const&) = delete;
sync_queue& operator=(sync_queue const&) = delete;

View File

@@ -88,9 +88,9 @@
typedef T value_type;
typedef Lockable mutex_type;
synchronized_value() noexept(is_nothrow_default_constructible<T>::value);
synchronized_value(T const& other) noexept(is_nothrow_copy_constructible<T>::value);
synchronized_value(T&& other) noexept(is_nothrow_move_constructible<T>::value);
synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
synchronized_value(synchronized_value const& rhs);
synchronized_value(synchronized_value&& other);
@@ -129,7 +129,7 @@
[section:constructor `synchronized_value()`]
synchronized_value() noexept(is_nothrow_default_constructible<T>::value);
synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
[variablelist
@@ -145,7 +145,7 @@
[section:constructor_vt `synchronized_value(T const&)`]
synchronized_value(T const& other) noexept(is_nothrow_copy_constructible<T>::value);
synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
[variablelist
@@ -175,11 +175,11 @@
[section:move_vt `synchronized_value(T&&)`]
synchronized_value(T&& other) noexept(is_nothrow_move_constructible<T>::value);
synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
[variablelist
[[Requires:] [`T` is `CopyMovable `.]]
[[Requires:] [`T` is `MoveConstructible `.]]
[[Effects:] [Move constructs the cloaked value_type]]
[[Throws:] [Any exception thrown by `value_type(value_type&&)`.]]
@@ -194,7 +194,7 @@
[variablelist
[[Requires:] [`T` is `CopyMovable `.]]
[[Requires:] [`T` is `MoveConstructible `.]]
[[Effects:] [Move constructs the cloaked value_type]]
[[Throws:] [Any exception thrown by `value_type(value_type&&)` or `mtx_.lock()`.]]
@@ -209,7 +209,7 @@
[variablelist
[[Requires:] [`T` is `Assignale`.]]
[[Requires:] [`T` is `Assignable`.]]
[[Effects:] [Copies the underlying value on a scope protected by the two mutexes. The mutex is not copied. The locks are acquired avoiding deadlock. For example, there is no problem if one thread assigns `a = b` and the other assigns `b = a`.]]
[[Return:] [`*this`]]
@@ -224,7 +224,7 @@
[variablelist
[[Requires:] [`T` is `Assignale`.]]
[[Requires:] [`T` is `Assignable`.]]
[[Effects:] [Copies the value on a scope protected by the mutex.]]
[[Return:] [`*this`]]
@@ -273,7 +273,7 @@
[variablelist
[[Requires:] [`T` is `Assignale`.]]
[[Requires:] [`T` is `Assignable`.]]
[[Effects:] [Swaps the data on a scope protected by both mutex. Both mutex are acquired to avoid dead-lock. The mutexes are not swapped.]]
[[Throws:] [Any exception thrown by `swap(value_, rhs.value)` or `mtx_.lock()` or `rhs_.mtx_.lock()`.]]

View File

@@ -8,10 +8,10 @@
[library Thread
[quickbook 1.5]
[version 4.4.0]
[version 4.5.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
[copyright 2011-14 Vicente J. Botet Escriba]
[copyright 2011-15 Vicente J. Botet Escriba]
[purpose C++ Library for launching threads and synchronizing data between them]
[category text]
[license

View File

@@ -125,7 +125,7 @@ the user to set the platform specific attributes. Boost.Thread stay in the middl
thread::attributes which allows to set at least in a portable way the stack size as follows:
boost::thread::attributes attrs;
attrs.set_size(4096*10);
attrs.set_stack_size(4096*10);
boost::thread deep_thought_2(attrs, find_the_question, 42);
Even for this simple attribute there could be portable issues as some platforms could require that the stack size
@@ -147,7 +147,7 @@ Next follows how the user could set the stack size and the scheduling policy on
// ... window version
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
// ... pthread version
pthread_attr_setschedpolicy(attr.get_native_handle(), SCHED_RR);
pthread_attr_setschedpolicy(attr.native_handle(), SCHED_RR);
#else
#error "Boost threads unavailable on this platform"
#endif
@@ -432,12 +432,14 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
class attributes; // EXTENSION
thread() noexcept;
~thread();
thread(const thread&) = delete;
thread& operator=(const thread&) = delete;
// move support
thread(thread&&) noexcept;
thread& operator=(thread&&) noexcept;
~thread();
template <class F>
explicit thread(F f);
@@ -456,10 +458,6 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
template <class F, class ...Args>
explicit thread(attributes& attrs, F&& f, Args&&... args);
// move support
thread(thread && x) noexcept;
thread& operator=(thread && x) noexcept;
void swap(thread& x) noexcept;
class id;

View File

@@ -0,0 +1,61 @@
// Copyright (C) 2014 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/caller_context.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executors/generic_executor_ref.hpp>
#include <string>
#include <iostream>
#include <boost/thread/caller_context.hpp>
boost::generic_executor_ref default_executor()
{
static boost::basic_thread_pool tp(4);
return boost::generic_executor_ref(tp);
}
void p2()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
std::cout << BOOST_CONTEXTOF << std::endl;
}
void p1()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
default_executor().submit(&p2);
boost::this_thread::sleep_for(boost::chrono::milliseconds(400));
std::cout << BOOST_CONTEXTOF << std::endl;
}
int main()
{
std::cout << BOOST_CONTEXTOF << std::endl;
default_executor().submit(&p1);
boost::this_thread::sleep_for(boost::chrono::seconds(5));
std::cout << BOOST_CONTEXTOF << std::endl;
return 1;
}

View File

@@ -35,31 +35,83 @@ int p1()
int main()
{
const int number_of_tests = 100;
const int number_of_tests = 200;
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
{
for (int i=0; i< number_of_tests; i++)
try
{
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f1.wait();
BOOST_ASSERT(f1.get()==1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
{
for (int i=0; i< number_of_tests; i++)
try
{
//boost::future<int> f1 = boost::async(boost::launch::async, &p1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(&p1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f2 = f1.fallback_to(-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f2.wait();
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
BOOST_ASSERT(f2.get()==1);
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << " ERRORRRRR exception thrown" << std::endl;
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
{
for (int i=0; i< number_of_tests; i++)
try
{
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1_ex);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f1.wait();
BOOST_ASSERT(f1.get_or(-1)==-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
@@ -75,18 +127,20 @@ int main()
boost::future<int> f2 = f1.fallback_to(-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f2.wait();
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
BOOST_ASSERT(f2.get()==-1);
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << " ERRORRRRR exception thrown" << std::endl;
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}

View File

@@ -104,6 +104,26 @@ int main()
boost::future<int&> f = compute_ref(0);
std::cout << f.get() << std::endl;
}
#if __cplusplus > 201103L
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
int i = 0;
boost::future<int&> f = boost::make_ready_future(std::ref(i));
std::cout << f.get() << std::endl;
}
#endif
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
int i = 0;
boost::future<int&> f = boost::make_ready_future(boost::ref(i));
std::cout << f.get() << std::endl;
}
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
const int i = 0;
boost::future<int const&> f = boost::make_ready_future(boost::cref(i));
std::cout << f.get() << std::endl;
}
// {
// std::cout << __FILE__ << " "<< __LINE__ << std::endl;
// boost::future<int> f = compute(2);

View File

@@ -22,7 +22,7 @@
typedef std::ostream the_ostream;
typedef std::istream the_istream;
#endif
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
{
@@ -30,9 +30,9 @@ void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
try {
for(int i=0; ;++i)
{
sbq.push_back(i);
sbq.push(i);
//sbq << i;
mos << "push_back(" << i << ") "<< sbq.size()<<"\n";
mos << "push(" << i << ") "<< sbq.size()<<"\n";
this_thread::sleep_for(chrono::milliseconds(200));
}
}
@@ -55,7 +55,7 @@ void consumer(
for(int i=0; ;++i)
{
int r;
sbq.pull_front(r);
sbq.pull(r);
//sbq >> r;
mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
@@ -78,7 +78,7 @@ void consumer2(the_ostream &mos, boost::sync_queue<int> & sbq)
for(int i=0; ;++i)
{
int r;
queue_op_status st = sbq.try_pull_front(r);
queue_op_status st = sbq.try_pull(r);
if (queue_op_status::closed == st) break;
if (queue_op_status::success == st) {
mos << i << " pull(" << r << ")\n";
@@ -98,9 +98,9 @@ void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
for(int i=0; ;++i)
{
int r;
queue_op_status res = sbq.wait_pull_front(r);
queue_op_status res = sbq.wait_pull(r);
if (res==queue_op_status::closed) break;
mos << i << " wait_pull_front(" << r << ")\n";
mos << i << " wait_pull(" << r << ")\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}

View File

@@ -21,7 +21,7 @@
typedef std::ostream the_ostream;
typedef std::istream the_istream;
#endif
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
#include <boost/thread/concurrent_queues/queue_views.hpp>
#include <boost/static_assert.hpp>

113
example/serial_executor.cpp Normal file
View File

@@ -0,0 +1,113 @@
// Copyright (C) 2015 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/config.hpp>
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/caller_context.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executors/serial_executor.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/thread/executors/executor_adaptor.hpp>
#include <boost/thread/executor.hpp>
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <string>
#include <iostream>
void p1()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(30));
std::cout << BOOST_CONTEXTOF << std::endl;
}
void p2()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
std::cout << BOOST_CONTEXTOF << std::endl;
}
int f1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
return 1;
}
int f2(int i)
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(2));
return i + 1;
}
void submit_some(boost::serial_executor& tp)
{
std::cout << BOOST_CONTEXTOF << std::endl;
for (int i = 0; i < 3; ++i) {
std::cout << BOOST_CONTEXTOF << std::endl;
tp.submit(&p2);
}
for (int i = 0; i < 3; ++i) {
std::cout << BOOST_CONTEXTOF << std::endl;
tp.submit(&p1);
}
std::cout << BOOST_CONTEXTOF << std::endl;
}
void at_th_entry(boost::basic_thread_pool& )
{
}
int test_executor_adaptor()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea1(4);
boost::serial_executor ea2(ea1);
submit_some(ea2);
boost::this_thread::sleep_for(boost::chrono::seconds(10));
}
#endif
// std::cout << BOOST_CONTEXTOF << std::endl;
}
catch (std::exception& ex)
{
std::cout << "ERROR= " << ex.what() << "" << std::endl;
return 1;
}
catch (...)
{
std::cout << " ERROR= exception thrown" << std::endl;
return 2;
}
}
// std::cout << BOOST_CONTEXTOF << std::endl;
return 0;
}
int main()
{
return test_executor_adaptor();
}

View File

@@ -0,0 +1,113 @@
// Copyright (C) 2015 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/config.hpp>
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/caller_context.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executors/serial_executor_cont.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/thread/executors/executor_adaptor.hpp>
#include <boost/thread/executor.hpp>
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <string>
#include <iostream>
void p1()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(30));
std::cout << BOOST_CONTEXTOF << std::endl;
}
void p2()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
std::cout << BOOST_CONTEXTOF << std::endl;
}
int f1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
return 1;
}
int f2(int i)
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(2));
return i + 1;
}
void submit_some(boost::serial_executor_cont& tp)
{
std::cout << BOOST_CONTEXTOF << std::endl;
for (int i = 0; i < 3; ++i) {
std::cout << BOOST_CONTEXTOF << std::endl;
tp.submit(&p2);
}
for (int i = 0; i < 3; ++i) {
std::cout << BOOST_CONTEXTOF << std::endl;
tp.submit(&p1);
}
std::cout << BOOST_CONTEXTOF << std::endl;
}
void at_th_entry(boost::basic_thread_pool& )
{
}
int test_executor_adaptor()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea1(4);
boost::serial_executor_cont ea2(ea1);
submit_some(ea2);
boost::this_thread::sleep_for(boost::chrono::seconds(10));
}
#endif
// std::cout << BOOST_CONTEXTOF << std::endl;
}
catch (std::exception& ex)
{
std::cout << "ERROR= " << ex.what() << "" << std::endl;
return 1;
}
catch (...)
{
std::cout << " ERROR= exception thrown" << std::endl;
return 2;
}
}
// std::cout << BOOST_CONTEXTOF << std::endl;
return 0;
}
int main()
{
return test_executor_adaptor();
}

86
example/this_executor.cpp Normal file
View File

@@ -0,0 +1,86 @@
// Copyright (C) 2014 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/caller_context.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executors/generic_executor_ref.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <string>
#include <iostream>
#include <boost/thread/caller_context.hpp>
struct current_executor_state_type {
boost::shared_ptr<boost::generic_executor_ref> current_executor_ptr;
template <class Executor>
void set_current_executor(Executor& ex)
{
current_executor_ptr = boost::make_shared<boost::generic_executor_ref>(ex);
}
boost::generic_executor_ref current_executor()
{
if (current_executor_ptr)
return *current_executor_ptr;
else
throw "";
}
};
thread_local current_executor_state_type current_executor_state;
boost::generic_executor_ref current_executor()
{
return current_executor_state.current_executor();
}
void p2()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
std::cout << BOOST_CONTEXTOF << std::endl;
}
void p1()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
current_executor().submit(&p2);
boost::this_thread::sleep_for(boost::chrono::milliseconds(400));
std::cout << BOOST_CONTEXTOF << std::endl;
}
int main()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::basic_thread_pool tp(4,
// at_thread_entry
[](boost::basic_thread_pool& pool)
{
current_executor_state.set_current_executor(pool);
}
);
tp.submit(&p1);
boost::this_thread::sleep_for(boost::chrono::seconds(5));
std::cout << BOOST_CONTEXTOF << std::endl;
return 1;
}

View File

@@ -1,4 +1,4 @@
// (C) Copyright 2013 Vicente J. Botet Escriba
// (C) Copyright 2013,2015 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)
@@ -12,6 +12,7 @@
#include <boost/thread/thread.hpp>
#endif
#include <boost/current_function.hpp>
#include <boost/io/ios_state.hpp>
#include <iomanip>
#include <boost/config/abi_prefix.hpp>
@@ -43,9 +44,11 @@ namespace boost
#endif
{
io::ios_flags_saver ifs(os);
os << ctx.filename << "["
os << std::setw(50) << ctx.filename << "["
<< std::setw(4) << std::right << std::dec<< ctx.lineno << "] ";
#if defined BOOST_THREAD_USES_LOG_CURRENT_FUNCTION
os << ctx.func << " " ;
#endif
}
return os;
}

View File

@@ -0,0 +1,209 @@
#ifndef BOOST_THREAD_CONCURRENT_DEQUE_ADAPTOR_HPP
#define BOOST_THREAD_CONCURRENT_DEQUE_ADAPTOR_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/concurrent_queues/deque_base.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <typename Queue>
class deque_adaptor_copyable_only :
public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
deque_adaptor_copyable_only() {}
// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }
// Modifiers
void close() { queue.close(); }
void push_back(const value_type& x) { queue.push_back(x); }
void pull_front(value_type& x) { queue.pull_front(x); };
value_type pull_front() { return queue.pull_front(); }
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
};
template <typename Queue>
class deque_adaptor_movable_only :
public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
deque_adaptor_movable_only() {}
// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }
// Modifiers
void close() { queue.close(); }
void pull_front(value_type& x) { queue.pull_front(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull_front() { return queue.pull_front(); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
};
template <typename Queue>
class deque_adaptor_copyable_and_movable :
public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
deque_adaptor_copyable_and_movable() {}
// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }
// Modifiers
void close() { queue.close(); }
void push_back(const value_type& x) { queue.push_back(x); }
void pull_front(value_type& x) { queue.pull_front(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull_front() { return queue.pull_front(); }
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
};
template <class Q, class T,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__ && ! defined __clang__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // __GNUC__
#elif defined _MSC_VER
#if _MSC_VER < 1700
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // _MSC_VER
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif
#else
bool Copyable = is_copy_constructible<T>::value,
bool Movable = has_move_emulation_enabled<T>::value
#endif
>
struct deque_adaptor;
template <class Q, class T>
struct deque_adaptor<Q, T, true, true> {
typedef deque_adaptor_copyable_and_movable<Q> type;
};
template <class Q, class T>
struct deque_adaptor<Q, T, true, false> {
typedef deque_adaptor_copyable_only<Q> type;
};
template <class Q, class T>
struct deque_adaptor<Q, T, false, true> {
typedef deque_adaptor_movable_only<Q> type;
};
}
template <typename Queue>
class deque_adaptor :
public detail::deque_adaptor<Queue, typename Queue::value_type>::type
{
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
virtual ~deque_adaptor() {};
};
}
using concurrent::deque_adaptor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,202 @@
#ifndef BOOST_THREAD_CONCURRENT_DEQUE_BASE_HPP
#define BOOST_THREAD_CONCURRENT_DEQUE_BASE_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/type_traits/is_copy_constructible.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <typename ValueType, class SizeType>
class deque_base_copyable_only
{
public:
typedef ValueType value_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~deque_base_copyable_only() {};
// Observers
virtual bool empty() const = 0;
virtual bool full() const = 0;
virtual size_type size() const = 0;
virtual bool closed() const = 0;
// Modifiers
virtual void close() = 0;
virtual void push_back(const value_type& x) = 0;
virtual void pull_front(value_type&) = 0;
virtual value_type pull_front() = 0;
virtual queue_op_status try_push_back(const value_type& x) = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_pull_front(value_type& elem) = 0;
};
template <typename ValueType, class SizeType>
class deque_base_movable_only
{
public:
typedef ValueType value_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~deque_base_movable_only() {};
// Observers
virtual bool empty() const = 0;
virtual bool full() const = 0;
virtual size_type size() const = 0;
virtual bool closed() const = 0;
// Modifiers
virtual void close() = 0;
virtual void pull_front(value_type&) = 0;
// enable_if is_nothrow_movable<value_type>
virtual value_type pull_front() = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_pull_front(value_type& elem) = 0;
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
};
template <typename ValueType, class SizeType>
class deque_base_copyable_and_movable
{
public:
typedef ValueType value_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~deque_base_copyable_and_movable() {};
// Observers
virtual bool empty() const = 0;
virtual bool full() const = 0;
virtual size_type size() const = 0;
virtual bool closed() const = 0;
// Modifiers
virtual void close() = 0;
virtual void push_back(const value_type& x) = 0;
virtual void pull_front(value_type&) = 0;
// enable_if is_nothrow_copy_movable<value_type>
virtual value_type pull_front() = 0;
virtual queue_op_status try_push_back(const value_type& x) = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_pull_front(value_type& elem) = 0;
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
};
template <class T, class ST,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__ && ! defined __clang__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // __GNUC__
#elif defined _MSC_VER
#if _MSC_VER < 1700
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // _MSC_VER
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif
#else
bool Copyable = is_copy_constructible<T>::value,
bool Movable = has_move_emulation_enabled<T>::value
#endif
>
struct deque_base;
template <class T, class ST>
struct deque_base<T, ST, true, true> {
typedef deque_base_copyable_and_movable<T, ST> type;
};
template <class T, class ST>
struct deque_base<T, ST, true, false> {
typedef deque_base_copyable_only<T, ST> type;
};
template <class T, class ST>
struct deque_base<T, ST, false, true> {
typedef deque_base_movable_only<T, ST> type;
};
}
template <class ValueType, class SizeType=std::size_t>
class deque_base :
public detail::deque_base<ValueType, SizeType>::type
{
public:
typedef ValueType value_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~deque_base() {};
};
}
using concurrent::deque_base;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,165 @@
#ifndef BOOST_THREAD_QUEUE_VIEWS_HPP
#define BOOST_THREAD_QUEUE_VIEWS_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/concurrent_queues/deque_base.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
template <typename Queue>
class deque_back_view
{
Queue* queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
deque_back_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
// Observers
bool empty() const { return queue->empty(); }
bool full() const { return queue->full(); }
size_type size() const { return queue->size(); }
bool closed() const { return queue->closed(); }
// Modifiers
void close() { queue->close(); }
void push(const value_type& x) { queue->push_back(x); }
void pull(value_type& x) { queue->pull_back(x); }
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue->pull_back(); }
queue_op_status try_push(const value_type& x) { return queue->try_push_back(x); }
queue_op_status try_pull(value_type& x) { return queue->try_pull_back(x); }
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_back(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_back(x); }
queue_op_status wait_push(const value_type& x) { return queue->wait_push_back(x); }
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_back(x); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_back(boost::move(x)); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_back(boost::move(x)); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_back(boost::move(x)); }
};
template <typename Queue>
class deque_front_view
{
Queue* queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
deque_front_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
// Observers
bool empty() const { return queue->empty(); }
bool full() const { return queue->full(); }
size_type size() const { return queue->size(); }
bool closed() const { return queue->closed(); }
// Modifiers
void close() { queue->close(); }
void push(const value_type& x) { queue->push_front(x); }
void pull(value_type& x) { queue->pull_front(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue->pull_front(); }
queue_op_status try_push(const value_type& x) { return queue->try_push_front(x); }
queue_op_status try_pull(value_type& x) { return queue->try_pull_front(x); }
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_front(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_front(x); }
queue_op_status wait_push(const value_type& x) { return queue->wait_push_front(x); }
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_front(x); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_front(forward<value_type>(x)); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_front(forward<value_type>(x)); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_front(forward<value_type>(x)); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_front(forward<value_type>(x)); }
};
#if ! defined BOOST_NO_CXX11_TEMPLATE_ALIASES
template <class T>
using deque_back = deque_back_view<deque_base<T> > ;
template <class T>
using deque_front = deque_front_view<deque_base<T> > ;
#else
template <class T>
struct deque_back : deque_back_view<deque_base<T> >
{
typedef deque_back_view<deque_base<T> > base_type;
deque_back(deque_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
};
template <class T>
struct deque_front : deque_front_view<deque_base<T> >
{
typedef deque_front_view<deque_base<T> > base_type;
deque_front(deque_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
};
#endif
// template <class Queue>
// deque_back_view<Queue> back(Queue & q) { return deque_back_view<Queue>(q); }
// template <class Queue>
// deque_front_view<Queue> front(Queue & q) { return deque_front_view<Queue>(q); }
//#if 0
// template <class T>
// deque_back<T> back(deque_base<T> & q) { return deque_back<T>(q); }
// template <class T>
// deque_front<T> front(deque_base<T> & q) { return deque_front<T>(q); }
//#else
// template <class T>
// typename deque_back<T>::type back(deque_base<T> & q) { return typename deque_back<T>::type(q); }
// template <class T>
// typename deque_front<T>::type front(deque_base<T> & q) { return typename deque_front<T>::type(q); }
//#endif
}
using concurrent::deque_back_view;
using concurrent::deque_front_view;
using concurrent::deque_back;
using concurrent::deque_front;
//using concurrent::back;
//using concurrent::front;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,223 @@
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_DEQUE_BASE_HPP
#define BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_DEQUE_BASE_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2013-2014. 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)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/throw_exception.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <class ValueType, class Queue>
class sync_deque_base
{
public:
typedef ValueType value_type;
typedef Queue underlying_queue_type;
typedef typename Queue::size_type size_type;
typedef queue_op_status op_status;
typedef typename chrono::steady_clock clock;
typedef typename clock::duration duration;
typedef typename clock::time_point time_point;
// Constructors/Assignment/Destructors
BOOST_THREAD_NO_COPYABLE(sync_deque_base)
inline sync_deque_base();
//template <typename Range>
//inline explicit sync_deque(Range range);
inline ~sync_deque_base();
// Observers
inline bool empty() const;
inline bool full() const;
inline size_type size() const;
inline bool closed() const;
// Modifiers
inline void close();
inline underlying_queue_type underlying_queue() {
lock_guard<mutex> lk(mtx_);
return boost::move(data_);
}
protected:
mutable mutex mtx_;
condition_variable not_empty_;
underlying_queue_type data_;
bool closed_;
inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
{
return data_.empty();
}
inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
{
return data_.empty();
}
inline size_type size(lock_guard<mutex>& ) const BOOST_NOEXCEPT
{
return data_.size();
}
inline bool closed(unique_lock<mutex>& lk) const;
inline bool closed(lock_guard<mutex>& lk) const;
inline void throw_if_closed(unique_lock<mutex>&);
inline void throw_if_closed(lock_guard<mutex>&);
inline void wait_until_not_empty(unique_lock<mutex>& lk);
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
inline queue_op_status wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&);
inline void notify_not_empty_if_needed(unique_lock<mutex>& )
{
not_empty_.notify_one();
}
inline void notify_not_empty_if_needed(lock_guard<mutex>& )
{
not_empty_.notify_one();
}
};
template <class ValueType, class Queue>
sync_deque_base<ValueType, Queue>::sync_deque_base() :
data_(), closed_(false)
{
BOOST_ASSERT(data_.empty());
}
template <class ValueType, class Queue>
sync_deque_base<ValueType, Queue>::~sync_deque_base()
{
}
template <class ValueType, class Queue>
void sync_deque_base<ValueType, Queue>::close()
{
{
lock_guard<mutex> lk(mtx_);
closed_ = true;
}
not_empty_.notify_all();
}
template <class ValueType, class Queue>
bool sync_deque_base<ValueType, Queue>::closed() const
{
lock_guard<mutex> lk(mtx_);
return closed(lk);
}
template <class ValueType, class Queue>
bool sync_deque_base<ValueType, Queue>::closed(unique_lock<mutex>&) const
{
return closed_;
}
template <class ValueType, class Queue>
bool sync_deque_base<ValueType, Queue>::closed(lock_guard<mutex>&) const
{
return closed_;
}
template <class ValueType, class Queue>
bool sync_deque_base<ValueType, Queue>::empty() const
{
lock_guard<mutex> lk(mtx_);
return empty(lk);
}
template <class ValueType, class Queue>
bool sync_deque_base<ValueType, Queue>::full() const
{
return false;
}
template <class ValueType, class Queue>
typename sync_deque_base<ValueType, Queue>::size_type sync_deque_base<ValueType, Queue>::size() const
{
lock_guard<mutex> lk(mtx_);
return size(lk);
}
template <class ValueType, class Queue>
void sync_deque_base<ValueType, Queue>::throw_if_closed(unique_lock<mutex>& lk)
{
if (closed(lk))
{
BOOST_THROW_EXCEPTION( sync_deque_is_closed() );
}
}
template <class ValueType, class Queue>
void sync_deque_base<ValueType, Queue>::throw_if_closed(lock_guard<mutex>& lk)
{
if (closed(lk))
{
BOOST_THROW_EXCEPTION( sync_deque_is_closed() );
}
}
template <class ValueType, class Queue>
void sync_deque_base<ValueType, Queue>::wait_until_not_empty(unique_lock<mutex>& lk)
{
for (;;)
{
if (! empty(lk)) break;
throw_if_closed(lk);
not_empty_.wait(lk);
}
}
template <class ValueType, class Queue>
bool sync_deque_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk)
{
for (;;)
{
if (! empty(lk)) break;
if (closed(lk)) return true;
not_empty_.wait(lk);
}
return false;
}
template <class ValueType, class Queue>
queue_op_status sync_deque_base<ValueType, Queue>::wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&tp)
{
for (;;)
{
if (! empty(lk)) return queue_op_status::success;
throw_if_closed(lk);
if (not_empty_.wait_until(lk, tp) == cv_status::timeout ) return queue_op_status::timeout;
}
}
} // detail
} // concurrent
} // boost
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -37,7 +37,7 @@ namespace detail
public:
typedef ValueType value_type;
typedef Queue underlying_queue_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
typedef queue_op_status op_status;
typedef typename chrono::steady_clock clock;

View File

@@ -27,12 +27,12 @@ namespace detail
template <typename Queue>
class queue_adaptor_copyable_only :
public boost::queue_base<typename Queue::value_type>
public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_adaptor_copyable_only() {}
@@ -46,29 +46,29 @@ namespace detail
// Modifiers
void close() { queue.close(); }
void push_back(const value_type& x) { queue.push_back(x); }
void push(const value_type& x) { queue.push(x); }
void pull_front(value_type& x) { queue.pull_front(x); };
value_type pull_front() { return queue.pull_front(); }
void pull(value_type& x) { queue.pull(x); };
value_type pull() { return queue.pull(); }
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status try_push(const value_type& x) { return queue.try_push(x); }
queue_op_status try_pull(value_type& x) { return queue.try_pull(x); }
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status nonblocking_push(const value_type& x) { return queue.nonblocking_push(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); }
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
queue_op_status wait_push(const value_type& x) { return queue.wait_push(x); }
queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); }
};
template <typename Queue>
class queue_adaptor_movable_only :
public boost::queue_base<typename Queue::value_type>
public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
@@ -84,30 +84,30 @@ namespace detail
void close() { queue.close(); }
void pull_front(value_type& x) { queue.pull_front(x); };
void pull(value_type& x) { queue.pull(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull_front() { return queue.pull_front(); }
value_type pull() { return queue.pull(); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status try_pull(value_type& x) { return queue.try_pull(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); }
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue.push(boost::move(x)); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push(boost::move(x)); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push(boost::move(x)); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push(boost::move(x)); }
};
template <typename Queue>
class queue_adaptor_copyable_and_movable :
public boost::queue_base<typename Queue::value_type>
public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
@@ -123,31 +123,31 @@ namespace detail
void close() { queue.close(); }
void push_back(const value_type& x) { queue.push_back(x); }
void push(const value_type& x) { queue.push(x); }
void pull_front(value_type& x) { queue.pull_front(x); };
void pull(value_type& x) { queue.pull(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull_front() { return queue.pull_front(); }
value_type pull() { return queue.pull(); }
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status try_push(const value_type& x) { return queue.try_push(x); }
queue_op_status try_pull(value_type& x) { return queue.try_pull(x); }
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status nonblocking_push(const value_type& x) { return queue.nonblocking_push(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); }
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
queue_op_status wait_push(const value_type& x) { return queue.wait_push(x); }
queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); }
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue.push(boost::move(x)); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push(boost::move(x)); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push(boost::move(x)); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push(boost::move(x)); }
};
template <class Q, class T,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__
#if defined __GNUC__ && ! defined __clang__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
@@ -195,7 +195,7 @@ namespace detail
{
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
virtual ~queue_adaptor() {};
};

View File

@@ -27,12 +27,12 @@ namespace concurrent
namespace detail
{
template <typename ValueType>
template <typename ValueType, class SizeType>
class queue_base_copyable_only
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_copyable_only() {};
@@ -46,28 +46,28 @@ namespace detail
// Modifiers
virtual void close() = 0;
virtual void push_back(const value_type& x) = 0;
virtual void push(const value_type& x) = 0;
virtual void pull_front(value_type&) = 0;
virtual value_type pull_front() = 0;
virtual void pull(value_type&) = 0;
virtual value_type pull() = 0;
virtual queue_op_status try_push_back(const value_type& x) = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status try_push(const value_type& x) = 0;
virtual queue_op_status try_pull(value_type&) = 0;
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_push(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull(value_type&) = 0;
virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
virtual queue_op_status wait_push(const value_type& x) = 0;
virtual queue_op_status wait_pull(ValueType& elem) = 0;
};
template <typename ValueType>
template <typename ValueType, class SizeType>
class queue_base_movable_only
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_movable_only() {};
@@ -80,29 +80,29 @@ namespace detail
// Modifiers
virtual void close() = 0;
virtual void pull_front(value_type&) = 0;
virtual void pull(value_type&) = 0;
// enable_if is_nothrow_movable<value_type>
virtual value_type pull_front() = 0;
virtual value_type pull() = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status try_pull(value_type&) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_pull(value_type&) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
virtual queue_op_status wait_pull(value_type& elem) = 0;
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
};
template <typename ValueType>
template <typename ValueType, class SizeType>
class queue_base_copyable_and_movable
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_copyable_and_movable() {};
@@ -116,30 +116,30 @@ namespace detail
// Modifiers
virtual void close() = 0;
virtual void push_back(const value_type& x) = 0;
virtual void push(const value_type& x) = 0;
virtual void pull_front(value_type&) = 0;
virtual void pull(value_type&) = 0;
// enable_if is_nothrow_copy_movable<value_type>
virtual value_type pull_front() = 0;
virtual value_type pull() = 0;
virtual queue_op_status try_push_back(const value_type& x) = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status try_push(const value_type& x) = 0;
virtual queue_op_status try_pull(value_type&) = 0;
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_push(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull(value_type&) = 0;
virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
virtual queue_op_status wait_push(const value_type& x) = 0;
virtual queue_op_status wait_pull(value_type& elem) = 0;
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
};
template <class T,
template <class T, class ST,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__
#if defined __GNUC__ && ! defined __clang__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
@@ -166,28 +166,28 @@ namespace detail
>
struct queue_base;
template <class T>
struct queue_base<T, true, true> {
typedef queue_base_copyable_and_movable<T> type;
template <class T, class ST>
struct queue_base<T, ST, true, true> {
typedef queue_base_copyable_and_movable<T, ST> type;
};
template <class T>
struct queue_base<T, true, false> {
typedef queue_base_copyable_only<T> type;
template <class T, class ST>
struct queue_base<T, ST, true, false> {
typedef queue_base_copyable_only<T, ST> type;
};
template <class T>
struct queue_base<T, false, true> {
typedef queue_base_movable_only<T> type;
template <class T, class ST>
struct queue_base<T, ST, false, true> {
typedef queue_base_movable_only<T, ST> type;
};
}
template <typename ValueType>
template <typename ValueType, class SizeType=std::size_t>
class queue_base :
public detail::queue_base<ValueType>::type
public detail::queue_base<ValueType, SizeType>::type
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base() {};
};

View File

@@ -43,27 +43,17 @@ namespace concurrent
// Modifiers
void close() { queue->close(); }
void push(const value_type& x) { queue->push_back(x); }
void push(const value_type& x) { queue->push(x); }
void pull(value_type& x) { queue->pull_back(x); }
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue->pull_back(); }
queue_op_status try_push(const value_type& x) { return queue->try_push(x); }
queue_op_status try_push(const value_type& x) { return queue->try_push_back(x); }
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push(x); }
queue_op_status wait_push(const value_type& x) { return queue->wait_push(x); }
queue_op_status try_pull(value_type& x) { return queue->try_pull_back(x); }
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_back(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_back(x); }
queue_op_status wait_push(const value_type& x) { return queue->wait_push_back(x); }
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_back(x); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_back(boost::move(x)); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_back(boost::move(x)); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_back(boost::move(x)); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push(boost::move(x)); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push(boost::move(x)); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push(boost::move(x)); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push(boost::move(x)); }
};
template <typename Queue>
@@ -88,20 +78,20 @@ namespace concurrent
void push(const value_type& x) { queue->push_front(x); }
void pull(value_type& x) { queue->pull_front(x); };
void pull(value_type& x) { queue->pull(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue->pull_front(); }
value_type pull() { return queue->pull(); }
queue_op_status try_push(const value_type& x) { return queue->try_push_front(x); }
queue_op_status try_pull(value_type& x) { return queue->try_pull_front(x); }
queue_op_status try_pull(value_type& x) { return queue->try_pull(x); }
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_front(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_front(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull(x); }
queue_op_status wait_push(const value_type& x) { return queue->wait_push_front(x); }
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_front(x); }
queue_op_status wait_pull(value_type& x) { return queue->wait_pull(x); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_front(forward<value_type>(x)); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_front(forward<value_type>(x)); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_front(forward<value_type>(x)); }

View File

@@ -0,0 +1,327 @@
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP
#define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2013-2014. 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)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/csbl/devector.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
template <class ValueType, class Container = csbl::devector<ValueType> >
class sync_deque
: public detail::sync_queue_base<ValueType, Container >
{
typedef detail::sync_queue_base<ValueType, Container > super;
public:
typedef ValueType value_type;
//typedef typename super::value_type value_type; // fixme
typedef typename super::underlying_queue_type underlying_queue_type;
typedef typename super::size_type size_type;
typedef typename super::op_status op_status;
// Constructors/Assignment/Destructors
BOOST_THREAD_NO_COPYABLE(sync_deque)
inline sync_deque();
//template <typename Range>
//inline explicit sync_deque(Range range);
inline ~sync_deque();
// Modifiers
inline void push_back(const value_type& x);
inline queue_op_status try_push_back(const value_type& x);
inline queue_op_status nonblocking_push_back(const value_type& x);
inline queue_op_status wait_push_back(const value_type& x);
inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
// Observers/Modifiers
inline void pull_front(value_type&);
// enable_if is_nothrow_copy_movable<value_type>
inline value_type pull_front();
inline queue_op_status try_pull_front(value_type&);
inline queue_op_status nonblocking_pull_front(value_type&);
inline queue_op_status wait_pull_front(ValueType& elem);
private:
inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline void pull_front(value_type& elem, unique_lock<mutex>& )
{
elem = boost::move(super::data_.front());
super::data_.pop_front();
}
inline value_type pull_front(unique_lock<mutex>& )
{
value_type e = boost::move(super::data_.front());
super::data_.pop_front();
return boost::move(e);
}
inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
{
super::data_.push_back(elem);
super::notify_not_empty_if_needed(lk);
}
inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
{
super::data_.push_back(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
};
template <class ValueType, class Container>
sync_deque<ValueType, Container>::sync_deque() :
super()
{
}
// template <class ValueType, class Container>
// template <class Range>
// explicit sync_deque<ValueType, Container>::sync_deque(Range range) :
// data_(), closed_(false)
// {
// try
// {
// typedef typename Range::iterator iterator_t;
// iterator_t first = boost::begin(range);
// iterator_t end = boost::end(range);
// for (iterator_t cur = first; cur != end; ++cur)
// {
// data_.push(boost::move(*cur));;
// }
// notify_not_empty_if_needed(lk);
// }
// catch (...)
// {
// delete[] data_;
// }
// }
template <class ValueType, class Container>
sync_deque<ValueType, Container>::~sync_deque()
{
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull_front(elem, lk);
return queue_op_status::success;
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
}
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
pull_front(elem, lk);
return queue_op_status::success;
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::try_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_pull_front(elem, lk);
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_pull_front(elem, lk);
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::nonblocking_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_pull_front(elem, lk);
}
template <class ValueType, class Container>
void sync_deque<ValueType, Container>::pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
pull_front(elem, lk);
}
// enable if ValueType is nothrow movable
template <class ValueType, class Container>
ValueType sync_deque<ValueType, Container>::pull_front()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull_front(lk);
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(elem, lk);
return queue_op_status::success;
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::try_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push_back(elem, lk);
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(elem, lk);
return queue_op_status::success;
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::wait_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_push_back(elem, lk);
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::nonblocking_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock()) return queue_op_status::busy;
return try_push_back(elem, lk);
}
template <class ValueType, class Container>
void sync_deque<ValueType, Container>::push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push_back(elem, lk);
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(boost::move(elem), lk);
return queue_op_status::success;
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push_back(boost::move(elem), lk);
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(boost::move(elem), lk);
return queue_op_status::success;
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_push_back(boost::move(elem), lk);
}
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_push_back(boost::move(elem), lk);
}
template <class ValueType, class Container>
void sync_deque<ValueType, Container>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push_back(boost::move(elem), lk);
}
template <class ValueType, class Container>
sync_deque<ValueType, Container>& operator<<(sync_deque<ValueType, Container>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
{
sbq.push_back(boost::move(elem));
return sbq;
}
template <class ValueType, class Container>
sync_deque<ValueType, Container>& operator<<(sync_deque<ValueType, Container>& sbq, ValueType const&elem)
{
sbq.push_back(elem);
return sbq;
}
template <class ValueType, class Container>
sync_deque<ValueType, Container>& operator>>(sync_deque<ValueType, Container>& sbq, ValueType &elem)
{
sbq.pull_front(elem);
return sbq;
}
}
using concurrent::sync_deque;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -39,14 +39,17 @@ namespace detail {
class priority_queue
{
private:
std::vector<Type> _elements;
Container _elements;
Compare _compare;
public:
typedef Type value_type;
typedef typename Container::size_type size_type;
explicit priority_queue(const Compare& compare = Compare())
: _elements(), _compare(compare)
{ }
std::size_t size() const
size_type size() const
{
return _elements.size();
}
@@ -67,17 +70,21 @@ namespace detail {
std::push_heap(_elements.begin(), _elements.end(), _compare);
}
Type pull()
void pop()
{
std::pop_heap(_elements.begin(), _elements.end(), _compare);
Type result = boost::move(_elements.back());
_elements.pop_back();
}
Type pull()
{
Type result = boost::move(_elements.front());
pop();
return boost::move(result);
}
Type const& top()
{
return _elements.back();
return _elements.front();
}
};
}

View File

@@ -15,7 +15,7 @@
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/csbl/deque.hpp>
#include <boost/thread/csbl/devector.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
@@ -29,11 +29,11 @@ namespace boost
{
namespace concurrent
{
template <typename ValueType>
template <class ValueType, class Container = csbl::devector<ValueType> >
class sync_queue
: public detail::sync_queue_base<ValueType, csbl::deque<ValueType> >
: public detail::sync_queue_base<ValueType, Container >
{
typedef detail::sync_queue_base<ValueType, csbl::deque<ValueType> > super;
typedef detail::sync_queue_base<ValueType, Container > super;
public:
typedef ValueType value_type;
@@ -45,65 +45,39 @@ namespace concurrent
// Constructors/Assignment/Destructors
BOOST_THREAD_NO_COPYABLE(sync_queue)
inline sync_queue();
//template <typename Range>
//template <class Range>
//inline explicit sync_queue(Range range);
inline ~sync_queue();
// Modifiers
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void push(const value_type& x);
inline bool try_push(const value_type& x);
inline bool try_push(no_block_tag, const value_type& x);
inline queue_op_status try_push(const value_type& x);
inline queue_op_status nonblocking_push(const value_type& x);
inline queue_op_status wait_push(const value_type& x);
inline void push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
#endif
inline void push_back(const value_type& x);
inline queue_op_status try_push_back(const value_type& x);
inline queue_op_status nonblocking_push_back(const value_type& x);
inline queue_op_status wait_push_back(const value_type& x);
inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x);
// Observers/Modifiers
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void pull(value_type&);
inline void pull(ValueType& elem, bool & closed);
// enable_if is_nothrow_copy_movable<value_type>
inline value_type pull();
inline shared_ptr<ValueType> ptr_pull();
#endif
inline void pull_front(value_type&);
// enable_if is_nothrow_copy_movable<value_type>
inline value_type pull_front();
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline bool try_pull(value_type&);
inline bool try_pull(no_block_tag,value_type&);
inline shared_ptr<ValueType> try_pull();
#endif
inline queue_op_status try_pull_front(value_type&);
inline queue_op_status nonblocking_pull_front(value_type&);
inline queue_op_status wait_pull_front(ValueType& elem);
inline queue_op_status try_pull(value_type&);
inline queue_op_status nonblocking_pull(value_type&);
inline queue_op_status wait_pull(ValueType& elem);
private:
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
#endif
inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline queue_op_status try_pull(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_pull(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_push(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void pull(value_type& elem, unique_lock<mutex>& )
{
elem = boost::move(super::data_.front());
@@ -115,26 +89,7 @@ namespace concurrent
super::data_.pop_front();
return boost::move(e);
}
inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& )
{
shared_ptr<value_type> res = make_shared<value_type>(boost::move(super::data_.front()));
super::data_.pop_front();
return res;
}
#endif
inline void pull_front(value_type& elem, unique_lock<mutex>& )
{
elem = boost::move(super::data_.front());
super::data_.pop_front();
}
inline value_type pull_front(unique_lock<mutex>& )
{
value_type e = boost::move(super::data_.front());
super::data_.pop_front();
return boost::move(e);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void push(const value_type& elem, unique_lock<mutex>& lk)
{
super::data_.push_back(elem);
@@ -146,29 +101,17 @@ namespace concurrent
super::data_.push_back(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
#endif
inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
{
super::data_.push_back(elem);
super::notify_not_empty_if_needed(lk);
}
inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
{
super::data_.push_back(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
};
template <typename ValueType>
sync_queue<ValueType>::sync_queue() :
template <class ValueType, class Container>
sync_queue<ValueType, Container>::sync_queue() :
super()
{
}
// template <typename ValueType>
// template <typename Range>
// explicit sync_queue<ValueType>::sync_queue(Range range) :
// template <class ValueType, class Container>
// template <class Range>
// explicit sync_queue<ValueType, Container>::sync_queue(Range range) :
// data_(), closed_(false)
// {
// try
@@ -188,47 +131,24 @@ namespace concurrent
// }
// }
template <typename ValueType>
sync_queue<ValueType>::~sync_queue()
template <class ValueType, class Container>
sync_queue<ValueType, Container>::~sync_queue()
{
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
super::throw_if_closed(lk);
return false;
}
pull(elem, lk);
return true;
}
template <typename ValueType>
shared_ptr<ValueType> sync_queue<ValueType>::try_pull(unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
super::throw_if_closed(lk);
return shared_ptr<ValueType>();
}
return ptr_pull(lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull_front(elem, lk);
pull(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
@@ -236,301 +156,165 @@ namespace concurrent
}
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
pull_front(elem, lk);
pull(elem, lk);
return queue_op_status::success;
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_pull(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_pull(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::try_pull(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_pull_front(elem, lk);
return try_pull(elem, lk);
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_pull_front(elem, lk);
return wait_pull(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_pull(no_block_tag,ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return false;
}
return try_pull(elem, lk);
}
template <typename ValueType>
boost::shared_ptr<ValueType> sync_queue<ValueType>::try_pull()
{
unique_lock<mutex> lk(super::mtx_);
return try_pull(lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::nonblocking_pull_front(ValueType& elem)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::nonblocking_pull(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_pull_front(elem, lk);
return try_pull(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_queue<ValueType>::pull(ValueType& elem)
template <class ValueType, class Container>
void sync_queue<ValueType, Container>::pull(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
pull(elem, lk);
}
template <typename ValueType>
void sync_queue<ValueType>::pull(ValueType& elem, bool & has_been_closed)
{
unique_lock<mutex> lk(super::mtx_);
has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) {return;}
pull(elem, lk);
}
// enable if ValueType is nothrow movable
template <typename ValueType>
ValueType sync_queue<ValueType>::pull()
template <class ValueType, class Container>
ValueType sync_queue<ValueType, Container>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull(lk);
}
template <typename ValueType>
boost::shared_ptr<ValueType> sync_queue<ValueType>::ptr_pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return ptr_pull(lk);
}
#endif
template <typename ValueType>
void sync_queue<ValueType>::pull_front(ValueType& elem)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
pull_front(elem, lk);
}
// enable if ValueType is nothrow movable
template <typename ValueType>
ValueType sync_queue<ValueType>::pull_front()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull_front(lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
{
super::throw_if_closed(lk);
if (super::closed(lk)) return queue_op_status::closed;
push(elem, lk);
return true;
}
template <typename ValueType>
bool sync_queue<ValueType>::try_push(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::try_push(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push_back(elem, lk);
return try_push(elem, lk);
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::wait_push(const ValueType& elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(elem, lk);
push(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::wait_push(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_push_back(elem, lk);
return wait_push(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(no_block_tag, const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock()) return false;
return try_push(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::nonblocking_push_back(const ValueType& elem)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::nonblocking_push(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock()) return queue_op_status::busy;
return try_push_back(elem, lk);
return try_push(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_queue<ValueType>::push(const ValueType& elem)
template <class ValueType, class Container>
void sync_queue<ValueType, Container>::push(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push(elem, lk);
}
#endif
template <typename ValueType>
void sync_queue<ValueType>::push_back(const ValueType& elem)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push_back(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
super::throw_if_closed(lk);
if (super::closed(lk)) return queue_op_status::closed;
push(boost::move(elem), lk);
return true;
}
template <typename ValueType>
bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(boost::move(elem), lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push_back(boost::move(elem), lk);
return try_push(boost::move(elem), lk);
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::wait_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(boost::move(elem), lk);
push(boost::move(elem), lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::wait_push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_push_back(boost::move(elem), lk);
return wait_push(boost::move(elem), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return false;
}
return try_push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::nonblocking_push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_push_back(boost::move(elem), lk);
return try_push(boost::move(elem), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_queue<ValueType>::push(BOOST_THREAD_RV_REF(ValueType) elem)
template <class ValueType, class Container>
void sync_queue<ValueType, Container>::push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
void sync_queue<ValueType>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
template <class ValueType, class Container>
sync_queue<ValueType, Container>& operator<<(sync_queue<ValueType, Container>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push_back(boost::move(elem), lk);
}
template <typename ValueType>
sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
{
sbq.push_back(boost::move(elem));
sbq.push(boost::move(elem));
return sbq;
}
template <typename ValueType>
sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, ValueType const&elem)
template <class ValueType, class Container>
sync_queue<ValueType, Container>& operator<<(sync_queue<ValueType, Container>& sbq, ValueType const&elem)
{
sbq.push_back(elem);
sbq.push(elem);
return sbq;
}
template <typename ValueType>
sync_queue<ValueType>& operator>>(sync_queue<ValueType>& sbq, ValueType &elem)
template <class ValueType, class Container>
sync_queue<ValueType, Container>& operator>>(sync_queue<ValueType, Container>& sbq, ValueType &elem)
{
sbq.pull_front(elem);
sbq.pull(elem);
return sbq;
}

View File

@@ -24,11 +24,12 @@ namespace concurrent
{
namespace detail
{
template <class T>
template <class T, class Clock = chrono::steady_clock>
struct scheduled_type
{
typedef typename chrono::steady_clock clock;
typedef chrono::steady_clock::time_point time_point;
typedef T value_type;
typedef Clock clock;
typedef typename clock::time_point time_point;
T data;
time_point time;
@@ -64,20 +65,17 @@ namespace detail
} //end detail namespace
template <class T>
template <class T, class Clock = chrono::steady_clock>
class sync_timed_queue
: private sync_priority_queue<detail::scheduled_type<T> >
: private sync_priority_queue<detail::scheduled_type<T, Clock> >
{
typedef detail::scheduled_type<T> stype;
typedef sync_priority_queue<stype> super;
public:
//typedef typename stype::clock clock; // fixme
typedef typename chrono::steady_clock clock;
typedef T value_type;
typedef Clock clock;
typedef typename clock::duration duration;
typedef typename clock::time_point time_point;
typedef T value_type;
//typedef typename super::value_type value_type; // fixme
typedef typename super::underlying_queue_type underlying_queue_type;
typedef typename super::size_type size_type;
typedef typename super::op_status op_status;
@@ -94,21 +92,34 @@ namespace detail
T pull();
void pull(T& elem);
queue_op_status pull_until(const clock::time_point& tp, T& elem);
queue_op_status pull_for(const clock::duration& dura, T& elem);
template <class Duration>
queue_op_status pull_until(chrono::time_point<clock,Duration> const& tp, T& elem);
template <class Rep, class Period>
queue_op_status pull_for(chrono::duration<Rep,Period> const& dura, T& elem);
queue_op_status try_pull(T& elem);
queue_op_status wait_pull(T& elem);
queue_op_status nonblocking_pull(T& elem);
void push(const T& elem, const time_point& tp);
void push(const T& elem, const duration& dura);
template <class Duration>
void push(const T& elem, chrono::time_point<clock,Duration> const& tp);
template <class Rep, class Period>
void push(const T& elem, chrono::duration<Rep,Period> const& dura);
queue_op_status try_push(const T& elem, const time_point& tp);
queue_op_status try_push(const T& elem, const duration& dura);
template <class Duration>
void push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp);
template <class Rep, class Period>
void push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura);
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, const time_point& tp);
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, const duration& dura);
template <class Duration>
queue_op_status try_push(const T& elem, chrono::time_point<clock,Duration> const& tp);
template <class Rep, class Period>
queue_op_status try_push(const T& elem, chrono::duration<Rep,Period> const& dura);
template <class Duration>
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp);
template <class Rep, class Period>
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura);
private:
T pull(unique_lock<mutex>&);
@@ -122,11 +133,10 @@ namespace detail
queue_op_status wait_pull(unique_lock<mutex>& lk, T& elem);
//queue_op_status nonblocking_pull(unique_lock<mutex>& lk, T& elem);
bool wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>&);
T pull_when_time_reached(unique_lock<mutex>&);
queue_op_status pull_when_time_reached_until(unique_lock<mutex>&, const clock::time_point& tp, T& elem);
template <class Duration>
queue_op_status pull_when_time_reached_until(unique_lock<mutex>&, chrono::time_point<clock,Duration> const& tp, T& elem);
bool time_not_reached(unique_lock<mutex>&);
bool time_not_reached(lock_guard<mutex>&);
bool empty_or_time_not_reached(unique_lock<mutex>&);
@@ -139,58 +149,80 @@ namespace detail
}; //end class
template <class T>
void sync_timed_queue<T>::push(const T& elem, const time_point& tp)
template <class T, class Clock>
template <class Duration>
void sync_timed_queue<T, Clock>::push(const T& elem, chrono::time_point<clock,Duration> const& tp)
{
super::push(stype(elem,tp));
}
template <class T>
void sync_timed_queue<T>::push(const T& elem, const duration& dura)
template <class T, class Clock>
template <class Rep, class Period>
void sync_timed_queue<T, Clock>::push(const T& elem, chrono::duration<Rep,Period> const& dura)
{
push(elem, clock::now() + dura);
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(const T& elem, const time_point& tp)
template <class T, class Clock>
template <class Duration>
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
{
super::push(stype(boost::move(elem),tp));
}
template <class T, class Clock>
template <class Rep, class Period>
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
{
push(boost::move(elem), clock::now() + dura);
}
template <class T, class Clock>
template <class Duration>
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp)
{
return super::try_push(stype(elem,tp));
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(const T& elem, const duration& dura)
template <class T, class Clock>
template <class Rep, class Period>
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::duration<Rep,Period> const& dura)
{
return try_push(elem,clock::now() + dura);
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(BOOST_THREAD_RV_REF(T) elem, const time_point& tp)
template <class T, class Clock>
template <class Duration>
queue_op_status sync_timed_queue<T, Clock>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
{
return super::try_push(stype(boost::move(elem), tp));
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(BOOST_THREAD_RV_REF(T) elem, const duration& dura)
template <class T, class Clock>
template <class Rep, class Period>
queue_op_status sync_timed_queue<T, Clock>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
{
return try_push(boost::move(elem), clock::now() + dura);
}
///////////////////////////
template <class T>
bool sync_timed_queue<T>::time_not_reached(unique_lock<mutex>&)
template <class T, class Clock>
bool sync_timed_queue<T, Clock>::time_not_reached(unique_lock<mutex>&)
{
return super::data_.top().time_not_reached();
}
template <class T>
bool sync_timed_queue<T>::time_not_reached(lock_guard<mutex>&)
template <class T, class Clock>
bool sync_timed_queue<T, Clock>::time_not_reached(lock_guard<mutex>&)
{
return super::data_.top().time_not_reached();
}
///////////////////////////
template <class T>
bool sync_timed_queue<T>::wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>& lk)
template <class T, class Clock>
bool sync_timed_queue<T, Clock>::wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>& lk)
{
for (;;)
{
@@ -207,8 +239,8 @@ namespace detail
}
///////////////////////////
template <class T>
T sync_timed_queue<T>::pull_when_time_reached(unique_lock<mutex>& lk)
template <class T, class Clock>
T sync_timed_queue<T, Clock>::pull_when_time_reached(unique_lock<mutex>& lk)
{
while (time_not_reached(lk))
{
@@ -219,11 +251,12 @@ namespace detail
return pull(lk);
}
template <class T>
template <class T, class Clock>
template <class Duration>
queue_op_status
sync_timed_queue<T>::pull_when_time_reached_until(unique_lock<mutex>& lk, const clock::time_point& tp, T& elem)
sync_timed_queue<T, Clock>::pull_when_time_reached_until(unique_lock<mutex>& lk, chrono::time_point<clock,Duration> const& tp, T& elem)
{
clock::time_point tpmin = (tp < super::data_.top().time) ? tp : super::data_.top().time;
chrono::time_point<clock,Duration> tpmin = (tp < super::data_.top().time) ? tp : super::data_.top().time;
while (time_not_reached(lk))
{
super::throw_if_closed(lk);
@@ -237,15 +270,15 @@ namespace detail
}
///////////////////////////
template <class T>
bool sync_timed_queue<T>::empty_or_time_not_reached(unique_lock<mutex>& lk)
template <class T, class Clock>
bool sync_timed_queue<T, Clock>::empty_or_time_not_reached(unique_lock<mutex>& lk)
{
if ( super::empty(lk) ) return true;
if ( time_not_reached(lk) ) return true;
return false;
}
template <class T>
bool sync_timed_queue<T>::empty_or_time_not_reached(lock_guard<mutex>& lk)
template <class T, class Clock>
bool sync_timed_queue<T, Clock>::empty_or_time_not_reached(lock_guard<mutex>& lk)
{
if ( super::empty(lk) ) return true;
if ( time_not_reached(lk) ) return true;
@@ -253,8 +286,8 @@ namespace detail
}
///////////////////////////
template <class T>
T sync_timed_queue<T>::pull(unique_lock<mutex>&)
template <class T, class Clock>
T sync_timed_queue<T, Clock>::pull(unique_lock<mutex>&)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
return boost::move(super::data_.pull().data);
@@ -263,8 +296,8 @@ namespace detail
#endif
}
template <class T>
T sync_timed_queue<T>::pull(lock_guard<mutex>&)
template <class T, class Clock>
T sync_timed_queue<T, Clock>::pull(lock_guard<mutex>&)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
return boost::move(super::data_.pull().data);
@@ -272,8 +305,8 @@ namespace detail
return super::data_.pull().data;
#endif
}
template <class T>
T sync_timed_queue<T>::pull()
template <class T, class Clock>
T sync_timed_queue<T, Clock>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
@@ -281,8 +314,8 @@ namespace detail
}
///////////////////////////
template <class T>
void sync_timed_queue<T>::pull(unique_lock<mutex>&, T& elem)
template <class T, class Clock>
void sync_timed_queue<T, Clock>::pull(unique_lock<mutex>&, T& elem)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
elem = boost::move(super::data_.pull().data);
@@ -291,8 +324,8 @@ namespace detail
#endif
}
template <class T>
void sync_timed_queue<T>::pull(lock_guard<mutex>&, T& elem)
template <class T, class Clock>
void sync_timed_queue<T, Clock>::pull(lock_guard<mutex>&, T& elem)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
elem = boost::move(super::data_.pull().data);
@@ -301,8 +334,8 @@ namespace detail
#endif
}
template <class T>
void sync_timed_queue<T>::pull(T& elem)
template <class T, class Clock>
void sync_timed_queue<T, Clock>::pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
@@ -310,9 +343,10 @@ namespace detail
}
//////////////////////
template <class T>
template <class T, class Clock>
template <class Duration>
queue_op_status
sync_timed_queue<T>::pull_until(const clock::time_point& tp, T& elem)
sync_timed_queue<T, Clock>::pull_until(chrono::time_point<clock,Duration> const& tp, T& elem)
{
unique_lock<mutex> lk(super::mtx_);
@@ -322,16 +356,17 @@ namespace detail
}
//////////////////////
template <class T>
template <class T, class Clock>
template <class Rep, class Period>
queue_op_status
sync_timed_queue<T>::pull_for(const clock::duration& dura, T& elem)
sync_timed_queue<T, Clock>::pull_for(chrono::duration<Rep,Period> const& dura, T& elem)
{
return pull_until(clock::now() + dura, elem);
}
///////////////////////////
template <class T>
queue_op_status sync_timed_queue<T>::try_pull(unique_lock<mutex>& lk, T& elem)
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::try_pull(unique_lock<mutex>& lk, T& elem)
{
if ( super::empty(lk) )
{
@@ -347,8 +382,8 @@ namespace detail
pull(lk, elem);
return queue_op_status::success;
}
template <class T>
queue_op_status sync_timed_queue<T>::try_pull(lock_guard<mutex>& lk, T& elem)
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::try_pull(lock_guard<mutex>& lk, T& elem)
{
if ( super::empty(lk) )
{
@@ -364,16 +399,16 @@ namespace detail
return queue_op_status::success;
}
template <class T>
queue_op_status sync_timed_queue<T>::try_pull(T& elem)
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::try_pull(T& elem)
{
lock_guard<mutex> lk(super::mtx_);
return try_pull(lk, elem);
}
///////////////////////////
template <class T>
queue_op_status sync_timed_queue<T>::wait_pull(unique_lock<mutex>& lk, T& elem)
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::wait_pull(unique_lock<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
@@ -385,16 +420,16 @@ namespace detail
return queue_op_status::success;
}
template <class T>
queue_op_status sync_timed_queue<T>::wait_pull(T& elem)
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::wait_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_pull(lk, elem);
}
// ///////////////////////////
// template <class T>
// queue_op_status sync_timed_queue<T>::wait_pull(unique_lock<mutex> &lk, T& elem)
// template <class T, class Clock>
// queue_op_status sync_timed_queue<T, Clock>::wait_pull(unique_lock<mutex> &lk, T& elem)
// {
// if (super::empty(lk))
// {
@@ -406,15 +441,15 @@ namespace detail
// return queue_op_status::success;
// }
// template <class T>
// queue_op_status sync_timed_queue<T>::wait_pull(T& elem)
// queue_op_status sync_timed_queue<T, Clock>::wait_pull(T& elem)
// {
// unique_lock<mutex> lk(super::mtx_);
// return wait_pull(lk, elem);
// }
///////////////////////////
template <class T>
queue_op_status sync_timed_queue<T>::nonblocking_pull(T& elem)
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::nonblocking_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (! lk.owns_lock()) return queue_op_status::busy;

View File

@@ -19,7 +19,7 @@
// [
// _Ty=non_copyable
// ]
#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_HDR_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
#ifndef BOOST_THREAD_USES_BOOST_DEQUE
#define BOOST_THREAD_USES_BOOST_DEQUE
#endif

View File

@@ -0,0 +1,100 @@
// Copyright (C) 2013 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_DEVECTOR_HPP
#define BOOST_CSBL_DEVECTOR_HPP
#include <boost/config.hpp>
#include <boost/thread/csbl/vector.hpp>
#include <boost/move/detail/move_helpers.hpp>
namespace boost
{
namespace csbl
{
template <class T>
class devector
{
typedef vector<T> vector_type;
vector<T> data_;
std::size_t front_index_;
BOOST_COPYABLE_AND_MOVABLE(devector)
template <class U>
void priv_push_back(BOOST_FWD_REF(U) x)
{ data_.push_back(boost::forward<U>(x)); }
public:
typedef typename vector_type::size_type size_type;
typedef typename vector_type::reference reference;
typedef typename vector_type::const_reference const_reference;
devector() : front_index_(0) {}
devector(devector const& x) BOOST_NOEXCEPT
: data_(x.data_),
front_index_(x.front_index_)
{}
devector(BOOST_RV_REF(devector) x) BOOST_NOEXCEPT
: data_(boost::move(x.data_)),
front_index_(x.front_index_)
{}
devector& operator=(BOOST_COPY_ASSIGN_REF(devector) x)
{
if (&x != this)
{
data_ = x.data_;
front_index_ = x.front_index_;
}
return *this;
}
devector& operator=(BOOST_RV_REF(devector) x)
BOOST_NOEXCEPT_IF(vector<T>::allocator_traits_type::propagate_on_container_move_assignment::value)
{
data_ = boost::move(x.data_);
front_index_ = x.front_index_;
return *this;
}
bool empty() const BOOST_NOEXCEPT
{ return data_.size() == front_index_; }
size_type size() const BOOST_NOEXCEPT
{ return data_.size() - front_index_; }
reference front() BOOST_NOEXCEPT
{ return data_[front_index_]; }
const_reference front() const BOOST_NOEXCEPT
{ return data_[front_index_]; }
reference back() BOOST_NOEXCEPT
{ return data_.back(); }
const_reference back() const BOOST_NOEXCEPT
{ return data_.back(); }
BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
void pop_front()
{
++front_index_;
if (empty()) {
data_.clear();
front_index_=0;
}
}
};
}
}
#endif // header

View File

@@ -11,7 +11,7 @@
#include <boost/config.hpp>
#if defined BOOST_THREAD_USES_BOOST_LIST || defined BOOST_NO_CXX11_HDR_LIST || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined BOOST_THREAD_USES_BOOST_LIST || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_THREAD_USES_BOOST_LIST
#define BOOST_THREAD_USES_BOOST_LIST
#endif

View File

@@ -0,0 +1,45 @@
// Copyright (C) 2015 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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_QUEUE_HPP
#define BOOST_CSBL_QUEUE_HPP
#include <boost/config.hpp>
// MSVC has some trouble instantiating a non_copyable type
//C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(606) : error C2248: 'non_copyable::non_copyable' : cannot access private member declared in class 'non_copyable'
// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(24) : see declaration of 'non_copyable::non_copyable'
// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(23) : see declaration of 'non_copyable'
// C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
// with
// [
// _Ty=non_copyable
// ]
#if defined BOOST_THREAD_USES_BOOST_QUEUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
#ifndef BOOST_THREAD_USES_BOOST_QUEUE
#define BOOST_THREAD_USES_BOOST_QUEUE
#endif
#include <boost/container/queue.hpp>
#else
#include <queue>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_QUEUE
using ::boost::container::queue;
#else
using ::std::queue;
#endif
}
}
#endif // header

View File

@@ -11,7 +11,7 @@
#include <boost/config.hpp>
#if defined BOOST_THREAD_USES_BOOST_VECTOR || defined BOOST_NO_CXX11_HDR_VECTOR || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined BOOST_THREAD_USES_BOOST_VECTOR || defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_MSVC
#ifndef BOOST_THREAD_USES_BOOST_VECTOR
#define BOOST_THREAD_USES_BOOST_VECTOR
#endif

View File

@@ -134,7 +134,7 @@ namespace boost
//BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END
#else
#if ! defined BOOST_MSVC
#if ! defined BOOST_MSVC && defined(BOOST_THREAD_PROVIDES_INVOKE)
#define BOOST_THREAD_RV_REF_ARG_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(Arg##n)
#define BOOST_THREAD_RV_REF_A_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(A##n)

View File

@@ -1,23 +0,0 @@
// (C) Copyright 2013 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_WORK_HPP
#define BOOST_THREAD_DETAIL_WORK_HPP
#include <boost/thread/detail/nullary_function.hpp>
namespace boost
{
namespace thread_detail
{
typedef detail::nullary_function<void()> work;
}
} // namespace boost
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP

View File

@@ -14,7 +14,7 @@
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/csbl/vector.hpp>
@@ -51,7 +51,7 @@ namespace executors
try
{
work task;
if (work_queue.try_pull_front(task) == queue_op_status::success)
if (work_queue.try_pull(task) == queue_op_status::success)
{
task();
return true;
@@ -87,7 +87,7 @@ namespace executors
for(;;)
{
work task;
queue_op_status st = work_queue.wait_pull_front(task);
queue_op_status st = work_queue.wait_pull(task);
if (st == queue_op_status::closed) return;
task();
}
@@ -269,18 +269,18 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
work_queue.push_back(work(closure));
work_queue.push(work(closure));
}
#endif
void submit(void (*closure)())
{
work_queue.push_back(work(closure));
work_queue.push(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work_queue.push_back(work(boost::forward<Closure>(closure)));
work_queue.push(work(boost::forward<Closure>(closure)));
}
/**

View File

@@ -0,0 +1,77 @@
// Copyright (C) 2014 Ian Forbed
// Copyright (C) 2014 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_EXECUTORS_DETAIL_PRIORITY_EXECUTOR_BASE_HPP
#define BOOST_THREAD_EXECUTORS_DETAIL_PRIORITY_EXECUTOR_BASE_HPP
#include <boost/atomic.hpp>
#include <boost/function.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/concurrent_queues/sync_timed_queue.hpp>
#include <boost/thread/executors/work.hpp>
namespace boost
{
namespace executors
{
namespace detail
{
template <class Queue>
class priority_executor_base
{
public:
//typedef boost::function<void()> work;
typedef executors::work_pq work;
protected:
typedef Queue queue_type;
queue_type _workq;
priority_executor_base() {}
public:
~priority_executor_base()
{
if(!closed())
{
this->close();
}
}
void close()
{
_workq.close();
}
bool closed()
{
return _workq.closed();
}
void loop()
{
try
{
for(;;)
{
work task;
queue_op_status st = _workq.wait_pull(task);
if (st == queue_op_status::closed) return;
task();
}
}
catch (...)
{
std::terminate();
return;
}
}
}; //end class
} //end detail namespace
} //end executors namespace
} //end boost namespace
#endif

View File

@@ -1,18 +1,22 @@
// Copyright (C) 2014 Ian Forbed
// Copyright (C) 2014 Vicente J. Botet Escriba
// Copyright (C) 2014-2015 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 SCHEDULED_EXECUTOR_HPP
#define SCHEDULED_EXECUTOR_HPP
#ifndef BOOST_THREAD_EXECUTORS_DETAIL_SCHEDULED_EXECUTOR_BASE_HPP
#define BOOST_THREAD_EXECUTORS_DETAIL_SCHEDULED_EXECUTOR_BASE_HPP
#include <boost/thread/concurrent_queues/sync_timed_queue.hpp>
#include <boost/thread/executors/detail/priority_executor_base.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/thread.hpp>
#include <boost/atomic.hpp>
#include <boost/function.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/concurrent_queues/sync_timed_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
@@ -20,74 +24,43 @@ namespace executors
{
namespace detail
{
class scheduled_executor_base
template <class Clock=chrono::steady_clock>
class scheduled_executor_base : public priority_executor_base<concurrent::sync_timed_queue<executors::work_pq, Clock > >
{
public:
typedef boost::function<void()> work;
//typedef executors::work work;
typedef chrono::steady_clock clock;
typedef clock::duration duration;
typedef clock::time_point time_point;
typedef executors::work_pq work;
typedef Clock clock;
typedef typename clock::duration duration;
typedef typename clock::time_point time_point;
protected:
concurrent::sync_timed_queue<work> _workq;
scheduled_executor_base() {}
public:
~scheduled_executor_base()
{
if(!closed())
if(! this->closed())
{
this->close();
}
}
void close()
{
_workq.close();
}
bool closed()
{
return _workq.closed();
}
void submit(work w)
{
_workq.push(w, clock::now());
}
void submit_at(work w, const time_point& tp)
{
_workq.push(w, tp);
this->_workq.push(boost::move(w), tp);
}
void submit_after(work w, const duration& dura)
{
_workq.push(w, dura);
this->_workq.push(boost::move(w), dura+clock::now());
}
void loop()
{
try
{
for(;;)
{
work task;
queue_op_status st = _workq.wait_pull(task);
if (st == queue_op_status::closed) return;
task();
}
}
catch (...)
{
std::terminate();
return;
}
}
}; //end class
} //end detail namespace
} //end executors namespace
} //end boost namespace
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -14,7 +14,7 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -44,7 +44,7 @@ namespace executors
work task;
try
{
if (work_queue.try_pull_front(task) == queue_op_status::success)
if (work_queue.try_pull(task) == queue_op_status::success)
{
task();
return true;
@@ -143,18 +143,18 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
work_queue.push_back(work(closure));
work_queue.push(work(closure));
}
#endif
void submit(void (*closure)())
{
work_queue.push_back(work(closure));
work_queue.push(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work_queue.push_back(work(boost::forward<Closure>(closure)));
work_queue.push(work(boost::forward<Closure>(closure)));
}
/**

View File

@@ -15,7 +15,7 @@ namespace boost
namespace executors
{
class scheduled_thread_pool : public detail::scheduled_executor_base
class scheduled_thread_pool : public detail::scheduled_executor_base<>
{
private:
thread_group _workers;
@@ -36,29 +36,9 @@ namespace executors
}
private:
typedef detail::scheduled_executor_base super;
inline void loop();
typedef detail::scheduled_executor_base<> super;
}; //end class
void scheduled_thread_pool::loop()
{
try
{
for(;;)
{
super::work task;
queue_op_status st = super::_workq.wait_pull(task);
if (st == queue_op_status::closed) return;
task();
}
}
catch (...)
{
std::terminate();
return;
}
}
} //end executors namespace
using executors::scheduled_thread_pool;

View File

@@ -10,6 +10,8 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/executors/detail/scheduled_executor_base.hpp>
#include <boost/chrono/time_point.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -51,9 +53,11 @@ namespace boost
class resubmit_at_executor
{
public:
typedef chrono::steady_clock clock;
typedef typename Scheduler::clock clock;
typedef typename Scheduler::work work;
resubmit_at_executor(Scheduler& sch, Executor& ex, clock::time_point const& tp) :
template <class Duration>
resubmit_at_executor(Scheduler& sch, Executor& ex, chrono::time_point<clock, Duration> const& tp) :
sch(sch),
ex(ex),
tp(tp),
@@ -98,7 +102,7 @@ namespace boost
private:
Scheduler& sch;
Executor& ex;
clock::time_point tp;
typename clock::time_point tp;
bool is_closed;
};
@@ -111,7 +115,8 @@ namespace boost
class scheduler_executor_wrapper
{
public:
typedef chrono::steady_clock clock;
typedef typename Scheduler::clock clock;
typedef typename Scheduler::work work;
typedef resubmit_at_executor<Scheduler, Executor> the_executor;
scheduler_executor_wrapper(Scheduler& sch, Executor& ex) :
@@ -132,13 +137,14 @@ namespace boost
return sch;
}
template <class Duration>
the_executor after(Duration const& rel_time)
template <class Rep, class Period>
the_executor after(chrono::duration<Rep,Period> const& rel_time)
{
return at(clock::now() + rel_time );
}
the_executor at(clock::time_point const& abs_time)
template <class Duration>
the_executor at(chrono::time_point<clock,Duration> const& abs_time)
{
return the_executor(sch, ex, abs_time);
}
@@ -154,9 +160,12 @@ namespace boost
class at_executor
{
public:
typedef chrono::steady_clock clock;
typedef typename Scheduler::clock clock;
typedef typename Scheduler::work work;
typedef typename clock::time_point time_point;
at_executor(Scheduler& sch, clock::time_point const& tp) :
template <class Duration>
at_executor(Scheduler& sch, chrono::time_point<clock,Duration> const& tp) :
sch(sch),
tp(tp),
is_closed(false)
@@ -200,18 +209,20 @@ namespace boost
private:
Scheduler& sch;
clock::time_point tp;
time_point tp;
bool is_closed;
}; //end class
/// A @c Scheduler using a specific thread. Note that a Scheduler is not an Executor.
/// It provides factory helper functions such as at/after that convert a @c Scheduler into an @c Executor
/// that submit the work at/after a specific time/duration respectively.
class scheduler : public detail::scheduled_executor_base
template <class Clock = chrono::steady_clock>
class scheduler : public detail::scheduled_executor_base<Clock>
{
public:
typedef chrono::steady_clock clock;
typedef clock::time_point time_point;
typedef typename detail::scheduled_executor_base<Clock>::work work;
typedef Clock clock;
scheduler()
: super(),
@@ -228,19 +239,20 @@ namespace boost
return scheduler_executor_wrapper<scheduler, Ex>(*this, ex);
}
template <class Duration>
at_executor<scheduler> after(Duration const& rel_time)
template <class Rep, class Period>
at_executor<scheduler> after(chrono::duration<Rep,Period> const& rel_time)
{
return at(rel_time + clock::now());
}
at_executor<scheduler> at(time_point const& tp)
template <class Duration>
at_executor<scheduler> at(chrono::time_point<clock,Duration> const& tp)
{
return at_executor<scheduler>(*this, tp);
}
private:
typedef detail::scheduled_executor_base super;
typedef detail::scheduled_executor_base<Clock> super;
thread thr;
};

View File

@@ -16,7 +16,7 @@ namespace executors
{
template <typename Executor>
class scheduling_adpator : public detail::scheduled_executor_base
class scheduling_adpator : public detail::scheduled_executor_base<>
{
private:
Executor& _exec;
@@ -26,7 +26,7 @@ namespace executors
scheduling_adpator(Executor& ex)
: super(),
_exec(ex),
_scheduler(&scheduling_adpator::loop, this) {}
_scheduler(&super::loop, this) {}
~scheduling_adpator()
{
@@ -40,30 +40,9 @@ namespace executors
}
private:
typedef detail::scheduled_executor_base super;
void loop();
typedef detail::scheduled_executor_base<> super;
}; //end class
template<typename Executor>
void scheduling_adpator<Executor>::loop()
{
try
{
for(;;)
{
super::work task;
queue_op_status st = super::_workq.wait_pull(task);
if (st == queue_op_status::closed) return;
_exec.submit(task);
}
}
catch (...)
{
std::terminate();
return;
}
}
} //end executors
using executors::scheduling_adpator;

View File

@@ -12,7 +12,7 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/executors/generic_executor_ref.hpp>
#include <boost/thread/future.hpp>
@@ -43,8 +43,13 @@ namespace executors
try_executing_one_task(work& task, boost::promise<void> &p)
: task(task), p(p) {}
void operator()() {
task();
p.set_value();
try {
task();
p.set_value();
} catch (...)
{
p.set_exception(current_exception());
}
}
};
public:
@@ -64,7 +69,7 @@ namespace executors
work task;
try
{
if (work_queue.try_pull_front(task) == queue_op_status::success)
if (work_queue.try_pull(task) == queue_op_status::success)
{
boost::promise<void> p;
try_executing_one_task tmp(task,p);
@@ -165,18 +170,18 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
work_queue.push_back(work(closure));
work_queue.push(work(closure));
}
#endif
void submit(void (*closure)())
{
work_queue.push_back(work(closure));
work_queue.push(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work_queue.push_back(work(boost::forward<Closure>(closure)));
work_queue.push(work(boost::forward<Closure>(closure)));
}
/**

View File

@@ -0,0 +1,170 @@
// Copyright (C) 2015 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)
//
// 2013/11 Vicente J. Botet Escriba
// first implementation of a simple serial scheduler.
#ifndef BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
#define BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/executors/generic_executor_ref.hpp>
#include <boost/thread/future.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
class serial_executor_cont
{
public:
/// type-erasure to store the works to do
typedef executors::work work;
private:
generic_executor_ref ex_;
future<void> fut_; // protected by mtx_
bool closed_; // protected by mtx_
mutex mtx_;
struct continuation {
work task;
template <class X>
struct result {
typedef void type;
};
continuation(BOOST_THREAD_RV_REF(work) tsk)
: task(boost::move(tsk)) {}
void operator()(future<void> f)
{
try {
task();
} catch (...) {
std::terminate();
}
}
};
bool closed(lock_guard<mutex>&) const
{
return closed_;
}
public:
/**
* \par Returns
* The underlying executor wrapped on a generic executor reference.
*/
generic_executor_ref& underlying_executor() BOOST_NOEXCEPT { return ex_; }
/// serial_executor_cont is not copyable.
BOOST_THREAD_NO_COPYABLE(serial_executor_cont)
/**
* \b Effects: creates a serial executor that runs closures in fifo order using one the associated executor.
*
* \b Throws: Whatever exception is thrown while initializing the needed resources.
*
* \b Notes:
* * The lifetime of the associated executor must outlive the serial executor.
* * The current implementation doesn't support submission from synchronous continuation, that is,
* - the executor must execute the continuation asynchronously or
* - the continuation can not submit to this serial executor.
*/
template <class Executor>
serial_executor_cont(Executor& ex)
: ex_(ex), fut_(make_ready_future()), closed_(false)
{
}
/**
* \b Effects: Destroys the thread pool.
*
* \b Synchronization: The completion of all the closures happen before the completion of the \c serial_executor_cont destructor.
*/
~serial_executor_cont()
{
// signal to the worker thread that there will be no more submissions.
close();
}
/**
* \b Effects: close the \c serial_executor_cont for submissions.
* The loop will work until there is no more closures to run.
*/
void close()
{
lock_guard<mutex> lk(mtx_);
closed_ = true;;
}
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed()
{
lock_guard<mutex> lk(mtx_);
return closed(lk);
}
/**
* Effects: none.
* Returns: always false.
* Throws: No.
* Remark: A serial executor can not execute one of its pending tasks as the tasks depends on the other tasks.
*/
bool try_executing_one()
{
return false;
}
/**
* \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
*
* \b Effects: The specified \c closure will be scheduled for execution after the last submitted closure finish.
* If the invoked closure throws an exception the \c serial_executor_cont will call \c std::terminate, as is the case with threads.
*
* \b Throws: \c sync_queue_is_closed if the executor is closed.
* Whatever exception that can be throw while storing the closure.
*
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
fut_ = fut_.then(ex_, continuation(work(closure)));
}
#endif
void submit(void (*closure)())
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
fut_ = fut_.then(ex_, continuation(work(closure)));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
fut_ = fut_.then(ex_, continuation(work(boost::forward<Closure>(closure))));
}
};
}
using executors::serial_executor_cont;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -8,36 +8,23 @@
#define BOOST_THREAD_EXECUTORS_WORK_HPP
#include <boost/thread/detail/config.hpp>
#if ! defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE \
&& ! defined BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
#define BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
//#define BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
#endif
#if defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
#include <boost/thread/detail/nullary_function.hpp>
namespace boost
{
namespace executors
{
typedef detail::nullary_function<void()> work;
}
} // namespace boost
#else
#include <boost/thread/csbl/functional.hpp>
namespace boost
{
namespace executors
{
typedef csbl::function<void()> work;
typedef detail::nullary_function<void()> work;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef detail::nullary_function<void()> work_pq;
//typedef csbl::function<void()> work_pq;
#else
typedef csbl::function<void()> work_pq;
#endif
}
} // namespace boost
#endif
#endif // BOOST_THREAD_EXECUTORS_WORK_HPP

View File

@@ -3,21 +3,22 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost
// (C) Copyright Vicente J. Botet Escriba 2014-2015. 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)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#if ! defined BOOST_NO_CXX11_RANGE_BASED_FOR
#include <boost/thread/detail/config.hpp>
#include <boost/thread/future.hpp>
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
#include <boost/thread/executors/basic_thread_pool.hpp>
#endif
#include <boost/thread/experimental/exception_list.hpp>
#include <boost/thread/experimental/parallel/v2/inline_namespace.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -49,16 +50,18 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
void handle_task_region_exceptions(exception_list& errors)
{
try {
boost::rethrow_exception(boost::current_exception());
//throw boost::current_exception();
throw;
}
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
catch (task_canceled_exception& ex)
{
}
#endif
catch (exception_list const& el)
{
for (boost::exception_ptr const& e: el)
for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it)
{
boost::exception_ptr const& e = *it;
try {
rethrow_exception(e);
}
@@ -80,7 +83,7 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
{
TRH& tr;
F f;
wrapped(TRH& tr, F&& f) : tr(tr), f(move(f))
wrapped(TRH& tr, BOOST_THREAD_RV_REF(F) f) : tr(tr), f(move(f))
{}
void operator()()
{
@@ -92,7 +95,7 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
{
lock_guard<mutex> lk(tr.mtx);
tr.canceled = true;
handle_task_region_exceptions(tr.exs);
throw;
}
}
};
@@ -109,22 +112,21 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
friend struct detail::wrapped;
#endif
template <typename F>
friend void task_region(F&& f);
friend void task_region(BOOST_THREAD_FWD_REF(F) f);
template<typename F>
friend void task_region_final(F&& f);
friend void task_region_final(BOOST_THREAD_FWD_REF(F) f);
template <class Ex, typename F>
friend void task_region(Ex&, F&& f);
friend void task_region(Ex&, BOOST_THREAD_FWD_REF(F) f);
template<class Ex, typename F>
friend void task_region_final(Ex&, F&& f);
friend void task_region_final(Ex&, BOOST_THREAD_FWD_REF(F) f);
void wait_all()
{
wait_for_all(group.begin(), group.end());
#if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
for (future<void>& f: group)
for (group_type::iterator it = group.begin(); it != group.end(); ++it)
{
future<void>& f = *it;
if (f.has_exception())
{
try
@@ -137,11 +139,9 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
}
}
}
#endif
if (exs.size() != 0)
{
boost::throw_exception(exs);
//throw exs;
}
}
protected:
@@ -184,29 +184,31 @@ protected:
}
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
mutable mutex mtx;
bool canceled;
#endif
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
Executor* ex;
#endif
exception_list exs;
csbl::vector<future<void>> group;
mutable mutex mtx;
typedef csbl::vector<future<void> > group_type;
group_type group;
public:
task_region_handle_gen(const task_region_handle_gen&) = delete;
task_region_handle_gen& operator=(const task_region_handle_gen&) = delete;
task_region_handle_gen* operator&() const = delete;
BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&))
BOOST_DELETED_FUNCTION(task_region_handle_gen& operator=(const task_region_handle_gen&))
BOOST_DELETED_FUNCTION(task_region_handle_gen* operator&() const)
public:
template<typename F>
void run(F&& f)
void run(BOOST_THREAD_FWD_REF(F) f)
{
lock_guard<mutex> lk(mtx);
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
if (canceled) {
boost::throw_exception(task_canceled_exception());
//throw task_canceled_exception();
{
lock_guard<mutex> lk(mtx);
if (canceled) {
boost::throw_exception(task_canceled_exception());
}
}
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
group.push_back(async(*ex, detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f))));
@@ -224,11 +226,12 @@ protected:
void wait()
{
lock_guard<mutex> lk(mtx);
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
if (canceled) {
boost::throw_exception(task_canceled_exception());
//throw task_canceled_exception{};
{
lock_guard<mutex> lk(mtx);
if (canceled) {
boost::throw_exception(task_canceled_exception());
}
}
#endif
wait_all();
@@ -244,9 +247,9 @@ protected:
{
default_executor tp;
template <typename F>
friend void task_region(F&& f);
friend void task_region(BOOST_THREAD_FWD_REF(F) f);
template<typename F>
friend void task_region_final(F&& f);
friend void task_region_final(BOOST_THREAD_FWD_REF(F) f);
protected:
task_region_handle() : task_region_handle_gen<default_executor>()
@@ -255,14 +258,14 @@ protected:
ex = &tp;
#endif
}
task_region_handle(const task_region_handle&) = delete;
task_region_handle& operator=(const task_region_handle&) = delete;
task_region_handle* operator&() const = delete;
BOOST_DELETED_FUNCTION(task_region_handle(const task_region_handle&))
BOOST_DELETED_FUNCTION(task_region_handle& operator=(const task_region_handle&))
BOOST_DELETED_FUNCTION(task_region_handle* operator&() const)
};
template <typename Executor, typename F>
void task_region_final(Executor& ex, F&& f)
void task_region_final(Executor& ex, BOOST_THREAD_FWD_REF(F) f)
{
task_region_handle_gen<Executor> tr(ex);
try
@@ -271,20 +274,19 @@ protected:
}
catch (...)
{
lock_guard<mutex> lk(tr.mtx);
detail::handle_task_region_exceptions(tr.exs);
}
tr.wait_all();
}
template <typename Executor, typename F>
void task_region(Executor& ex, F&& f)
void task_region(Executor& ex, BOOST_THREAD_FWD_REF(F) f)
{
task_region_final(ex, forward<F>(f));
}
template <typename F>
void task_region_final(F&& f)
void task_region_final(BOOST_THREAD_FWD_REF(F) f)
{
task_region_handle tr;
try
@@ -293,14 +295,13 @@ protected:
}
catch (...)
{
lock_guard<mutex> lk(tr.mtx);
detail::handle_task_region_exceptions(tr.exs);
}
tr.wait_all();
}
template <typename F>
void task_region(F&& f)
void task_region(BOOST_THREAD_FWD_REF(F) f)
{
task_region_final(forward<F>(f));
}
@@ -312,5 +313,4 @@ protected:
#include <boost/config/abi_suffix.hpp>
#endif
#endif
#endif // header

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_FUTURE_ERROR_HPP
#define BOOST_THREAD_FUTURES_FUTURE_ERROR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/futures/future_error_code.hpp>
#include <boost/system/error_code.hpp>
#include <stdexcept>
namespace boost
{
class BOOST_SYMBOL_VISIBLE future_error
: public std::logic_error
{
system::error_code ec_;
public:
future_error(system::error_code ec)
: logic_error(ec.message()),
ec_(ec)
{
}
const system::error_code& code() const BOOST_NOEXCEPT
{
return ec_;
}
};
class BOOST_SYMBOL_VISIBLE future_uninitialized:
public future_error
{
public:
future_uninitialized() :
future_error(system::make_error_code(future_errc::no_state))
{}
};
class BOOST_SYMBOL_VISIBLE broken_promise:
public future_error
{
public:
broken_promise():
future_error(system::make_error_code(future_errc::broken_promise))
{}
};
class BOOST_SYMBOL_VISIBLE future_already_retrieved:
public future_error
{
public:
future_already_retrieved():
future_error(system::make_error_code(future_errc::future_already_retrieved))
{}
};
class BOOST_SYMBOL_VISIBLE promise_already_satisfied:
public future_error
{
public:
promise_already_satisfied():
future_error(system::make_error_code(future_errc::promise_already_satisfied))
{}
};
class BOOST_SYMBOL_VISIBLE task_already_started:
public future_error
{
public:
task_already_started():
future_error(system::make_error_code(future_errc::promise_already_satisfied))
{}
};
class BOOST_SYMBOL_VISIBLE task_moved:
public future_error
{
public:
task_moved():
future_error(system::make_error_code(future_errc::no_state))
{}
};
class promise_moved:
public future_error
{
public:
promise_moved():
future_error(system::make_error_code(future_errc::no_state))
{}
};
}
#endif // header

View File

@@ -1,12 +1,12 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// (C) Copyright 2011-2012,2015 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_FUTURE_ERROR_CODE_HPP
#define BOOST_THREAD_FUTURE_ERROR_CODE_HPP
#ifndef BOOST_THREAD_FUTURES_FUTURE_ERROR_CODE_HPP
#define BOOST_THREAD_FUTURES_FUTURE_ERROR_CODE_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/core/scoped_enum.hpp>

View File

@@ -0,0 +1,30 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_FUTURE_STATUS_HPP
#define BOOST_THREAD_FUTURES_FUTURE_STATUS_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/core/scoped_enum.hpp>
namespace boost
{
//enum class future_status
BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status)
{
ready,
timeout,
deferred
}
BOOST_SCOPED_ENUM_DECLARE_END(future_status)
namespace future_state
{
enum state { uninitialized, waiting, ready, moved, deferred };
}
}
#endif // header

View File

@@ -0,0 +1,21 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_IS_FUTURE_TYPE_HPP
#define BOOST_THREAD_FUTURES_IS_FUTURE_TYPE_HPP
#include <boost/type_traits/integral_constant.hpp>
namespace boost
{
template<typename T>
struct is_future_type : false_type
{
};
}
#endif // header

View File

@@ -0,0 +1,30 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_LAUNCH_HPP
#define BOOST_THREAD_FUTURES_LAUNCH_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/core/scoped_enum.hpp>
namespace boost
{
//enum class launch
BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch)
{
none = 0,
async = 1,
deferred = 2,
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
executor = 4,
#endif
any = async | deferred
}
BOOST_SCOPED_ENUM_DECLARE_END(launch)
}
#endif // header

View File

@@ -0,0 +1,74 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_WAIT_FOR_ALL_HPP
#define BOOST_THREAD_FUTURES_WAIT_FOR_ALL_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/futures/is_future_type.hpp>
#include <boost/core/enable_if.hpp>
namespace boost
{
template<typename Iterator>
typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end)
{
for(Iterator current=begin;current!=end;++current)
{
current->wait();
}
}
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<typename F1,typename F2>
typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2)
{
f1.wait();
f2.wait();
}
template<typename F1,typename F2,typename F3>
void wait_for_all(F1& f1,F2& f2,F3& f3)
{
f1.wait();
f2.wait();
f3.wait();
}
template<typename F1,typename F2,typename F3,typename F4>
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4)
{
f1.wait();
f2.wait();
f3.wait();
f4.wait();
}
template<typename F1,typename F2,typename F3,typename F4,typename F5>
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
{
f1.wait();
f2.wait();
f3.wait();
f4.wait();
f5.wait();
}
#else
template<typename F1, typename... Fs>
void wait_for_all(F1& f1, Fs&... fs)
{
bool dummy[] = { (f1.wait(), true), (fs.wait(), true)... };
// prevent unused parameter warning
(void) dummy;
}
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)}
}
#endif // header

View File

@@ -0,0 +1,161 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_WAIT_FOR_ANY_HPP
#define BOOST_THREAD_FUTURES_WAIT_FOR_ANY_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/futures/is_future_type.hpp>
#include <boost/thread/lock_algorithms.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/next_prior.hpp>
#include <boost/scoped_array.hpp>
#include <iterator>
#include <vector>
namespace boost
{
namespace detail
{
template <class Future>
class waiter_for_any_in_seq
{
struct registered_waiter;
typedef std::vector<int>::size_type count_type;
struct registered_waiter
{
typedef Future future_type;
future_type* future_;
typedef typename Future::notify_when_ready_handle notify_when_ready_handle;
notify_when_ready_handle handle;
count_type index;
registered_waiter(future_type & a_future,
notify_when_ready_handle handle_, count_type index_) :
future_(&a_future), handle(handle_), index(index_)
{
}
};
struct all_futures_lock
{
#ifdef _MANAGED
typedef std::ptrdiff_t count_type_portable;
#else
typedef count_type count_type_portable;
#endif
count_type_portable count;
boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
all_futures_lock(std::vector<registered_waiter>& waiters) :
count(waiters.size()), locks(new boost::unique_lock<boost::mutex>[count])
{
for (count_type_portable i = 0; i < count; ++i)
{
locks[i] = BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(waiters[i].future_->mutex()));
}
}
void lock()
{
boost::lock(locks.get(), locks.get() + count);
}
void unlock()
{
for (count_type_portable i = 0; i < count; ++i)
{
locks[i].unlock();
}
}
};
boost::condition_variable_any cv;
std::vector<registered_waiter> waiters_;
count_type future_count;
public:
waiter_for_any_in_seq() :
future_count(0)
{
}
template <typename F>
void add(F& f)
{
if (f.valid())
{
registered_waiter waiter(f, f.notify_when_ready(cv), future_count);
try
{
waiters_.push_back(waiter);
}
catch (...)
{
f.future_->unnotify_when_ready(waiter.handle);
throw;
}
++future_count;
}
}
#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
template <typename F1, typename ... Fs>
void add(F1& f1, Fs&... fs)
{
add(f1);
add(fs...);
}
#endif
count_type wait()
{
all_futures_lock lk(waiters_);
for (;;)
{
for (count_type i = 0; i < waiters_.size(); ++i)
{
if (waiters_[i].future_->is_ready(lk.locks[i]))
{
return waiters_[i].index;
}
}
cv.wait(lk);
}
}
~waiter_for_any_in_seq()
{
for (count_type i = 0; i < waiters_.size(); ++i)
{
waiters_[i].future_->unnotify_when_ready(waiters_[i].handle);
}
}
};
}
template <typename Iterator>
typename boost::disable_if<is_future_type<Iterator> , Iterator>::type wait_for_any(Iterator begin, Iterator end)
{
if (begin == end) return end;
detail::waiter_for_any_in_seq<typename std::iterator_traits<Iterator>::value_type> waiter;
for (Iterator current = begin; current != end; ++current)
{
waiter.add(*current);
}
return boost::next(begin, waiter.wait());
}
}
#endif // header

View File

@@ -1,12 +1,13 @@
#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
// (C) Copyright 2011,2012,2015 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/config.hpp>
#include <boost/assert.hpp>
#include <pthread.h>
#include <boost/throw_exception.hpp>
#include <boost/core/ignore_unused.hpp>
@@ -26,13 +27,12 @@
#endif
#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L
#if (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \
|| (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21)
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
#endif
#include <boost/config/abi_prefix.hpp>
@@ -123,10 +123,12 @@ namespace boost
void unlock()
{
int res = posix::pthread_mutex_unlock(&m);
if (res)
{
boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
}
(void)res;
BOOST_ASSERT(res == 0);
// if (res)
// {
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
// }
}
bool try_lock()
@@ -219,10 +221,12 @@ namespace boost
void unlock()
{
int res = posix::pthread_mutex_unlock(&m);
if (res)
{
boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
}
(void)res;
BOOST_ASSERT(res == 0);
// if (res)
// {
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
// }
}
bool try_lock()

View File

@@ -27,16 +27,19 @@
#endif
#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L
#if (defined _POSIX_TIMEOUTS && (_POSIX_TIMEOUTS-0)>=200112L) \
|| (defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ >= 21)
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
#if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \
|| defined __ANDROID__
#define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
#endif
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK)
#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
#endif
@@ -48,7 +51,7 @@ namespace boost
{
private:
pthread_mutex_t m;
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_cond_t cond;
bool is_locked;
pthread_t owner;
@@ -58,7 +61,7 @@ namespace boost
BOOST_THREAD_NO_COPYABLE(recursive_mutex)
recursive_mutex()
{
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_mutexattr_t attr;
int const init_attr_res=pthread_mutexattr_init(&attr);
@@ -99,12 +102,12 @@ namespace boost
~recursive_mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));

View File

@@ -25,7 +25,9 @@
#include <utility>
#if defined(__ANDROID__)
#include <asm/page.h> // http://code.google.com/p/android/issues/detail?id=39983
# ifndef PAGE_SIZE
# define PAGE_SIZE 4096
# endif
#endif
#include <pthread.h>
@@ -113,8 +115,13 @@ namespace boost
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
std::map<void const*,boost::detail::tss_data_node> tss_data;
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// These data must be at the end so that the access to the other fields doesn't change
// when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined.
// Another option is to have them always
pthread_mutex_t* cond_mutex;
pthread_cond_t* current_cond;
//#endif
typedef std::vector<std::pair<condition_variable*, mutex*>
//, hidden_allocator<std::pair<condition_variable*, mutex*> >
> notify_list_t;
@@ -134,8 +141,10 @@ namespace boost
thread_handle(0),
done(false),join_started(false),joined(false),
thread_exit_callbacks(0),
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
cond_mutex(0),
current_cond(0),
//#endif
notify(),
async_states_()
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
@@ -250,7 +259,7 @@ namespace boost
inline
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
{
return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns));
return boost::this_thread::no_interruption_point::hiden::sleep_for(boost::detail::to_timespec(ns));
}
#endif
#endif // BOOST_THREAD_USES_CHRONO

View File

@@ -12,8 +12,8 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/detail/work.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -39,7 +39,7 @@ namespace boost
work task;
try
{
if (work_queue.try_pull_front(task) == queue_op_status::success)
if (work_queue.try_pull(task) == queue_op_status::success)
{
task();
return true;
@@ -144,23 +144,23 @@ namespace boost
void submit(Closure & closure)
{
work w ((closure));
work_queue.push_back(boost::move(w));
work_queue.push(boost::move(w));
//work_queue.push(work(closure)); // todo check why this doesn't work
}
#endif
void submit(void (*closure)())
{
work w ((closure));
work_queue.push_back(boost::move(w));
//work_queue.push_back(work(closure)); // todo check why this doesn't work
work_queue.push(boost::move(w));
//work_queue.push(work(closure)); // todo check why this doesn't work
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work w =boost::move(closure);
work_queue.push_back(boost::move(w));
//work_queue.push_back(work(boost::move(closure))); // todo check why this doesn't work
work_queue.push(boost::move(w));
//work_queue.push(work(boost::move(closure))); // todo check why this doesn't work
}
/**

View File

@@ -285,7 +285,6 @@ namespace boost
// Oops, we weren't called often enough, we're stuck
return 0xFFFFFFFF;
}
#else
#endif
inline detail::gettickcount64_t GetTickCount64_()
{

View File

@@ -7,7 +7,7 @@
#ifndef BOOST_NO_EXCEPTIONS
#include <boost/thread/future_error_code.hpp>
#include <boost/thread/futures/future_error_code.hpp>
#include <string>
namespace boost

View File

@@ -36,8 +36,6 @@
#include <set>
#include <vector>
#include "./timeconv.inl"
namespace boost
{
namespace detail
@@ -98,13 +96,10 @@ namespace boost
}
delete current_node;
}
for(std::map<void const*,tss_data_node>::iterator next=thread_info->tss_data.begin(),
current,
end=thread_info->tss_data.end();
next!=end;)
while (!thread_info->tss_data.empty())
{
current=next;
++next;
std::map<void const*,detail::tss_data_node>::iterator current
= thread_info->tss_data.begin();
if(current->second.func && (current->second.value!=0))
{
(*current->second.func)(current->second.value);
@@ -164,7 +159,7 @@ namespace boost
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();
//thread_info->self.reset();
detail::set_current_thread_data(thread_info.get());
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
BOOST_TRY

View File

@@ -1,151 +0,0 @@
// 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;
const int NANOSECONDS_PER_MILLISECOND = 1000000;
const int MICROSECONDS_PER_SECOND = 1000000;
const int NANOSECONDS_PER_MICROSECOND = 1000;
#if defined BOOST_THREAD_USES_DATETIME
inline void to_time(int milliseconds, boost::xtime& xt)
{
int res = 0;
res = boost::xtime_get(&xt, boost::TIME_UTC_);
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
NANOSECONDS_PER_MILLISECOND);
if (xt.nsec >= NANOSECONDS_PER_SECOND)
{
++xt.sec;
xt.nsec -= NANOSECONDS_PER_SECOND;
}
}
#endif
#if defined(BOOST_HAS_PTHREADS)
#if defined BOOST_THREAD_USES_DATETIME
inline void to_timespec(const boost::xtime& xt, timespec& ts)
{
ts.tv_sec = static_cast<int>(xt.sec);
ts.tv_nsec = static_cast<int>(xt.nsec);
if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
{
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
}
}
#endif
inline void to_time(int milliseconds, timespec& ts)
{
#if defined BOOST_THREAD_USES_DATETIME
boost::xtime xt;
to_time(milliseconds, xt);
to_timespec(xt, ts);
#else
ts.tv_sec += (milliseconds / MILLISECONDS_PER_SECOND);
ts.tv_nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
NANOSECONDS_PER_MILLISECOND);
if (ts.tv_nsec >= NANOSECONDS_PER_SECOND)
{
++ts.tv_sec;
ts.tv_nsec -= NANOSECONDS_PER_SECOND;
}
#endif
}
#if defined BOOST_THREAD_USES_DATETIME
inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)
{
boost::xtime cur;
int res = 0;
res = boost::xtime_get(&cur, boost::TIME_UTC_);
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
if (boost::xtime_cmp(xt, cur) <= 0)
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
}
else
{
ts.tv_sec = xt.sec - cur.sec;
ts.tv_nsec = xt.nsec - cur.nsec;
if( ts.tv_nsec < 0 )
{
ts.tv_sec -= 1;
ts.tv_nsec += NANOSECONDS_PER_SECOND;
}
if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
{
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
}
}
}
#endif
#endif
#if defined BOOST_THREAD_USES_DATETIME
inline void to_duration(boost::xtime xt, int& milliseconds)
{
boost::xtime cur;
int res = 0;
res = boost::xtime_get(&cur, boost::TIME_UTC_);
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
if (boost::xtime_cmp(xt, cur) <= 0)
milliseconds = 0;
else
{
if (cur.nsec > xt.nsec)
{
xt.nsec += NANOSECONDS_PER_SECOND;
--xt.sec;
}
milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
NANOSECONDS_PER_MILLISECOND);
}
}
inline void to_microduration(boost::xtime xt, int& microseconds)
{
boost::xtime cur;
int res = 0;
res = boost::xtime_get(&cur, boost::TIME_UTC_);
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
if (boost::xtime_cmp(xt, cur) <= 0)
microseconds = 0;
else
{
if (cur.nsec > xt.nsec)
{
xt.nsec += NANOSECONDS_PER_SECOND;
--xt.sec;
}
microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) /
NANOSECONDS_PER_MICROSECOND);
}
}
#endif
}
// Change Log:
// 1 Jun 01 Initial creation.

View File

@@ -44,7 +44,7 @@
#include <wrl\ftm.h>
#include <windows.system.threading.h>
#pragma comment(lib, "runtimeobject.lib")
#endif
#endif
namespace boost
{
@@ -198,7 +198,7 @@ namespace boost
namespace detail
{
std::atomic_uint threadCount;
bool win32::scoped_winrt_thread::start(thread_func address, void *parameter, unsigned int *thrdId)
{
Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IThreadPoolStatics> threadPoolFactory;
@@ -220,7 +220,7 @@ namespace boost
m_completionHandle = completionHandle;
// Create new work item.
Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem =
Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem =
Microsoft::WRL::Callback<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::System::Threading::IWorkItemHandler, Microsoft::WRL::FtmBase>>
([address, parameter, completionHandle](ABI::Windows::Foundation::IAsyncAction *)
{
@@ -274,13 +274,10 @@ namespace boost
}
boost::detail::heap_delete(current_node);
}
for(std::map<void const*,detail::tss_data_node>::iterator next=current_thread_data->tss_data.begin(),
current,
end=current_thread_data->tss_data.end();
next!=end;)
while (!current_thread_data->tss_data.empty())
{
current=next;
++next;
std::map<void const*,detail::tss_data_node>::iterator current
= current_thread_data->tss_data.begin();
if(current->second.func && (current->second.value!=0))
{
(*current->second.func)(current->second.value);
@@ -346,7 +343,7 @@ namespace boost
return true;
#endif
}
bool thread::start_thread_noexcept(const attributes& attr)
{
#if BOOST_PLAT_WINDOWS_RUNTIME
@@ -367,7 +364,7 @@ namespace boost
return true;
#endif
}
thread::thread(detail::thread_data_ptr data):
thread_info(data)
{}
@@ -529,11 +526,10 @@ namespace boost
unsigned thread::physical_concurrency() BOOST_NOEXCEPT
{
#if BOOST_PLAT_WINDOWS_RUNTIME
#if BOOST_PLAT_WINDOWS_RUNTIME || (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
return hardware_concurrency();
#else
unsigned cores = 0;
#if !(defined(__MINGW32__) || defined (__MINGW64__))
DWORD size = 0;
GetLogicalProcessorInformation(NULL, &size);
@@ -550,7 +546,6 @@ namespace boost
if (buffer[i].Relationship == RelationProcessorCore)
++cores;
}
#endif
return cores;
#endif
}
@@ -633,10 +628,60 @@ namespace boost
}
}
#ifndef UNDER_CE
#if !BOOST_PLAT_WINDOWS_RUNTIME
namespace detail_
{
typedef struct _REASON_CONTEXT {
ULONG Version;
DWORD Flags;
union {
LPWSTR SimpleReasonString;
struct {
HMODULE LocalizedReasonModule;
ULONG LocalizedReasonId;
ULONG ReasonStringCount;
LPWSTR *ReasonStrings;
} Detailed;
} Reason;
} REASON_CONTEXT, *PREASON_CONTEXT;
static REASON_CONTEXT default_reason_context={0/*POWER_REQUEST_CONTEXT_VERSION*/, 0x00000001/*POWER_REQUEST_CONTEXT_SIMPLE_STRING*/, (LPWSTR)L"generic"};
typedef BOOL (WINAPI *setwaitabletimerex_t)(HANDLE, const LARGE_INTEGER *, LONG, PTIMERAPCROUTINE, LPVOID, PREASON_CONTEXT, ULONG);
static inline BOOL WINAPI SetWaitableTimerEx_emulation(HANDLE hTimer, const LARGE_INTEGER *lpDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext, ULONG TolerableDelay)
{
return SetWaitableTimer(hTimer, lpDueTime, lPeriod, pfnCompletionRoutine, lpArgToCompletionRoutine, FALSE);
}
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 6387) // MSVC sanitiser warns that GetModuleHandleA() might fail
#endif
static inline setwaitabletimerex_t SetWaitableTimerEx()
{
static setwaitabletimerex_t setwaitabletimerex_impl;
if(setwaitabletimerex_impl)
return setwaitabletimerex_impl;
void (*addr)()=(void (*)()) GetProcAddress(
#if !defined(BOOST_NO_ANSI_APIS)
GetModuleHandleA("KERNEL32.DLL"),
#else
GetModuleHandleW(L"KERNEL32.DLL"),
#endif
"SetWaitableTimerEx");
if(addr)
setwaitabletimerex_impl=(setwaitabletimerex_t) addr;
else
setwaitabletimerex_impl=&SetWaitableTimerEx_emulation;
return setwaitabletimerex_impl;
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
}
#endif
#endif
bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
{
detail::win32::handle handles[3]={0};
detail::win32::handle handles[4]={0};
unsigned handle_count=0;
unsigned wait_handle_index=~0U;
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
@@ -659,32 +704,24 @@ namespace boost
#ifndef UNDER_CE
#if !BOOST_PLAT_WINDOWS_RUNTIME
unsigned const min_timer_wait_period=20;
// Preferentially use coalescing timers for better power consumption and timer accuracy
if(!target_time.is_sentinel())
{
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
if(time_left.milliseconds > min_timer_wait_period)
timer_handle=CreateWaitableTimer(NULL,false,NULL);
if(timer_handle!=0)
{
// for a long-enough timeout, use a waitable timer (which tracks clock changes)
timer_handle=CreateWaitableTimer(NULL,false,NULL);
if(timer_handle!=0)
ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
if(time_left.milliseconds/20>tolerable) // 5%
tolerable=time_left.milliseconds/20;
LARGE_INTEGER due_time=get_due_time(target_time);
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
if(set_time_succeeded)
{
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)
{
timeout_index=handle_count;
handles[handle_count++]=timer_handle;
}
timeout_index=handle_count;
handles[handle_count++]=timer_handle;
}
}
else if(!target_time.relative)
{
// convert short absolute-time timeouts into relative ones, so we don't race against clock changes
target_time=detail::timeout(time_left.milliseconds);
}
}
#endif
#endif
@@ -751,32 +788,24 @@ namespace boost
#ifndef UNDER_CE
#if !BOOST_PLAT_WINDOWS_RUNTIME
unsigned const min_timer_wait_period=20;
// Preferentially use coalescing timers for better power consumption and timer accuracy
if(!target_time.is_sentinel())
{
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
if(time_left.milliseconds > min_timer_wait_period)
timer_handle=CreateWaitableTimer(NULL,false,NULL);
if(timer_handle!=0)
{
// for a long-enough timeout, use a waitable timer (which tracks clock changes)
timer_handle=CreateWaitableTimer(NULL,false,NULL);
if(timer_handle!=0)
ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
if(time_left.milliseconds/20>tolerable) // 5%
tolerable=time_left.milliseconds/20;
LARGE_INTEGER due_time=get_due_time(target_time);
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
if(set_time_succeeded)
{
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)
{
timeout_index=handle_count;
handles[handle_count++]=timer_handle;
}
timeout_index=handle_count;
handles[handle_count++]=timer_handle;
}
}
else if(!target_time.relative)
{
// convert short absolute-time timeouts into relative ones, so we don't race against clock changes
target_time=detail::timeout(time_left.milliseconds);
}
}
#endif
#endif

View File

@@ -1,130 +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)
// boostinspect:nounnamed
namespace {
const int MILLISECONDS_PER_SECOND = 1000;
const int NANOSECONDS_PER_SECOND = 1000000000;
const int NANOSECONDS_PER_MILLISECOND = 1000000;
const int MICROSECONDS_PER_SECOND = 1000000;
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_);
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
NANOSECONDS_PER_MILLISECOND);
if (xt.nsec >= NANOSECONDS_PER_SECOND)
{
++xt.sec;
xt.nsec -= NANOSECONDS_PER_SECOND;
}
}
#if defined(BOOST_HAS_PTHREADS)
inline void to_timespec(const boost::xtime& xt, timespec& ts)
{
ts.tv_sec = static_cast<int>(xt.sec);
ts.tv_nsec = static_cast<int>(xt.nsec);
if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
{
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
}
}
inline void to_time(int milliseconds, timespec& ts)
{
boost::xtime xt;
to_time(milliseconds, xt);
to_timespec(xt, ts);
}
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_);
if (boost::xtime_cmp(xt, cur) <= 0)
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
}
else
{
ts.tv_sec = xt.sec - cur.sec;
ts.tv_nsec = xt.nsec - cur.nsec;
if( ts.tv_nsec < 0 )
{
ts.tv_sec -= 1;
ts.tv_nsec += NANOSECONDS_PER_SECOND;
}
if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
{
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
}
}
}
#endif
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_);
if (boost::xtime_cmp(xt, cur) <= 0)
milliseconds = 0;
else
{
if (cur.nsec > xt.nsec)
{
xt.nsec += NANOSECONDS_PER_SECOND;
--xt.sec;
}
milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
NANOSECONDS_PER_MILLISECOND);
}
}
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_);
if (boost::xtime_cmp(xt, cur) <= 0)
microseconds = 0;
else
{
if (cur.nsec > xt.nsec)
{
xt.nsec += NANOSECONDS_PER_SECOND;
--xt.sec;
}
microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) /
NANOSECONDS_PER_MICROSECOND);
}
}
}
// Change Log:
// 1 Jun 01 Initial creation.

View File

@@ -73,5 +73,13 @@ namespace boost
}
}
#else //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
#ifdef _MSC_VER
// Prevent LNK4221 warning with link=static
namespace boost { namespace link_static_warning_inhibit {
extern __declspec(dllexport) void foo() { }
} }
#endif
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)

View File

@@ -34,6 +34,7 @@ project
<toolset>gcc:<cxxflags>-Wno-variadic-macros
#<toolset>gcc:<cxxflags>-Wunused-local-typedefs
<toolset>gcc:<cxxflags>-Wunused-function
<toolset>gcc:<cxxflags>-Wno-unused-parameter
<toolset>darwin:<cxxflags>-Wextra
<toolset>darwin:<cxxflags>-pedantic
@@ -43,18 +44,20 @@ project
<toolset>darwin:<cxxflags>-Wno-variadic-macros
#<toolset>darwin:<cxxflags>-Wunused-local-typedefs
<toolset>darwin:<cxxflags>-Wunused-function
<toolset>darwin:<cxxflags>-Wno-unused-parameter
#<toolset>pathscale:<cxxflags>-Wextra
<toolset>pathscale:<cxxflags>-Wno-long-long
<toolset>pathscale:<cxxflags>-pedantic
<toolset>clang:<warnings>on
<toolset>clang:<cxxflags>-Wextra
#<toolset>clang:<cxxflags>-pedantic
<toolset>clang:<warnings>on
<toolset>clang:<cxxflags>-Wno-long-long
#<toolset>clang:<cxxflags>-ansi
#<toolset>clang:<cxxflags>-fpermissive # doesn't work
<toolset>clang:<cxxflags>-Wunused-function
<toolset>clang:<cxxflags>-Wno-unused-parameter
#<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
#<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
@@ -97,6 +100,10 @@ project
<toolset>intel:<cxxflags>-wd593,981
<toolset>intel:<cxxflags>-wd1418
<toolset>intel:<cxxflags>-wd2415
<toolset>msvc:<cxxflags>/wd4100
<toolset>msvc:<cxxflags>/wd4512
<toolset>msvc:<cxxflags>/wd6246
;
rule thread-run ( sources )
@@ -115,7 +122,7 @@ rule thread-test ( sources )
sources = $(sources) winrt_init.cpp ;
return
[ run $(sources) ../build//boost_thread : : :
<library>/boost/test//boost_unit_test_framework/<link>static
<library>/boost/test//boost_unit_test_framework
]
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
: : :
@@ -286,8 +293,11 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run test_7328.cpp ]
[ thread-run test_7571.cpp ]
[ thread-run test_9319.cpp ]
[ thread-run test_9711.cpp ]
#[ thread-run test_9711.cpp ] This is an invalid use of ::then deferred.
[ thread-run test_9856.cpp ]
[ thread-compile test_10963.cpp : : test_10963_c ]
[ thread-run test_10964.cpp ]
[ thread-test test_11053.cpp ]
;
@@ -676,6 +686,12 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2-noit ./sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp : sync_queue__multi_thread_p ]
;
test-suite ts_sync_deque
:
[ thread-run2-noit ./sync/mutual_exclusion/sync_deque/single_thread_pass.cpp : sync_deque__single_thread_p ]
[ thread-run2-noit ./sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp : sync_deque__multi_thread_p ]
;
test-suite ts_sync_bounded_queue
:
[ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp : sync_bounded_q_single_thread_p ]
@@ -707,6 +723,12 @@ rule thread-compile ( sources : reqs * : name )
#[ thread-run2-noit ./sync/mutual_exclusion/queue_views/multi_thread_pass.cpp : queue_views__multi_thread_p ]
;
test-suite ts_deque_views
:
[ thread-run2-noit ./sync/mutual_exclusion/deque_views/single_thread_pass.cpp : deque_views__single_thread_p ]
#[ thread-run2-noit ./sync/mutual_exclusion/deque_views/multi_thread_pass.cpp : deque_views__multi_thread_p ]
;
#explicit ts_this_thread ;
test-suite ts_this_thread
:
@@ -787,6 +809,8 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2 ../example/user_scheduler.cpp : ex_user_scheduler ]
[ thread-run2 ../example/executor.cpp : ex_executor ]
[ thread-run2 ../example/generic_executor_ref.cpp : ex_generic_executor_ref ]
[ thread-run2 ../example/serial_executor.cpp : ex_serial_executor ]
[ thread-run2 ../example/serial_executor_cont.cpp : ex_serial_executor_cont ]
[ thread-run2 ../example/future_when_all.cpp : ex_future_when_all ]
[ thread-run2 ../example/parallel_accumulate.cpp : ex_parallel_accumulate ]
[ thread-run2 ../example/parallel_quick_sort.cpp : ex_parallel_quick_sort ]
@@ -926,6 +950,8 @@ rule thread-compile ( sources : reqs * : name )
explicit ts_ ;
test-suite ts_
:
[ thread-run2 ../example/this_executor.cpp : ex_this_executor ]
[ thread-run2 ../example/default_executor.cpp : ex_default_executor ]
;
}

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2014 Vicente J. Botet Escriba
// Copyright (C) 2014-2015 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)
@@ -18,13 +18,10 @@
#include <boost/detail/lightweight_test.hpp>
#if ! defined BOOST_NO_CXX11_RANGE_BASED_FOR
#if ! defined BOOST_NO_CXX11_LAMBDAS && defined(BOOST_THREAD_PROVIDES_INVOKE)
using boost::experimental::parallel::v2::task_region;
using boost::experimental::parallel::v2::task_region_handle;
using boost::experimental::parallel::v1::exception_list;
#endif
#if ! defined BOOST_NO_CXX11_LAMBDAS
void run_no_exception()
{
@@ -135,7 +132,9 @@ void run_exception_1()
{
std::cout << "task3" << std::endl;
});
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
BOOST_TEST(false);
#endif
});
BOOST_TEST(false);
}
@@ -278,16 +277,19 @@ void run_nested_exception()
BOOST_TEST(task21_flag);
}
#endif
int main()
{
#if ! defined BOOST_NO_CXX11_LAMBDAS
run_no_exception();
run_no_exception_wait();
run_exception();
run_exception_1();
run_nested_exception();
#endif
return boost::report_errors();
}
#else
int main()
{
return boost::report_errors();
}
#endif

View File

@@ -85,7 +85,7 @@ public:
return *this;
}
int operator()()
int operator()() const
{
boost::this_thread::sleep_for(ms(200));
return 3;
@@ -167,6 +167,48 @@ struct check_timer {
int main()
{
{
try {
boost::async(f0);
} catch (std::exception& ex)
{
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
BOOST_TEST(false && "exception thrown");
}
catch (...)
{
BOOST_TEST(false && "exception thrown");
}
}
{
try {
boost::async(boost::launch::async, f0);
} catch (std::exception& ex)
{
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
BOOST_TEST(false && "exception thrown");
}
catch (...)
{
BOOST_TEST(false && "exception thrown");
}
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
try {
boost::async(boost::launch::deferred, f0);
} catch (std::exception& ex)
{
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
BOOST_TEST(false && "exception thrown");
}
catch (...)
{
BOOST_TEST(false && "exception thrown");
}
}
#endif
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
try

View File

@@ -51,6 +51,29 @@ void p3(boost::future<int> f)
int main()
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
try
{
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
BOOST_TEST(f1.valid());
{
boost::future<int> f2 = f1.then(&p2);
BOOST_TEST(f2.valid());
}
BOOST_TEST(! f1.valid());
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
BOOST_TEST(false);
}
catch (...)
{
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
BOOST_TEST(false);
}
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);

View File

@@ -17,6 +17,7 @@
#include <boost/thread/future.hpp>
#include <boost/thread/thread.hpp>
#include <boost/core/ref.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_USES_CHRONO
@@ -128,49 +129,49 @@ int main()
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
}
}
// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
// {
// typedef int& T;
// {
// boost::promise<T> p;
// boost::future<T> f = p.get_future();
//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
// boost::thread(func3, boost::move(p)).detach();
//#else
// int j=5;
// p.set_value(j);
//#endif
// BOOST_TEST(f.valid());
// int k=4;
// BOOST_TEST(f.get_or(k) == 5);
//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
// BOOST_TEST(!f.valid());
//#endif
// }
// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
// {
// boost::promise<T> p;
// boost::future<T> f = p.get_future();
//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
// boost::thread(func4, boost::move(p)).detach();
//#else
// p.set_exception(boost::make_exception_ptr(3.5));
//#endif
// try
// {
// BOOST_TEST(f.valid());
// int j=4;
// BOOST_TEST(f.get_or(j) == 4);
// }
// catch (...)
// {
// BOOST_TEST(false);
// }
//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
// BOOST_TEST(!f.valid());
//#endif
// }
// }
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
typedef int& T;
{
boost::promise<T> p;
boost::future<T> f = p.get_future();
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
boost::thread(func3, boost::move(p)).detach();
#else
int j=5;
p.set_value(j);
#endif
BOOST_TEST(f.valid());
int k=4;
BOOST_TEST(f.get_or(boost::ref(k)) == 5);
#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
BOOST_TEST(!f.valid());
#endif
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::promise<T> p;
boost::future<T> f = p.get_future();
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
boost::thread(func4, boost::move(p)).detach();
#else
p.set_exception(boost::make_exception_ptr(3.5));
#endif
try
{
BOOST_TEST(f.valid());
int j=4;
BOOST_TEST(f.get_or(boost::ref(j)) == 4);
}
catch (...)
{
BOOST_TEST(false);
}
#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
BOOST_TEST(!f.valid());
#endif
}
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;

View File

@@ -72,6 +72,30 @@ int main()
}
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
BOOST_TEST(f1.valid());
boost::future<int> f2 = f1.then(&p2);
boost::future<int> f3 = f1.then(&p2);
BOOST_TEST(f2.valid());
BOOST_TEST(f3.valid());
try
{
BOOST_TEST(f2.get()==2);
BOOST_TEST(f3.get()==2);
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
BOOST_TEST(false);
}
catch (...)
{
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
BOOST_TEST(false);
}
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
BOOST_TEST(f1.valid());

View File

@@ -0,0 +1,455 @@
// Copyright (C) 2014 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/sync_deque.hpp>
// class sync_deque<T>
// sync_deque();
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/concurrent_queues/sync_deque.hpp>
#include <boost/thread/concurrent_queues/deque_adaptor.hpp>
#include <boost/thread/concurrent_queues/deque_views.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/static_assert.hpp>
class non_copyable
{
BOOST_THREAD_MOVABLE_ONLY(non_copyable)
int val;
public:
non_copyable(int v) : val(v){}
non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
bool operator==(non_copyable const& x) const {return val==x.val;}
template <typename OSTREAM>
friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x )
{
os << x.val;
return os;
}
};
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_STATIC_ASSERT( ! boost::is_copy_constructible<non_copyable>::value );
BOOST_STATIC_ASSERT( boost::has_move_emulation_enabled<non_copyable>::value );
#endif
int main()
{
{
// default queue invariants
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// default queue invariants
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_front<int> q(sq);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_pull fails
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_front<int> q(sq);
int i;
BOOST_TEST( boost::queue_op_status::empty == q.try_pull(i));
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// empty queue push rvalue/copyable succeeds
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
q.push(1);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue push lvalue/copyable succeeds
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
int i;
q.push(i);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#if 0
{
// empty queue push rvalue/non_copyable succeeds
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
boost::deque_back<non_copyable> q(sq);
q.push(non_copyable(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue push rvalue/non_copyable succeeds
boost::deque_adaptor<boost::sync_deque<non_copyable> > q;
//boost::sync_deque<non_copyable> q;
//boost::deque_back<non_copyable> q(sq);
non_copyable nc(1);
q.push_back(boost::move(nc));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue push rvalue succeeds
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
q.push(1);
q.push(2);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 2u);
BOOST_TEST(! q.closed());
}
{
// empty queue push lvalue succeeds
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
int i;
q.push(i);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue/copyable succeeds
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue/copyable succeeds
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#if 0
{
// empty queue try_push rvalue/non-copyable succeeds
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
boost::deque_back<non_copyable> q(sq);
non_copyable nc(1);
BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue try_push lvalue succeeds
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
int i;
BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue succeeds
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#if 0
{
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
boost::deque_back<non_copyable> q(sq);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
boost::deque_back<non_copyable> q(sq);
non_copyable nc(1);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_front<int> q(sq);
sq.push_back(1);
int i;
q.pull(i);
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
boost::deque_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
non_copyable nc2(2);
q.pull(nc2);
BOOST_TEST_EQ(nc1, nc2);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_front<int> q(sq);
sq.push_back(1);
int i = q.pull();
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
boost::deque_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
non_copyable nc = q.pull();
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull_front succeed
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_front<int> q(sq);
sq.push_back(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.try_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull_front succeed
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
boost::deque_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue nonblocking_pull_front succeed
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_front<int> q(sq);
sq.push_back(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue nonblocking_pull_front succeed
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
boost::deque_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
boost::deque_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_front<int> q(sq);
sq.push_back(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
boost::deque_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// closed invariants
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
q.close();
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
{
// closed invariants
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_front<int> q(sq);
q.close();
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
{
// closed queue push fails
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
q.close();
try {
q.push(1);
BOOST_TEST(false);
} catch (...) {
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
}
{
// 1-element closed queue pull succeed
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_front<int> q(sq);
sq.push_back(1);
q.close();
int i;
q.pull(i);
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
{
// 1-element closed queue wait_pull_front succeed
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_front<int> q(sq);
sq.push_back(1);
q.close();
int i;
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
{
// closed empty queue wait_pull_front fails
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_front<int> q(sq);
q.close();
BOOST_TEST(q.empty());
BOOST_TEST(q.closed());
int i;
BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i));
BOOST_TEST(q.empty());
BOOST_TEST(q.closed());
}
return boost::report_errors();
}

View File

@@ -12,7 +12,7 @@
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
#include <boost/thread/concurrent_queues/queue_views.hpp>
@@ -117,7 +117,7 @@ int main()
//boost::sync_queue<non_copyable> q;
//boost::queue_back<non_copyable> q(sq);
non_copyable nc(1);
q.push_back(boost::move(nc));
q.push(boost::move(nc));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -206,7 +206,7 @@ int main()
#if 0
{
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
// empty queue nonblocking_push rvalue/non-copyable succeeds
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_back<non_copyable> q(sq);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
@@ -217,7 +217,7 @@ int main()
}
#endif
{
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
// empty queue nonblocking_push rvalue/non-copyable succeeds
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_back<non_copyable> q(sq);
non_copyable nc(1);
@@ -228,10 +228,10 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
// 1-element queue pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
sq.push_back(1);
sq.push(1);
int i;
q.pull(i);
BOOST_TEST_EQ(i, 1);
@@ -241,11 +241,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
// 1-element queue pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
sq.push(boost::move(nc1));
non_copyable nc2(2);
q.pull(nc2);
BOOST_TEST_EQ(nc1, nc2);
@@ -255,10 +255,10 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
// 1-element queue pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
sq.push_back(1);
sq.push(1);
int i = q.pull();
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
@@ -267,11 +267,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
// 1-element queue pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
sq.push(boost::move(nc1));
non_copyable nc = q.pull();
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
@@ -280,10 +280,10 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull_front succeed
// 1-element queue try_pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
sq.push_back(1);
sq.push(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.try_pull(i));
BOOST_TEST_EQ(i, 1);
@@ -293,11 +293,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull_front succeed
// 1-element queue try_pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
sq.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
BOOST_TEST_EQ(nc, nc1);
@@ -307,10 +307,10 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue nonblocking_pull_front succeed
// 1-element queue nonblocking_pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
sq.push_back(1);
sq.push(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i));
BOOST_TEST_EQ(i, 1);
@@ -320,11 +320,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue nonblocking_pull_front succeed
// 1-element queue nonblocking_pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
sq.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
BOOST_TEST_EQ(nc, nc1);
@@ -334,11 +334,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
// 1-element queue wait_pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
sq.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
BOOST_TEST_EQ(nc, nc1);
@@ -348,10 +348,10 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
// 1-element queue wait_pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
sq.push_back(1);
sq.push(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
BOOST_TEST_EQ(i, 1);
@@ -361,11 +361,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
// 1-element queue wait_pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
sq.push_back(boost::move(nc1));
sq.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
BOOST_TEST_EQ(nc, nc1);
@@ -414,7 +414,7 @@ int main()
// 1-element closed queue pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
sq.push_back(1);
sq.push(1);
q.close();
int i;
q.pull(i);
@@ -425,10 +425,10 @@ int main()
BOOST_TEST(q.closed());
}
{
// 1-element closed queue wait_pull_front succeed
// 1-element closed queue wait_pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
sq.push_back(1);
sq.push(1);
q.close();
int i;
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
@@ -439,7 +439,7 @@ int main()
BOOST_TEST(q.closed());
}
{
// closed empty queue wait_pull_front fails
// closed empty queue wait_pull fails
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
q.close();

View File

@@ -0,0 +1,256 @@
// Copyright (C) 2013 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/concurrent_queues/sync_deque.hpp>
// class sync_deque<T>
// push || pull;
#include <boost/config.hpp>
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_VERSION 4
#include <boost/thread/concurrent_queues/sync_deque.hpp>
#include <boost/thread/future.hpp>
#include <boost/thread/barrier.hpp>
#include <boost/detail/lightweight_test.hpp>
template <typename ValueType>
struct call_push_back
{
boost::sync_deque<ValueType> *q_;
boost::barrier *go_;
call_push_back(boost::sync_deque<ValueType> *q, boost::barrier *go) :
q_(q), go_(go)
{
}
typedef void result_type;
void operator()()
{
go_->count_down_and_wait();
q_->push_back(42);
}
};
template <typename ValueType>
struct call_pull_front
{
boost::sync_deque<ValueType> *q_;
boost::barrier *go_;
call_pull_front(boost::sync_deque<ValueType> *q, boost::barrier *go) :
q_(q), go_(go)
{
}
typedef ValueType result_type;
ValueType operator()()
{
go_->count_down_and_wait();
return q_->pull_front();
}
};
template <typename ValueType>
struct call_wait_pull_front
{
boost::sync_deque<ValueType> *q_;
boost::barrier *go_;
call_wait_pull_front(boost::sync_deque<ValueType> *q, boost::barrier *go) :
q_(q), go_(go)
{
}
typedef boost::queue_op_status result_type;
boost::queue_op_status operator()(ValueType& v)
{
go_->wait();
return q_->wait_pull_front(v);
}
};
void test_concurrent_push_back_and_pull_front_on_empty_queue()
{
boost::sync_deque<int> q;
boost::barrier go(2);
boost::future<void> push_done;
boost::future<int> pull_done;
try
{
push_done=boost::async(boost::launch::async,
call_push_back<int>(&q,&go));
pull_done=boost::async(boost::launch::async,
call_pull_front<int>(&q,&go));
push_done.get();
BOOST_TEST_EQ(pull_done.get(), 42);
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
void test_concurrent_push_back_and_wait_pull_front_on_empty_queue()
{
boost::sync_deque<int> q;
const unsigned int n = 3;
boost::barrier go(n);
boost::future<boost::queue_op_status> pull_done[n];
int results[n];
try
{
for (unsigned int i =0; i< n; ++i)
pull_done[i]=boost::async(boost::launch::async,
call_wait_pull_front<int>(&q,&go),
boost::ref(results[i]));
for (unsigned int i =0; i< n; ++i)
q.push_back(42);
for (unsigned int i = 0; i < n; ++i) {
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success);
BOOST_TEST_EQ(results[i], 42);
}
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
void test_concurrent_wait_pull_front_and_close_on_empty_queue()
{
boost::sync_deque<int> q;
const unsigned int n = 3;
boost::barrier go(n);
boost::future<boost::queue_op_status> pull_done[n];
int results[n];
try
{
for (unsigned int i =0; i< n; ++i)
pull_done[i]=boost::async(boost::launch::async,
call_wait_pull_front<int>(&q,&go),
boost::ref(results[i]));
q.close();
for (unsigned int i = 0; i < n; ++i) {
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed);
}
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
#endif
void test_concurrent_push_back_on_empty_queue()
{
boost::sync_deque<int> q;
const unsigned int n = 3;
boost::barrier go(n);
boost::future<void> push_done[n];
try
{
for (unsigned int i =0; i< n; ++i)
push_done[i]=boost::async(boost::launch::async,
call_push_back<int>(&q,&go));
}
catch (...)
{
BOOST_TEST(false);
}
try
{
for (unsigned int i = 0; i < n; ++i)
push_done[i].get();
}
catch (...)
{
BOOST_TEST(false);
}
try
{
BOOST_TEST(!q.empty());
for (unsigned int i =0; i< n; ++i)
BOOST_TEST_EQ(q.pull_front(), 42);
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
void test_concurrent_pull_front_on_queue()
{
boost::sync_deque<int> q;
const unsigned int n = 3;
boost::barrier go(n);
boost::future<int> pull_done[n];
try
{
for (unsigned int i =0; i< n; ++i)
q.push_back(42);
for (unsigned int i =0; i< n; ++i)
pull_done[i]=boost::async(boost::launch::async,
#if ! defined BOOST_NO_CXX11_LAMBDAS
[&q,&go]() -> int
{
go.wait();
return q.pull_front();
}
#else
call_pull_front<int>(&q,&go)
#endif
);
for (unsigned int i = 0; i < n; ++i)
BOOST_TEST_EQ(pull_done[i].get(), 42);
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
int main()
{
test_concurrent_push_back_and_pull_front_on_empty_queue();
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
test_concurrent_push_back_and_wait_pull_front_on_empty_queue();
test_concurrent_wait_pull_front_and_close_on_empty_queue();
#endif
test_concurrent_push_back_on_empty_queue();
test_concurrent_pull_front_on_queue();
return boost::report_errors();
}

View File

@@ -0,0 +1,403 @@
// Copyright (C) 2013,2015 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/concurrent_queues/sync_deque.hpp>
// class sync_deque<T>
// sync_deque();
#define BOOST_THREAD_VERSION 4
#include <boost/thread/concurrent_queues/sync_deque.hpp>
#include <boost/detail/lightweight_test.hpp>
class non_copyable
{
BOOST_THREAD_MOVABLE_ONLY(non_copyable)
int val;
public:
non_copyable(int v) : val(v){}
non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
bool operator==(non_copyable const& x) const {return val==x.val;}
template <typename OSTREAM>
friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x )
{
os << x.val;
return os;
}
};
int main()
{
{
// default queue invariants
boost::sync_deque<int> q;
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_pull fails
boost::sync_deque<int> q;
int i;
BOOST_TEST( boost::queue_op_status::empty == q.try_pull_front(i));
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// empty queue push rvalue/copyable succeeds
boost::sync_deque<int> q;
q.push_back(1);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue push lvalue/copyable succeeds
boost::sync_deque<int> q;
int i;
q.push_back(i);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue push rvalue/non_copyable succeeds
boost::sync_deque<non_copyable> q;
q.push_back(non_copyable(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue push rvalue/non_copyable succeeds
boost::sync_deque<non_copyable> q;
non_copyable nc(1);
q.push_back(boost::move(nc));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue push rvalue succeeds
boost::sync_deque<int> q;
q.push_back(1);
q.push_back(2);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 2u);
BOOST_TEST(! q.closed());
}
{
// empty queue push lvalue succeeds
boost::sync_deque<int> q;
int i;
q.push_back(i);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue/copyable succeeds
boost::sync_deque<int> q;
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue/copyable succeeds
boost::sync_deque<int> q;
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_deque<non_copyable> q;
BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_deque<non_copyable> q;
non_copyable nc(1);
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push lvalue succeeds
boost::sync_deque<int> q;
int i=1;
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue succeeds
boost::sync_deque<int> q;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
boost::sync_deque<non_copyable> q;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
boost::sync_deque<non_copyable> q;
non_copyable nc(1);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
boost::sync_deque<int> q;
q.push_back(1);
int i;
q.pull_front(i);
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
boost::sync_deque<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc2(2);
q.pull_front(nc2);
BOOST_TEST_EQ(nc1, nc2);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
boost::sync_deque<int> q;
q.push_back(1);
int i = q.pull_front();
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
boost::sync_deque<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc = q.pull_front();
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull_front succeed
boost::sync_deque<int> q;
q.push_back(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull_front succeed
boost::sync_deque<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue nonblocking_pull_front succeed
boost::sync_deque<int> q;
q.push_back(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue nonblocking_pull_front succeed
boost::sync_deque<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
boost::sync_deque<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
boost::sync_deque<int> q;
q.push_back(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
boost::sync_deque<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// closed invariants
boost::sync_deque<int> q;
q.close();
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
{
// closed queue push fails
boost::sync_deque<int> q;
q.close();
try {
q.push_back(1);
BOOST_TEST(false);
} catch (...) {
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
}
{
// 1-element closed queue pull succeed
boost::sync_deque<int> q;
q.push_back(1);
q.close();
int i;
q.pull_front(i);
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
{
// 1-element closed queue wait_pull_front succeed
boost::sync_deque<int> q;
q.push_back(1);
q.close();
int i;
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
{
// closed empty queue wait_pull_front fails
boost::sync_deque<int> q;
q.close();
BOOST_TEST(q.empty());
BOOST_TEST(q.closed());
int i;
BOOST_TEST(boost::queue_op_status::closed == q.wait_pull_front(i));
BOOST_TEST(q.empty());
BOOST_TEST(q.closed());
}
return boost::report_errors();
}

View File

@@ -45,7 +45,7 @@ void test_pull(const int n)
pq.push(i);
}
BOOST_TEST(!pq.empty());
BOOST_TEST_EQ(pq.size(), n);
BOOST_TEST_EQ(pq.size(), std::size_t(n));
pq.close();
BOOST_TEST(pq.closed());
boost::barrier b(n);
@@ -71,7 +71,7 @@ void test_push(const int n)
}
tg.join_all();
BOOST_TEST(!pq.empty());
BOOST_TEST_EQ(pq.size(), n);
BOOST_TEST_EQ(pq.size(), std::size_t(n));
}
void test_both(const int n)
@@ -88,7 +88,7 @@ void test_both(const int n)
}
tg.join_all();
BOOST_TEST(pq.empty());
BOOST_TEST_EQ(pq.size(), 0);
BOOST_TEST_EQ(pq.size(), std::size_t(0));
}
void push_range(sync_pq* q, const int begin, const int end)

View File

@@ -1,5 +1,5 @@
// Copyright (C) 2014 Ian Forbed
// Copyright (C) 2014 Vicente J. Botet Escriba
// Copyright (C) 2014,2015 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)
@@ -55,7 +55,7 @@ void test_pull_for()
boost::queue_op_status st = pq.pull_for(milliseconds(500), val);
steady_clock::duration diff = steady_clock::now() - start;
BOOST_TEST(boost::queue_op_status::timeout == st);
BOOST_TEST(diff < milliseconds(510) && diff > milliseconds(500));
BOOST_TEST(diff < milliseconds(550) && diff > milliseconds(500));
}
void test_pull_until()
@@ -66,7 +66,7 @@ void test_pull_until()
boost::queue_op_status st = pq.pull_until(start + milliseconds(500), val);
steady_clock::duration diff = steady_clock::now() - start;
BOOST_TEST(boost::queue_op_status::timeout == st);
BOOST_TEST(diff < milliseconds(510) && diff > milliseconds(500));
BOOST_TEST(diff < milliseconds(550) && diff > milliseconds(500));
}
void test_nonblocking_pull()
@@ -111,19 +111,19 @@ int main()
sync_pq pq;
BOOST_TEST(pq.empty());
BOOST_TEST(!pq.closed());
BOOST_TEST_EQ(pq.size(), 0);
BOOST_TEST_EQ(pq.size(), std::size_t(0));
for(int i = 1; i <= 5; i++){
pq.push(i);
BOOST_TEST(!pq.empty());
BOOST_TEST_EQ(pq.size(), i);
BOOST_TEST_EQ(pq.size(), std::size_t(i));
}
for(int i = 6; i <= 10; i++){
boost::queue_op_status succ = pq.try_push(i);
BOOST_TEST(succ == boost::queue_op_status::success );
BOOST_TEST(!pq.empty());
BOOST_TEST_EQ(pq.size(), i);
BOOST_TEST_EQ(pq.size(), std::size_t(i));
}
for(int i = 10; i > 5; i--){
@@ -149,17 +149,15 @@ int main()
//test_pull_until_when_not_empty();
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if 0
{
// empty queue try_push rvalue/non-copyable succeeds
boost::concurrent::sync_priority_queue<non_copyable> q;
BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable()));
BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
//fixme
// empty queue try_push rvalue/non-copyable succeeds
@@ -183,17 +181,16 @@ int main()
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
// {
// // empty queue try_push rvalue succeeds
// boost::concurrent::sync_priority_queue<int> q;
// BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
// BOOST_TEST(! q.empty());
// BOOST_TEST(! q.full());
// BOOST_TEST_EQ(q.size(), 1u);
// BOOST_TEST(! q.closed());
// }
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if 0
{
// empty queue try_push rvalue succeeds
boost::concurrent::sync_priority_queue<int> q;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue nonblocking_push rvalue/non-copyable succeeds
boost::concurrent::sync_priority_queue<non_copyable> q;
@@ -203,17 +200,16 @@ int main()
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
// {
// // empty queue nonblocking_push rvalue/non-copyable succeeds
// boost::concurrent::sync_priority_queue<non_copyable> q;
// non_copyable nc(1);
// BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
// BOOST_TEST(! q.empty());
// BOOST_TEST(! q.full());
// BOOST_TEST_EQ(q.size(), 1u);
// BOOST_TEST(! q.closed());
// }
{
// empty queue nonblocking_push rvalue/non-copyable succeeds
boost::concurrent::sync_priority_queue<non_copyable> q;
non_copyable nc(1);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{

View File

@@ -30,18 +30,18 @@ void test_all()
sync_tq pq;
BOOST_TEST(pq.empty());
BOOST_TEST(!pq.closed());
BOOST_TEST_EQ(pq.size(), 0);
BOOST_TEST_EQ(pq.size(), std::size_t(0));
for(int i = 1; i <= 5; i++){
pq.push(i, milliseconds(i*100));
BOOST_TEST(!pq.empty());
BOOST_TEST_EQ(pq.size(), i);
BOOST_TEST_EQ(pq.size(), std::size_t(i));
}
for(int i = 6; i <= 10; i++){
pq.push(i,steady_clock::now() + milliseconds(i*100));
BOOST_TEST(!pq.empty());
BOOST_TEST_EQ(pq.size(), i);
BOOST_TEST_EQ(pq.size(), std::size_t(i));
}
for(int i = 1; i <= 10; i++){
@@ -63,20 +63,20 @@ void test_all_with_try()
sync_tq pq;
BOOST_TEST(pq.empty());
BOOST_TEST(!pq.closed());
BOOST_TEST_EQ(pq.size(), 0);
BOOST_TEST_EQ(pq.size(), std::size_t(0));
for(int i = 1; i <= 5; i++){
boost::queue_op_status st = pq.try_push(i, milliseconds(i*100));
BOOST_TEST(st == boost::queue_op_status::success );
BOOST_TEST(!pq.empty());
BOOST_TEST_EQ(pq.size(), i);
BOOST_TEST_EQ(pq.size(), std::size_t(i));
}
for(int i = 6; i <= 10; i++){
boost::queue_op_status st = pq.try_push(i,steady_clock::now() + milliseconds(i*100));
BOOST_TEST(st == boost::queue_op_status::success );
BOOST_TEST(!pq.empty());
BOOST_TEST_EQ(pq.size(), i);
BOOST_TEST_EQ(pq.size(), std::size_t(i));
}
for(int i = 1; i <= 10; i++){

View File

@@ -15,7 +15,6 @@
#endif
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/future.hpp>
@@ -23,13 +22,13 @@
#include <boost/detail/lightweight_test.hpp>
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
struct call_push
{
boost::sync_queue<int> *q_;
boost::sync_queue<ValueType> *q_;
boost::barrier *go_;
call_push(boost::sync_queue<int> *q, boost::barrier *go) :
call_push(boost::sync_queue<ValueType> *q, boost::barrier *go) :
q_(q), go_(go)
{
}
@@ -38,53 +37,16 @@ struct call_push
{
go_->count_down_and_wait();
q_->push(42);
}
};
template <typename ValueType>
struct call_pull
{
boost::sync_queue<int> *q_;
boost::barrier *go_;
call_pull(boost::sync_queue<int> *q, boost::barrier *go) :
q_(q), go_(go)
{
}
typedef int result_type;
int operator()()
{
go_->count_down_and_wait();
return q_->pull();
}
};
#endif
template <typename ValueType>
struct call_push_back
{
boost::sync_queue<ValueType> *q_;
boost::barrier *go_;
call_push_back(boost::sync_queue<ValueType> *q, boost::barrier *go) :
q_(q), go_(go)
{
}
typedef void result_type;
void operator()()
{
go_->count_down_and_wait();
q_->push_back(42);
}
};
template <typename ValueType>
struct call_pull_front
{
boost::sync_queue<ValueType> *q_;
boost::barrier *go_;
call_pull_front(boost::sync_queue<ValueType> *q, boost::barrier *go) :
call_pull(boost::sync_queue<ValueType> *q, boost::barrier *go) :
q_(q), go_(go)
{
}
@@ -92,17 +54,17 @@ struct call_pull_front
ValueType operator()()
{
go_->count_down_and_wait();
return q_->pull_front();
return q_->pull();
}
};
template <typename ValueType>
struct call_wait_pull_front
struct call_wait_pull
{
boost::sync_queue<ValueType> *q_;
boost::barrier *go_;
call_wait_pull_front(boost::sync_queue<ValueType> *q, boost::barrier *go) :
call_wait_pull(boost::sync_queue<ValueType> *q, boost::barrier *go) :
q_(q), go_(go)
{
}
@@ -110,11 +72,10 @@ struct call_wait_pull_front
boost::queue_op_status operator()(ValueType& v)
{
go_->wait();
return q_->wait_pull_front(v);
return q_->wait_pull(v);
}
};
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
void test_concurrent_push_and_pull_on_empty_queue()
{
boost::sync_queue<int> q;
@@ -127,27 +88,9 @@ void test_concurrent_push_and_pull_on_empty_queue()
try
{
push_done=boost::async(boost::launch::async,
#if ! defined BOOST_NO_CXX11_LAMBDAS
[&q,&go]()
{
go.wait();
q.push(42);
}
#else
call_push(&q,&go)
#endif
);
call_push<int>(&q,&go));
pull_done=boost::async(boost::launch::async,
#if ! defined BOOST_NO_CXX11_LAMBDAS
[&q,&go]() -> int
{
go.wait();
return q.pull();
}
#else
call_pull(&q,&go)
#endif
);
call_pull<int>(&q,&go));
push_done.get();
BOOST_TEST_EQ(pull_done.get(), 42);
@@ -159,6 +102,68 @@ void test_concurrent_push_and_pull_on_empty_queue()
}
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
void test_concurrent_push_and_wait_pull_on_empty_queue()
{
boost::sync_queue<int> q;
const unsigned int n = 3;
boost::barrier go(n);
boost::future<boost::queue_op_status> pull_done[n];
int results[n];
try
{
for (unsigned int i =0; i< n; ++i)
pull_done[i]=boost::async(boost::launch::async,
call_wait_pull<int>(&q,&go),
boost::ref(results[i]));
for (unsigned int i =0; i< n; ++i)
q.push(42);
for (unsigned int i = 0; i < n; ++i) {
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success);
BOOST_TEST_EQ(results[i], 42);
}
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
void test_concurrent_wait_pull_and_close_on_empty_queue()
{
boost::sync_queue<int> q;
const unsigned int n = 3;
boost::barrier go(n);
boost::future<boost::queue_op_status> pull_done[n];
int results[n];
try
{
for (unsigned int i =0; i< n; ++i)
pull_done[i]=boost::async(boost::launch::async,
call_wait_pull<int>(&q,&go),
boost::ref(results[i]));
q.close();
for (unsigned int i = 0; i < n; ++i) {
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed);
}
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
#endif
void test_concurrent_push_on_empty_queue()
{
boost::sync_queue<int> q;
@@ -170,20 +175,25 @@ void test_concurrent_push_on_empty_queue()
{
for (unsigned int i =0; i< n; ++i)
push_done[i]=boost::async(boost::launch::async,
#if ! defined BOOST_NO_CXX11_LAMBDAS
[&q,&go]()
{
go.wait();
q.push(42);
}
#else
call_push(&q,&go)
#endif
);
call_push<int>(&q,&go));
}
catch (...)
{
BOOST_TEST(false);
}
try
{
for (unsigned int i = 0; i < n; ++i)
push_done[i].get();
}
catch (...)
{
BOOST_TEST(false);
}
try
{
BOOST_TEST(!q.empty());
for (unsigned int i =0; i< n; ++i)
BOOST_TEST_EQ(q.pull(), 42);
@@ -218,174 +228,7 @@ void test_concurrent_pull_on_queue()
return q.pull();
}
#else
call_pull(&q,&go)
#endif
);
for (unsigned int i = 0; i < n; ++i)
BOOST_TEST_EQ(pull_done[i].get(), 42);
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
#endif
void test_concurrent_push_back_and_pull_front_on_empty_queue()
{
boost::sync_queue<int> q;
boost::barrier go(2);
boost::future<void> push_done;
boost::future<int> pull_done;
try
{
push_done=boost::async(boost::launch::async,
call_push_back<int>(&q,&go));
pull_done=boost::async(boost::launch::async,
call_pull_front<int>(&q,&go));
push_done.get();
BOOST_TEST_EQ(pull_done.get(), 42);
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
void test_concurrent_push_back_and_wait_pull_front_on_empty_queue()
{
boost::sync_queue<int> q;
const unsigned int n = 3;
boost::barrier go(n);
boost::future<boost::queue_op_status> pull_done[n];
int results[n];
try
{
for (unsigned int i =0; i< n; ++i)
pull_done[i]=boost::async(boost::launch::async,
call_wait_pull_front<int>(&q,&go),
boost::ref(results[i]));
for (unsigned int i =0; i< n; ++i)
q.push_back(42);
for (unsigned int i = 0; i < n; ++i) {
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success);
BOOST_TEST_EQ(results[i], 42);
}
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
void test_concurrent_wait_pull_front_and_close_on_empty_queue()
{
boost::sync_queue<int> q;
const unsigned int n = 3;
boost::barrier go(n);
boost::future<boost::queue_op_status> pull_done[n];
int results[n];
try
{
for (unsigned int i =0; i< n; ++i)
pull_done[i]=boost::async(boost::launch::async,
call_wait_pull_front<int>(&q,&go),
boost::ref(results[i]));
q.close();
for (unsigned int i = 0; i < n; ++i) {
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed);
}
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
#endif
void test_concurrent_push_back_on_empty_queue()
{
boost::sync_queue<int> q;
const unsigned int n = 3;
boost::barrier go(n);
boost::future<void> push_done[n];
try
{
for (unsigned int i =0; i< n; ++i)
push_done[i]=boost::async(boost::launch::async,
call_push_back<int>(&q,&go));
}
catch (...)
{
BOOST_TEST(false);
}
try
{
for (unsigned int i = 0; i < n; ++i)
push_done[i].get();
}
catch (...)
{
BOOST_TEST(false);
}
try
{
BOOST_TEST(!q.empty());
for (unsigned int i =0; i< n; ++i)
BOOST_TEST_EQ(q.pull_front(), 42);
BOOST_TEST(q.empty());
}
catch (...)
{
BOOST_TEST(false);
}
}
void test_concurrent_pull_front_on_queue()
{
boost::sync_queue<int> q;
const unsigned int n = 3;
boost::barrier go(n);
boost::future<int> pull_done[n];
try
{
for (unsigned int i =0; i< n; ++i)
q.push_back(42);
for (unsigned int i =0; i< n; ++i)
pull_done[i]=boost::async(boost::launch::async,
#if ! defined BOOST_NO_CXX11_LAMBDAS
[&q,&go]() -> int
{
go.wait();
return q.pull_front();
}
#else
call_pull_front<int>(&q,&go)
call_pull<int>(&q,&go)
#endif
);
@@ -401,18 +244,13 @@ void test_concurrent_pull_front_on_queue()
int main()
{
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
test_concurrent_push_and_pull_on_empty_queue();
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
test_concurrent_push_and_wait_pull_on_empty_queue();
test_concurrent_wait_pull_and_close_on_empty_queue();
#endif
test_concurrent_push_on_empty_queue();
test_concurrent_pull_on_queue();
#endif
test_concurrent_push_back_and_pull_front_on_empty_queue();
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
test_concurrent_push_back_and_wait_pull_front_on_empty_queue();
test_concurrent_wait_pull_front_and_close_on_empty_queue();
#endif
test_concurrent_push_back_on_empty_queue();
test_concurrent_pull_front_on_queue();
return boost::report_errors();
}

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
// Copyright (C) 2013,2015 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)
@@ -10,7 +10,6 @@
// sync_queue();
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/sync_queue.hpp>
@@ -47,79 +46,8 @@ int main()
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
{
// empty queue try_pull fails
boost::sync_queue<int> q;
int i;
BOOST_TEST(! q.try_pull(i));
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_pull fails
boost::sync_queue<int> q;
BOOST_TEST(! q.try_pull());
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// empty queue push rvalue/copyable succeeds
boost::sync_queue<int> q;
q.push(1);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue push lvalue/copyable succeeds
boost::sync_queue<int> q;
int i;
q.push(i);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue try_pull fails
boost::sync_queue<int> q;
int i;
BOOST_TEST( boost::queue_op_status::empty == q.try_pull_front(i));
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// empty queue push rvalue/copyable succeeds
boost::sync_queue<int> q;
q.push_back(1);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue push lvalue/copyable succeeds
boost::sync_queue<int> q;
int i;
q.push_back(i);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if 0
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue push rvalue/non_copyable succeeds
boost::sync_queue<non_copyable> q;
@@ -164,7 +92,7 @@ int main()
{
// empty queue try_push rvalue/copyable succeeds
boost::sync_queue<int> q;
BOOST_TEST(q.try_push(1));
BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -173,79 +101,18 @@ int main()
{
// empty queue try_push rvalue/copyable succeeds
boost::sync_queue<int> q;
BOOST_TEST(q.try_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
#if 0
{
// empty queue push rvalue/non_copyable succeeds
boost::sync_queue<non_copyable> q;
q.push_back(non_copyable(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue push rvalue/non_copyable succeeds
boost::sync_queue<non_copyable> q;
non_copyable nc(1);
q.push_back(boost::move(nc));
BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue push rvalue succeeds
boost::sync_queue<int> q;
q.push_back(1);
q.push_back(2);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 2u);
BOOST_TEST(! q.closed());
}
{
// empty queue push lvalue succeeds
boost::sync_queue<int> q;
int i;
q.push_back(i);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue/copyable succeeds
boost::sync_queue<int> q;
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue/copyable succeeds
boost::sync_queue<int> q;
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if 0
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
BOOST_TEST(q.try_push(non_copyable()));
BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -256,7 +123,7 @@ int main()
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
non_copyable nc(1);
BOOST_TEST(q.try_push(boost::move(nc)));
BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -267,7 +134,7 @@ int main()
// empty queue try_push lvalue succeeds
boost::sync_queue<int> q;
int i=1;
BOOST_TEST(q.try_push(i));
BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -276,61 +143,18 @@ int main()
{
// empty queue try_push rvalue succeeds
boost::sync_queue<int> q;
BOOST_TEST(q.try_push(boost::no_block, 1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
#if 0
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable()));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
non_copyable nc(1);
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(boost::move(nc)));
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue try_push lvalue succeeds
boost::sync_queue<int> q;
int i=1;
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue succeeds
boost::sync_queue<int> q;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if 0
{
// empty queue try_push rvalue/non-copyable succeeds
// empty queue nonblocking_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
BOOST_TEST(q.try_push(boost::no_block, non_copyable(1)));
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -338,10 +162,10 @@ int main()
}
#endif
{
// empty queue try_push rvalue/non-copyable succeeds
// empty queue nonblocking_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
non_copyable nc(1);
BOOST_TEST(q.try_push(boost::no_block, boost::move(nc)));
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -400,7 +224,7 @@ int main()
boost::sync_queue<int> q;
q.push(1);
int i;
BOOST_TEST(q.try_pull(i));
BOOST_TEST(boost::queue_op_status::success == q.try_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -413,7 +237,7 @@ int main()
non_copyable nc1(1);
q.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(q.try_pull(nc));
BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -421,11 +245,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull succeed
// 1-element queue nonblocking_pull succeed
boost::sync_queue<int> q;
q.push(1);
int i;
BOOST_TEST(q.try_pull(boost::no_block, i));
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -433,12 +257,12 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull succeed
// 1-element queue nonblocking_pull succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(q.try_pull(boost::no_block, nc));
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -446,11 +270,38 @@ int main()
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull succeed
// 1-element queue wait_pull succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull succeed
boost::sync_queue<int> q;
q.push(1);
boost::shared_ptr<int> i = q.try_pull();
BOOST_TEST_EQ(*i, 1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
@@ -480,28 +331,6 @@ int main()
BOOST_TEST(q.closed());
}
}
{
// closed empty queue try_pull_front closed
boost::sync_queue<int> q;
q.close();
int i;
BOOST_TEST(boost::queue_op_status::closed == q.try_pull_front(i));
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
{
// closed empty queue nonblocking_pull_front closed
boost::sync_queue<int> q;
q.close();
int i;
BOOST_TEST(boost::queue_op_status::closed == q.nonblocking_pull_front(i));
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
{
// 1-element closed queue pull succeed
boost::sync_queue<int> q;
@@ -515,195 +344,13 @@ int main()
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
#endif
#if 0
{
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
non_copyable nc(1);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
// 1-element closed queue wait_pull succeed
boost::sync_queue<int> q;
q.push_back(1);
int i;
q.pull_front(i);
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc2(2);
q.pull_front(nc2);
BOOST_TEST_EQ(nc1, nc2);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
boost::sync_queue<int> q;
q.push_back(1);
int i = q.pull_front();
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull_front succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc = q.pull_front();
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull_front succeed
boost::sync_queue<int> q;
q.push_back(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull_front succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue nonblocking_pull_front succeed
boost::sync_queue<int> q;
q.push_back(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue nonblocking_pull_front succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
boost::sync_queue<int> q;
q.push_back(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue wait_pull_front succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push_back(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// closed invariants
boost::sync_queue<int> q;
q.close();
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
{
// closed queue push fails
boost::sync_queue<int> q;
q.close();
try {
q.push_back(1);
BOOST_TEST(false);
} catch (...) {
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
}
{
// 1-element closed queue pull succeed
boost::sync_queue<int> q;
q.push_back(1);
q.push(1);
q.close();
int i;
q.pull_front(i);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -711,26 +358,13 @@ int main()
BOOST_TEST(q.closed());
}
{
// 1-element closed queue wait_pull_front succeed
boost::sync_queue<int> q;
q.push_back(1);
q.close();
int i;
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(q.closed());
}
{
// closed empty queue wait_pull_front fails
// closed empty queue wait_pull fails
boost::sync_queue<int> q;
q.close();
BOOST_TEST(q.empty());
BOOST_TEST(q.closed());
int i;
BOOST_TEST(boost::queue_op_status::closed == q.wait_pull_front(i));
BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i));
BOOST_TEST(q.empty());
BOOST_TEST(q.closed());
}

44
test/test_10963.cpp Normal file
View File

@@ -0,0 +1,44 @@
// Copyright (C) 2014 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 4
#include <boost/config.hpp>
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/future.hpp>
#include <boost/static_assert.hpp>
struct TestCallback
{
typedef boost::future<void> result_type;
result_type operator()(boost::future<void> future) const
{
future.get();
return boost::make_ready_future();
}
result_type operator()(boost::future<boost::future<void> > future) const
{
future.get();
return boost::make_ready_future();
}
};
int main()
{
#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS
boost::promise<void> test_promise;
boost::future<void> test_future(test_promise.get_future());
auto f1 = test_future.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<boost::future<void> > >::value);
#endif
return 0;
}

76
test/test_10964.cpp Normal file
View File

@@ -0,0 +1,76 @@
// Copyright (C) 2015 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 4
#include <boost/config.hpp>
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/future.hpp>
#include <boost/static_assert.hpp>
struct TestCallback
{
typedef boost::future<void> result_type;
result_type operator()(boost::future<void> future) const
{
future.get();
return boost::make_ready_future();
}
result_type operator()(boost::future<boost::future<void> > future) const
{
future.get();
return boost::make_ready_future();
}
};
void p1()
{
}
int main()
{
#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
auto f1 = boost::make_ready_future().then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
f1.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
auto f1 = boost::make_ready_future().then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.unwrap();
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
f2.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
auto f1 = boost::make_ready_future().then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.unwrap();
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
auto f3 = f2.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
f3.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
boost::make_ready_future().then(
TestCallback()).unwrap().then(TestCallback()).get();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
boost::future<void> f = boost::async(p1);
f.then(
TestCallback()).unwrap().then(TestCallback()).get();
}
#endif
return 0;
}

70
test/test_11053.cpp Normal file
View File

@@ -0,0 +1,70 @@
// Copyright (C) 2015 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 4
#include <boost/thread.hpp>
#include <boost/thread/tss.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
struct A
{
void DoWork()
{
std::cout << "A: doing work\n";
if (!m_ptr.get())
m_ptr.reset(new WorkSpace());
// do not very much
for (size_t i = 0; i < 10; ++i)
m_ptr->a += 10;
}
private:
struct WorkSpace
{
int a;
WorkSpace() : a(0) {}
};
boost::thread_specific_ptr<WorkSpace> m_ptr;
};
struct B
{
void DoWork()
{
std::cout << "B: doing work\n";
if (!m_ptr.get())
m_ptr.reset(new A());
m_ptr->DoWork();
}
private:
boost::thread_specific_ptr<A> m_ptr;
};
struct C
{
void DoWork()
{
std::cout << "C: doing work\n";
if (!m_ptr.get())
m_ptr.reset(new B());
m_ptr->DoWork();
}
private:
boost::thread_specific_ptr<B> m_ptr;
};
int main(int ac, char** av)
{
std::cout << "test starting\n";
boost::shared_ptr<C> p_C(new C);
boost::thread cWorker(&C::DoWork, p_C);
cWorker.join();
std::cout << "test stopping\n";
return 0;
}

View File

@@ -5,7 +5,7 @@
#define BOOST_THREAD_VERSION 2
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
#define BOOST_TEST_MODULE Boost.Threads: 2309
#include <boost/test/unit_test.hpp>
#include <iostream>
@@ -40,7 +40,7 @@
}
}
void test()
BOOST_AUTO_TEST_CASE(test)
{
try
{
@@ -61,14 +61,5 @@
}
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* tests =
BOOST_TEST_SUITE("Boost.Threads: 2309");
tests->add(BOOST_TEST_CASE(&test));
return tests;
}

View File

@@ -3,7 +3,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
#define BOOST_TEST_MODULE Boost.Threads: thread attributes test suite
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread_only.hpp>
@@ -29,7 +29,7 @@ void simple_thread()
test_value = 999;
}
void test_native_handle()
BOOST_AUTO_TEST_CASE(test_native_handle)
{
boost::thread_attributes attrs;
@@ -51,7 +51,7 @@ void test_native_handle()
}
void test_stack_size()
BOOST_AUTO_TEST_CASE(test_stack_size)
{
boost::thread_attributes attrs;
@@ -70,18 +70,8 @@ void do_test_creation_with_attrs()
BOOST_CHECK_EQUAL(test_value, 999);
}
void test_creation_with_attrs()
BOOST_AUTO_TEST_CASE(test_creation_with_attrs)
{
timed_test(&do_test_creation_with_attrs, 1);
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: thread attributes test suite");
test->add(BOOST_TEST_CASE(test_native_handle));
test->add(BOOST_TEST_CASE(test_stack_size));
test->add(BOOST_TEST_CASE(test_creation_with_attrs));
return test;
}

View File

@@ -24,18 +24,37 @@ void foo(IntPromise p)
void bar(boost::future<int> fooResult)
{
try {
std::cout << "bar" << std::endl;
int i = fooResult.get(); // Code hangs on this line (Due to future already being locked by the set_value call)
std::cout << "i: " << i << std::endl;
} catch(...) {
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
}
}
int main()
{
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
try {
IntPromise p(new boost::promise<int>());
boost::thread t(boost::bind(foo, p));
boost::future<int> f1 = p->get_future();
//f1.then(launch::deferred, boost::bind(bar, _1));
f1.then(boost::launch::deferred, &bar);
t.join();
} catch(...) {
return 1;
}
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
try {
IntPromise p(new boost::promise<int>());
boost::thread t(boost::bind(foo, p));
boost::future<int> f1 = p->get_future();
f1.then(boost::launch::async, &bar);
t.join();
} catch(...) {
return 2;
}
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
}

29
test/test_9856.cpp Normal file
View File

@@ -0,0 +1,29 @@
#include "boost/atomic.hpp"
#include "boost/thread.hpp"
#include <iostream>
using namespace boost;
int main() {
atomic<size_t> total(0), failures(0);
#pragma omp parallel shared(total, failures) num_threads(1000)
{
mutex mtx;
condition_variable cond;
unique_lock<mutex> lk(mtx);
for (int i = 0; i < 500; i++) {
++total;
if (cv_status::timeout != cond.wait_for(lk, chrono::milliseconds(10)))
++failures;
}
}
if(failures)
std::cout << "There were " << failures << " failures out of " << total << " timed waits." << std::endl;
if((100*failures)/total>10)
{
std::cerr << "This exceeds 10%, so failing the test." << std::endl;
return 1;
}
return 0;
}

View File

@@ -7,7 +7,7 @@
#define BOOST_THREAD_VERSION 2
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
#define BOOST_TEST_MODULE Boost.Threads: condition test suite
#include <boost/thread/detail/config.hpp>
#include <boost/thread/condition.hpp>
@@ -156,7 +156,7 @@ void do_test_condition_waits()
BOOST_CHECK_EQUAL(data.awoken, 5);
}
void test_condition_waits()
BOOST_AUTO_TEST_CASE(test_condition_waits)
{
// We should have already tested notify_one here, so
// a timed test with the default execution_monitor::use_condition
@@ -176,20 +176,8 @@ void do_test_condition_wait_is_a_interruption_point()
}
void test_condition_wait_is_a_interruption_point()
BOOST_AUTO_TEST_CASE(test_condition_wait_is_a_interruption_point)
{
timed_test(&do_test_condition_wait_is_a_interruption_point, 1);
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: condition test suite");
test->add(BOOST_TEST_CASE(&test_condition_waits));
test->add(BOOST_TEST_CASE(&test_condition_wait_is_a_interruption_point));
return test;
}

View File

@@ -4,7 +4,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
#define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_all test suite
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread_only.hpp>
@@ -202,7 +202,7 @@ void do_test_notify_all_following_notify_one_wakes_all_threads()
thread3.join();
}
void test_condition_notify_all()
BOOST_AUTO_TEST_CASE(test_condition_notify_all)
{
timed_test(&do_test_condition_notify_all_wakes_from_wait, timeout_seconds);
timed_test(&do_test_condition_notify_all_wakes_from_wait_with_predicate, timeout_seconds);
@@ -213,14 +213,4 @@ void test_condition_notify_all()
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: condition test suite");
test->add(BOOST_TEST_CASE(&test_condition_notify_all));
return test;
}

View File

@@ -5,6 +5,8 @@
#define BOOST_THREAD_VERSION 2
#define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_one test suite
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread_only.hpp>
@@ -135,7 +137,7 @@ void do_test_multiple_notify_one_calls_wakes_multiple_threads()
thread3.join();
}
void test_condition_notify_one()
BOOST_AUTO_TEST_CASE(test_condition_notify_one)
{
timed_test(&do_test_condition_notify_one_wakes_from_wait, timeout_seconds, execution_monitor::use_mutex);
timed_test(&do_test_condition_notify_one_wakes_from_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
@@ -144,15 +146,3 @@ void test_condition_notify_one()
timed_test(&do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
timed_test(&do_test_multiple_notify_one_calls_wakes_multiple_threads, timeout_seconds, execution_monitor::use_mutex);
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: condition test suite");
test->add(BOOST_TEST_CASE(&test_condition_notify_one));
return test;
}

View File

@@ -5,6 +5,8 @@
#define BOOST_THREAD_VERSION 2
#define BOOST_TEST_MODULE Boost.Threads: condition_variable test suite
#include <boost/thread/detail/config.hpp>
#include <boost/thread/condition.hpp>
@@ -152,7 +154,7 @@ void do_test_cv_any_timed_wait_relative_times_out()
}
void test_timed_wait_times_out()
BOOST_AUTO_TEST_CASE(test_timed_wait_times_out)
{
timed_test(&do_test_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
timed_test(&do_test_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
@@ -164,14 +166,4 @@ void test_timed_wait_times_out()
timed_test(&do_test_cv_any_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: condition test suite");
test->add(BOOST_TEST_CASE(&test_timed_wait_times_out));
return test;
}

View File

@@ -5,6 +5,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
#define BOOST_TEST_MODULE Boost.Threads: futures test suite
#include <boost/thread/thread_only.hpp>
#include <boost/thread/mutex.hpp>
@@ -93,7 +94,7 @@ void set_promise_exception_thread(boost::promise<int>* p)
}
void test_store_value_from_thread()
BOOST_AUTO_TEST_CASE(test_store_value_from_thread)
{
LOG;
try {
@@ -122,8 +123,7 @@ void test_store_value_from_thread()
}
}
void test_store_exception()
BOOST_AUTO_TEST_CASE(test_store_exception)
{
LOG;
boost::promise<int> pi3;
@@ -145,7 +145,7 @@ void test_store_exception()
BOOST_CHECK(fi3.get_state()==boost::future_state::ready);
}
void test_initial_state()
BOOST_AUTO_TEST_CASE(test_initial_state)
{
LOG;
boost::unique_future<int> fi;
@@ -166,7 +166,7 @@ void test_initial_state()
}
}
void test_waiting_future()
BOOST_AUTO_TEST_CASE(test_waiting_future)
{
LOG;
boost::promise<int> pi;
@@ -181,7 +181,7 @@ void test_waiting_future()
BOOST_CHECK(i==0);
}
void test_cannot_get_future_twice()
BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice)
{
LOG;
boost::promise<int> pi;
@@ -198,7 +198,7 @@ void test_cannot_get_future_twice()
}
}
void test_set_value_updates_future_state()
BOOST_AUTO_TEST_CASE(test_set_value_updates_future_state)
{
LOG;
boost::promise<int> pi;
@@ -213,7 +213,7 @@ void test_set_value_updates_future_state()
BOOST_CHECK(fi.get_state()==boost::future_state::ready);
}
void test_set_value_can_be_retrieved()
BOOST_AUTO_TEST_CASE(test_set_value_can_be_retrieved)
{
LOG;
boost::promise<int> pi;
@@ -231,7 +231,7 @@ void test_set_value_can_be_retrieved()
BOOST_CHECK(fi.get_state()==boost::future_state::ready);
}
void test_set_value_can_be_moved()
BOOST_AUTO_TEST_CASE(test_set_value_can_be_moved)
{
LOG;
// boost::promise<int> pi;
@@ -249,7 +249,7 @@ void test_set_value_can_be_moved()
// BOOST_CHECK(fi.get_state()==boost::future_state::ready);
}
void test_future_from_packaged_task_is_waiting()
BOOST_AUTO_TEST_CASE(test_future_from_packaged_task_is_waiting)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -262,7 +262,7 @@ void test_future_from_packaged_task_is_waiting()
BOOST_CHECK(i==0);
}
void test_invoking_a_packaged_task_populates_future()
BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_populates_future)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -279,7 +279,7 @@ void test_invoking_a_packaged_task_populates_future()
BOOST_CHECK(i==42);
}
void test_invoking_a_packaged_task_twice_throws()
BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_twice_throws)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -297,7 +297,7 @@ void test_invoking_a_packaged_task_twice_throws()
}
void test_cannot_get_future_twice_from_task()
BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice_from_task)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -313,7 +313,7 @@ void test_cannot_get_future_twice_from_task()
}
}
void test_task_stores_exception_if_function_throws()
BOOST_AUTO_TEST_CASE(test_task_stores_exception_if_function_throws)
{
LOG;
boost::packaged_task<int> pt(throw_runtime_error);
@@ -341,7 +341,7 @@ void test_task_stores_exception_if_function_throws()
}
void test_void_promise()
BOOST_AUTO_TEST_CASE(test_void_promise)
{
LOG;
boost::promise<void> p;
@@ -354,7 +354,7 @@ void test_void_promise()
f.get();
}
void test_reference_promise()
BOOST_AUTO_TEST_CASE(test_reference_promise)
{
LOG;
boost::promise<int&> p;
@@ -371,7 +371,7 @@ void test_reference_promise()
void do_nothing()
{}
void test_task_returning_void()
BOOST_AUTO_TEST_CASE(test_task_returning_void)
{
LOG;
boost::packaged_task<void> pt(do_nothing);
@@ -392,7 +392,7 @@ int& return_ref()
return global_ref_target;
}
void test_task_returning_reference()
BOOST_AUTO_TEST_CASE(test_task_returning_reference)
{
LOG;
boost::packaged_task<int&> pt(return_ref);
@@ -408,7 +408,7 @@ void test_task_returning_reference()
BOOST_CHECK(&i==&global_ref_target);
}
void test_shared_future()
BOOST_AUTO_TEST_CASE(test_shared_future)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -428,7 +428,7 @@ void test_shared_future()
BOOST_CHECK(i==42);
}
void test_copies_of_shared_future_become_ready_together()
BOOST_AUTO_TEST_CASE(test_copies_of_shared_future_become_ready_together)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -467,7 +467,7 @@ void test_copies_of_shared_future_become_ready_together()
BOOST_CHECK(i==42);
}
void test_shared_future_can_be_move_assigned_from_unique_future()
BOOST_AUTO_TEST_CASE(test_shared_future_can_be_move_assigned_from_unique_future)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -483,7 +483,7 @@ void test_shared_future_can_be_move_assigned_from_unique_future()
BOOST_CHECK(sf.get_state()==boost::future_state::waiting);
}
void test_shared_future_void()
BOOST_AUTO_TEST_CASE(test_shared_future_void)
{
LOG;
boost::packaged_task<void> pt(do_nothing);
@@ -501,7 +501,7 @@ void test_shared_future_void()
sf.get();
}
void test_shared_future_ref()
BOOST_AUTO_TEST_CASE(test_shared_future_ref)
{
LOG;
boost::promise<int&> p;
@@ -515,7 +515,7 @@ void test_shared_future_ref()
BOOST_CHECK(&f.get()==&i);
}
void test_can_get_a_second_future_from_a_moved_promise()
BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_promise)
{
LOG;
boost::promise<int> pi;
@@ -533,7 +533,7 @@ void test_can_get_a_second_future_from_a_moved_promise()
BOOST_CHECK(fi2.get()==42);
}
void test_can_get_a_second_future_from_a_moved_void_promise()
BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_void_promise)
{
LOG;
boost::promise<void> pi;
@@ -549,7 +549,7 @@ void test_can_get_a_second_future_from_a_moved_void_promise()
BOOST_CHECK(fi2.is_ready());
}
void test_unique_future_for_move_only_udt()
BOOST_AUTO_TEST_CASE(test_unique_future_for_move_only_udt)
{
LOG;
boost::promise<X> pt;
@@ -560,7 +560,7 @@ void test_unique_future_for_move_only_udt()
BOOST_CHECK(res.i==42);
}
void test_unique_future_for_string()
BOOST_AUTO_TEST_CASE(test_unique_future_for_string)
{
LOG;
boost::promise<std::string> pt;
@@ -611,7 +611,7 @@ void do_nothing_callback(boost::promise<int>& /*pi*/)
++callback_called;
}
void test_wait_callback()
BOOST_AUTO_TEST_CASE(test_wait_callback)
{
LOG;
callback_called=0;
@@ -626,7 +626,7 @@ void test_wait_callback()
BOOST_CHECK(callback_called==1);
}
void test_wait_callback_with_timed_wait()
BOOST_AUTO_TEST_CASE(test_wait_callback_with_timed_wait)
{
LOG;
callback_called=0;
@@ -665,7 +665,7 @@ void wait_callback_for_task(boost::packaged_task<int>& pt)
}
void test_wait_callback_for_packaged_task()
BOOST_AUTO_TEST_CASE(test_wait_callback_for_packaged_task)
{
LOG;
callback_called=0;
@@ -680,7 +680,7 @@ void test_wait_callback_for_packaged_task()
BOOST_CHECK(callback_called==1);
}
void test_packaged_task_can_be_moved()
BOOST_AUTO_TEST_CASE(test_packaged_task_can_be_moved)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -708,7 +708,7 @@ void test_packaged_task_can_be_moved()
BOOST_CHECK(fi.is_ready());
}
void test_destroying_a_promise_stores_broken_promise()
BOOST_AUTO_TEST_CASE(test_destroying_a_promise_stores_broken_promise)
{
LOG;
boost::unique_future<int> f;
@@ -728,7 +728,7 @@ void test_destroying_a_promise_stores_broken_promise()
}
}
void test_destroying_a_packaged_task_stores_broken_promise()
BOOST_AUTO_TEST_CASE(test_destroying_a_packaged_task_stores_broken_promise)
{
LOG;
boost::unique_future<int> f;
@@ -754,7 +754,7 @@ int make_int_slowly()
return 42;
}
void test_wait_for_either_of_two_futures_1()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_1)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -772,7 +772,7 @@ void test_wait_for_either_of_two_futures_1()
BOOST_CHECK(f1.get()==42);
}
void test_wait_for_either_of_two_futures_2()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_2)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -790,7 +790,7 @@ void test_wait_for_either_of_two_futures_2()
BOOST_CHECK(f2.get()==42);
}
void test_wait_for_either_of_three_futures_1()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_1)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -811,7 +811,7 @@ void test_wait_for_either_of_three_futures_1()
BOOST_CHECK(f1.get()==42);
}
void test_wait_for_either_of_three_futures_2()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_2)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -832,7 +832,7 @@ void test_wait_for_either_of_three_futures_2()
BOOST_CHECK(f2.get()==42);
}
void test_wait_for_either_of_three_futures_3()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_3)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -853,7 +853,7 @@ void test_wait_for_either_of_three_futures_3()
BOOST_CHECK(f3.get()==42);
}
void test_wait_for_either_of_four_futures_1()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_1)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -877,7 +877,7 @@ void test_wait_for_either_of_four_futures_1()
BOOST_CHECK(f1.get()==42);
}
void test_wait_for_either_of_four_futures_2()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_2)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -901,7 +901,7 @@ void test_wait_for_either_of_four_futures_2()
BOOST_CHECK(f2.get()==42);
}
void test_wait_for_either_of_four_futures_3()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_3)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -925,7 +925,7 @@ void test_wait_for_either_of_four_futures_3()
BOOST_CHECK(f3.get()==42);
}
void test_wait_for_either_of_four_futures_4()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_4)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -949,7 +949,7 @@ void test_wait_for_either_of_four_futures_4()
BOOST_CHECK(f4.get()==42);
}
void test_wait_for_either_of_five_futures_1()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_1)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -976,7 +976,7 @@ void test_wait_for_either_of_five_futures_1()
BOOST_CHECK(f1.get()==42);
}
void test_wait_for_either_of_five_futures_2()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_2)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -1002,7 +1002,7 @@ void test_wait_for_either_of_five_futures_2()
BOOST_CHECK(!f5.is_ready());
BOOST_CHECK(f2.get()==42);
}
void test_wait_for_either_of_five_futures_3()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_3)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -1028,7 +1028,7 @@ void test_wait_for_either_of_five_futures_3()
BOOST_CHECK(!f5.is_ready());
BOOST_CHECK(f3.get()==42);
}
void test_wait_for_either_of_five_futures_4()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_4)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -1054,7 +1054,7 @@ void test_wait_for_either_of_five_futures_4()
BOOST_CHECK(!f5.is_ready());
BOOST_CHECK(f4.get()==42);
}
void test_wait_for_either_of_five_futures_5()
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_5)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -1081,7 +1081,7 @@ void test_wait_for_either_of_five_futures_5()
BOOST_CHECK(f5.get()==42);
}
void test_wait_for_either_invokes_callbacks()
BOOST_AUTO_TEST_CASE(test_wait_for_either_invokes_callbacks)
{
LOG;
callback_called=0;
@@ -1098,7 +1098,7 @@ void test_wait_for_either_invokes_callbacks()
BOOST_CHECK(fi.get()==42);
}
void test_wait_for_any_from_range()
BOOST_AUTO_TEST_CASE(test_wait_for_any_from_range)
{
LOG;
unsigned const count=10;
@@ -1133,7 +1133,7 @@ void test_wait_for_any_from_range()
}
}
void test_wait_for_all_from_range()
BOOST_AUTO_TEST_CASE(test_wait_for_all_from_range)
{
LOG;
unsigned const count=10;
@@ -1153,7 +1153,7 @@ void test_wait_for_all_from_range()
}
}
void test_wait_for_all_two_futures()
BOOST_AUTO_TEST_CASE(test_wait_for_all_two_futures)
{
LOG;
unsigned const count=2;
@@ -1173,7 +1173,7 @@ void test_wait_for_all_two_futures()
}
}
void test_wait_for_all_three_futures()
BOOST_AUTO_TEST_CASE(test_wait_for_all_three_futures)
{
LOG;
unsigned const count=3;
@@ -1193,7 +1193,7 @@ void test_wait_for_all_three_futures()
}
}
void test_wait_for_all_four_futures()
BOOST_AUTO_TEST_CASE(test_wait_for_all_four_futures)
{
LOG;
unsigned const count=4;
@@ -1213,7 +1213,7 @@ void test_wait_for_all_four_futures()
}
}
void test_wait_for_all_five_futures()
BOOST_AUTO_TEST_CASE(test_wait_for_all_five_futures)
{
LOG;
unsigned const count=5;
@@ -1232,68 +1232,3 @@ void test_wait_for_all_five_futures()
BOOST_CHECK(futures[j].is_ready());
}
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: futures test suite");
test->add(BOOST_TEST_CASE(test_initial_state));
test->add(BOOST_TEST_CASE(test_waiting_future));
test->add(BOOST_TEST_CASE(test_cannot_get_future_twice));
test->add(BOOST_TEST_CASE(test_set_value_updates_future_state));
test->add(BOOST_TEST_CASE(test_set_value_can_be_retrieved));
test->add(BOOST_TEST_CASE(test_set_value_can_be_moved));
test->add(BOOST_TEST_CASE(test_store_value_from_thread));
test->add(BOOST_TEST_CASE(test_store_exception));
test->add(BOOST_TEST_CASE(test_future_from_packaged_task_is_waiting));
test->add(BOOST_TEST_CASE(test_invoking_a_packaged_task_populates_future));
test->add(BOOST_TEST_CASE(test_invoking_a_packaged_task_twice_throws));
test->add(BOOST_TEST_CASE(test_cannot_get_future_twice_from_task));
test->add(BOOST_TEST_CASE(test_task_stores_exception_if_function_throws));
test->add(BOOST_TEST_CASE(test_void_promise));
test->add(BOOST_TEST_CASE(test_reference_promise));
test->add(BOOST_TEST_CASE(test_task_returning_void));
test->add(BOOST_TEST_CASE(test_task_returning_reference));
test->add(BOOST_TEST_CASE(test_shared_future));
test->add(BOOST_TEST_CASE(test_copies_of_shared_future_become_ready_together));
test->add(BOOST_TEST_CASE(test_shared_future_can_be_move_assigned_from_unique_future));
test->add(BOOST_TEST_CASE(test_shared_future_void));
test->add(BOOST_TEST_CASE(test_shared_future_ref));
test->add(BOOST_TEST_CASE(test_can_get_a_second_future_from_a_moved_promise));
test->add(BOOST_TEST_CASE(test_can_get_a_second_future_from_a_moved_void_promise));
test->add(BOOST_TEST_CASE(test_unique_future_for_move_only_udt));
test->add(BOOST_TEST_CASE(test_unique_future_for_string));
test->add(BOOST_TEST_CASE(test_wait_callback));
test->add(BOOST_TEST_CASE(test_wait_callback_with_timed_wait));
test->add(BOOST_TEST_CASE(test_wait_callback_for_packaged_task));
test->add(BOOST_TEST_CASE(test_packaged_task_can_be_moved));
test->add(BOOST_TEST_CASE(test_destroying_a_promise_stores_broken_promise));
test->add(BOOST_TEST_CASE(test_destroying_a_packaged_task_stores_broken_promise));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_two_futures_1));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_two_futures_2));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_1));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_2));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_3));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_1));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_2));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_3));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_4));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_1));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_2));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_3));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_4));
test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_5));
test->add(BOOST_TEST_CASE(test_wait_for_either_invokes_callbacks));
test->add(BOOST_TEST_CASE(test_wait_for_any_from_range));
test->add(BOOST_TEST_CASE(test_wait_for_all_from_range));
test->add(BOOST_TEST_CASE(test_wait_for_all_two_futures));
test->add(BOOST_TEST_CASE(test_wait_for_all_three_futures));
test->add(BOOST_TEST_CASE(test_wait_for_all_four_futures));
test->add(BOOST_TEST_CASE(test_wait_for_all_five_futures));
return test;
}

View File

@@ -5,13 +5,15 @@
#define BOOST_THREAD_VERSION 2
#define BOOST_TEST_MODULE Boost.Threads: generic locks test suite
#include <boost/test/unit_test.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread_only.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/condition_variable.hpp>
void test_lock_two_uncontended()
BOOST_AUTO_TEST_CASE(test_lock_two_uncontended)
{
boost::mutex m1,m2;
@@ -87,7 +89,7 @@ void lock_pair(boost::mutex* m1,boost::mutex* m2)
l2(*m2,boost::adopt_lock);
}
void test_lock_two_other_thread_locks_in_order()
BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_order)
{
boost::mutex m1,m2;
wait_data locked;
@@ -106,7 +108,7 @@ void test_lock_two_other_thread_locks_in_order()
t.join();
}
void test_lock_two_other_thread_locks_in_opposite_order()
BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_opposite_order)
{
boost::mutex m1,m2;
wait_data locked;
@@ -125,7 +127,7 @@ void test_lock_two_other_thread_locks_in_opposite_order()
t.join();
}
void test_lock_five_uncontended()
BOOST_AUTO_TEST_CASE(test_lock_five_uncontended)
{
boost::mutex m1,m2,m3,m4,m5;
@@ -176,7 +178,7 @@ void lock_five(boost::mutex* m1,boost::mutex* m2,boost::mutex* m3,boost::mutex*
m5->unlock();
}
void test_lock_five_other_thread_locks_in_order()
BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_order)
{
boost::mutex m1,m2,m3,m4,m5;
wait_data locked;
@@ -195,7 +197,7 @@ void test_lock_five_other_thread_locks_in_order()
t.join();
}
void test_lock_five_other_thread_locks_in_different_order()
BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_different_order)
{
boost::mutex m1,m2,m3,m4,m5;
wait_data locked;
@@ -224,7 +226,7 @@ void lock_n(boost::mutex* mutexes,unsigned count)
}
void test_lock_ten_other_thread_locks_in_different_order()
BOOST_AUTO_TEST_CASE(test_lock_ten_other_thread_locks_in_different_order)
{
unsigned const num_mutexes=10;
@@ -285,7 +287,7 @@ namespace boost
void test_lock_five_in_range()
BOOST_AUTO_TEST_CASE(test_lock_five_in_range)
{
unsigned const num_mutexes=5;
dummy_mutex mutexes[num_mutexes];
@@ -350,7 +352,7 @@ public:
};
void test_lock_five_in_range_custom_iterator()
BOOST_AUTO_TEST_CASE(test_lock_five_in_range_custom_iterator)
{
unsigned const num_mutexes=5;
dummy_mutex mutexes[num_mutexes];
@@ -368,7 +370,7 @@ class dummy_mutex2:
{};
void test_lock_ten_in_range_inherited_mutex()
BOOST_AUTO_TEST_CASE(test_lock_ten_in_range_inherited_mutex)
{
unsigned const num_mutexes=10;
dummy_mutex2 mutexes[num_mutexes];
@@ -381,7 +383,7 @@ void test_lock_ten_in_range_inherited_mutex()
}
}
void test_try_lock_two_uncontended()
BOOST_AUTO_TEST_CASE(test_try_lock_two_uncontended)
{
dummy_mutex m1,m2;
@@ -391,7 +393,7 @@ void test_try_lock_two_uncontended()
BOOST_CHECK(m1.is_locked);
BOOST_CHECK(m2.is_locked);
}
void test_try_lock_two_first_locked()
BOOST_AUTO_TEST_CASE(test_try_lock_two_first_locked)
{
dummy_mutex m1,m2;
m1.lock();
@@ -407,7 +409,7 @@ void test_try_lock_two_first_locked()
BOOST_CHECK(!l1.owns_lock());
BOOST_CHECK(!l2.owns_lock());
}
void test_try_lock_two_second_locked()
BOOST_AUTO_TEST_CASE(test_try_lock_two_second_locked)
{
dummy_mutex m1,m2;
m2.lock();
@@ -424,7 +426,7 @@ void test_try_lock_two_second_locked()
BOOST_CHECK(!l2.owns_lock());
}
void test_try_lock_three()
BOOST_AUTO_TEST_CASE(test_try_lock_three)
{
int const num_mutexes=3;
@@ -469,7 +471,7 @@ void test_try_lock_three()
}
}
void test_try_lock_four()
BOOST_AUTO_TEST_CASE(test_try_lock_four)
{
int const num_mutexes=4;
@@ -517,7 +519,7 @@ void test_try_lock_four()
}
}
void test_try_lock_five()
BOOST_AUTO_TEST_CASE(test_try_lock_five)
{
int const num_mutexes=5;
@@ -568,31 +570,3 @@ void test_try_lock_five()
}
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: generic locks test suite");
test->add(BOOST_TEST_CASE(&test_lock_two_uncontended));
test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_order));
test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_opposite_order));
test->add(BOOST_TEST_CASE(&test_lock_five_uncontended));
test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_order));
test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_different_order));
test->add(BOOST_TEST_CASE(&test_lock_five_in_range));
test->add(BOOST_TEST_CASE(&test_lock_five_in_range_custom_iterator));
test->add(BOOST_TEST_CASE(&test_lock_ten_in_range_inherited_mutex));
test->add(BOOST_TEST_CASE(&test_lock_ten_other_thread_locks_in_different_order));
test->add(BOOST_TEST_CASE(&test_try_lock_two_uncontended));
test->add(BOOST_TEST_CASE(&test_try_lock_two_first_locked));
test->add(BOOST_TEST_CASE(&test_try_lock_two_second_locked));
test->add(BOOST_TEST_CASE(&test_try_lock_three));
test->add(BOOST_TEST_CASE(&test_try_lock_four));
test->add(BOOST_TEST_CASE(&test_try_lock_five));
return test;
}

View File

@@ -2,22 +2,16 @@
//
// 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_TEST_MODULE Boost.Threads: hardware_concurrency test suite
#include <boost/thread/thread_only.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread/mutex.hpp>
void test_hardware_concurrency_is_non_zero()
BOOST_AUTO_TEST_CASE(test_hardware_concurrency_is_non_zero)
{
BOOST_CHECK(boost::thread::hardware_concurrency()!=0);
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: hardware concurrency test suite");
test->add(BOOST_TEST_CASE(test_hardware_concurrency_is_non_zero));
return test;
}

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