2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-03 09:42:16 +00:00

Compare commits

...

665 Commits

Author SHA1 Message Date
Peter Dimov
13959e3a5e Add -j3 to .travis.yml to reduce build time and avoid timeouts 2017-09-10 13:46:44 +03:00
Vicente J. Botet Escriba
3556f298c7 Merge branch 'develop' of github.com:boostorg/thread into develop 2017-09-09 18:42:58 +02:00
Vicente J. Botet Escriba
091e8c8088 reduce the number of travis jobs. 2017-09-09 18:42:23 +02:00
Vicente J. Botet Escriba
eda6b64491 Merge pull request #140 from SSE4/clang_windows_fixes
- switch to boost winapi, to avoid duplicated definitions when compil…
2017-09-07 00:56:11 +02:00
Vicente J. Botet Escriba
ee24ff8dd1 commit CI files. 2017-09-07 00:29:29 +02:00
SSE4
dfe39c630f Merge pull request #1 from Lastique/clang_windows_fixes_fixes
Fix compilation of Boost.WinAPI-based Boost.Thread
2017-09-06 09:36:01 +07:00
Andrey Semashev
a1460b6b0d Fixed incorrect call to GetCurrentThreadId. 2017-09-05 21:43:42 +03:00
Andrey Semashev
02f3290765 Added a missing include. 2017-09-05 21:42:43 +03:00
SSE4
5f0eeeff66 - additional WinAPI definitions 2017-08-31 16:12:16 +07:00
SSE4
e63257ff7f - switch to boost winapi, to avoid duplicated definitions when compiling using Clang on Windows 2017-08-31 14:52:13 +07:00
Vicente J. Botet Escriba
39c23ddf5a Interrup the threads before joining on schedulers. 2017-08-28 09:16:20 +02:00
Vicente J. Botet Escriba
3ee73c866d INcrease the threashold of spourious timeouts. 2017-08-28 09:15:39 +02:00
Vicente J. Botet Escriba
584b9c2d29 Merge pull request #131 from Lastique/fix_ticket12730
Changed signatures of TLS cleanup hooks for consistency with MSVC RTL.
2017-08-27 20:57:04 +02:00
Andrey Semashev
349f59d92d Changed signatures of TLS cleanup hooks for consistency with MSVC RTL.
This should fix startup of executables statically linked with Boost.Thread
because of undefined return value of the thread/process startup hooks.

Should fix https://svn.boost.org/trac10/ticket/12730.
2017-08-27 19:17:23 +03:00
Vicente J. Botet Escriba
e99ec0a283 Update copyright. 2017-08-26 10:50:51 +02:00
Vicente J. Botet Escriba
5920e4c7af Update copyright. 2017-08-26 10:50:15 +02:00
Vicente J. Botet Escriba
13f3d7ed87 Update changes. 2017-08-26 10:48:11 +02:00
Vicente J. Botet Escriba
738ab19573 Update to new version 4.8.0with changes. 2017-08-26 10:41:58 +02:00
Vicente J. Botet Escriba
510e66aef7 rename make_ready to notify_deferred. 2017-08-26 10:39:31 +02:00
Vicente J. Botet Escriba
19c590a881 manage with #12949. 2017-08-26 10:38:37 +02:00
Vicente J. Botet Escriba
395e3d786b #130 - Bug in boost::condition_variable on Windows. 2017-08-24 09:04:26 +02:00
Vicente J. Botet Escriba
fdc0cbcd8c #130 - Bug in boost::condition_variable on Windows. 2017-08-24 08:45:36 +02:00
Vicente J. Botet Escriba
f27a2921da manage with #13019 - ABI compatibility for BOOST_THREAD_PROVIDES_INTERRUPTIONS incomplete. 2017-08-23 00:33:57 +02:00
Vicente J. Botet Escriba
bb32aa3164 manage with 13163-boost::detail::heap_new does not have a variadic variant. 2017-08-22 23:48:23 +02:00
Vicente J. Botet Escriba
70b887a7bd Merge branch 'develop' of github.com:boostorg/thread into develop 2017-08-16 20:31:11 +02:00
Vicente J. Botet Escriba
28bf345c96 make more evident that timespec is realtime and not monotonic. 2017-08-16 20:30:59 +02:00
Vicente J. Botet Escriba
6a1eed0fa8 Merge pull request #129 from shinobu-x/wip-sk-20170815
Do not include same header twice
2017-08-16 07:41:23 +02:00
Shinobu Kinjo
c4d5488f7a Do not include same header twice
include/boost/thread/pthread/shared_mutex.hpp
2017-08-15 07:29:10 +09:00
Vicente J. Botet Escriba
24a22b66ef Workaround deprecated ::getpagesize(). 2017-08-13 07:19:42 +02:00
Vicente J. Botet Escriba
9579dc2056 Merge pull request #126 from Lastique/patch-6
Use BOOST_MAY_ALIAS from Boost.Config.
2017-08-03 23:02:41 +02:00
Vicente J. Botet Escriba
89e694cc56 Merge pull request #127 from dkolsen-pgi/sleep_until
Fix sleep_until() to use a realtime clock
2017-08-03 23:00:23 +02:00
David Olsen
047205fbbd Fix sleep_until() to use a realtime clock
boost::this_thread::no_interruption_point::hidden::sleep_until() takes an absolute time as a parameter and converts it to a duration for the length of time to sleep.  But the current time that the absolute time is compared against came from timespec_now(), which, on Linux at least, uses CLOCK_MONOTONIC, which "represents monotonic time since some unspecified starting point."  Since timespec_now() may have a different starting point than the time that was passed to sleep_until(), that can result in sleep_until() sleeping for an *extremely* long time, causing the program to appear to hang.

Change sleep_until() to get the current time from timespec_now_realtime(), which uses CLOCK_REALTIME, which has the same epoch as the time that is passed to sleep_until().
2017-08-02 15:19:32 -07:00
Andrey Semashev
23e7135f2c Use BOOST_MAY_ALIAS from Boost.Config. 2017-07-29 17:09:18 +03:00
Vicente J. Botet Escriba
d4cff01c72 #12519. 2017-06-11 11:30:59 +02:00
Vicente J. Botet Escriba
5f7dc381c7 Merge pull request #125 from vslavik/fix-comparison
Don't compare shared_ptr<> to 0
2017-06-07 17:57:21 +02:00
Václav Slavík
ea0bc01400 Don't compare shared_ptr<> to 0
Update the code to consistently use a check for .get() == 0, as was
already done in most, but not all, places, to avoid issues with
ambiguous overloaded operator== and operator!=.
2017-06-07 17:24:40 +02:00
Vicente J. Botet Escriba
3bc883d114 Merge pull request #124 from florianbehrens/patch-1
Fixed future::then template argument in documentation.
2017-05-24 12:18:21 +02:00
Florian Behrens
2e2850ff94 Fixed future::then template argument in documentation. 2017-05-24 12:03:38 +02:00
Vicente J. Botet Escriba
1a8019f499 Merge pull request #123 from Lastique/fix_entry_manager
Fix entry_manager constructor not accepting entry_ptr rvalue
2017-05-23 21:54:30 +02:00
Andrey Semashev
bf4b38b0af Fixed entry_manager constructor not accepting entry_ptr rvalue. This resolves compilation failures with MinGW. 2017-05-22 13:11:11 +03:00
Vicente J. Botet Escriba
f78b10a450 Merge pull request #122 from vincenthsu/develop
Fix sync_bounded_queue<>::size()
2017-05-11 01:33:43 +02:00
Vincent Hsu
603689372c Fix sync_bounded_queue<>::size() 2017-05-10 13:12:01 +08:00
Vicente J. Botet Escriba
5b05d6a8c8 fix compile error. 2017-05-07 16:01:10 +02:00
Vicente J. Botet Escriba
12c0fe14cd fix compile error. 2017-05-07 09:05:12 +02:00
Vicente J. Botet Escriba
ace2b8f89e rollback and use RAII. 2017-05-06 23:04:52 +02:00
Vicente J. Botet Escriba
24188f295c fix missing remove aiter while return. 2017-05-06 22:53:41 +02:00
Vicente J. Botet Escriba
653671bc0e fix compilation error. 2017-05-06 14:43:49 +02:00
Vicente J. Botet Escriba
c251497758 Avoid throwing on destructor: condition_variable. 2017-05-06 12:09:23 +02:00
Vicente J. Botet Escriba
69435fa44e try to fix lock on destructor issues. 2017-05-06 03:58:13 +02:00
Vicente J. Botet Escriba
6bc6fcab9a fix compilation error :( 2017-05-04 19:16:04 +02:00
Vicente J. Botet Escriba
50bac8c0eb fix compilation error :( 2017-05-04 07:58:58 +02:00
Vicente J. Botet Escriba
d709d4707c comment failing test. It is surely a bad test. 2017-05-01 03:39:53 +02:00
Vicente J. Botet Escriba
879db6841d try to fix compilation error on windows condition_variable.hpp. 2017-05-01 02:58:45 +02:00
Vicente J. Botet Escriba
2ce385b949 Add missing iostream. 2017-04-29 18:19:02 +02:00
Vicente J. Botet Escriba
21458fcc67 Add missing iostream. 2017-04-29 17:56:32 +02:00
Vicente J. Botet Escriba
d83b7ddc0f Merge branch 'develop' of github.com:boostorg/thread into develop 2017-04-29 17:35:01 +02:00
Vicente J. Botet Escriba
5ee3e8d04b manage with #12888. 2017-04-29 16:17:07 +02:00
Vicente J. Botet Escriba
dcafe1e17d Add noexcept(false) in destructor that could throw in C++11. 2017-04-29 16:15:57 +02:00
Vicente J. Botet Escriba
8dfa7c2e42 fix issue throw() noexcept issue. 2017-04-29 16:14:41 +02:00
Vicente J. Botet Escriba
c83d30f526 manage with #12874. 2017-04-29 16:13:52 +02:00
Vicente J. Botet Escriba
51b367df53 manage with 12958. 2017-04-29 16:12:35 +02:00
Vicente J. Botet Escriba
da83662e1a added test for 12949. 2017-04-29 16:11:31 +02:00
Vicente J. Botet Escriba
36861e5b67 Comment error. Need to be fixed. 2017-04-29 16:10:43 +02:00
Vicente J. Botet Escriba
67df4dd84e Merge pull request #120 from MarcelRaad/patch-2
Remove wrong MSVC version check
2017-04-21 02:10:19 +02:00
Marcel Raad
676521808d Remove wrong MSVC version check
There is no compiler with (_MSC_VER > 2000) and taking the legacy codepath would probably break compilation again when there is. As (_MSC_VER < 1300) (that would be MSVC up to 6.0 from 1998) is not supported by Boost anymore anyway and cannot compile Boost.Thread, this codepath can just be removed completely.
2017-03-24 22:28:41 +01:00
Vicente J. Botet Escriba
65f98979ff replace and by && to make the code portable 2017-03-01 19:39:56 +01:00
Vicente J. Botet Escriba
496acc1161 disable some tests with C++98. 2017-02-28 23:29:28 +01:00
Vicente J. Botet Escriba
30dff7f84a try to fix MONOTONIC timming issue. 2017-02-28 23:28:44 +01:00
Vicente J. Botet Escriba
7cb5d5bb46 Merge pull request #118 from Oberon00/loop-executor-no-polling
Loop executor: Don't poll but wait in loop() + test enhanchment.
2017-02-28 19:55:10 +01:00
Christian Neumüller
74c98b7fab loop_executor: (Re)activate and enhanche test. 2017-02-28 18:50:09 +01:00
Christian Neumüller
2ed0c2ad5f Loop executor: Don't poll but wait in loop(). 2017-02-28 18:50:08 +01:00
Vicente J. Botet Escriba
c969a6cf9c Fix uninitialized variables in scoped thread examples. Disable detach example for clang std::thread, it crashes. 2017-02-28 08:22:15 +01:00
Vicente J. Botet Escriba
c7348b29cf Compile conditionally to try to fix the timespec monotonic issue. This is not a final solution as we need to add two defines while building Boost.Thread, but atleast will allow to check if the solution work. 2017-02-25 22:41:00 +01:00
Vicente J. Botet Escriba
0d850b47ab Merge branch 'develop' of github.com:boostorg/thread into develop 2017-02-24 15:21:19 +01:00
Vicente J. Botet Escriba
9bbf9bed80 rollback MONOTONIC_CLOCK change as it seems it introduce regressions. 2017-02-24 15:20:04 +01:00
Vicente J. Botet Escriba
aadf0acce3 Merge pull request #114 from aargor/develop
Update MSC version check for VS2017RTW
2017-02-24 15:08:13 +01:00
Aaron Gorenstein
bd0379af57 Update MSC version check for VS2017RTW 2017-02-21 13:35:44 -08:00
Vicente J. Botet Escriba
544eda51bd make use of MONOTONIC_CLOCK when available. 2017-02-18 10:34:36 +01:00
Vicente J. Botet Escriba
e16705a72a Added more functors to scoped threads. 2017-02-18 10:22:34 +01:00
Vicente J. Botet Escriba
61a26492c3 use SFINAE for wait_for_all is_future_type. 2017-02-18 10:21:45 +01:00
Vicente J. Botet Escriba
854c61f597 Added Thread parameter in scoped_thread and thread_guard classes. 2017-01-25 13:20:08 +01:00
Vicente J. Botet Escriba
4d4ddcdc36 Merge branch 'develop' of github.com:boostorg/thread into develop 2017-01-25 08:13:22 +01:00
Vicente J. Botet Escriba
9347d9b731 Added Thread parameter in scoped_thread and thread_guard classes. 2017-01-25 08:13:04 +01:00
Vicente J. Botet Escriba
0a4733c9ad Merge pull request #110 from Lastique/fix_mingw
Compilation fixes for MinGW. Support for MSVC on ARM.
2017-01-22 10:19:54 +01:00
Andrey Semashev
b96d05461f Compilation fixes for MinGW. Support for MSVC on ARM.
1. Apparently, some versions of MinGW declare interlocked intrinsics
without volatile qualifiers. To avoid compilation failures cast away
volatile from pointers. This should also work with qualified pointers as
well.

2. Changed interlocked read/write helpers for MSVC. VS2012 and later have
the option to change volatile behavior to the standard C++. In that mode,
volatile no longer enforces memory ordering. To ensure the correct
behavior of the helpers, use compiler barriers to prohibit code
reordering. Also, limit the version to x86 only.

3. Added a separate version of interlocked read/write helpers for MSVC on
ARM. To avoid dependency on the compiler switch, use intrinsics to load
and store values and also emit the hardware memory fence.

4. Added two versions of interlocked read/write helpers for gcc and
compatible compilers. One version is based on __atomic intrinsics, the
other one (for older versions) uses inline assembler. These versions
should be more optimal than the generic fallback.
2017-01-07 20:08:30 +03:00
Vicente J. Botet Escriba
41f19bb098 Merge pull request #109 from jhunold/extra_semi
Remove trailing ";"
2017-01-06 20:58:30 +01:00
Jürgen Hunold
050a45aaa4 Remove trailing ";"
clang warning: extra ';' after member function definition [-Wextra-semi]
2017-01-06 10:01:37 +01:00
Vicente J. Botet Escriba
23cff22e5a fix category in thread_excaption. 2017-01-02 01:21:02 +01:00
Vicente J. Botet Escriba
a75995475a Merge pull request #107 from equal-l2/patch-1
fix typo
2016-12-19 23:54:49 +01:00
equal-l2
3ac5fd0916 fix typo
Just in case
2016-12-20 06:27:06 +09:00
Vicente J. Botet Escriba
56bce64d32 Merge pull request #106 from apolukhin/doc_clarify
Less ambiguous definition for lock(...) functions
2016-12-08 18:56:38 +01:00
Antony Polukhin
4385984215 Less ambiguous definition for lock(...) functions 2016-12-04 02:55:02 +03:00
Vicente J. Botet Escriba
425b9924f0 Update README.md 2016-11-05 23:37:45 +01:00
Vicente J. Botet Escriba
1309e9aa4b version 4.7.2. 2016-11-04 00:57:41 +01:00
Vicente J. Botet Escriba
50a926e973 update doc 1.63. 2016-11-04 00:56:37 +01:00
Vicente J. Botet Escriba
a0bda34054 fix typo in merge. 2016-11-04 00:52:59 +01:00
Vicente J. Botet Escriba
3a9a296e55 Merge pull request #105 from apolukhin/fixing_lost_notify
Fix minor possibility of loosing the notify
2016-11-03 08:06:34 +01:00
Antony Polukhin
184d7504b7 Fix minor possibility of loosing the notify 2016-11-02 23:13:26 +03:00
Vicente J. Botet Escriba
2f8b5794b7 Merge pull request #104 from rick68/patch-9
fix compile failed with boost::user_scheduler
2016-10-24 09:10:36 +02:00
Wei-Ming Yang
7e7d3bf1a7 fix compile failed with boost::user_scheduler
The `work` is not in namespace `boost::thread_detail` anymore.
2016-10-24 08:24:25 +08:00
Vicente J. Botet Escriba
f8b76aa907 Merge pull request #103 from rick68/patch-8
fix relational operators of boost::synchronized_value<>
2016-10-22 23:47:09 +02:00
Vicente J. Botet Escriba
7eeae5b265 Merge pull request #102 from rick68/patch-7
fix boost::synchronized_value<>::load()
2016-10-22 12:30:40 +02:00
Wei-Ming Yang
e71f52f9ed fix relational operators of boost::synchronized_value<>
fix incorrect relational operators.
2016-10-22 17:53:10 +08:00
Wei-Ming Yang
cd41de6e3f fix boost::synchronized_value<>::load()
The data member `boost::synchronized_value<>::value_` is not mutable, so boost::synchronized_value<>::load() could not be const.
2016-10-22 17:18:28 +08:00
Rene Rivera
c70647988d Add, and update, documentation build targets. 2016-10-07 23:07:36 -05:00
Vicente J. Botet Escriba
866ff746ae fix queue_back/front_view: documentation mismatch 2016-09-06 20:10:50 +02:00
Vicente J. Botet Escriba
807f429e17 update history. 2016-09-06 18:49:57 +02:00
Vicente J. Botet Escriba
5450e98c6b Use BOOST_THREAD_ASYNC_FUTURE_WAITS instead of BOOST_THREAD_FUTURE_BLOCKING and wait instead of join. See #11851 and #12220. 2016-09-03 17:18:53 +02:00
Vicente J. Botet Escriba
c52a34c2cf format. 2016-09-01 07:41:20 +02:00
Vicente J. Botet Escriba
fc748dbddf 12293- make the unwrap constructor explicit. 2016-08-20 09:27:47 +02:00
Vicente J. Botet Escriba
e34d343c12 avoid to unlock the mutext befote release_waiters. 2016-08-15 22:50:23 +02:00
Vicente J. Botet Escriba
eeb24a6a6a Merge branch 'develop' of github.com:boostorg/thread into develop 2016-08-10 07:48:35 +02:00
Vicente J. Botet Escriba
25b2062881 update history and version. 2016-08-10 07:48:25 +02:00
Vicente J. Botet Escriba
9d33a59542 Merge pull request #92 from Lastique/fix_msvc8_compilation
Fixed compilation with MSVC-8.
2016-08-10 07:43:37 +02:00
Vicente J. Botet Escriba
41f93eb513 Add test for 12293. 2016-08-09 02:49:23 +02:00
Vicente J. Botet Escriba
63484911c6 fix compile error when INTERRUPTIONS are not provided. 2016-08-09 02:48:26 +02:00
Vicente J. Botet Escriba
bb2c38aa61 Fix result_of signature and unlonk before notyfying. 2016-08-09 02:47:22 +02:00
Vicente J. Botet Escriba
8cf36f18cc rename make_exceptional to make exceptional_future. 2016-08-09 02:46:00 +02:00
Vicente J. Botet Escriba
7ffdc5e10a Merge pull request #90 from rick68/patch-3
fix a bug in try_lock_wrapper<>::operator=()
2016-08-07 13:05:40 +02:00
Vicente J. Botet Escriba
25864ce33a Merge pull request #93 from vslavik/fix-shadowing-warnings
Fix variable shadowing warnings (Clang)
2016-08-07 13:04:09 +02:00
Vicente J. Botet Escriba
f0c50a00c0 Merge pull request #96 from zonr/develop
rename async_func.hpp to invoker.hpp.
2016-08-07 13:01:38 +02:00
Vicente J. Botet Escriba
b511472614 Merge pull request #95 from rick68/patch-5
fix a mistake in boost::completion_latch
2016-08-07 13:00:31 +02:00
Vicente J. Botet Escriba
13c15cd002 Merge pull request #97 from rick68/patch-6
fix a mistake in sync_timed_queue<>::pull_until()
2016-08-07 12:58:22 +02:00
Vicente J. Botet Escriba
1296bf4de9 Merge pull request #91 from Lastique/patch-6
Add shared_lock_guard to the included lock types
2016-08-07 12:57:09 +02:00
Wei-Ming Yang
9c80dd207e fix a mistake in sync_timed_queue<>::pull_until()
The type of `super::not_empty_` in `sync_timed_queue<>` is `boost::condition_variable`, and the return type of `wait_until()` is `boost::cv_status`.
2016-07-31 12:12:55 +08:00
Zonr Chang
0f2fed0577 rename async_func.hpp to invoker.hpp.
This removes vestiges of commit 1d7da085.
2016-07-26 16:07:29 +08:00
Wei-Ming Yang
96390e1b46 fix a mistake in boost::completion_latch
The constructor `completion_latch(std::size_t count, void(*funct)())` does not use any template arguments.
2016-07-26 07:39:10 +08:00
Václav Slavík
e2ff1e4c67 Fix variable shadowing warnings (Clang)
Fix multiple instance of declarations shadowing either local variables
or fields.
2016-07-24 22:03:07 +02:00
Andrey Semashev
49ab2e8619 Fixed compilation with MSVC-8.
Make sure _WIN32_WINNT is defined when windows.h is included. This is
achieved by (a) making sure boost/detail/winapi/config.hpp is included
before any other headers and (b) BOOST_USE_WINDOWS_H is defined so that
the header defines _WIN32_WINNT based on the default target Windows
version. This ensures that all APIs used by the implementation are
available.

Also extracted WIN32_LEAN_AND_MEAN definition to the Jamfile so that it is
consistently defined for all translation units instead of only tss*.cpp.
2016-07-16 19:50:46 +03:00
Andrey Semashev
96b96b4e42 Add shared_lock_guard to the included lock types 2016-07-13 14:42:06 +04:00
Wei-Ming Yang
a774cac3f2 fix a bug in try_lock_wrapper<>::operator=()
It invokes the copy constructor that already be deleted.
2016-07-13 15:34:01 +08:00
Vicente J. Botet Escriba
6ec16408fc Merge pull request #89 from rick68/patch-2
fix a bug in upgrade_to_unique_lock<>::operator=()
2016-07-13 07:00:39 +02:00
Wei-Ming Yang
850f3eced3 fix a bug in upgrade_to_unique_lock<>::operator=()
It invokes the copy constructor that already be deleted.
2016-07-13 12:42:20 +08:00
Vicente J. Botet Escriba
fde2e061f5 Merge pull request #88 from rick68/patch-1
fix typos in boost::upgrade_lock
2016-07-11 22:45:18 +02:00
Wei-Ming Yang
e5c086cef4 fix typos in boost::upgrade_lock
Corrects the class name in exception messages.
2016-07-12 01:17:41 +08:00
Vladimir Prus
0b5e4f88b5 Support "b2 install". 2016-07-08 15:12:17 +03:00
Vicente J. Botet Escriba
8d150587fa Merge pull request #87 from timblechmann/feature/msvc-2015
win32: compile fix for msvc2015
2016-06-28 14:19:10 +02:00
Tim Blechmann
206ff0ba7c win32: compile fix for msvc2015 2016-06-20 11:11:17 +02:00
Vicente J. Botet Escriba
0ef1b1b760 Merge pull request #83 from v4hn/spell-out-thread-ns
specify boost:: prefix for future threads
2016-05-26 07:39:30 +02:00
Michael Görner
ab9f931bce specify boost:: prefix for future threads
This makes the usage of the boost::thread class consistent within the header
2016-05-26 01:18:16 +02:00
Vicente J. Botet Escriba
21b084384c Merge pull request #86 from MarcelRaad/windows_version
Fix Windows version problems
2016-05-25 23:26:16 +02:00
Marcel Raad
ccca616330 Fix Windows version problems
- the target Windows version was hardcoded to Windows 95
  in thread.cpp if not already defined
- the include for BOOST_USE_WINAPI_VERSION was missing
2016-05-25 15:54:28 +02:00
Vicente J. Botet Escriba
2c3acef281 remove unuseful files. 2016-04-21 19:11:55 +02:00
Vicente J. Botet Escriba
587ad42548 fix hiden rename 2016-04-21 00:10:30 +02:00
Vicente J. Botet Escriba
ef401d81db Merge branch 'develop' of github.com:boostorg/thread into develop 2016-04-20 23:59:40 +02:00
Vicente J. Botet Escriba
57f34e1ea4 fix memory leak. 2016-04-20 23:52:30 +02:00
Vicente J. Botet Escriba
daae305bf7 fix memory leak. 2016-04-20 23:50:43 +02:00
Vicente J. Botet Escriba
55a1325f30 call interrupt only if joinable. 2016-04-20 23:50:16 +02:00
Vicente J. Botet Escriba
46f0be2dce Describe what happens on thread::interrupt with a non-a-thread. 2016-04-20 23:49:46 +02:00
Vicente J. Botet Escriba
98dbc9da41 Merge pull request #81 from blastrock/develop
fix crash in regression tests because of tls
2016-04-20 23:40:54 +02:00
Vicente J. Botet Escriba
640e1acb98 Merge pull request #78 from brycelelbach/patch-1
Fix typo in implementation detail namespace
2016-04-20 23:20:19 +02:00
Vicente J. Botet Escriba
7f2535015d Merge pull request #82 from akrzemi1/patch-1
docs: thread_interruption never calls terminate()
2016-04-20 23:19:05 +02:00
Vicente J. Botet Escriba
aab2891cdb fix scoped_thread move assignement description. 2016-04-20 23:12:55 +02:00
Andrzej Krzemieński
8bbe005bbc docs: thread_interruption never calls terminate()
This note in the docs tries to clarify that exception `thread_interrupted` leaving the thread-main function never triggers a call to `std::terminate`. The previous wording used word 'terminate' in a way that made the semantics ambiguous.
2016-04-20 09:10:10 +02:00
Philippe Daouadi
db5898ba46 fix crash in regression tests because of tls 2016-04-18 10:23:23 +02:00
Vicente J. Botet Escriba
c7a5122fd3 Merge branch 'develop' of github.com:boostorg/thread into develop 2016-04-17 23:59:52 +02:00
Vicente J. Botet Escriba
b932b8c015 Merge pull request #80 from blastrock/develop
Fix leak in tls
2016-04-17 23:59:29 +02:00
Vicente J. Botet Escriba
411798367b call on_desctruction on scoped_thread move assignment. 2016-04-17 23:41:21 +02:00
Philippe Daouadi
e29a4129e8 fix leak in tls 2016-04-16 10:48:40 +02:00
Vicente J. Botet Escriba
f6febf8dfc update las changes in history. 2016-04-01 00:26:58 +02:00
Vicente J. Botet Escriba
2fd8a8dd55 update las changes in history. 2016-04-01 00:20:10 +02:00
Vicente J. Botet Escriba
9db70b803d add missing template parameter in wait_until. 2016-03-25 00:02:04 +01:00
Vicente J. Botet Escriba
47357de276 rollback BOOST_THREAD_PATCH. 2016-03-23 23:15:50 +01:00
Vicente J. Botet Escriba
382ac5a426 update release notes. 2016-03-05 11:13:41 +01:00
Vicente J. Botet Escriba
317a735836 try to manage with #12036. 2016-03-05 11:07:54 +01:00
Vicente J. Botet Escriba
ae22c68ab7 fix #11494. 2016-03-05 10:43:33 +01:00
Vicente J. Botet Escriba
4fb88b29fa take in account error in condition_variable_any::wait_until. 2016-02-28 23:49:29 +01:00
Vicente J. Botet Escriba
a45f36cbc6 Take in account possible issue while initializing cout. #12013 2016-02-28 19:26:38 +01:00
Vicente J. Botet Escriba
5fba7f88a6 Merge branch 'develop' of github.com:boostorg/thread into develop 2016-02-28 19:24:43 +01:00
Vicente J. Botet Escriba
ad7b36dd34 Merge pull request #79 from Lastique/patch-5
Fix compilation on Windows
2016-02-27 22:28:44 +01:00
Andrey Semashev
408d82ded9 Fixed compilation on Windows
Add a missing include for get_milliseconds_until and namespace qualification.
2016-02-27 21:48:23 +03:00
Bryce Adelstein-Lelbach
3f5c0bfb6c Fix typo in implementation detail namespace
Either I'm missing something or hidden has been misspelled as 'hiden' here.
2016-02-19 10:00:25 -08:00
Vicente J. Botet Escriba
8a5cf38a3c Merge pull request #76 from zerotypos-found/fix_typo
Fix typo in doc: a -> an, an -> a
2016-02-05 08:30:51 +01:00
Vicente J. Botet Escriba
0ddc3d40fa Merge pull request #77 from Bklyn/doc-fix
Fix some typos
2016-02-05 08:29:13 +01:00
Caleb Epstein
565c8e0bb8 Fix some typos 2016-02-04 16:03:37 -05:00
zerotypos-found
6954e6ca64 Fix typo in doc: a -> an, an -> a. 2015-12-22 13:19:09 +09:00
Vicente J. Botet Escriba
568275dc5f Merge branch 'feature/add_launch_sync_policy' into develop 2015-12-20 15:36:48 +01:00
Vicente J. Botet Escriba
1d04db8887 Merge branch 'develop' into feature/add_launch_sync_policy 2015-12-19 23:07:04 +01:00
Vicente J. Botet Escriba
7beae6ac06 Merge pull request #75 from zerotypos-found/fix_typo
Fix doc typo
2015-12-08 06:29:12 +01:00
zerotypos-found
dc078f0394 Fix doc typo. 2015-12-08 12:57:28 +09:00
Vicente J. Botet Escriba
6374e09021 update fixes. 2015-12-06 10:27:32 +01:00
Vicente J. Botet Escriba
9f55587ab0 add missing detach in thread assignment V2. #11796. 2015-12-05 14:49:13 +01:00
Vicente J. Botet Escriba
674e1304ef take care of #11818. deferred continuations should not wait too soon. 2015-11-24 22:58:08 +01:00
Vicente J. Botet Escriba
4ad37504ee #11817. missing include file. 2015-11-24 06:50:08 +01:00
Vicente J. Botet Escriba
29849ca3ec manage with bad destructor version documentation. #11795. 2015-11-16 23:16:45 +01:00
Vicente J. Botet Escriba
a636c8d605 Merge branch 'develop' into feature/add_launch_sync_policy 2015-11-15 00:07:51 +01:00
Vicente J. Botet Escriba
dbf0160b1e uncomment previous failing fallback_to test. 2015-11-14 12:38:37 +01:00
Vicente J. Botet Escriba
60a8cb9b5c Merge pull request #74 from tvbuehler/fix-future-resource-leak
fix increasing memory usage / unjoined threads in .then()
2015-11-14 08:37:25 +01:00
Stefan Bühler
8cba434c59 neither continuation nor parent need mutex protection 2015-11-13 12:18:38 +01:00
Stefan Bühler
feab8add3f refactor deferred execute calls 2015-11-13 12:18:38 +01:00
Stefan Bühler
f36857ffef explicitly clear continuation parent state 2015-11-13 12:18:38 +01:00
Stefan Bühler
4ba8415b08 drop sentinel in continuation/unwrap states
- instead keep the inner state alive in places where we move ourself after we
  locked the inner state
2015-11-13 12:18:34 +01:00
Vicente J. Botet Escriba
aa608685af rename centinel by sentinel. reset it as soon as the non deferred continuation is launched so that resources are released. 2015-11-11 00:31:59 +01:00
Vicente J. Botet Escriba
ba43e202c3 add implicit unwrap test. 2015-11-11 00:29:15 +01:00
Vicente J. Botet Escriba
3edbf67ef0 add unwrap/wait/get test. 2015-11-10 07:40:31 +01:00
Vicente J. Botet Escriba
7b67789f98 Avoid ambiguity with C++17 std::invoke. 2015-11-09 23:58:15 +01:00
Vicente J. Botet Escriba
3f7f34b634 minor cleanup on condition_variable. 2015-11-08 17:30:29 +01:00
Vicente J. Botet Escriba
c0fe04ecc9 ensure the void* in the cleanup is shared during the call. 2015-11-08 11:04:40 +01:00
Vicente J. Botet Escriba
eb6d819218 remove unused typedef. 2015-11-08 10:58:36 +01:00
Vicente J. Botet Escriba
578bb1b3ed Merge pull request #72 from ya1gaurav/patch-2
Remove duplicate conditional check.
2015-11-06 19:35:44 +01:00
Gaurav
40b3dc0c2c Remove duplicate conditional check.
thread_info already checked against Null at line no 86, no need to check again.
2015-11-03 14:28:37 +05:30
Vicente J. Botet Escriba
55536c3e23 first commit for launch::sync policy. 2015-10-29 17:22:32 +01:00
Vicente J. Botet Escriba
c0317c5206 Add return *this in invoker assignment. 2015-10-29 11:06:48 +01:00
Vicente J. Botet Escriba
06d2571ec6 Merge branch 'master' into develop 2015-10-22 23:05:13 +02:00
Vicente J. Botet Escriba
fdaba4efe7 try to fix Windows issue with system::time_point arithmetic. 2015-10-22 23:04:23 +02:00
Vicente J. Botet Escriba
8a7cd83123 Merge branch 'develop' 2015-10-22 11:22:27 +02:00
Vicente J. Botet Escriba
98a5e343f8 fix compiler error on time_point_cast. 2015-10-22 11:15:20 +02:00
Vicente J. Botet Escriba
89d8e18c82 Merge branch 'develop' 2015-10-22 00:43:17 +02:00
Vicente J. Botet Escriba
d9492530bd fix timi_point conversion. 2015-10-21 20:19:56 +02:00
Vicente J. Botet Escriba
f6c732b124 Merge branch 'develop' 2015-10-21 18:59:44 +02:00
Vicente J. Botet Escriba
dcc3227668 don't use steady clock if not supported. 2015-10-20 10:03:51 +02:00
Vicente J. Botet Escriba
b3d237731a avoid Boost.Test. 2015-10-20 10:03:15 +02:00
Vicente J. Botet Escriba
4321b59c1e Merge branch 'develop' 2015-10-20 00:23:51 +02:00
Vicente J. Botet Escriba
67759325eb update version 2015-10-20 00:23:06 +02:00
Vicente J. Botet Escriba
8153e2a652 try to fix MSVC issue with template class. 2015-10-19 20:01:42 +02:00
Vicente J. Botet Escriba
7876163c68 make sync optional. 2015-10-19 00:50:29 +02:00
Vicente J. Botet Escriba
805fa41a4e try to fix issues with gcc-3.x.y with not supported -Wno-variadic-macros. 2015-10-18 18:50:34 +02:00
Vicente J. Botet Escriba
0e6376d93a make async return a blocking future. 2015-10-18 18:47:24 +02:00
Vicente J. Botet Escriba
bf1fc5158e Added launch::inherit and specialize the behavior for the(launch::inherit, Cont). 2015-10-18 04:17:27 +02:00
Vicente J. Botet Escriba
1e4e9ab84c #11734. future::then(Cont) should be able to execute the contination on undetermined thread. 2015-10-18 00:36:25 +02:00
Vicente J. Botet Escriba
88ab663ac5 Merge branch 'feature/non_blocking_futures' into develop 2015-10-17 14:57:39 +02:00
Vicente J. Botet Escriba
0ab63b9248 Remove counting when async future blocking. 2015-10-17 11:38:06 +02:00
Vicente J. Botet Escriba
73053e4abe merge from develop. 2015-10-17 10:51:50 +02:00
Vicente J. Botet Escriba
9a4fbbec5d Merge branch 'develop' 2015-10-17 08:22:38 +02:00
Vicente J. Botet Escriba
b4744a2aa8 then can be now sync. The destructor of a shared state that joins check for thread_ifbefore join. Adde continuation_shared_state to share common behavior. 2015-10-17 00:44:45 +02:00
Vicente J. Botet Escriba
4169bcee44 Addoverloadsfor shared. 2015-10-17 00:40:53 +02:00
Vicente J. Botet Escriba
baf516e82f comment serial conttest. 2015-10-17 00:40:23 +02:00
Vicente J. Botet Escriba
cc309eef8d refactor ::then(f) in function of ::then(launch_policy, f). 2015-10-15 23:31:38 +02:00
Vicente J. Botet Escriba
45cc1704ef fix some missing decay. Cleanup adding init. 2015-10-15 19:19:07 +02:00
Vicente J. Botet Escriba
278a06fd47 Merge pull request #71 from jhunold/executors_fix
Fix executor forward
2015-10-12 23:49:48 +02:00
Jürgen Hunold
6ed577f4eb Fix executor forward
correct namespace and type
2015-10-12 08:01:19 +02:00
Vicente J. Botet Escriba
bf8459cf23 Merge from develop. 2015-10-11 23:34:45 +02:00
Vicente J. Botet Escriba
ad3cf1189e More fixes for some move semantic issues C++03. 2015-10-11 21:30:54 +02:00
Vicente J. Botet Escriba
b8db8fef8b Use parent executor (#11716). Add promise::set_executor and packaged_task::set_executor (#11717). Fix some move semantic issues C++03. 2015-10-11 19:56:38 +02:00
Vicente J. Botet Escriba
384c71dbe6 minor updates. 2015-10-11 18:45:58 +02:00
Vicente J. Botet Escriba
111574cf0c minor updat on configuration. 2015-10-10 15:47:28 +02:00
Vicente J. Botet Escriba
759601d08a Merge pull request #70 from mauve/fix-provides-executors-doc
doc: add PROVIDES_EXECUTORS to the config table
2015-10-10 10:26:01 +02:00
Vicente J. Botet Escriba
c60d152102 Merge pull request #69 from mauve/fix-then-docs
doc: then() on future take an executor
2015-10-10 10:24:18 +02:00
Mikael Olenfalk
6ff4fe1a89 doc: add PROVIDES_EXECUTORS to the config table 2015-10-10 09:04:38 +02:00
Mikael Olenfalk
2c0c4ead7f doc: then() on future take an executor 2015-10-10 08:54:37 +02:00
Vicente J. Botet Escriba
dacd6deb0a Add static_shared_from_this and make use of it. 2015-10-09 08:53:47 +02:00
Vicente J. Botet Escriba
c7df715709 Merge branch 'develop' 2015-10-06 23:27:17 +02:00
Vicente J. Botet Escriba
ddd26b5bb8 remove comments after \ continuator macro. 2015-10-04 18:06:59 +02:00
Vicente J. Botet Escriba
f0228ff559 fix shared_state_nullary_task_lifetime_issue_bad_use_of_direct_pointer on C++98 compilers. 2015-10-04 02:10:33 +02:00
Vicente J. Botet Escriba
4acaddd166 rollback fix shared_state_nullary_task_lifetime_issue_bad_use_of_direct_pointer on C++98 compilersas there is a compile error to fix. 2015-10-03 20:26:47 +02:00
Vicente J. Botet Escriba
3a65295d7d replace >> by > >. 2015-09-30 23:58:03 +02:00
Vicente J. Botet Escriba
773f8bfcb4 replace >> by > >. 2015-09-30 23:57:00 +02:00
Vicente J. Botet Escriba
8afcbe22af uncomment fixed test after merge from develop. 2015-09-30 00:08:16 +02:00
Vicente J. Botet Escriba
450f34daed merge from develop. 2015-09-30 00:01:33 +02:00
Vicente J. Botet Escriba
ea9eb62802 fix shared_state_nullary_task_lifetime_issue_bad_use_of_direct_pointer. 2015-09-29 21:57:52 +02:00
Vicente J. Botet Escriba
971c028c9a thread::try_join_until: Avoid busy wait if system clock changes. #11688. 2015-09-28 21:46:16 +02:00
Vicente J. Botet Escriba
3f8618b42b update release notes. 2015-09-27 16:27:06 +02:00
Vicente J. Botet Escriba
9a8759a3dd rollback physical_concurrency changes and take care of patch #10788. #11683. 2015-09-27 15:14:58 +02:00
Vicente J. Botet Escriba
9ac736a4c4 Apply patch fromPR - Do not wake up computer from sleep. #11368. 2015-09-27 14:30:16 +02:00
Vicente J. Botet Escriba
730cb550e6 Merge branch 'develop' 2015-09-27 08:24:26 +02:00
Vicente J. Botet Escriba
8f5de1d7c3 make condition_variable_any steady when BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC. 2015-09-25 07:35:25 +02:00
Vicente J. Botet Escriba
0fdd4fc620 remove comments. 2015-09-24 01:36:41 +02:00
Vicente J. Botet Escriba
a86e2ebcc4 Dont use nanosleep on sleep_for if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC. 2015-09-24 01:25:22 +02:00
Vicente J. Botet Escriba
18cbf4b055 rollback reverse the use of dattime and chrono when chrono is acceptable. 2015-09-24 01:24:08 +02:00
Vicente J. Botet Escriba
6029447774 Merge branch 'develop' of github.com:boostorg/thread into develop 2015-09-24 00:08:22 +02:00
Vicente J. Botet Escriba
205a1d7e2b apply patch ref #7720. 2015-09-24 00:07:11 +02:00
Vicente J. Botet Escriba
2af9c7b98e Merge pull request #66 from BenWiederhake/fix-auto-ptr/develop
Avoid deprecated auto_ptr
2015-09-19 19:59:25 +02:00
Ben Wiederhake
baca517058 Avoid deprecated auto_ptr 2015-09-19 18:14:41 +02:00
Vicente J. Botet Escriba
26486b0288 Merge pull request #65 from mclow/develop
Remove use of deprecated macros in documentation
2015-09-12 08:50:27 +02:00
Marshall Clow
f8ff41e34b Remove use of deprecated macros in documentation 2015-09-11 15:30:34 -07:00
Vicente J. Botet Escriba
16ece266a4 Merge pull request #64 from MarcelRaad/patch-1
Fix for future with RTTI off
2015-09-11 18:32:59 +02:00
Marcel Raad
4224a9f4df Fix for future with RTTI off
895b4a0ac5 introduced dynamic_casts. This breaks boost::future with RTTI turned off, which worked before. static_casts should be enough here.
2015-09-11 11:06:32 +02:00
Vicente J. Botet Escriba
2e17e028b1 use serial_executor instead of serial_executor_cont. 2015-09-08 21:55:48 +02:00
Vicente J. Botet Escriba
febe4a814d comment trace to see the error. 2015-09-08 21:39:33 +02:00
Vicente J. Botet Escriba
242cf35c51 Try patch for oldticket #3926 - thread_specific_ptr + dlopen library causes a SIGSEGV 2015-09-08 19:24:15 +02:00
Vicente J. Botet Escriba
c1ee2bfbd8 fix issue with latch:wait when count is already 0. 2015-09-08 18:25:20 +02:00
Vicente J. Botet Escriba
b30cde32d4 reverse the use of dattime and chrono when chrono is acceptable. 2015-09-08 18:22:44 +02:00
Vicente J. Botet Escriba
ac3f7eb037 comment sleep_for overload on nanoseconds on windows. 2015-09-05 16:17:36 +02:00
Vicente J. Botet Escriba
9f883f6ad7 Add a possible implementation of a steady condition_variable. 2015-09-03 23:44:03 +02:00
Vicente J. Botet Escriba
b332f17825 Added failing test for #11611. 2015-09-02 22:39:26 +02:00
Vicente J. Botet Escriba
a3497e1ffc Merge branch 'develop' 2015-08-22 07:20:49 +02:00
Vicente J. Botet Escriba
89b119f65f Merge branch 'develop' of github.com:boostorg/thread into develop 2015-08-21 18:38:14 +02:00
Vicente J. Botet Escriba
1ae07f3f3a Add shared_timed_mutex typedef. 2015-08-21 18:37:42 +02:00
Vicente J. Botet Escriba
0143748de8 Add test_11499. 2015-08-21 18:37:08 +02:00
Vicente J. Botet Escriba
ac603f6bd1 fix devector allocator_traits_type specific usage. 2015-08-21 18:35:36 +02:00
Vicente J. Botet Escriba
6aeac1e33e Merge pull request #61 from jzmaddock/patch-2
Move Oracle workaround to correct location
2015-08-21 00:00:38 +02:00
jzmaddock
ff375e2780 Move Oracle workaround to correct location 2015-08-20 10:51:23 +01:00
Vicente J. Botet Escriba
5b1c755e42 Merge pull request #60 from jzmaddock/patch-1
Fix to get Thread lib building with Oracle C++
2015-08-19 06:33:59 +02:00
jzmaddock
b8dbe960b7 Fix to get Thread lib building with Oracle C++
See https://svn.boost.org/trac/boost/ticket/11550
2015-08-18 18:20:25 +01:00
Vicente J. Botet Escriba
4f9a08c418 fix for(;;){} . 2015-07-01 13:21:39 +02:00
Vicente J. Botet Escriba
44272d3b7c fix for(;;); . 2015-06-29 08:43:01 +02:00
Vicente J. Botet Escriba
ccd1cd5808 fix Link to archived copy of article. 2015-06-28 11:27:02 +02:00
Vicente J. Botet Escriba
8c974800f9 try to remove yet more warnings. 2015-06-23 19:05:32 +02:00
Vicente J. Botet Escriba
6e002ae3ec try to remove more warnings. 2015-06-21 23:09:15 +02:00
Vicente J. Botet Escriba
2a375808c4 Merge branch 'develop' of github.com:boostorg/thread into develop 2015-06-21 17:38:13 +02:00
Vicente J. Botet Escriba
55c21919fc try to remove some warnings. 2015-06-21 17:37:30 +02:00
Vicente J. Botet Escriba
91e2cded63 Merge pull request #57 from MarcelRaad/patch-1
Fix typo
2015-06-05 18:12:58 +02:00
Marcel Raad
b980b88474 Fix typo
There was a typo in the code with both BOOST_USE_WINDOWS_H and BOOST_NO_ANSI_APIS defined.
2015-06-05 17:48:53 +02:00
Vicente J. Botet Escriba
7cb5211e25 fix typo on poly lockables. 2015-05-29 20:02:08 +02:00
Vicente J. Botet Escriba
958b773d05 Merge from develop. 2015-05-18 22:35:17 +02:00
Vicente J. Botet Escriba
4d45da6c06 Apply patch #11302. 2015-05-18 21:26:46 +02:00
Vicente J. Botet Escriba
e39703ff18 Merge branch 'develop' of github.com:boostorg/thread into develop 2015-05-15 15:07:08 +02:00
Vicente J. Botet Escriba
aafd5ca726 applie patch for #11266. 2015-05-15 15:05:09 +02:00
Vicente J. Botet Escriba
9b69912801 Merge pull request #54 from tempoz/patch-5
Remove unused parameter
2015-05-14 18:18:31 +02:00
Vicente J. Botet Escriba
259c08473d Merge branch 'develop' of github.com:boostorg/thread into develop 2015-05-14 18:08:52 +02:00
Vicente J. Botet Escriba
6ca3a99cbc Merge pull request #56 from danieljames/link-fix
Link to archived copy of article.
2015-05-12 22:39:59 +02:00
Daniel James
3dcd875944 Link to archived copy of article.
The original is no longer available.

Fixes: https://svn.boost.org/trac/boost/ticket/11185
2015-05-12 18:52:23 +01:00
Vicente J. Botet Escriba
58e8addad6 Try to get rid of bad link issue while defining global new. 2015-05-06 13:51:21 +02:00
Vicente J. Botet Escriba
87615d54dd cleanup unused function set_exceptional_if_invalid. 2015-05-06 09:48:54 +02:00
Vicente J. Botet Escriba
d322aba077 Merge pull request #55 from jessicah/tests-fix-error-message
Tests: correct #error message in recursive_mutex/native_handle_pass
2015-05-05 20:50:32 +02:00
Jessica Hamilton
c0afe2d873 Tests: correct #error message in recursive_mutex/native_handle_pass 2015-05-06 02:14:13 +12:00
Vicente J. Botet Escriba
5488482a44 simplify launch_continuation interface. 2015-05-04 23:06:39 +02:00
Vicente J. Botet Escriba
1480d6fc99 simplify launch_continuation interface. 2015-05-04 18:24:09 +02:00
Vicente J. Botet Escriba
131c92a7d8 propagate unwrap fixes. 2015-05-04 00:19:12 +02:00
Vicente J. Botet Escriba
71d9a0a120 fix issue with unwrap shared state. Take care of exceptions on the unwrapped future. 2015-05-03 22:52:52 +02:00
Vicente J. Botet Escriba
b7b2a463cf fix issue with unwrap shared state. 2015-05-03 22:32:17 +02:00
Vicente J. Botet Escriba
c50d0ac4ba try to fix issue with continuation on unwrap shared state. 2015-05-03 16:51:41 +02:00
Vicente J. Botet Escriba
1b2736012c Merge branch 'fix/basic_thread_pool_bad_use_of_scoped_thread' into develop 2015-05-03 14:36:57 +02:00
Vicente J. Botet Escriba
5205fa71bf Fixed some missing lock.unlock(). 2015-05-03 14:30:52 +02:00
Vicente J. Botet Escriba
ba2988a8f7 Fixed issue with basic_thread_pool scoped threads. 2015-05-03 10:42:42 +02:00
Vicente J. Botet Escriba
650956bd3b First draft of non-blocking. Fixed issue with basic_thread_pool scoped threads. Now when the result of async(ex,f) is not stored, there is a lifetime issue with shared_state_nullary_task use of direct pointer to the shared state, however there is some weak_ptr issues :(. 2015-05-03 10:13:08 +02:00
Vicente J. Botet Escriba
e598796eaf Add assertion on future continuation parameter is ready. As noted in #11256, there some serious issues with the parameter passed and with lock on locked mutextes :(. 2015-05-02 16:29:06 +02:00
Vicente J. Botet Escriba
bce7eabba2 fix make_exceptional issue. 2015-04-30 01:11:39 +02:00
Vicente J. Botet Escriba
0218136ed7 Try to see if share_from_this helps on the thread sanitize data race. 2015-04-25 15:41:49 +02:00
Vicente J. Botet Escriba
461bf803fc Avoid data race in std::cout. 2015-04-25 11:17:20 +02:00
Vicente J. Botet Escriba
1bd78bbeea cleanup commented code. 2015-04-25 11:16:03 +02:00
Vicente J. Botet Escriba
348da6b7e4 fix memory leack in test. 2015-04-25 10:11:01 +02:00
Vicente J. Botet Escriba
e850218c49 ref #11174 - boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite. 2015-04-25 00:20:53 +02:00
Vicente J. Botet Escriba
385eefd3b3 ref #11174 - boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite. 2015-04-25 00:20:05 +02:00
Zoey Greer
2ddf7aad0b Remove unused parameter
lk is unused in get_state, naming it causes build warnings
2015-04-22 19:37:36 -04:00
Vicente J. Botet Escriba
c9433c2a5b rollback ref #11174 - boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite. 2015-04-22 22:49:26 +02:00
Vicente J. Botet Escriba
8853a4cbdf ref #11174 - boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite. 2015-04-22 07:23:38 +02:00
Vicente J. Botet Escriba
6f53279b50 ref #11174 - boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite. 2015-04-18 19:26:07 +02:00
Vicente J. Botet Escriba
f25bc8bbab Merge branch 'develop' 2015-04-18 11:56:34 +02:00
Vicente J. Botet Escriba
5c442e068c update compliance. 2015-04-18 07:10:43 +02:00
Vicente J. Botet Escriba
0bed674233 ref #11192- boost::future<>::then() with an executor doesn't compile when the callback returns a future 2015-04-18 07:04:50 +02:00
Vicente J. Botet Escriba
66193b0d38 Test with generic lambdas. 2015-04-17 18:31:34 +02:00
Vicente J. Botet Escriba
45c9a1d7fd ref #11192- boost::future<>::then() with an executor doesn't compile when the callback returns a future 2015-04-17 18:30:49 +02:00
Niall Douglas
0d8ddfe378 Merge pull request #51 from MarcelRaad/patch-1
Respect BOOST_USE_WINDOWS_H again
2015-04-03 17:11:17 +01:00
Vicente J. Botet Escriba
74f479d5c9 Fix non_copyable class in queue/dequeue view tests. 2015-03-29 19:34:28 +02:00
Vicente J. Botet Escriba
dbf793e7eb Don't execute test for launch::deferred if BOOST_THREAD_PROVIDES_VARIADIC_THREAD is not defined. 2015-03-29 19:28:05 +02:00
Marcel Raad
b5c6f760c5 Respect BOOST_USE_WINDOWS_H again
With the GetTickCount64 and WinRT fixes, the Windows API functions were always re-declared regardless of BOOST_USE_WINDOWS_H. This breaks clang-cl, which complains about conflicting definitions.
2015-03-26 13:43:44 +01:00
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
Vicente J. Botet Escriba
a8ad389bdd Merge branch 'develop' into feature/task_region 2014-11-06 07:42:36 +01:00
Vicente J. Botet Escriba
69c1d40750 Merge branch 'develop' into feature/promise_set_value_emplace 2014-11-05 23:43:02 +01:00
Vicente J. Botet Escriba
58698f44f1 More renamming and added some comments on scheduler.hpp. 2014-11-05 19:41:56 +01:00
Vicente J. Botet Escriba
37afdd2e9a Moved test_scheduler_p to a explicit test_suite. 2014-11-05 01:03:44 +01:00
Vicente J. Botet Escriba
c87b24923a Added scheduler at/after/on executor factory helper functions. 2014-11-05 00:41:29 +01:00
Vicente J. Botet Escriba
1210fc4859 Add missing include file. 2014-11-05 00:38:21 +01:00
Vicente J. Botet Escriba
d8b6ae6266 Ensure that the numbers of pools is at least 1. 2014-11-05 00:37:52 +01:00
Vicente J. Botet Escriba
04e2223d5e Minor renamming. 2014-11-04 22:51:25 +01:00
Vicente J. Botet Escriba
579748e7a0 Avoid locking while doing callback. 2014-11-04 22:48:57 +01:00
Vicente J. Botet Escriba
41c3914aaf Don't try-catch on try_executing_one_task. 2014-11-02 19:42:18 +01:00
Vicente J. Botet Escriba
8693eec4a4 Make submit strong-thread safe. 2014-11-02 19:41:57 +01:00
Vicente J. Botet Escriba
3f699750a8 Avoid locking while doing callback. 2014-11-02 19:41:42 +01:00
Vicente J. Botet Escriba
4f8243cf59 Remove waiting_empty_. 2014-11-02 19:41:25 +01:00
Vicente J. Botet Escriba
4f01891da7 Added not_ready and timeout queue_op_status. Make sync_timed_queue and sync_priority_queue conform to the sync_queue interface. Aapt the test to the new interface. 2014-11-02 15:13:37 +01:00
Vicente J. Botet Escriba
efab5af918 Fix inspection issue. 2014-11-02 15:11:28 +01:00
Vicente J. Botet Escriba
4d03b410a8 Update executors doc adding thread executor. 2014-11-02 15:10:15 +01:00
Vicente J. Botet Escriba
c1925df81c Fix task exception silently ignored. Make submit throw if closed. join the threads created by the thread_executor 2014-11-02 15:09:11 +01:00
Vicente J. Botet Escriba
cbf9fe8a5c Fix inspection issues. 2014-11-02 15:08:44 +01:00
Vicente J. Botet Escriba
6fd7dc0d94 Added move semantics for C++11 compilers. Need of a detail::priority_queue. Tried to do it for C++98, but heap_push/heap_pop algorithms are not move aware:(. 2014-11-01 22:18:32 +01:00
Vicente J. Botet Escriba
a2f2924298 Added missing file sync_queue_base and refactor the concurrent queues to make use of this class. 2014-11-01 22:18:09 +01:00
Vicente J. Botet Escriba
49d485f1aa Removed BOOST_THREAD_QUEUE_DEPRECATE_OLD for priority and timed queues. 2014-11-01 11:21:09 +01:00
Vicente J. Botet Escriba
d7251f223e Added sync_queue_base and refactor the concurrent queues to make use of this class. Make other refactor on priority and timed queues. 2014-11-01 11:02:18 +01:00
Vicente J. Botet Escriba
20a6ef7de8 Added wait_until_not_empty, wait_until_not_empty_or_closed. Rename _q_qempty to _not_empty. 2014-11-01 01:14:41 +01:00
Vicente J. Botet Escriba
d5c41e4c4a Added tyy_pus returning queue_op_status. Rename is_closed to closed. 2014-10-31 23:49:34 +01:00
Vicente J. Botet Escriba
b96b9904b7 move scheduled_executor_base.hpp and declare scheduled_thread_pool::worker_loop inline. 2014-10-31 08:21:27 +01:00
Vicente J. Botet Escriba
304240b206 Move priority/timed queues to concurrent name space and scheduled executors to executors name spapce. 2014-10-31 08:03:15 +01:00
Vicente J. Botet Escriba
c61c139933 merged scheduled executors GSOC project from Ian Forbed. 2014-10-31 00:19:10 +01:00
Vicente J. Botet Escriba
c3b98129e4 Added task_region documentation. 2014-10-26 19:44:32 +01:00
Vicente J. Botet Escriba
3891eeef52 fix issue with C++98 exception library. 2014-10-26 19:43:47 +01:00
Vicente J. Botet Escriba
f1370b1255 Added a task_region_handle_gen that referes to an existing executor, so that we don't create one each time. 2014-10-26 15:17:25 +01:00
Vicente J. Botet Escriba
69f2a1df72 Added fib_task_region example and allows to work without executors. 2014-10-26 13:21:25 +01:00
Vicente J. Botet Escriba
700301e382 Added exception_list and task_region. 2014-10-26 11:27:18 +01:00
Vicente J. Botet Escriba
952aa44a98 Added promise::emplace and variadic make_ready_future. 2014-10-25 23:31:09 +02:00
Vicente J. Botet Escriba
5fb51a74fe remove thread_was_interrupted and fix wait_internal pending issue. 2014-10-24 18:43:26 +02:00
Vicente J. Botet Escriba
02bb6abef4 Merge pull request #29 from awulkiew/patch-1
Change members order in win32 thread_data_base to match ctor initializer...
2014-10-23 00:39:04 +02:00
Adam Wulkiewicz
1a4bd71616 Change members order in win32 thread_data_base to match ctor initializer list. 2014-10-23 00:01:37 +02:00
Vicente J. Botet Escriba
63dd439992 update history. 2014-10-12 16:28:29 +02:00
Vicente J. Botet Escriba
1029fa9c59 take in account deferred/ready futures on variadic when_all/when_any. 2014-10-12 15:47:16 +02:00
Vicente J. Botet Escriba
3e28ea806c Added deferred then tests. 2014-10-11 07:33:57 +02:00
Vicente J. Botet Escriba
07dc40a9ff Added missing boost/config.hpp file when checking for BOOST_NO_CXX11_DECLTYPE. 2014-10-09 06:51:02 +02:00
Vicente J. Botet Escriba
6f91af2154 Try to address #9569. 2014-10-05 09:11:58 +02:00
Vicente J. Botet Escriba
c3cff80557 Merge branch 'develop' of github.com:boostorg/thread into develop 2014-10-05 09:07:18 +02:00
Vicente J. Botet Escriba
729c8b63bb added missing file. 2014-10-05 09:06:52 +02:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
6fe7f44ea0 Clarified issue #6782 which can now be closed. 2014-10-04 19:47:48 +01:00
Vicente J. Botet Escriba
8fd4755e79 Added shared_future::then executor. 2014-10-04 10:36:57 +02:00
Vicente J. Botet Escriba
02b007a20e Make nullary_function copyable and movable following Boost.Move. Make use of std::shared_ptr when available. 2014-10-04 10:36:44 +02:00
Vicente J. Botet Escriba
c0c78e87fc Make invoker copyable and movable following Boost.Move. 2014-10-04 10:36:31 +02:00
Vicente J. Botet Escriba
58cde5af05 Trying to use std::function for executors::work. This doesn't works yet. 2014-10-03 21:46:57 +02:00
Vicente J. Botet Escriba
c1f2c8a1f1 Added shared_ptr.hpp. 2014-10-03 21:43:50 +02:00
Vicente J. Botet Escriba
bacf5b52ec The added commented lines should work, but don't. 2014-10-03 21:42:42 +02:00
Vicente J. Botet Escriba
3babf7966e update doc for future/shared_future::then(Executor, Fct). 2014-10-02 22:34:47 +02:00
Vicente J. Botet Escriba
f3de7bf10f Add fuutre::then(ex, fct). 2014-10-02 07:36:52 +02:00
Vicente J. Botet Escriba
90154217cf Added const to shred_future::then(). 2014-10-01 08:34:34 +02:00
Vicente J. Botet Escriba
ac0b2f9ba7 minor changes to unwrap. 2014-10-01 07:55:36 +02:00
Vicente J. Botet Escriba
da739e680a Merge pull request #27 from Lastique/patch-4
Fix GCC warnings about initialization order
2014-09-30 23:54:06 +02:00
Andrey Semashev
b240b097c7 Fix GCC warnings about initialization order 2014-09-30 22:42:13 +04:00
Vicente J. Botet Escriba
debe2fb0d1 Merge pull request #26 from Lastique/patch-3
Fix compilation with BOOST_USE_WINDOWS_H defined
2014-09-30 20:38:35 +02:00
Andrey Semashev
b264ec8fc0 Fix compilation with BOOST_USE_WINDOWS_H defined
Don't use macros defined only in Windows SDK 6.0 and later as this breaks compilation with MinGW and older MSVC.
2014-09-30 22:17:44 +04:00
Vicente J. Botet Escriba
372f8fe10f Merge branch 'develop' of github.com:boostorg/thread into develop 2014-09-29 23:22:16 +02:00
Vicente J. Botet Escriba
e3c240df0a shared_future<R>::then() should be const. 2014-09-29 23:22:03 +02:00
Niall Douglas
748ea5164e Merge pull request #25 from MarcelRaad/patch-1
Fix GetTickCount return type
2014-09-29 19:18:38 +01:00
Vicente J. Botet Escriba
b44627f97d don't use std::queue with MSVC 11. 2014-09-29 00:19:35 +02:00
Vicente J. Botet Escriba
c8cd7d1d08 don't check for is_ready on all the futures when using when_wny. 2014-09-29 00:19:18 +02:00
Vicente J. Botet Escriba
f0d0c0551b rollback to not define BOOST_RESULT_OF_USE_DECLTYPE. 2014-09-29 00:00:49 +02:00
Vicente J. Botet Escriba
bb72eadbd8 Added validation of invalid inner future in wrap. 2014-09-29 00:00:06 +02:00
Marcel Raad
f52f32afda Fix GetTickCount return type
int as a return type results in a signed/unsigned mismatch warning with MSVC (although disabled by default), and it doesn't even compile with clang-cl if the definiton from the Windows header was included before.
2014-09-28 21:25:36 +02:00
Vicente J. Botet Escriba
b973e9b32e remove BOOST_THREAD_NO_CXX11_DECLTYPE_N3276. 2014-09-28 13:46:21 +02:00
Vicente J. Botet Escriba
1ffef9ed2d Add missing invoke.hpp include. 2014-09-28 13:40:16 +02:00
Vicente J. Botet Escriba
f24ea524bd Remove confusing may be remark and replace T by FutTypes. 2014-09-28 11:55:35 +02:00
Vicente J. Botet Escriba
4111471ba5 fix typo on file guard. 2014-09-28 09:19:42 +02:00
Vicente J. Botet Escriba
5e970b987e remove warning. 2014-09-28 00:34:15 +02:00
Vicente J. Botet Escriba
c7b5729cf3 Avoid the use fo invoke if not available, even if the semantics is not the same. 2014-09-27 19:59:25 +02:00
Vicente J. Botet Escriba
291ebded8e update changes and compliance with last fixed issues. 2014-09-27 19:58:17 +02:00
Vicente J. Botet Escriba
0c2c8ed3b8 Update doc with last modifications from Concurrent TS. 2014-09-27 19:57:33 +02:00
Vicente J. Botet Escriba
5294dfa149 Update doc with last modifications from Concurrent TS. 2014-09-27 16:45:39 +02:00
Vicente J. Botet Escriba
7f5dfb633d MSVC 10 doesn't provide std::is_copy_constructible. Make use of the boost version. 2014-09-26 06:48:40 +02:00
Vicente J. Botet Escriba
f381a7d591 Don't delete copy constructor when rvalue references are disabled. 2014-09-25 07:25:39 +02:00
Vicente J. Botet Escriba
aceabda609 try to avoid to unlock prematurely to see if this is the cause of the test_latch spourious failure. 2014-09-24 08:09:40 +02:00
Vicente J. Botet Escriba
dc4b619b57 Don't delete copy constructor when rvalue references are disabled. 2014-09-23 23:34:42 +02:00
Vicente J. Botet Escriba
abb3fc97e0 fix reported error. 2014-09-23 23:30:26 +02:00
Vicente J. Botet Escriba
ec6ae7b9b4 Take in account small durations. 2014-09-23 23:29:38 +02:00
Vicente J. Botet Escriba
8c5ba97d39 Don't use lambdas on test if not available. 2014-09-21 18:59:08 +02:00
Vicente J. Botet Escriba
617b979214 try a workaround with MSVC for error C3520: 'T' : parameter pack must be expanded in this context. 2014-09-21 18:58:41 +02:00
Vicente J. Botet Escriba
96667cfcce MSVC 10 doesn't provide std::is_move_constructible. Let as if all classes were movable in this case. 2014-09-21 18:58:23 +02:00
Vicente J. Botet Escriba
a981650ce9 cleanup. 2014-09-20 16:11:03 +02:00
Vicente J. Botet Escriba
00b25853b2 Added when_all/when_any iterators tests. 2014-09-20 16:05:19 +02:00
Vicente J. Botet Escriba
ef04ce8bce enable disabled test. 2014-09-20 14:53:06 +02:00
Vicente J. Botet Escriba
5091ad705f Added when_any/variadic_pass.cpp. 2014-09-20 14:37:47 +02:00
Vicente J. Botet Escriba
b77f802c47 variadic when_all/when_any must retur tuple instead of vector even when all the types are the same.. 2014-09-20 13:25:50 +02:00
Vicente J. Botet Escriba
da945436c1 avoid call to boost::get_system_time() when relative is true. 2014-09-14 21:51:01 +02:00
Vicente J. Botet Escriba
27befdf26f Added test for threads_specific_ptr<void>. 2014-09-14 21:49:31 +02:00
Vicente J. Botet Escriba
f73007910a replace unique_ptr<T> by optional<T> on shared_state when rvalue references are supported by the compiler, as optional<T> doesn't use Boost.Move. 2014-09-14 21:12:44 +02:00
Vicente J. Botet Escriba
8c3cfacf06 emulate template alias queue views. 2014-09-14 21:00:27 +02:00
Vicente J. Botet Escriba
7d4392e157 try to get rid of missing std::is_copy_constructible < gcc-4.5. 2014-09-14 09:09:59 +02:00
Vicente J. Botet Escriba
aff3f424a9 move sync_queue_closed to concurrent directory. 2014-09-13 22:17:19 +02:00
Vicente J. Botet Escriba
546ca909c4 try to avoid issue with < gcc-4.5 - error: 'is_copy_constructible' is not a member of 'std'. 2014-09-13 22:16:57 +02:00
Vicente J. Botet Escriba
7dac51706c Merge branch 'develop' 2014-09-12 23:40:30 +02:00
Vicente J. Botet Escriba
5ee0e27b5a add more try catch to trac the source of the error. 2014-09-12 22:50:56 +02:00
Vicente J. Botet Escriba
b4fd7fdeb1 fail test when exception cautch instead of rethrow it. 2014-09-11 13:33:43 +02:00
Vicente J. Botet Escriba
c75ea7db89 force the use of lambdas when available on multi_thread_pass test. 2014-09-11 13:32:11 +02:00
Vicente J. Botet Escriba
19294dc756 Change ref by ptr on queue fields of queue_views so that the default constructors can be generated on MSVC. 2014-09-11 13:30:48 +02:00
Vicente J. Botet Escriba
52a360775e cleanup. 2014-09-11 07:32:40 +02:00
Vicente J. Botet Escriba
c632b75db1 fix uninitialized variable. 2014-09-11 07:29:53 +02:00
Vicente J. Botet Escriba
11e4c950ac fix 10478 data race in boost/thread/future.hpp 2014-09-10 13:44:44 +02:00
Vicente J. Botet Escriba
8440e9a7d8 add tests on non_intettuption_point::sleep_... 2014-09-10 13:42:15 +02:00
Vicente J. Botet Escriba
02bc292c20 document non_intettuption_point::sleep_... 2014-09-10 13:41:11 +02:00
Vicente J. Botet Escriba
6d68bac44b fix move semantic issues on promise::set_value. Prepare the use of unique_ptr<T,D> to fix allocator issue. 2014-09-09 13:21:01 +02:00
Vicente J. Botet Escriba
5d0d128cab let movelib do the std adaptation. 2014-09-09 13:15:51 +02:00
Vicente J. Botet Escriba
ec542d3c8b remove commented code. 2014-09-08 05:49:10 +02:00
Vicente J. Botet Escriba
6e3216643b Remove future_traits<> as there are always an specialization. 2014-09-07 19:46:02 +02:00
Vicente J. Botet Escriba
016f5653cf Added when_all().then() tests. 2014-09-07 09:04:00 +02:00
Vicente J. Botet Escriba
ce46539183 Added when_all/when_any/queue_views tests. 2014-09-06 23:30:50 +02:00
Vicente J. Botet Escriba
e93035ce42 Added run_if_is_deferred to shared_future. 2014-09-06 23:30:36 +02:00
Vicente J. Botet Escriba
53a46593a8 make classes using BOOST_THREAD_MOVABLE_ONLY<T> satisfy is_copy_constructible<T>::value == false. 2014-09-06 14:20:59 +02:00
Vicente J. Botet Escriba
c2426b8fad fix missin common virtual function in queue_base_copyable_only. 2014-09-06 14:19:37 +02:00
Vicente J. Botet Escriba
7d841f6337 fix typo. 2014-09-06 14:18:36 +02:00
Vicente J. Botet Escriba
556bbde8a7 Implemented when_all/when_any when a tuple is returned. 2014-09-04 20:00:03 +02:00
Vicente J. Botet Escriba
a0c1462a6a merge from develop. 2014-09-02 21:41:59 +02:00
Vicente J. Botet Escriba
234df13faf remove BOOST_THREAD_USES_LOG. 2014-09-01 19:59:30 +02:00
Vicente J. Botet Escriba
24983f0bce Let the deferred tests be executed when BOOST_THREAD_PROVIDES_VARIADIC_THREAD is defined. 2014-08-31 20:05:43 +02:00
Vicente J. Botet Escriba
722997379b Added thread pool join function. 2014-08-31 18:16:49 +02:00
Vicente J. Botet Escriba
f36f5d6dbb Added more async deferred tests. 2014-08-31 18:16:14 +02:00
Vicente J. Botet Escriba
9ee1044f92 Merge branch 'develop' of github.com:boostorg/thread into develop 2014-08-31 09:00:04 +02:00
Vicente J. Botet Escriba
ebeb36646c Add test for issue #10340. 2014-08-31 08:59:40 +02:00
Vicente J. Botet Escriba
8ebf0e7f21 take in account ready tasks on when_all/when_any. 2014-08-31 08:57:27 +02:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
0dc2f69bc1 Fixed typo in just made merge for WinRT support. 2014-08-30 18:58:43 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
c3b549d947 Merge branch 'MSOpenTech-winrt2' into develop 2014-08-30 18:24:46 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
6552cf64b5 Fixed up WinRT support patch not compiling on WinRT. 2014-08-30 18:24:13 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
d5f335b8a4 Merge branch 'winrt2' of https://github.com/MSOpenTech/thread into MSOpenTech-winrt2 2014-08-30 17:16:17 +01:00
Vicente J. Botet Escriba
80591fb64d try to fix 10428 for uinque_ptr issues. 2014-08-30 17:57:12 +02:00
Vicente J. Botet Escriba
0543b522cb try to fix 10340. 2014-08-30 17:54:12 +02:00
Vicente J. Botet Escriba
3dbc5d0664 Added when_all/when_any documentation. 2014-08-30 13:43:42 +02:00
Vicente J. Botet Escriba
2d0272345b update doc cith generic executor and queue views. 2014-08-30 10:07:08 +02:00
Vicente J. Botet Escriba
f1a274b51c make it possible to have polymorphic queue copyable_only/movable_only/copyable_and_movable. 2014-08-29 21:06:15 +02:00
Vicente J. Botet Escriba
b7f1706ab8 Add test won when_all iterators for c++98 compilers. 2014-08-29 21:04:33 +02:00
Vicente J. Botet Escriba
f299fb8083 fix typo. 2014-08-29 12:51:42 +02:00
Vicente J. Botet Escriba
074dcbcbf5 make polymorphic queues move operations only available if C++11 RVALE supported. 2014-08-28 22:26:02 +02:00
Vicente J. Botet Escriba
af6f80a3c7 Added generic_executor_ref.cpp tp regression tests. 2014-08-27 13:36:58 +02:00
Vicente J. Botet Escriba
957253401f Try to fix invoker making it ComyConstructible and Movable. 2014-08-27 13:35:59 +02:00
Vicente J. Botet Escriba
3195253230 rollback last merge as it is breaking all the regression tests. 2014-08-27 00:16:19 +02:00
Vicente J. Botet Escriba
4336a7bbe3 Merge pull request #24 from MarcelRaad/patch-1
Use BOOST_THREAD_RV_REF for move constructors
2014-08-26 18:44:38 +02:00
Marcel Raad
3b75d6dabc Use BOOST_THREAD_RV_REF for move constructors
If BOOST_THREAD_FWD_REF is used, the copy constructor is re-declared. Tested with clang 3.4.
2014-08-26 10:17:26 +02:00
Vicente J. Botet Escriba
fc0d7e23b3 remove todo comments. 2014-08-25 17:17:50 +02:00
Vicente J. Botet Escriba
aeabda8d45 make use of move when a rvalue is used and make use of BOOST_THREAD_FWD_REF when a URef is used. 2014-08-24 22:48:06 +02:00
Vicente J. Botet Escriba
3bde7e103c Added virtual submit(work&). 2014-08-24 18:17:59 +02:00
Vicente J. Botet Escriba
ea0889485e Make use of BOOST_THREAD_COPYABLE_AND_MOVABLE and BOOST_THREAD_COPY_ASSIGN_REF when appropriated. 2014-08-24 18:16:28 +02:00
Vicente J. Botet Escriba
d4d46c64dd fix loop_executor run_queued_closures issue. 2014-08-23 19:14:21 +02:00
Vicente J. Botet Escriba
f3fa80c866 Added generic_executor_ref, queue_base and queue views, fix some issues in executors. 2014-08-23 18:29:47 +02:00
Vicente J. Botet Escriba
7e21f24991 Merge branch 'develop' of github.com:boostorg/thread into develop 2014-08-21 19:18:56 +02:00
Vicente J. Botet Escriba
2037a64c51 Avoid pedantic clang watnings. 2014-08-21 19:17:27 +02:00
Vicente J. Botet Escriba
8bfd1cea31 fix typo. 2014-08-21 19:16:41 +02:00
Niall Douglas
a26e7eb8c4 Merge pull request #22 from eldiener/master
For clang turn warnings to 'on' and remove '-pedantic' to avoid Boost PP...
2014-08-05 10:10:05 +01:00
Edward Diener
e47eba8751 For clang turn warnings to 'on' and remove '-pedantic' to avoid Boost PP warnings. 2014-08-04 19:30:29 -04:00
Eric Niebler
8aef8000d9 Merge branch 'master' into develop 2014-08-03 12:12:27 -07:00
Niall Douglas
78f1044c68 The previous mingw32 fix unfortunately broke mingw-w64, so that is now fixed too. 2014-08-02 21:38:31 +01:00
Niall Douglas
26042ca26a Fixed mingw32 compile breakage. 2014-08-02 18:56:08 +01:00
Vicente J. Botet Escriba
74132067ba prepare tss<void>. 2014-07-31 19:29:19 +02:00
Vicente J. Botet Escriba
c4d42e6b6c make use of wait_pull_front instead of pull_front. 2014-07-31 19:28:04 +02:00
Vicente J. Botet Escriba
59c504d5d8 Merge pull request #21 from Lastique/patch-3
Fixed compilation with gcc 4.6 in C++11 mode
2014-07-31 07:11:42 +02:00
Andrey Semashev
b81a838a43 Fixed compilation with gcc 4.6 in C++11 mode
The compiler considers invoke() call ambiguous when the function object is actually a function pointer. This caused compilation errors in Boost.Coroutine, which uses invoke() through call_once(). Also added missing includes.
2014-07-31 02:27:33 +04:00
Steve Gates
a06dde3794 Merge branch 'develop' into winrt2
Conflicts:
	include/boost/thread/win32/thread_primitives.hpp
	src/win32/gettickcount64.cpp
2014-07-18 12:19:46 -07:00
Steve Gates
726a3faf19 Removing QueueUserAPC on Windows Runtime. 2014-07-17 10:49:09 -07:00
Steve Gates
c977c8d420 Qualifying some functions calls in thread_primitives.hpp to avoid potentially ambiguity. 2014-07-10 18:09:24 -07:00
Steve Gates
a1faacd7bb Fixing up copyrights that got reordered. 2014-07-09 16:43:48 -07:00
Steve Gates
866b78cbd0 Addressing more feedback:
Reverting disabling thread attributes for WinRT.
Created common GetSystemInfo/GetNativeSystemInfo function.
Fix this_thread get_id() bug on WinRT.
Enabled initializing the Windows Runtime in each test for execution. This
is not when using in Windows store/phone applications, just if a desktop
app.
2014-07-09 15:47:37 -07:00
Steve Gates
0861f81b05 Merge branch 'develop' of https://github.com/boostorg/thread into feedback 2014-07-08 14:53:47 -07:00
Steve Gates
6488028a22 Incorporating feedback: removed copyright, removed some ifdefs. 2014-07-08 14:53:39 -07:00
Steve Gates
9ceea9822f Enabling Boost.Thread to be used in the Windows Runtime.
This involves basically 3 changes:
1. Using __declspec(thread) instead of the Tls APIs.
2. Using Windows::System::Threading since Win32 Threading APIs aren't allowed.
3. Updating or replacing some banned APIs like WaitForSingleObject with WaitForSingleObjectEx.
2014-07-02 14:21:43 -07:00
278 changed files with 22366 additions and 6403 deletions

40
.gitignore vendored Normal file
View File

@@ -0,0 +1,40 @@
#mac
.DS_Store
#projects
.project
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
bin/*
test/bin/*
*.exe
*.out
*.app
#doc
doc/html

365
.travis.yml Normal file
View File

@@ -0,0 +1,365 @@
# Copyright 2016, 2017 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
language: cpp
sudo: false
python: "2.7"
os:
- linux
- osx
branches:
only:
- master
- develop
- /feature\/.*/
env:
matrix:
- BOGUS_JOB=true
matrix:
exclude:
- env: BOGUS_JOB=true
include:
# - os: linux
# compiler: g++-4.7
# env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=c++11
# addons:
# apt:
# packages:
# - g++-4.7
# sources:
# - ubuntu-toolchain-r-test
#
# - os: linux
# compiler: g++-4.8
# env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=c++11
# addons:
# apt:
# packages:
# - g++-4.8
# sources:
# - ubuntu-toolchain-r-test
#
# - os: linux
# compiler: g++-4.9
# env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=c++11
# addons:
# apt:
# packages:
# - g++-4.9
# sources:
# - ubuntu-toolchain-r-test
#
# - os: linux
# compiler: g++-5
# env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++98
# addons:
# apt:
# packages:
# - g++-5
# sources:
# - ubuntu-toolchain-r-test
#
# - os: linux
# compiler: g++-5
# env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++11
# addons:
# apt:
# packages:
# - g++-5
# sources:
# - ubuntu-toolchain-r-test
#
# - os: linux
# compiler: g++-5
# env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14
# addons:
# apt:
# packages:
# - g++-5
# sources:
# - ubuntu-toolchain-r-test
#
# - os: linux
# compiler: g++-5
# env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++1z
# addons:
# apt:
# packages:
# - g++-5
# sources:
# - ubuntu-toolchain-r-test
#
# - os: linux
# compiler: g++-6
# env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++98
# addons:
# apt:
# packages:
# - g++-6
# sources:
# - ubuntu-toolchain-r-test
#
# - os: linux
# compiler: g++-6
# env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11
# addons:
# apt:
# packages:
# - g++-6
# sources:
# - ubuntu-toolchain-r-test
#
# - os: linux
# compiler: g++-6
# env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14
# addons:
# apt:
# packages:
# - g++-6
# sources:
# - ubuntu-toolchain-r-test
#
# - os: linux
# compiler: g++-6
# env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z
# addons:
# apt:
# packages:
# - g++-6
# sources:
# - ubuntu-toolchain-r-test
- os: linux
dist: trusty
compiler: g++-7
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++98
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
dist: trusty
compiler: g++-7
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++11
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
dist: trusty
compiler: g++-7
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++14
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
dist: trusty
compiler: g++-7
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++1z
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
# - os: linux
# compiler: clang++-3.5
# env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=c++11
# addons:
# apt:
# packages:
# - clang-3.5
# sources:
# - ubuntu-toolchain-r-test
# - llvm-toolchain-precise-3.5#
#
# - os: linux
# compiler: clang++-3.6
# env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=c++11
# addons:
# apt:
# packages:
# - clang-3.6
# sources:
# - ubuntu-toolchain-r-test
# - llvm-toolchain-precise-3.6
#
# - os: linux
# compiler: clang++-3.7
# env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=c++11
# addons:
# apt:
# packages:
# - clang-3.7
# sources:
# - ubuntu-toolchain-r-test
# - llvm-toolchain-precise-3.7
#
# - os: linux
# compiler: clang++-3.8
# env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++11
# addons:
# apt:
# packages:
# - clang-3.8
# sources:
# - ubuntu-toolchain-r-test
# - llvm-toolchain-precise-3.8
#
# - os: linux
# compiler: clang++-3.8
# env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++14
# addons:
# apt:
# packages:
# - clang-3.8
# sources:
# - ubuntu-toolchain-r-test
# - llvm-toolchain-precise-3.8
#
# - os: linux
# compiler: clang++-3.8
# env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++1z
# addons:
# apt:
# packages:
# - clang-3.8
# sources:
# - ubuntu-toolchain-r-test
# - llvm-toolchain-precise-3.8
#
# - os: linux
# compiler: clang++-3.9
# env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++11
# addons:
# apt:
# packages:
# - clang-3.9
# sources:
# - ubuntu-toolchain-r-test
# - llvm-toolchain-precise-3.9
#
# - os: linux
# compiler: clang++-3.9
# env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++14
# addons:
# apt:
# packages:
# - clang-3.9
# sources:
# - ubuntu-toolchain-r-test
# - llvm-toolchain-precise-3.9
#
# - os: linux
# compiler: clang++-3.9
# env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++1z
# addons:
# apt:
# packages:
# - clang-3.9
# sources:
# - ubuntu-toolchain-r-test
# - llvm-toolchain-precise-3.9
#
- os: linux
compiler: clang++-4.0
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++98
addons:
apt:
packages:
- clang-4.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- os: linux
compiler: clang++-4.0
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++11
addons:
apt:
packages:
- clang-4.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- os: linux
compiler: clang++-4.0
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++14
addons:
apt:
packages:
- clang-4.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- os: linux
compiler: clang++-4.0
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++1z
addons:
apt:
packages:
- clang-4.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++98
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++11
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++1z
install:
- BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
- cd ..
- git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
- cd boost-root
- git submodule update --init tools/build
- git submodule update --init libs/config
- git submodule update --init tools/boostdep
- mkdir -p libs/thread
- cp -r $TRAVIS_BUILD_DIR/* libs/thread
- python tools/boostdep/depinst/depinst.py thread
- ./bootstrap.sh
- ./b2 headers
script:
- |-
echo "using $TOOLSET : : $COMPILER : <cxxflags>-std=$CXXSTD ;" > ~/user-config.jam
- ./b2 -j3 libs/thread/test toolset=$TOOLSET
notifications:
email:
on_success: always

View File

@@ -6,3 +6,5 @@ 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).

41
appveyor.yml Normal file
View File

@@ -0,0 +1,41 @@
# Copyright 2016, 2017 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
version: 1.0.{build}-{branch}
shallow_clone: true
branches:
only:
- master
- develop
- /feature\/.*/
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
TOOLSET: msvc-12.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-14.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
install:
- set BOOST_BRANCH=develop
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
- cd ..
- git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
- cd boost-root
- git submodule update --init tools/build
- git submodule update --init libs/config
- git submodule update --init tools/boostdep
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\thread\
- python tools/boostdep/depinst/depinst.py thread
- cmd /c bootstrap
- b2 headers
build: off
test_script:
- b2 libs/mp11/test toolset=%TOOLSET%

View File

@@ -60,30 +60,36 @@ project boost/thread
<toolset>gcc:<cxxflags>-Wno-long-long
#<toolset>gcc:<cxxflags>-ansi
#<toolset>gcc:<cxxflags>-fpermissive
<toolset>gcc:<cxxflags>-Wno-variadic-macros
<toolset>gcc-4:<cxxflags>-Wno-variadic-macros
<toolset>gcc-5:<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
#<toolset>darwin:<cxxflags>-ansi
<toolset>darwin:<cxxflags>-fpermissive
<toolset>darwin:<cxxflags>-Wno-long-long
<toolset>darwin:<cxxflags>-Wno-variadic-macros
#<toolset>darwin:<cxxflags>-Wno-variadic-macros
<toolset>darwin-4:<cxxflags>-Wno-variadic-macros
<toolset>darwin-5:<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:<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:<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,8 +122,12 @@ project boost/thread
<toolset>intel:<cxxflags>-wd1418
<toolset>intel:<cxxflags>-wd2415
<toolset>msvc:<cxxflags>/wd4100
<toolset>msvc:<cxxflags>/wd4512
<toolset>msvc:<cxxflags>/wd6246
<target-os>windows:<define>WIN32_LEAN_AND_MEAN
<target-os>windows:<define>BOOST_USE_WINDOWS_H
# : default-build <threading>multi
: usage-requirements # pass these requirement to dependents (i.e. users)
@@ -308,3 +318,5 @@ lib boost_thread
<link>static:<define>BOOST_THREAD_USE_LIB=1
<conditional>@usage-requirements
;
boost-install boost_thread ;

View File

@@ -1,13 +1,13 @@
// Copyright (c) 2013, Petr Machata, Red Hat Inc.
//
// Use modification and distribution are subject to the boost Software
// License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).
#include "../../../boost/atomic.hpp"
#include "../../../boost/static_assert.hpp"
// Copyright (c) 2013, Petr Machata, Red Hat Inc.
//
// Use modification and distribution are subject to the boost Software
// License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).
int main(int argc, char *argv[])
{
BOOST_STATIC_ASSERT(BOOST_ATOMIC_FLAG_LOCK_FREE);
return 0;
}
#include "../../../boost/atomic.hpp"
#include "../../../boost/static_assert.hpp"
int main(int argc, char *argv[])
{
BOOST_STATIC_ASSERT(BOOST_ATOMIC_FLAG_LOCK_FREE);
return 0;
}

View File

@@ -29,4 +29,12 @@ boostbook standalone
<xsl:param>boost.root=../../../..
;
###############################################################################
alias boostdoc
: thread
:
:
: ;
explicit boostdoc ;
alias boostrelease ;
explicit boostrelease ;

View File

@@ -1,5 +1,6 @@
[/
(C) Copyright 2007-8 Anthony Williams.
(C) Copyright 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).

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[/
(C) Copyright 2007-8 Anthony Williams.
(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).

View File

@@ -1,6 +1,6 @@
[/
(C) Copyright 2007-11 Anthony Williams.
(C) Copyright 2011-14 Vicente J. Botet Escriba.
(C) Copyright 2011-17 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
@@ -8,6 +8,302 @@
[section:changes History]
[heading Version 4.8.0 - boost 1.66]
[*Know Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
* [@http://svn.boost.org/trac/boost/ticket/10964 #10964] future<future<T>>::unwrap().then() Deadlocks
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 master regression test] to see the last regression test snapshot.
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/12949 #12949] using sleep_for in a thread context without including boost/thread/thread.hpp yields incorrect behaviour when BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC is defined
* [@http://svn.boost.org/trac/boost/ticket/13019 #13019] ABI compatibility for BOOST_THREAD_PROVIDES_INTERRUPTIONS incomplete
* [@http://svn.boost.org/trac/boost/ticket/13163 #13163] boost::detail::heap_new does not have a variadic variant
* [@https://github.com/boostorg/thread/issues/130 #130] windows: Bug in boost::condition_variable on Windows
[heading Version 4.7.4 - boost 1.65]
[*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/12519 #12519] boost::thread::try_join_for does not return after timeout
* [@http://svn.boost.org/trac/boost/ticket/12874 #12874] future<> extension constructor must be under BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
* [@http://svn.boost.org/trac/boost/ticket/12888 #12888] Linking with boost thread does not work on mingw/gcc 4.4
* [@http://svn.boost.org/trac/boost/ticket/12958 #12958] sync_bounded_queue::wait_pull_front( lve ) might throw
* [@http://svn.boost.org/trac/boost/ticket/13077 #13077] Linking to static 64bit libboost_thread fails DLL initialization
* [@http://svn.boost.org/trac/boost/ticket/13155 #13155] log doesn't build on a system with pthreads
* [@https://github.com/boostorg/thread/issues/121 #121] on_tls_prepare is broken under VS2017
[heading Version 4.7.3 - boost 1.64]
[*Fixed Bugs:]
* [@https://github.com/boostorg/thread/issues/113 #113] Add a Thread template on all the scoped thread and thread guard classes
* [@https://github.com/boostorg/thread/issues/117 #117] loop_executor should block on it's work_queue instead of polling
* [@https://github.com/boostorg/thread/issues/119 #119] basic_condition_variable::relocker::~relocker can throw an exception
[heading Version 4.7.2 - boost 1.63]
[*Fixed Bugs:]
* fix boost::synchronized_value<>::load()
* fix relational operators of boost::synchronized_value<>
* fix compile failed with boost::user_scheduler
* Fix minor possibility of loosing the notify
[heading Version 4.7.1 - boost 1.62]
[*Know Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
Please define BOOST_THREAD_PATCH to apply the patch that could unfortunately results is a regression as described in [@http://svn.boost.org/trac/boost/ticket/12049 #12049].
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 master regression test] to see the last regression test snapshot.
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/11097 #11097] test_scheduled_tp - ThreadSanitizer: heap-use-after-free
* [@http://svn.boost.org/trac/boost/ticket/11951 #11951] Memory leak in boost::when_all
* [@http://svn.boost.org/trac/boost/ticket/12102 #12102] condition_variable_fwd.hpp fails to compile when BOOST_THREAD_PROVIDES_INTERRUPTIONS is disabled
* [@http://svn.boost.org/trac/boost/ticket/12120 #12120] Performance improvement in thread/barrier.hpp
* [@http://svn.boost.org/trac/boost/ticket/12146 #12146] make_exceptional_future is not mentioned in the docs
* [@http://svn.boost.org/trac/boost/ticket/12202 #12202] shared_lock should be in shared_mutex header
* [@http://svn.boost.org/trac/boost/ticket/12220 #12220] Memory leak in future::then()
* [@http://svn.boost.org/trac/boost/ticket/12293 #12293] boost::future::then lambda called before future is ready.
* [@http://svn.boost.org/trac/boost/ticket/12350 #12350] shared_mutex (pthreads) unlocked too early in unlock_shared()
* [@http://svn.boost.org/trac/boost/ticket/12371 #12371] boost thread/future.hpp fails to build
and several PR
* #88 fix typos in boost::upgrade_lock
* #89 fix a bug in upgrade_to_unique_lock<>::operator=()
* #90 fix a bug in try_lock_wrapper<>::operator=()
* #91 Add shared_lock_guard to the included lock types
* #92 Fixed compilation with MSVC-8.
* #93 Fix variable shadowing warnings (Clang)
* #94 fix bugs in boost::barrier
* #95 fix a mistake in boost::completion_latch
* #96 rename async_func.hpp to invoker.hpp.
* #97 fix a mistake in sync_timed_queue<>::pull_until()
[heading Version 4.7.0 - boost 1.61]
[*Know Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
Please define BOOST_THREAD_PATCH to apply the patch that could unfortunately results is a regression as described in [@http://svn.boost.org/trac/boost/ticket/12049 #12049].
* [@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/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
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 regression test snapshot.
[*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/11772 #11772] Add a launch::sync policy
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/11494 #11494] boost::this_thread::yield() is marked as deprecated in the synopsis
* [@http://svn.boost.org/trac/boost/ticket/11562 #11562] (condition_variable_any::wait_until + recursive_mutex + steady_clock) timer expires after computer time is set forward on Ubuntu 64-bit
* [@http://svn.boost.org/trac/boost/ticket/12013 #12013] F_pass and FArgs_pass tests segfault
* [@http://svn.boost.org/trac/boost/ticket/12036 #12036] boost::physical_concurrency always returns 0 if BOOST_USE_WINAPI_VERSION is not defined
[heading Version 4.6.0 - boost 1.60]
[*Know Bugs:]
* [@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/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/10942 #10942] Boost.Thread fails to build on Cygwin.
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 regression test snapshot.
[*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/11231 #11231] Allow to set continuation future's destructor behavior to non-blocking
* [@http://svn.boost.org/trac/boost/ticket/11424 #11424] Provide shared_timed_mutex as an alternative name for shared_mutex and deprecate the use of shared_mutex as a timed mutex
* [@http://svn.boost.org/trac/boost/ticket/11734 #11734] future::then(Cont) should be able to execute the continuation on undetermined thread
* [@http://svn.boost.org/trac/boost/ticket/11736 #11736] Allow to use launch::executor on future::then(launch::executor, cont)
* [@http://svn.boost.org/trac/boost/ticket/11737 #11737] Add a launch::inherit policy that can be used on ::then() to use the policy of the parent future
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/6377 #6377] Condition variable blocks when changing time
* [@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/7665 #7665] this_thread::sleep_for no longer uses steady_clock in thread
* [@http://svn.boost.org/trac/boost/ticket/7720 #7720] exception lock_error while intensive locking/unlocking of mutex
* [@http://svn.boost.org/trac/boost/ticket/9309 #9309] test_latch fails often on clang-darwin-tot11
* [@http://svn.boost.org/trac/boost/ticket/10788 #10788] GetLogicalProcessor isn't available for Windows platform less or equals to 0x0502
* [@http://svn.boost.org/trac/boost/ticket/11090 #11090] ex_future_unwrap- ThreadSanitizer: lock-order-inversion (potential deadlock)
* [@http://svn.boost.org/trac/boost/ticket/11158 #11158] Pthread thread deadlock when faketime used
* [@http://svn.boost.org/trac/boost/ticket/11174 #11174] boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite
* [@http://svn.boost.org/trac/boost/ticket/11185 #11185] Incorrect URL redirection
* [@http://svn.boost.org/trac/boost/ticket/11192 #11192] boost::future<>::then() with an executor doesn't compile when the callback returns a future
* [@http://svn.boost.org/trac/boost/ticket/11250 #11250] future made from make_exceptional fails on assertion in destructor
* [@http://svn.boost.org/trac/boost/ticket/11256 #11256] future<>::is_ready() == false in continuation function
* [@http://svn.boost.org/trac/boost/ticket/11261 #11261] bad use of scoped threads in basic_thread_pool
* [@http://svn.boost.org/trac/boost/ticket/11262 #11262] bad use of direct pointer in shared_state_nullary_task
* [@http://svn.boost.org/trac/boost/ticket/11263 #11263] lock already locked lock
* [@http://svn.boost.org/trac/boost/ticket/11266 #11266] boost::packaged_task has invalid variadic signature
* [@http://svn.boost.org/trac/boost/ticket/11302 #11302] boost thread doesn't build with BOOST_THREAD_PATCH.
* [@http://svn.boost.org/trac/boost/ticket/11322 #11322] sleep_for() nanoseconds overload will always return too early on windows
* [@http://svn.boost.org/trac/boost/ticket/11329 #11329] using declarative for GetProcessHeap, .... fails
* [@http://svn.boost.org/trac/boost/ticket/11368 #11368] boost thread's usage of CreateWaitableTimer wakes PC from sleep (doh)
* [@http://svn.boost.org/trac/boost/ticket/11377 #11377] Boost condition variable always waits for system clock deadline
* [@http://svn.boost.org/trac/boost/ticket/11435 #11435] gcc compiler warning in future.hpp
* [@http://svn.boost.org/trac/boost/ticket/11555 #11555] devector.hpp assumes allocator_traits_type is always present
* [@http://svn.boost.org/trac/boost/ticket/11562 #11562] (condition_variable_any::wait_until + recursive_mutex + steady_clock) timer expires after computer time is set forward on Ubuntu 64-bit
* [@http://svn.boost.org/trac/boost/ticket/11672 #11672] Thread: Should use unique_ptr, not auto_ptr
* [@http://svn.boost.org/trac/boost/ticket/11688 #11688] thread::try_join_until: Avoid busy wait if system clock changes
* [@http://svn.boost.org/trac/boost/ticket/11672 #11716] ::then(f) should inherit the parent Executor
* [@http://svn.boost.org/trac/boost/ticket/11795 #11795] Incorrect version specification for documentation of thread destructor
* [@http://svn.boost.org/trac/boost/ticket/11796 #11796] Thread move assignment operator, does not detach previous thread data
* [@http://svn.boost.org/trac/boost/ticket/11817 #11817] 'sync_queue_is_closed' was not declared in boost/thread/executors/thread_executor.hpp
* [@http://svn.boost.org/trac/boost/ticket/11818 #11818] future.then will be blocked if promise is set after the invocation of then
* [@http://svn.boost.org/trac/boost/ticket/12049 #12049] Assertion failure from detached threads during shutdown
[heading Version 4.5.0 - boost 1.58]
[*Know Bugs:]
* [@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/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/9311 #9311] ex_lambda_future fails on msvc-11.0
* [@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 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 ( [@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]
[*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
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.
[*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,
[*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/6227 #6227] Synchro: Use of variadic templates on Generic Locking Algorithms on compilers providing them
* [@http://svn.boost.org/trac/boost/ticket/10298 #10298] Synchro: Added queue views.
* [@http://svn.boost.org/trac/boost/ticket/10300 #10300] Async: Added generic_executor_ref.
* [@http://svn.boost.org/trac/boost/ticket/10552 #10552] Add make_valid_future
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/6782 #6782] call_once uses incorrect barrier intrinsic on Visual Studio
* [@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/7665 #7665] this_thread::sleep_for no longer uses steady_clock in thread
* [@http://svn.boost.org/trac/boost/ticket/9307 #9307] future::fallback_to assert with ERRORRRRR boost: mutex lock failed in pthread_mutex_lock: Invalid argument
* [@http://svn.boost.org/trac/boost/ticket/9308 #9308] future::async fails with terminate called throwing an exception when called with a lambda - clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9425 #9425] Boost promise & future does not use supplied allocator for value storage
* [@http://svn.boost.org/trac/boost/ticket/9558 #9558] future continuations unit test hangs in get()/pthread_cond_wait() on Mac 10.7/32-bit/x86/darwin-4.2.1
* [@http://svn.boost.org/trac/boost/ticket/9787 #9787] [windows] Small duration value passed down to basic_timed_mutex::try_lock_until and condition_variable::wait_until can cause infinite or near infinite wait for win32
* [@http://svn.boost.org/trac/boost/ticket/9880 #9880] [windows] boost::condition_variable.timed_wait() exception if system time < 1970
* [@http://svn.boost.org/trac/boost/ticket/10159 #10159] GCC 4.4 error sorry, unimplemented
* [@http://svn.boost.org/trac/boost/ticket/10196 #10196] thread_specific_ptr does not support void*
* [@http://svn.boost.org/trac/boost/ticket/10296 #10296] Boost.Thread 1.56 rc1 does not compile on Mingw
* [@http://svn.boost.org/trac/boost/ticket/10297 #10297] Boost.Thread 1.56 rc1 hangs when built with clang on armhf
* [@http://svn.boost.org/trac/boost/ticket/10340 #10340] No boost::promise<T>::set_value(const T&) overload present in C++03 mode
* [@http://svn.boost.org/trac/boost/ticket/10425 #10425] Missing documentation for when_all/when_any.
* [@http://svn.boost.org/trac/boost/ticket/10426 #10426] Take in account the deferred futures in when_all.
* [@http://svn.boost.org/trac/boost/ticket/10427 #10427] Take in account the deferred and ready futures in when_any.
* [@http://svn.boost.org/trac/boost/ticket/10428 #10428] Adapt to new unique_ptr interface in Boost.Move
* [@http://svn.boost.org/trac/boost/ticket/10465 #10465] Missing implementation of when_all/when_any when the result is a tuple.
* [@http://svn.boost.org/trac/boost/ticket/10476 #10476] classes using BOOST_THREAD_MOVABLE_ONLY<T> dont satisfy is_copy_constructible<T>::value == false
* [@http://svn.boost.org/trac/boost/ticket/10478 #10478] Data race in boost/thread/future.hpp
* [@http://svn.boost.org/trac/boost/ticket/10529 #10529] The pthread/condition_variable_any constructor reports incorrect error code for pthread_cond_init
* [@http://svn.boost.org/trac/boost/ticket/10563 #10563] shared_future<R>::then should be const
[heading Version 4.3.0 - boost 1.56]
[*Know Bugs:]
@@ -28,7 +324,7 @@
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/release/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 snapshot.
[*Sever limitations:]
@@ -496,9 +792,6 @@ been moved to __thread_id__.
The following features will be included in next releases.
# Complete the C++11 missing features, in particular
* [@http://svn.boost.org/trac/boost/ticket/6227 #6227] C++11 compliance: Use of variadic templates on Generic Locking Algorithms on compilers providing them.
# Add some minor features, in particular
* [@http://svn.boost.org/trac/boost/ticket/7589 #7589] Synchro: Add polymorphic lockables.
@@ -506,13 +799,6 @@ The following features will be included in next releases.
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Synchro: Add externally locked streams.
* [@http://svn.boost.org/trac/boost/ticket/8514 #8514] Async: Add a thread_pool executor with work stealing.
# Add some of the extension proposed in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3428.pdf A Standardized Representation of Asynchronous Operations] or extension to them, in particular
* [@http://svn.boost.org/trac/boost/ticket/7446 #7446] Async: Add when_any.
* [@http://svn.boost.org/trac/boost/ticket/7447 #7447] Async: Add when_all.
* [@http://svn.boost.org/trac/boost/ticket/7448 #7448] Async: Add async taking a scheduler parameter.
* [@http://svn.boost.org/trac/boost/ticket/8516 #8516] Async: Add future/shared_future::then taking a scheduler as parameter.
# And some additional extensions related to futures as:
* [@http://svn.boost.org/trac/boost/ticket/8517 #8517] Async: Add a variadic shared_future::then.

View File

@@ -1,13 +1,15 @@
[/
(C) Copyright 2011-2013 Vicente J. Botet Escriba.
(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).
]
[section:compliance Conformance and Extension]
[////////////////////////////////////////////]
[section:cpp11 C++11 standard Thread library]
[///////////////////////////////////////////]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 - Standard for Programming Language C++]]]
@@ -88,6 +90,7 @@
]
[endsect]
[section:cxx14 C++14 standard Thread library - accepted changes]
[//////////////////////////////////////////////////////////////]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.html Working Draft, Standard for Programming Language C++]]
@@ -101,9 +104,36 @@
[endsect]
[section:cxx1y C++1y TS Concurrency - On going proposals]
[section:cxx1y C++14 TS Extensions for Concurrency V1 ]
[/////////////////////////////////////////////////////]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4107.html N4107-Extensions for Concurrency]]
[table Improvements to std::future<T> and related APIs]
[[Section] [Description] [Status] [Comments]]
[[2.1] [ - ] [ - ] [ - ]]
[[2.2] [Class template future] [Partial] [ - ]]
[[2.2] [then] [ Partial ] [ without implicit unwrapping #10550 and blocking #10551 ]]
[[2.2] [is_ready] [ Yes ] [ - ]]
[[2.3] [Class template shared_future] [Partial] [ - ]]
[[2.3] [then] [ Partial ] [ Without implicit unwrapping #10550 and blocking #10551 ]]
[[2.3] [is_ready] [ Yes ] [ - ]]
[[2.4] [Function template when_all] [Partial] [ interface not complete #10426 and blocking #10551 ]]
[[2.5] [Function template when_any] [Partial] [ interface not complete #10427 and blocking #10551 ]]
[[2.6] [Function template when_any_back] [No] [ #XXXX ]]
[[2.7] [Function template make_ready_future] [Yes] [ - ]]
]
[endsect]
[section:cxx1y C++1z TS Concurrency - On going proposals]
[///////////////////////////////////////////////////////]
[section:latch C++ Latches and Barriers]
[//////////////////////////////////////]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3600 C++ Latches and Barriers]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3817.html N3817 C++ Latches and Barriers]]
@@ -116,6 +146,7 @@
[endsect]
[section:queue C++ Concurrent Queues]
[///////////////////////////////////]
[note [@ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3533.html N3533 C++ Concurrent Queues]]
@@ -159,56 +190,61 @@
[[X.3.4] [Managed Indirection] [No] [ - ]]
]
[endsect]
[section:executors Asynchronous Executors]
While Boost.Thread implementation of executors would not use dynamic polymorphism, it is worth comparing with the current trend on the standard.
[section:executors Executors and Schedulers]
[//////////////////////////////////////////]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3785.pdf N3785 Executors and Schedulers]]
[table Asynchronous Executors
[table Executors and Schedulers
[[Section] [Description] [Status] [Comments]]
[[V.1.1] [Class executor] [Yes] [ - ]]
[[V.1.1] [add] [Yes] [ renamed with a function template submit ]]
[[V.1.1] [num_of_pendin_closures] [No] [ ]]
[[V.1.1] [Class `executor`] [Yes] [ - ]]
[[V.1.1] [`add`] [Yes] [ renamed with a function template `submit` ]]
[[V.1.1] [`num_of_pendin_closures`] [No] [ ]]
[[V.1.2] [Class sceduled_executor] [No] [ - ]]
[[V.1.2] [add_at] [No] [ renamed with a function template submit_at ]]
[[V.1.2] [add_after] [No] [ renamed with a function template submit_after ]]
[[V.1.2] [`add_at`] [No] [ renamed with a function template `scheduler::submit_at` ]]
[[V.1.2] [`add_after`] [No] [ renamed with a function template `scheduler::submit_after` ]]
[[V.2] [Concrete executor classes] [No] [ - ]]
[[V.2.1] [thread_pool] [Yes] [ static version Basic_thread_pool, dynamic one execduler_adaptor<basic_thread_pool> ]]
[[V.2.2] [serial_executor] [yes] [ - ]]
[[V.2.3] [loop_executor] [Yes] [ static version loop_scheduler, dynamic one execduler_adaptor<loop_scheduler> ]]
[[V.2.4] [inline_executor] [Yes] [ static version inline_executor, dynamic one execduler_adaptor<inline_executor> ]]
[[V.2.5] [thread_executor] [Yes] [ static version thread_executor, dynamic one execduler_adaptor<thread_executor> ]]
[[V.2.1] [`thread_pool`] [Yes] [ static version `basic_thread_pool`, dynamic one `execduler_adaptor<basic_thread_pool>` ]]
[[V.2.2] [`serial_executor`] [yes] [ - ]]
[[V.2.3] [`loop_executor`] [Yes] [ static version loop_scheduler, dynamic one `execduler_adaptor<loop_scheduler>` ]]
[[V.2.4] [`inline_executor`] [Yes] [ static version `inline_executor`, dynamic one `execduler_adaptor<inline_executor>` ]]
[[V.2.5] [`thread_executor`] [Yes] [ static version `thread_executor`, dynamic one `execduler_adaptor<thread_executor>` ]]
]
[endsect]
[section:async Improvements to std::future<T> and Related APIs]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3784.pdf N3784-Improvements to `std::future<T> and Related APIs]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3857.pdf N3857-Improvements to std::future<T> and Related APIs]]
[note These functions are based on [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3634.pdf [*N3634 - Improvements to std::future<T> and related APIs]] C++1y proposal by N. Gustafsson, A. Laksberg, H. Sutter, S. Mithani.]
[table Improvements to std::future<T> and related APIs]
[table `async, future/shared_future::then`and Executors
[[Section] [Description] [Status] [Comments]]
[[30.6.6] [Class template future] [Partial] [ - ]]
[[30.6.6] [unwrap constructor] [Yes] [ - ]]
[[30.6.6] [then] [Yes] [ - ]]
[[30.6.6] [unwrap] [Yes] [ - ]]
[[30.6.6] [ready] [Partial] [ is_ready ]]
[[30.6.7] [Class template shared_future] [Partial] [ - ]]
[[30.6.6] [unwrap constructor] [Yes] [ - ]]
[[30.6.7] [then] [Yes] [ - ]]
[[30.6.7] [unwrap] [No] [ #XXXX ]]
[[30.6.7] [ready] [Partial] [ is_ready ]]
[[30.6.X] [Function template when_all] [Partial] [ interface not complete #7447 ]]
[[30.6.X] [Function template when_any] [Partial] [ interface not complete #7446 ]]
[[30.6.X] [Function template when_any_swaped] [No] [ #XXXX ]]
[[30.6.X] [Function template make_ready_future] [Yes] [ - ]]
[[30.6.8] [Function template async ] [Yes] [ - ]]
[[30.6.6] [`future<T>::then`] [Yes] [ ]]
[[30.6.7] [`shared_future<T>::then`] [Yes] [ ]]
[[30.6.8] [`async`] [Yes] [ - ]]
]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4143.pdf N4143-Executors and schedulers, revision 4]]
[table Executors and Schedulers - revision 4
[[Section] [Description] [Status] [Comments]]
[[VI.A] [Executor Concept] [Yes] [ `wrapper_type` renamed by `work` and `spawn by `submit` ]]
[[VI.A.1] [`thread_per_task_executor] [Yes] [ renamed `thread_executor`]]
[[VI.A.2] [`thread_pool_executor`] [Yes] [ renamed `basic_thread_pool`]]
[[VI.A.3] [`system_executor`] [No] [ - ]]
[[VI.A.4] [`loop_executor`] [Yes] [ - ]]
[[VI.A.5] [`serial_executor`] [yes] [ - ]]
[[VI.B] [`executor_ref`] [yes] [ - ]]
[[VI.C] [`executor`] [yes] [ renamed `gen_executor_ref` ]]
[[VI.D] [Free Functions and Helper Objects] [partial] [ - ]]
[[VI.D] [`make_package`] [No] [ - ]]
[[VI.D] [`spawn_future`] [No] [ `async(Ex&, ...)` is similar but returns a blocking future. ]]
[[VI.D] [`spawn`] [No] [ - ]]
[[VI.D] [`task_wrapper`] [No] [ renamed `resubmitter` ]]
[[VI.D] [`set_executor`] [No] [ renamed `resubmit` ]]
[[VI.D] [`function_wrapper`] [Partial] [ renamed `work` ]]
]
[endsect]
[//////////////////////////////////////////////////////////////
[section:stream_mutex C++ Stream Mutexes - C++ Stream Guards]
[/////////////////////////////////////////////////////////////]
While Boost.Thread implementation of stream mutexes differ in the approach, it is worth comparing with the current trend on the standard.
@@ -236,7 +272,7 @@ While Boost.Thread implementation of stream mutexes differ in the approach, it i
[endsect]
///////////////////////////////]
[endsect]
[endsect]

View File

@@ -1,5 +1,5 @@
[/
(C) Copyright 20012 Vicente J. Botet Escriba.
(C) Copyright 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).
@@ -23,6 +23,7 @@
[[PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN] [DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN] [NO] [YES] [YES] ]
[[PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION] [DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSION] [NO] [YES] [YES] ]
[[PROVIDES_EXECUTORS] [-] [NO] [NO] [NO] ]
[[PROVIDES_EXPLICIT_LOCK_CONVERSION] [DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION] [NO] [YES] [YES] ]
[[PROVIDES_FUTURE] [DONT_PROVIDE_FUTURE] [NO] [YES] [YES] ]
[[PROVIDES_FUTURE_CTOR_ALLOCATORS] [DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS] [NO] [YES] [YES] ]
@@ -80,7 +81,7 @@ When `BOOST_THREAD_VERSION>3` && defined BOOST_THREAD_PLATFORM_PTHREAD define `
[section:move Boost.Atomic]
Boost.Thread uses by default an Boost.Atomic in POSIX platforms to implement call_once..
Boost.Thread uses by default Boost.Atomic in POSIX platforms to implement call_once..
Define `BOOST_THREAD_USES_ATOMIC ` if you want to use Boost.Atomic.
Define `BOOST_THREAD_DONT_USE_ATOMIC ` if you don't want to use Boost.Atomic or if it is not supported in your platform.

View File

@@ -260,14 +260,14 @@ Locks provide an explicit bool conversion operator when the compiler provides th
The library provides un implicit conversion to an undefined type that can be used as a conditional expression.
#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
operator ``['unspecified-bool-type]``() const;
bool operator!() const;
#else
explicit operator bool() const;
#endif
The user should use the lock.owns_lock() when a explicit conversion is required.
The user should use the lock.owns_lock() when an explicit conversion is required.
[section:bool_conversion `operator `['unspecified-bool-type]`() const`]
@@ -324,7 +324,7 @@ the library declare these types as
}
BOOST_SCOPED_ENUM_DECLARE_END(future_errc)
These macros allows to use 'future_errc' in almost all the cases as an scoped enum.
These macros allows to use 'future_errc' in almost all the cases as a scoped enum.
There are however some limitations:
@@ -346,14 +346,14 @@ use
And instead of
#ifdef BOOST_NO_SCOPED_ENUMS
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
template <>
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type { };
#endif
use
#ifdef BOOST_NO_SCOPED_ENUMS
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
template <>
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { };
#endif

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

@@ -1,5 +1,6 @@
[/
(C) Copyright 2008-11 Anthony Williams.
(C) Copyright 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).
@@ -28,9 +29,11 @@
enum class launch
{
none = unspecified,
async = unspecified,
deferred = unspecified,
executor = unspecified,
inherit = unspecified,
any = async | deferred
};
@@ -79,48 +82,55 @@
struct uses_allocator<packaged_task <S>, Alloc>;
template <class F>
future<typename result_of<typename decay<F>::type()>::type>
async(F f);
future<typename result_of<typename decay<F>::type()>::type>
async(F f);
template <class F>
future<typename result_of<typename decay<F>::type()>::type>
async(launch policy, F f);
future<typename result_of<typename decay<F>::type()>::type>
async(launch policy, F f);
template <class F, class... Args>
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(F&& f, Args&&... args);
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(F&& f, Args&&... args);
template <class F, class... Args>
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(launch policy, F&& f, Args&&... args);
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(launch policy, F&& f, Args&&... args);
template <class Executor, class F, class... Args>
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(Executor &ex, F&& f, Args&&... args);
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(Executor &ex, F&& f, Args&&... args);
template<typename Iterator>
void wait_for_all(Iterator begin,Iterator end); // EXTENSION
void wait_for_all(Iterator begin,Iterator end); // EXTENSION
template<typename F1,typename... FS>
void wait_for_all(F1& f1,Fs&... fs); // EXTENSION
void wait_for_all(F1& f1,Fs&... fs); // EXTENSION
template<typename Iterator>
Iterator wait_for_any(Iterator begin,Iterator end); // EXTENSION
Iterator wait_for_any(Iterator begin,Iterator end); // EXTENSION
template<typename F1,typename... Fs>
unsigned wait_for_any(F1& f1,Fs&... fs); // EXTENSION
unsigned wait_for_any(F1& f1,Fs&... fs); // EXTENSION
template <class InputIterator>
future<std::vector<typename InputIterator::value_type::value_type>>
when_all(InputIterator first, InputIterator last);
template <typename... T>
future<std::tuple<decay_t<T>...> when_all(T&&... futures);
template <class InputIterator>
future<std::vector<typename InputIterator::value_type::value_type>>
when_any(InputIterator first, InputIterator last); // EXTENSION
template <typename... T>
future<std::tuple<decay_t<T>...> when_any(T&&... futures);
template <typename T>
future<typename decay<T>::type> make_future(T&& value); // DEPRECATED
future<typename decay<T>::type> make_future(T&& value); // DEPRECATED
future<void> make_future(); // DEPRECATED
template <typename T>
future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
future<void> make_ready_future(); // EXTENSION
//template <typename T>
//future<T> make_ready_future(exception_ptr ex); // DEPRECATED
//template <typename T, typename E>
//future<T> make_ready_future(E ex); // DEPRECATED
exceptional_ptr make_exceptional(exception_ptr ex); // EXTENSION
exceptional_ptr make_exceptional_future(exception_ptr ex); // EXTENSION
template <typename E>
exceptional_ptr make_exceptional(E ex); // EXTENSION
exceptional_ptr make_exceptional(); // EXTENSION
exceptional_ptr make_exceptional_future(E ex); // EXTENSION
exceptional_ptr make_exceptional_future(); // EXTENSION
template <typename T>
@@ -157,14 +167,27 @@
enum class launch
{
none = unspecified,
async = unspecified,
deferred = unspecified,
executor = unspecified,
inherit = unspecified,
any = async | deferred
};
The enum type launch is a bitmask type with launch::async and launch::deferred denoting individual bits.
A future created with `promise<>` or with a `packaged_task<>` or with `make_ready_future`/`make_exceptional_future` (has no associated launch policy), has an implicit a launch policy of `launch::none`.
A future created by `async(launch::async, ...)` or `::then(launch::async, ...)` has associated a launch policy `launch::async`.
A future created by `async(launch::deferred, ...)` or `::then(launch::deferred, ...)` has associated a launch policy `launch::deferred`.
A future created by `async(Executor, ...)` or `::then(Executor, ...)` or `::then(launch::executor, ...)` has associated a launch policy `launch::executor`.
A future created by `async(...)` or `::then(...)` has associated a launch policy `launch::none`.
A future created by `::then(launch::inherit, ...)` has associated a launch policy parent future.
The `executor` and the `inherit` launch policies have a sense only can be user only on `then()`.
[endsect]
[///////////////////////////////////////////////////////////////////////////]
[section:is_error_code_enum Specialization `is_error_code_enum<future_errc>`]
@@ -326,20 +349,20 @@ The object's `name` virtual function returns a pointer to the string "future".]]
// move support
__unique_future__(__unique_future__ && other) noexcept;
__unique_future__(__unique_future__<__unique_future__<R>>&& rhs); // EXTENSION
explicit __unique_future__(__unique_future__<__unique_future__<R>>&& rhs); // EXTENSION
__unique_future__& operator=(__unique_future__ && other) noexcept;
// factories
shared_future<R> share();
template<typename F>
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(F&& func); // EXTENSION
template<typename S, typename F>
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
then(S& scheduler, F&& func); // EXTENSION NOT_YET_IMPLEMENTED
template<typename Ex, typename F>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(Ex& executor, F&& func); // EXTENSION
template<typename F>
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(launch policy, F&& func); // EXTENSION
see below unwrap(); // EXTENSION
@@ -430,7 +453,7 @@ associated with `*this`. `other` is not associated with any shared state.]]
[///////////////////////////////////////////////////////////////////]
[section:unwrap_move_constructor Unwrap Move Constructor - EXTENSION]
__unique_future__(__unique_future__<__unique_future__<R>>&& other); // EXTENSION
explicit __unique_future__(__unique_future__<__unique_future__<R>>&& other); // EXTENSION
[warning This constructor is experimental and subject to change in future versions.
There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
@@ -438,6 +461,7 @@ There are not too much tests yet, so it is possible that you can find out some t
[variablelist
[[Requires:] [`other.valid()`.]
[[Effects:] [Constructs a new __unique_future__, and transfers ownership of the shared state associated with `other` and unwrapping the inner future (see `unwrap()`).]]
[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
@@ -756,6 +780,8 @@ prior to waiting.]]
[[Returns:] [`true` if `*this` is associated with a shared state, `false`
otherwise.]]
[[Remarks:] [The result of this function is not stable and that the future could become invalid even if the function returned true or vice-versa.]]
[[Throws:] [Nothing.]]
]
@@ -771,6 +797,8 @@ otherwise.]]
[[Returns:] [`true` if `*this` is associated with a shared state and that result is ready for retrieval, `false`
otherwise.]]
[[Remarks:] [The result of this function is not stable and that the future could become not ready even if the function returned true or vice-versa.]]
[[Throws:] [Nothing.]]
]
@@ -786,6 +814,8 @@ otherwise.]]
[[Returns:] [`true` if `*this` is associated with a shared state, that result is ready for retrieval, and the result is a
stored value, `false` otherwise.]]
[[Remarks:] [The result of this function is not stable and the future could lost its value even if the function returned true or vice-versa.]]
[[Throws:] [Nothing.]]
]
@@ -801,6 +831,8 @@ stored value, `false` otherwise.]]
[[Returns:] [`true` if `*this` is associated with a shared state, that result is ready for retrieval, and the result is a
stored exception, `false` otherwise.]]
[[Remarks:] [The result of this function is not stable and the future could lost its exception even if the function returned true or vice-versa.]]
[[Throws:] [Nothing.]]
]
@@ -816,7 +848,9 @@ stored exception, `false` otherwise.]]
[[Effects:] [If `*this` is associated with a shared state, waits until the result is ready. If the result is not ready on
entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]
[[Returns:] [a exception_ptr, storring or not an exception.]]
[[Returns:] [an exception_ptr, storing or not an exception.]]
[[Remarks:] [The result of this function is not stable and the future could lost its exception even if the function returned a valid `exception_ptr` or vice-versa.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]
@@ -835,6 +869,8 @@ entry, and the result has a ['wait callback] set, that callback is invoked prior
[[Returns:] [__uninitialized__ if `*this` is not associated with a shared state. __ready__ if the shared state
associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
[[Remarks:] [The result of this function is not stable.]]
[[Throws:] [Nothing.]]
]
@@ -860,13 +896,13 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
[section:then Member function `then()` - EXTENSION]
template<typename F>
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(F&& func); // EXTENSION
template<typename S, typename F>
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
then(S& scheduler, F&& func); // EXTENSION NOT_YET_IMPLEMENTED
template<typename Ex, typename F>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(Ex& executor, F&& func); // EXTENSION
template<typename F>
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(launch policy, F&& func); // EXTENSION
[warning These functions are experimental and subject to change in future versions.
@@ -877,36 +913,61 @@ There are not too much tests yet, so it is possible that you can find out some t
[variablelist
[[Notes:] [The three functions differ only by input parameters. The first only takes a callable object which accepts a
future object as a parameter. The second function takes a scheduler as the first parameter and a callable object as
future object as a parameter. The second function takes an executor as the first parameter and a callable object as
the second parameter. The third function takes a launch policy as the first parameter and a callable object as the
second parameter.]]
[[Requires:] [`INVOKE(DECAY_COPY (std::forward<F>(func)), std::move(*this))` shall be a valid expression.]]
[[Effects:] [
- The continuation is called when the object's shared state is ready (has a value or exception stored).
All the functions create a shared state that is associated with the returned future object. Additionally,
- The continuation launches according to the specified policy or scheduler.
- When the object's shared state is ready, the continuation
`INVOKE(DECAY_COPY(std::forward<F>(func)), std::move(*this))` is called depending on the overload (see below) with the call to DECAY_COPY() being evaluated in the thread that called then.
- When the scheduler or launch policy is not provided the continuation inherits the
parent's launch policy or scheduler.
- Any value returned from the continuation is stored as the result in the shared state of the resulting `future`.
Any exception propagated from the execution of the continuation is stored as the exceptional result in the shared state of the resulting `future`.
- If the parent was created with `promise<<` or with a `packaged_task<>` (has no associated launch policy), the
continuation behaves the same as the third overload with a policy argument of `launch::async | launch::deferred` and
the same argument for func.
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy or
scheduler, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
The continuation launches according to the specified policy or executor or noting.
- When the launch policy is `launch::none` the continuation is called on an unspecified thread of execution.
- When the launch policy is `launch::async` the continuation is called on a new thread of execution.
- When the launch policy is `launch::deferred` the continuation is called on demand.
- When the launch policy is `launch::executor` the continuation is called on one of the thread of execution of the executor.
- When the launch policy is `launch::inherit` the continuation inherits the parent's launch policy or executor.
- When the executor or launch policy is not provided (first overload) is if as if launch::none was specified.
- When the executor is provided (second overload) the continuation is called on one of the thread of execution of the executor.
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy
executor, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
`launch::deferred`.
]]
[[Returns:] [An object of type `__unique_future__<typename boost::result_of<F(__unique_future__)>` that refers to the shared state created by the continuation.]]
[[Notes:] [
- Note that nested futures are not implicitly unwrapped yet. This could be subject to change in future versions.
- The returned futures behave as the ones returned from boost::async, the destructor of the future object returned from then will block. This could be subject to change in future versions.
]]
[[Postconditions:] [
- The `__unique_future__` object passed to the parameter of the continuation function is a copy of the original `__unique_future__`.
- `valid() == false` on original future object immediately after it returns.
- `valid() == false` on original future; `valid() == true` on the `future` returned from then.
[/ In case of implicit unwrapping, the validity of the `future` returned from `then` cannot be established until after the completion of the functor passed into `then`. In such case, the resulting `future` becomes ready with an exception of type `future_error`, with an error code of `future_errc::broken_promise`. ]
]]
@@ -928,19 +989,19 @@ There are not too much tests yet, so it is possible that you can find out some t
[variablelist
[[Notes:] [Removes the outermost future and returns a future with the associated state been a proxy of inner future.]]
[[Notes:] [Removes the outermost future and returns a future with the associated state been a proxy of the outer future.]]
[[Effects:] [
- Returns a future that becomes ready when the shared state of the inner future is ready.
- Returns a future that becomes ready when the shared state of the outer and inner future is ready. The validity of the future returned from `get()` applied on the outer future cannot be established a priori. If it is not valid, this future is forced to be valid and becomes ready with an exception of type `future_error`, with an error code of `future_errc::broken_promise`.
]]
[[Returns:] [An object of type future with the associated state been a proxy of inner future.]]
[[Returns:] [An object of type future with the associated state been a proxy of outer future.]]
[[Postconditions:] [
- The returned future has `valid() == true` regardless of the validity of the inner future.
- The returned future has `valid() == true`.
]]
@@ -975,19 +1036,19 @@ There are not too much tests yet, so it is possible that you can find out some t
// factories
template<typename F>
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
then(F&& func); // EXTENSION
__unique_future__<typename boost::result_of<F(shared_future)>::type>
then(F&& func) const; // EXTENSION
template<typename S, typename F>
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
then(S& scheduler, F&& func); // EXTENSION NOT_YET_IMPLEMENTED
__unique_future__<typename boost::result_of<F(shared_future)>::type>
then(S& scheduler, F&& func) const; // EXTENSION
template<typename F>
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
then(launch policy, F&& func); // EXTENSION
__unique_future__<typename boost::result_of<F(shared_future)>::type>
then(launch policy, F&& func) const; // EXTENSION
void swap(shared_future& other);
// retrieving the value
see below get();
see below get() const;
exception_ptr get_exception_ptr(); // EXTENSION
@@ -1033,9 +1094,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
@@ -1296,7 +1357,7 @@ stored exception, `false` otherwise.]]
[[Effects:] [If `*this` is associated with a shared state, waits until the result is ready. If the result is not ready on
entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]
[[Returns:] [a exception_ptr, storring or not an exception.]]
[[Returns:] [an exception_ptr, storing or not an exception.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]
@@ -1324,14 +1385,14 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
[section:then Member function `then()` EXTENSION]
template<typename F>
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
then(F&& func); // EXTENSION
template<typename S, typename F>
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
then(S& scheduler, F&& func); // EXTENSION NOT_YET_IMPLEMENTED
__unique_future__<typename boost::result_of<F(shared_future)>::type>
then(F&& func) const; // EXTENSION
template<typename Ex, typename F>
__unique_future__<typename boost::result_of<F(shared_future)>::type>
then(Ex& executor, F&& func) const; // EXTENSION
template<typename F>
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
then(launch policy, F&& func); // EXTENSION
__unique_future__<typename boost::result_of<F(shared_future)>::type>
then(launch policy, F&& func) const; // EXTENSION
[warning These functions are experimental and subject to change in future versions.
@@ -1342,36 +1403,63 @@ There are not too much tests yet, so it is possible that you can find out some t
[variablelist
[[Notes:] [The three functions differ only by input parameters. The first only takes a callable object which accepts a
shared_future object as a parameter. The second function takes a scheduler as the first parameter and a callable object as
shared_future object as a parameter. The second function takes an executor as the first parameter and a callable object as
the second parameter. The third function takes a launch policy as the first parameter and a callable object as the
second parameter.]]
[[Requires:] [`INVOKE(DECAY_COPY (std::forward<F>(func)), *this)` shall be a valid expression.]]
[[Effects:] [
- The continuation is called when the object's shared state is ready (has a value or exception stored).
All the functions create a shared state that is associated with the returned future object. Additionally,
- The continuation launches according to the specified policy or scheduler.
- When the object's shared state is ready, the continuation
`INVOKE(DECAY_COPY(std::forward<F>(func)), *this)` is called depending on the overload (see below) with the call to DECAY_COPY() being evaluated in the thread that called then.
- When the scheduler or launch policy is not provided the continuation inherits the
parent's launch policy or scheduler.
- Any value returned from the continuation is stored as the result in the shared state of the resulting `future`.
Any exception propagated from the execution of the continuation is stored as the exceptional result in the shared state of the resulting `future`.
- If the parent was created with `promise` or with a `packaged_task` (has no associated launch policy), the
continuation behaves the same as the third overload with a policy argument of `launch::async | launch::deferred` and
the same argument for func.
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy or
scheduler, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
`launch::deferred`
The continuation launches according to the specified policy or executor or noting.
- When the launch policy is `launch::none` the continuation is called on an unspecified thread of execution.
- When the launch policy is `launch::async` the continuation is called on a new thread of execution.
- When the launch policy is `launch::deferred` the continuation is called on demand.
- When the launch policy is `launch::executor` the continuation is called on one of the thread of execution of the executor.
- When the launch policy is `launch::inherit` the continuation inherits the parent's launch policy or executor.
- When the executor or launch policy is not provided (first overload) is if as if launch::none was specified.
- When the executor is provided (second overload) the continuation is called on one of the thread of execution of the executor.
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy
executor, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
`launch::deferred`.
]]
[[Returns:] [An object of type `__unique_future__<typename boost::result_of<F(shared_future)>` that refers to the shared state created by the continuation.]]
[[Notes:] [
- Note that nested futures are not implicitly unwrapped yet. This could be subject to change in future versions.
- The returned futures behave as the ones returned from boost::async, the destructor of the future object returned from then will block. This could be subject to change in future versions.
]]
[[Postconditions:] [
- The future object is moved to the parameter of the continuation function .
- `valid() == false` on original future object immediately after it returns.
- `valid() == true` on original `shared_future`; `valid() == true` on the `future` returned from then.
[/- In case of implicit unwrapping, the validity of the `future` returned from `then` cannot be established until after the completion of the functor passed into `then`. In such case, the resulting `future` becomes ready with an exception of type `future_error`, with an error code of `future_errc::broken_promise`. ]
]]
@@ -1927,19 +2015,17 @@ __packaged_task__.]]
The function template async provides a mechanism to launch a function potentially in a new thread and
provides the result of the function in a future object with which it shares a shared state.
[warning `async(launch::deferred, F)` is NOT YET IMPLEMENTED!]
[heading Non-Variadic variant]
template <class F>
__unique_future__<typename result_of<typename decay<F>::type()>::type>
async(F&& f);
__unique_future__<typename result_of<typename decay<F>::type()>::type>
async(F&& f);
template <class F>
__unique_future__<typename result_of<typename decay<F>::type()>::type>
async(launch policy, F&& f);
__unique_future__<typename result_of<typename decay<F>::type()>::type>
async(launch policy, F&& f);
template <class Executor, class F>
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(Executor &ex, F&& f, Args&&... args);
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(Executor &ex, F&& f, Args&&... args);
[variablelist
[[Requires:] [
@@ -1955,7 +2041,7 @@ shall be a valid expression.
The first function behaves the same as a call to the second function with a policy argument of
`launch::async | launch::deferred` and the same arguments for `F`.
The second function creates a shared state that is associated with the returned future object.
The second and third functions create a shared state that is associated with the returned future object.
The further behavior of the second function depends on the policy argument as follows (if more than one of these conditions applies, the implementation may choose any of the corresponding policies):
@@ -1963,7 +2049,14 @@ The further behavior of the second function depends on the policy argument as fo
- if `policy & launch::deferred` is non-zero - Stores `decay_copy(boost::forward<F>(f))` in the shared state. This copy of `f` constitute a deferred function. Invocation of the deferred function evaluates `boost::move(g)()` where `g` is the stored value of `decay_copy(boost::forward<F>(f))`. The shared state is not made ready until the function has completed. The first call to a non-timed waiting function on an asynchronous return object referring to this shared state shall invoke the deferred function in the thread that called the waiting function. Once evaluation of `boost::move(g)()` begins, the function is no longer considered deferred. (Note: If this policy is specified together with other policies, such as when using a policy value of `launch::async | launch::deferred`, implementations should defer invocation or the selection of the policy when no more concurrency can be effectively exploited.)
- if no valid launch policy is provided the behaviour is undefined.
- if no valid launch policy is provided the behavior is undefined.
The further behavior of the third function is as follows:
- The Executor::submit() function is given a function<void ()> which calls `INVOKE (DECAY_COPY
(std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...). The implementation of the executor
is decided by the programmer.
]]
@@ -1991,22 +2084,22 @@ If the implementation chooses the `launch::async` policy,
]]
[[Remarks:] [The first signature shall not participate in overload resolution if decay<F>::type is boost::launch.
]]
[[Remarks::] [The first signature shall not participate in overload resolution if `decay_t<F> is `boost::
launch` or `boost::is_executor<F>` is `true_type`.]]
]
[heading Variadic variant]
template <class F, class... Args>
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(F&& f, Args&&... args);
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(F&& f, Args&&... args);
template <class F, class... Args>
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(launch policy, F&& f, Args&&... args);
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(launch policy, F&& f, Args&&... args);
template <class Executor, class F, class... Args>
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(Executor &ex, F&& f, Args&&... args);
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
async(Executor &ex, F&& f, Args&&... args);
[warning the variadic prototype is provided only on C++11 compilers supporting rvalue references, variadic templates, decltype and a standard library providing <tuple> (waiting for a boost::tuple that is move aware), and BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK is defined.]
@@ -2087,19 +2180,19 @@ with the return from the last function that releases the shared state, whichever
[section:wait_for_any Non-member function `wait_for_any()` - EXTENSION]
template<typename Iterator>
Iterator wait_for_any(Iterator begin,Iterator end); // EXTENSION
Iterator wait_for_any(Iterator begin,Iterator end); // EXTENSION
template<typename F1,typename F2>
unsigned wait_for_any(F1& f1,F2& f2); // EXTENSION
unsigned wait_for_any(F1& f1,F2& f2); // EXTENSION
template<typename F1,typename F2,typename F3>
unsigned wait_for_any(F1& f1,F2& f2,F3& f3); // EXTENSION
unsigned wait_for_any(F1& f1,F2& f2,F3& f3); // EXTENSION
template<typename F1,typename F2,typename F3,typename F4>
unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4); // EXTENSION
unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4); // EXTENSION
template<typename F1,typename F2,typename F3,typename F4,typename F5>
unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5); // EXTENSION
unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5); // EXTENSION
[variablelist
@@ -2127,19 +2220,19 @@ with any of the futures being waited for. `std::bad_alloc` if memory could not
[section:wait_for_all Non-member function `wait_for_all()` - EXTENSION]
template<typename Iterator>
void wait_for_all(Iterator begin,Iterator end); // EXTENSION
void wait_for_all(Iterator begin,Iterator end); // EXTENSION
template<typename F1,typename F2>
void wait_for_all(F1& f1,F2& f2); // EXTENSION
void wait_for_all(F1& f1,F2& f2); // EXTENSION
template<typename F1,typename F2,typename F3>
void wait_for_all(F1& f1,F2& f2,F3& f3); // EXTENSION
void wait_for_all(F1& f1,F2& f2,F3& f3); // EXTENSION
template<typename F1,typename F2,typename F3,typename F4>
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4); // EXTENSION
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4); // EXTENSION
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); // EXTENSION
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5); // EXTENSION
[variablelist
@@ -2158,24 +2251,179 @@ __unique_future__ or __shared_future__.]]
[endsect]
[/////////////////////////////////////////////////////////////////////]
[section:when_all Non-member function `when_all()` - EXTENSION]
template <class InputIterator>
future<std::vector<typename InputIterator::value_type::value_type>>
when_all(InputIterator first, InputIterator last);
template <typename... FutTypes>
future<std::tuple<decay_t<FutTypes>...> when_all(FutTypes&&... futures);
[variablelist
[[Requires:] [
- For the first overload, `InputIterator`'s value type shall be convertible to `future<R>` or `shared_future<R>`.
All `R` types must be the same. If any of the `future<R>` or `shared_future<R>` objects are in invalid state (i.e. `valid() == false`), the behavior is undefined.
- For the second overload, `FutTypes` is of type `future<R>` or `shared_future<R>`. The effect of calling `when_all` on a `future` or a `shared_future` object for which `valid() == false` is undefined.
]]
[[Notes:] [
- There are two variations of `when_all`. The first version takes a pair of `InputIterators`. The second takes any arbitrary number of `future<R0>` and `shared_future<R1>` objects, where `R0` and `R1` need not be the same type.
- Calling the first signature of `when_all` where `InputIterator` first equals last, returns a future with an empty `vector` that is immediately ready.
- Calling the second signature of `when_all` with no arguments returns a future<tuple<>> that is immediately ready.
]]
[[Effects:] [
- If any of the futures supplied to a call to `when_all` refer to deferred tasks that have not started execution, those tasks are executed before the call to `when_all` returns. Once all such tasks have been executed, the call to `when_all` returns immediately.
- The call to `when_all` does not wait for non-deferred tasks, or deferred tasks that have already started executing elsewhere, to complete before returning.
- Once all the `future`s/`shared_future`s supplied to the call to `when_all` are ready, the `future`s/`shared_future`s are moved/copied into the associated state of the future returned from the call to `when_all`, preserving the order of the futures supplied to `when_all`.
- The collection is then stored as the result in a newly created shared state.
- A new future object that refers to the shared state is created. The exact type of the future is further described below.
- The `future` returned by `when_all` will not throw an exception when calling `wait()` or `get()`, but the futures held in the output collection may.
]]
[[Returns:] [
- `future<tuple<>>` if `when_all` is called with zero arguments.
- `future<vector<future<R>>>` if the input cardinality is unknown at compile and the iterator pair yields `future<R>`. The order of the futures in the output vector will be the same as given by the input iterator.
- `future<vector<shared_future<R>>>` if the input cardinality is unknown at compile time and the iterator pair yields `shared_future<R>`. The order of the futures in the output vector will be the same as given by the input iterator.
- `future<tuple<decay_t<FutTypes>...>>` if inputs are fixed in number.
]]
[[Postconditions:] [
- All input futures valid() == false.
- All input shared future valid() == true.
- valid() == true.
]]
]
[endsect]
[/////////////////////////////////////////////////////////////////////]
[section:when_any Non-member function `when_any()` - EXTENSION]
template <class InputIterator>
future<std::vector<typename InputIterator::value_type::value_type>>
when_any(InputIterator first, InputIterator last);
template <typename... FutTypes>
future<std::tuple<decay_t<FutTypes>...>
when_any(FutTypes&&... futures);
[variablelist
[[Requires:] [
- For the first overload, `InputIterator`'s value type shall be convertible to `future<R>` or `shared_future<R>`. All `R` types must be the same. If any of the `future<R>` or `shared_future<R>` objects are in invalid state (i.e. `valid() == false`), the behavior is undefined.
- For the second overload, `FutTypes` is of type `future<R>` or `shared_future<R>`. The effect of calling `when_any` on a `future` or a `shared_future` object for which `valid() == false is undefined`.
]]
[[Notes:] [
- There are two variations of `when_any `. The first version takes a pair of `InputIterators`. The second takes any arbitrary number of `future<R0>` and `shared_future<R1>` objects, where `R0` and `R1` need not be the same type.
- Calling the first signature of `when_any ` where `InputIterator` first equals last, returns a future with an empty `vector` that is immediately ready.
- Calling the second signature of `when_any` with no arguments returns a future<tuple<>> that is immediately ready.
]]
[[Effects:] [
- Each of the futures supplied to `when_any` is checked in the order supplied. If a given future is ready, then no further futures are checked, and the call to `when_any` returns immediately. If a given future refers to a deferred task that has not yet started execution, then no further futures are checked, that task is executed, and the call to `when_any` then returns immediately.
- The call to `when_any` does not wait for non-deferred tasks, or deferred tasks that have already started executing elsewhere, to complete before returning.
- Once at least one of the futures supplied to the call to `when_any` are ready, the futures are moved into the associated state of the future returned from the call to `when_any`, preserving the order of the futures supplied to `when_any`. That future is then ready.
- The collection is then stored as the result in a newly created shared state.
- A new future object that refers to the shared state is created. The exact type of the future is further described below.
- The future returned by `when_any` will not throw an exception when calling `wait()` or `get()`, but the futures held in the output collection may.
]]
[[Returns:] [
- `future<tuple<>>` if `when_any ` is called with zero arguments.
- `future<vector<future<R>>>` if the input cardinality is unknown at compile and the iterator pair yields `future<R>`. The order of the futures in the output vector will be the same as given by the input iterator.
- `future<vector<shared_future<R>>>` if the input cardinality is unknown at compile time and the iterator pair yields `shared_future<R>`. The order of the futures in the output vector will be the same as given by the input iterator.
- `future<tuple<decat_t<FutTypes>...>>` if inputs are fixed in number.
]]
[[Postconditions:] [
- All input futures valid() == false.
- All input shared_futures valid() == true.
- valid() == true.
]]
]
[endsect]
[/////////////////////////////////////////////////////////////////////////////]
[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
future<T> make_ready_future(exception_ptr ex); // DEPRECATED
template <typename T, typename E>
future<T> make_ready_future(E ex); // DEPRECATED
future<T> make_ready_future(E ex); // DEPRECATED
[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.
.]]
@@ -2203,12 +2451,12 @@ Otherwise the value is copied to the shared state of the returned function.
[endsect]
[/////////////////////////////////////////////////////////////////////////////]
[section:make_exceptional Non-member function `make_exceptional()` EXTENSION]
[section:make_exceptional_future Non-member function `make_exceptional_future()` EXTENSION]
exceptional_ptr make_exceptional(exception_ptr ex); // EXTENSION
exceptional_ptr make_exceptional_future(exception_ptr ex); // EXTENSION
template <typename E>
exceptional_ptr make_exceptional(E ex); // EXTENSION
exceptional_ptr make_exceptional(); // EXTENSION
exceptional_ptr make_exceptional_future(E ex); // EXTENSION
exceptional_ptr make_exceptional_future(); // EXTENSION
[variablelist
@@ -2228,7 +2476,7 @@ An exceptional_ptr instance implicitly convertible to a future<T>
[section:make_future Non-member function `make_future()` DEPRECATED]
template <typename T>
future<typename decay<T>::type> make_future(T&& value); // DEPRECATED
future<typename decay<T>::type> make_future(T&& value); // DEPRECATED
future<void> make_future(); // DEPRECATED
@@ -2264,7 +2512,7 @@ Otherwise the value is copied to the shared state of the returned function.
[section:make_shared_future Non-member function `make_shared_future()` DEPRECATED]
template <typename T>
shared_future<typename decay<T>::type> make_shared_future(T&& value); // DEPRECATED
shared_future<typename decay<T>::type> make_shared_future(T&& value); // DEPRECATED
shared_future<void> make_shared_future(); // DEPRECATED
[variablelist

View File

@@ -1,5 +1,6 @@
[/
(C) Copyright 2008-11 Anthony Williams.
(C) Copyright 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).
@@ -93,7 +94,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.
@@ -325,7 +326,7 @@ Using a `shared_future` solves the issue
[heading share()]
Namming the return type when declaring the `shared_future` is needed; auto is not available within template argument lists.
Naming the return type when declaring the `shared_future` is needed; auto is not available within template argument lists.
Here `share()` could be used to simplify the code
void better_second_use( type arg ) {
@@ -343,7 +344,7 @@ Here `share()` could be used to simplify the code
[heading Writing on get()]
The user can either read or write the future avariable.
The user can either read or write the future variable.
void write_to_get( type arg ) {
@@ -364,7 +365,7 @@ The user can either read or write the future avariable.
This works because the `shared_future<>::get()` function returns a non-const reference to the appropriate storage.
Of course the access to this storage must be ensured by the user. The library doesn't ensure the access to the internal storage is thread safe.
There has been some work by the C++ standard committe on an `atomic_future` that behaves as an `atomic` variable, that is is thread_safe,
There has been some work by the C++ standard committee on an `atomic_future` that behaves as an `atomic` variable, that is thread_safe,
and a `shared_future` that can be shared between several threads, but there were not enough consensus and time to get it ready for C++11.
[endsect]
@@ -443,10 +444,10 @@ Input Parameters:
success and one for error handling. However this option has not been retained for the moment.
The lambda function takes a future as its input which carries the exception
through. This makes propagating exceptions straightforward. This approach also simplifies the chaining of continuations.
* Scheduler: Providing an overload to `.then`, to take a scheduler reference places great flexibility over the execution
* Executor: Providing an overload to `.then`, to take an executor reference places great flexibility over the execution
of the future in the programmer's hand. As described above, often taking a launch policy is not sufficient for powerful
asynchronous operations. The lifetime of the scheduler must outlive the continuation.
* Launch policy: if the additional flexibility that the scheduler provides is not required.
asynchronous operations. The lifetime of the executor must outlive the continuation.
* Launch policy: if the additional flexibility that the executor provides is not required.
Return values: The decision to return a future was based primarily on the ability to chain multiple continuations using
`.then()`. This benefit of composability gives the programmer incredible control and flexibility over their code. Returning

View File

@@ -240,9 +240,9 @@ The following class describes a so-called monitor pattern.
template <
typename Lockable=mutex
>
class basic_monitor : protected basic_lockable_adapter<Lockable> { // behaves like an BasicLockable for the derived classes
class basic_monitor : protected basic_lockable_adapter<Lockable> { // behaves like a BasicLockable for the derived classes
protected:
typedef unspecified synchronizer; // is an strict lock guard
typedef unspecified synchronizer; // is a strict lock guard
};
[/shared_monitor]

View File

@@ -869,7 +869,7 @@ any other threads have shared ownership, blocks until exclusive ownership can be
[variablelist
[[Precondition:] [The calling thread shall hold a upgrade lock on the mutex.]]
[[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]]
[[Effects:] [The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread without blocking.
For this conversion to be successful, this thread must be the only thread holding any ownership of the lock.
@@ -893,7 +893,7 @@ If the conversion is not successful, the upgrade ownership of m is retained.]]
[variablelist
[[Precondition:] [The calling thread shall hold a upgrade lock on the mutex.]]
[[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]]
[[Effects:] [If the tick period of `rel_time` is not exactly convertible to the native tick period, the duration shall be rounded up to the nearest native tick period.
The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread within the relative timeout specified by `rel_time`.
@@ -919,7 +919,7 @@ If the conversion is not successful, the upgrade ownership of m is retained.]]
[variablelist
[[Precondition:] [The calling thread shall hold a upgrade lock on the mutex.]]
[[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]]
[[Effects:] [The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread within the absolute timeout specified by `abs_time`.
If `abs_time` has already passed, the function attempts to obtain exclusive ownership without blocking (as if by calling `__try_unlock_upgrade_and_lock()`).
@@ -2150,7 +2150,7 @@ object passed to the constructor.]]
__nested_strict_lock is a model of __StrictLock.
A nested strict lock is a scoped lock guard ensuring a mutex is locked on its
scope, by taking ownership of an nesting lock, locking the mutex on construction if not already locked
scope, by taking ownership of a nesting lock, locking the mutex on construction if not already locked
and restoring the ownership to the nesting lock on destruction.
@@ -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);
@@ -3034,8 +3034,8 @@ An instance of __reverse_lock doesn't ['own] the lock never.
[[Effects:] [Locks the __lockable_concept_type__ objects supplied as
arguments in an unspecified and indeterminate order in a way that
avoids deadlock. It is safe to call this function concurrently from
multiple threads with the same mutexes (or other lockable objects) in
different orders without risk of deadlock. If any of the __lock_ref__
multiple threads for any set of mutexes (or other lockable objects) in
any order without risk of deadlock. If any of the __lock_ref__
or __try_lock_ref__ operations on the supplied
__lockable_concept_type__ objects throws an exception any locks
acquired by the function will be released before the function exits.]]
@@ -3062,8 +3062,8 @@ are locked by the calling thread.]]
[[Effects:] [Locks all the __lockable_concept_type__ objects in the
supplied range in an unspecified and indeterminate order in a way that
avoids deadlock. It is safe to call this function concurrently from
multiple threads with the same mutexes (or other lockable objects) in
different orders without risk of deadlock. If any of the __lock_ref__
multiple threads for any set of mutexes (or other lockable objects) in
any order without risk of deadlock. If any of the __lock_ref__
or __try_lock_ref__ operations on the __lockable_concept_type__
objects in the supplied range throws an exception any locks acquired
by the function will be released before the function exits.]]

482
doc/parallel.qbk Normal file
View File

@@ -0,0 +1,482 @@
[/
/ 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)
/]
[//////////////////////////////////////////////////////////]
[section:parallel Parallel - Fork-Join -- EXPERIMENTAL]
[section:fork_join Fork-Join]
[warning These features are experimental and subject to change in future versions. There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
[note These features are based on the [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4088.pdf [* n4088 - Task Region R3]] C++1y proposal from P. Halpern, A. Robison, A. Laksberg, H. Sutter, et al. The text that follows has been adapted from this paper to show the differences.]
The major difference respect to the standard proposal is that we are able to use a common executor for several task regions.
[note
Up to now, Boost.Thread doesn't implement the parallel algorithms as defined in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4105.pdf [* n4105 - Information technology Programming languages, their environments and system software interfaces Technical Specification for C++ Extensions for Parallelism]].
]
[////////////////////]
[section Introduction]
This module introduces a C++11/c++14 library function template `task_region` and a library class `task_region_handle`
with member functions `run` and `wait` that together enable developers to write expressive and portable fork-join
parallel code.
The working draft for the Parallelism TS [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4105.pdf [*N4105]] augments the STL algorithms with the inclusion of parallel execution policies. Programmers use these as a basis to write additional high-level algorithms that can be implemented in terms of the provided parallel algorithms. However, the scope of n4105 does not include lower-level mechanisms to express arbitrary fork-join parallelism
The `task_region`, `run` and the `wait` functions provided by this library are based on the `task_group` concept that is a part of the common subset of the PPL and the TBB libraries.
[endsect] [/ Introduction]
[/////////////////////////]
[section:tutorial Tutorial]
Consider an example of a parallel traversal of a tree, where a user-provided function compute is applied to each node of the tree, returning the sum of the results:
template<typename Func>
int traverse(node *n, Func&& compute)
{
int left = 0, right = 0;
task_region([&](task_region_handle& tr) {
if (n->left)
tr.run([&] { left = traverse(n->left, compute); });
if (n->right)
tr.run([&] { right = traverse(n->right, compute); });
});
return compute(n) + left + right;
}
The example above demonstrates the use of two of the functions proposed in this paper, `task_region` and
`task_region_handle::run`.
The `task_region` function delineates a region in a program code potentially containing invocations of tasks
spawned by the `run` member function of the `task_region_handle` class.
The run function spawns a task, a unit of work that is allowed to execute in parallel with respect to the caller.
Any parallel tasks spawned by `run` within the `task_region` are joined back to a single thread of execution at
the end of the `task_region`.
`run` takes a user-provided function object `f` and starts it asynchronously - i.e. it may return before the
execution of `f` completes. The implementation's scheduler may choose to run `f` immediately or delay running
`f` until compute resources become available.
A `task_region_handle` can be constructed only by `task_region` because it has no public constructors.
Thus, `run` can be invoked (directly or indirectly) only from a user-provided function passed to `task_region`:
void g();
void f(task_region_handle& tr)
{
tr.run(g); // OK, invoked from within task_region in h
}
void h()
{
task_region(f);
}
int main()
{
task_region_handle tr; // Error: no public constructor
tr.run(g); // No way to call run outside of a task_region
return 0;
}
[endsect] [/ Tutorial]
[////////////////]
[section:examples Examples]
[section:fib Parallel Fibonacci]
This is surely the worst implementation of the Fibonacci function. Anyway, here it is, as it is simple and shows the fork-join structure clearly. `Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2)`, so the task decomposition is trivial.
int fib_task_region(int n)
{
using boost::experimental::parallel::task_region;
using boost::experimental::parallel::task_region_handle;
if (n == 0) return 0;
if (n == 1) return 1;
int n1;
int n2;
task_region([&](task_region_handle& trh)
{
trh.run([&]
{
n1 = fib_task_region(n - 1);
});
n2 = fib_task_region(n - 2);
});
return n1 + n2;
}
int main()
{
for (int i = 0; i<10; ++i) {
std::cout << fib_task_region(i) << " ";
}
std::cout << std::endl;
}
[endsect] [/ Fib]
[section:fibex Parallel Fibonacci - Specific executor]
The previous example make use of an implementation defined way to spawn the tasks. Often the user wants to master how the task must be spawned. There is an overload of `task_region` that accept an additional `Executor` parameter and a function that takes as parameter a `task_region_handle_gen<Executor>`. `task_region_handle_gen<Executor>` run uses this executor to spawn the tasks.
template <class Ex>
int fib_task_region_gen( Ex& ex, int n)
{
using boost::experimental::parallel::task_region;
using boost::experimental::parallel::task_region_handle_gen;
if (n == 0) return 0;
if (n == 1) return 1;
int n1;
int n2;
task_region(ex, [&](task_region_handle_gen<Ex>& trh) // (2)
{
trh.run([&]
{
n1 = fib_task_region(n - 1);
});
n2 = fib_task_region(n - 2);
});
return n1 + n2;
}
int main()
{
boost::basic_thread_pool tp; // (1)
for (int i = 0; i<10; ++i) {
std::cout << fib_task_region_gen(tp,i) << " ";
}
std::cout << std::endl;
return 0;
}
The specific executor is declared in line (1) and it is used in line (2).
[endsect] [/ Fib ex]
[section:quick_sort Parallel Accumulate]
[endsect] [/ Accumulate]
[section:quick_sort Parallel Quick Sort]
[endsect] [/ QuickSort]
[endsect] [/ Examples]
[////////////////////////]
[section:rationale Design Rationale]
[endsect] [/ Design Rationale]
[endsect] [/ Fork-Join]
[/////////////////////]
[section:ref Reference -- EXPERIMENTAL]
[/////////////////////////]
[section:v1 Parallel V1]
[section:exception_list Header `<experimental/exception_list.hpp>`]
namespace boost
{
namespace experimental
{
namespace parallel
{
inline namespace v1
{
class exception_list;
} // v1
} // parallel
} // experimental
} // boost
[/////////////////////////]
[section:exception_list Class `exception_list`]
namespace boost
{
namespace experimental
{
namespace parallel
{
inline namespace v1
{
class exception_list: public std::exception
{
public:
typedef 'implementation defined' const_iterator;
~exception_list() noexcept {}
void add(exception_ptr const& e);
size_t size() const noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const char* what() const noexcept;
};
} // v1
} // parallel
} // experimental
} // boost
[endsect] [/ exception_list]
[endsect] [/ exception_list.hpp]
[endsect] [/ Parallel V1]
[////////////////////////////////////////////////////////////////////]
[section:v2 Parallel V2]
[////////////////////////////////////////////////////////////////////]
[section:concepts Concepts]
[////////////////////////////////////////////////////////////////////]
[section:regionCallable Concept `Region_Callable`]
[endsect] [/ Region_Callable]
[////////////////////////////////////////////////////////////////////]
[section:taskCallable Concept `Task_Callable`]
[endsect] [/ Task_Callable]
[////////////////////////////////////////////////////////////////////]
[endsect] [/ Concepts]
[////////////////////////////////////////////////////////////////////]
[section:task_region Header `<experimental/task_region.hpp>`]
namespace boost
{
namespace experimental
{
namespace parallel
{
inline namespace v2
{
class task_canceled_exception;
template <class Executor>
class task_region_handle_gen;
using default_executor = 'implementation defined';
class task_region_handle;
template <typename Executor, typename F>
void task_region_final(Executor& ex, F&& f);
template <typename F>
void task_region_final(F&& f);
template <typename Executor, typename F>
void task_region(Executor& ex, F&& f);
template <typename F>
void task_region(F&& f);
} // v2
} // parallel
} // experimental
} // boost
[////////////////////////////////////////////////////////////////////]
[section:task_canceled_exception Class `task_canceled_exception `]
namespace boost
{
namespace experimental
{
namespace parallel
{
inline namespace v2
{
class task_canceled_exception: public std::exception
{
public:
task_canceled_exception() noexcept;
task_canceled_exception(const task_canceled_exception&) noexcept;
task_canceled_exception& operator=(const task_canceled_exception&) noexcept;
virtual const char* what() const noexcept;
};
} // v2
} // parallel
} // experimental
} // boost
[endsect] [/ task_canceled_exception]
[////////////////////////////////////////////////////////////////////]
[section:task_region_handle_gen Template Class `task_region_handle_gen<>`]
namespace boost
{
namespace experimental
{
namespace parallel
{
inline namespace v2
{
template <class Executor>
class task_region_handle_gen
{
protected:
task_region_handle_gen(Executor& ex);
~task_region_handle_gen();
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;
template<typename F>
void run(F&& f);
void wait();
};
} // v2
} // parallel
} // experimental
} // boost
[endsect] [/ task_region_handle_gen]
[////////////////////////////////////////////////////////////////////]
[section:default_executor Class `default_executor `]
namespace boost
{
namespace experimental
{
namespace parallel
{
inline namespace v2
{
using default_executor = 'implementation defined';
} // v2
} // parallel
} // experimental
} // boost
[endsect] [/ default_executor]
[////////////////////////////////////////////////////////////////////]
[section:task_region_handle Class `task_region_handle `]
namespace boost
{
namespace experimental
{
namespace parallel
{
inline namespace v2
{
class task_region_handle :
public task_region_handle_gen<default_executor>
{
protected:
task_region_handle();
task_region_handle(const task_region_handle&) = delete;
task_region_handle& operator=(const task_region_handle&) = delete;
task_region_handle* operator&() const = delete;
};
} // v2
} // parallel
} // experimental
} // boost
[endsect] [/ task_region_handle]
[////////////////////////////////////////////////////////////////////]
[section:task_region_final Template Function `task_region_final `]
namespace boost
{
namespace experimental
{
namespace parallel
{
inline namespace v2
{
template <typename Executor, typename F>
void task_region_final(Executor& ex, F&& f);
template <typename F>
void task_region_final(F&& f);
} // v2
} // parallel
} // experimental
} // boost
[endsect] [/ task_region_final]
[////////////////////////////////////////////////////////////////////]
[section:task_region Template Function `task_region `]
namespace boost
{
namespace experimental
{
namespace parallel
{
inline namespace v2
{
template <typename Executor, typename F>
void task_region(Executor& ex, F&& f);
template <typename F>
void task_region(F&& f);
} // v2
} // parallel
} // experimental
} // boost
[endsect] [/ task_region]
[endsect] [/ task_region.hpp]
[endsect] [/ Parallel V2]
[endsect] [/ Reference]
[endsect] [/ Parallel]

View File

@@ -15,24 +15,25 @@
struct detach;
struct join_if_joinable;
struct interrupt_and_join_if_joinable;
template <class CallableThread = join_if_joinable>
template <class CallableThread = join_if_joinable, class Thread = thread>
class strict_scoped_thread;
template <class CallableThread = join_if_joinable>
template <class CallableThread = join_if_joinable, class Thread = thread>
class scoped_thread;
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
template <class CallableThread, class Thread = thread>
void swap(scoped_thread<Callable, Thread>& lhs, scoped_threadCallable, 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
@@ -54,7 +55,8 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
struct detach
{
void operator()(thread& t)
template <class Thread>
void operator()(Thread& t)
{
t.detach();
}
@@ -64,7 +66,8 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
struct join_if_joinable
{
void operator()(thread& t)
template <class Thread>
void operator()(Thread& t)
{
if (t.joinable())
{
@@ -79,7 +82,8 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
struct interrupt_and_join_if_joinable
{
void operator()(thread& t)
template <class Thread>
void operator()(Thread& t)
{
t.interrupt();
if (t.joinable())
@@ -96,7 +100,7 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
// #include <boost/thread/scoped_thread.hpp>
template <class CallableThread = join_if_joinable>
template <class CallableThread = join_if_joinable, class Thread = ::boost::thread>
class strict_scoped_thread
{
thread t_; // for exposition purposes only
@@ -105,7 +109,7 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
strict_scoped_thread(strict_scoped_thread const&) = delete;
strict_scoped_thread& operator=(strict_scoped_thread const&) = delete;
explicit strict_scoped_thread(thread&& t) noexcept;
explicit strict_scoped_thread(Thread&& t) noexcept;
template <typename F&&, typename ...Args>
explicit strict_scoped_thread(F&&, Args&&...);
@@ -114,15 +118,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]
@@ -130,7 +134,7 @@ This wrapper can be used to join the thread before destroying it seems a natural
[section:default_constructor Constructor from a __thread]
explicit strict_scoped_thread(thread&& t) noexcept;
explicit strict_scoped_thread(Thread&& t) noexcept;
[variablelist
@@ -150,7 +154,7 @@ This wrapper can be used to join the thread before destroying it seems a natural
[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()`.]]
@@ -180,7 +184,7 @@ This wrapper can be used to join the thread before destroying it seems a natural
#include <boost/thread/scoped_thread.hpp>
template <class CallableThread>
template <class CallableThread, class Thread = thread>
class scoped_thread
{
thread t_; // for exposition purposes only
@@ -230,16 +234,17 @@ This wrapper can be used to join the thread before destroying it seems a natural
};
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
template <class CallableThread, class Thread = thread>
void swap(scoped_thread<CallableThread,Thread>& lhs,scoped_thread<CallableThread,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.
@@ -291,16 +296,14 @@ same non-deprecated interface with the exception of the construction.
[variablelist
[[Effects:] [Transfers ownership of the scoped_thread managed by `other` (if
any) to `*this`.
any) to `*this` after having called to `CallableThread()(t_)`.
- if defined `BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE`: If there was a `scoped_thread` previously associated with `*this` then that `scoped_thread` is detached, DEPRECATED
- if defined `BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE`: If the `scoped_thread` is joinable calls to std::terminate.
]]
[[Postconditions:] [`other->get_id()==thread::id()` and `get_id()` returns the value of `other.get_id()` prior to the assignment.]]
[[Throws:] [Nothing]]
[[Throws:] [Nothing: The `CallableThread()(t_)` should not throw when joining the thread as the scoped variable is on a scope outside the thread function.]]
]
@@ -312,9 +315,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 +332,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()`.]]
@@ -506,7 +509,8 @@ any) to `*this`.
#include <boost/thread/scoped_thread.hpp>
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
template <class CallableThread, class Thread = thread>
void swap(scoped_thread<Callable, Thread>& lhs, scoped_threadCallable, Thread>& rhs) noexcept;
[variablelist

View File

@@ -110,10 +110,10 @@ where
* `q` denotes a value of type `Q`,
* `e` denotes a value of type Q::value_type,
* `u` denotes a value of type Q::size_type,
* `lve` denotes a lvalue referece of type Q::value_type,
* `rve` denotes a rvalue referece of type Q::value_type:
* `lve` denotes an lvalue reference of type Q::value_type,
* `rve` denotes an rvalue reference of type Q::value_type:
[/* `spe` denotes a shared_ptr<Q::value_type>]
* `qs` denotes a variable of of type `queus_op_status`,
* `qs` denotes a variable of of type `queue_op_status`,
[/////////////////////////////////////]
@@ -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.]]
@@ -229,12 +229,12 @@ where
[endsect]
[/////////////////////////////////////]
[section:non_waaiting Non-waiting Concurrent Queue Operations]
[section:non_waiting Non-waiting Concurrent Queue Operations]
The ConcurrentQueue concept models a queue with .
The ConcurrentQueue concept models a queue with Non-waiting operations.
A type `Q` meets the ConcurrentQueue requirements if the following expressions are well-formed and have the specified semantics
A type `Q` meets the ConcurrentQueue requirements if is a model of a BasicConcurrentQueue and the following expressions are well-formed and have the specified semantics
* `s = q.try_push_back(e);`
* `s = q.try_push_back(rve);`
@@ -246,8 +246,8 @@ where
* `e` denotes a value of type `Q::value_type`,
* `s` denotes a value of type `queue_status`,
* `u` denotes a value of type `Q::size_type`,
* `lve` denotes a lvalue referece of type Q::value_type,
* `rve` denotes a rvalue referece of type Q::value_type:
* `lve` denotes an lvalue reference of type Q::value_type,
* `rve` denotes an rvalue reference of type Q::value_type:
[/* `spe` denotes a shared_ptr<Q::value_type>]
@@ -281,7 +281,7 @@ where
[endsect]
[/////////////////////////////////////]
[section:try_push_back_m `s = q.try_push_back(rve());`]
[section:try_push_back_m `s = q.try_push_back(rve);`]
[variablelist
@@ -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.]]
@@ -345,7 +345,7 @@ For cases when blocking for mutual exclusion is undesirable, we have non-blockin
The interface is the same as the try operations but is allowed to also return queue_op_status::busy
in case the operation is unable to complete without blocking.
Non-blocking operations are provided only for BlockingQueues
Non-blocking operations are provided only for lock based queues
* `s = q.nonblocking_push_back(nb, e);`
* `s = q.nonblocking_push_back(nb, rve);`
@@ -357,8 +357,8 @@ where
* `q` denotes a value of type `Q`,
* `e` denotes a value of type Q::value_type,
* `s` denotes a value of type `queue_status`,
* `lve` denotes a lvalue referece of type Q::value_type,
* `rve` denotes a rvalue referece of type Q::value_type:
* `lve` denotes an lvalue reference of type Q::value_type,
* `rve` denotes an rvalue reference of type Q::value_type:
[/* `spe` denotes a shared_ptr<Q::value_type>]
@@ -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.]]
@@ -545,7 +545,7 @@ Closed queues add the following valid expressions
[[Return:] [
- If the queue is closed retun `queue_op_status::closed`,
- If the queue is closed return `queue_op_status::closed`,
- otherwise, return `queue_op_status::success` if no exception is thrown.
@@ -616,6 +616,207 @@ Closed queues add the following valid expressions
[endsect]
[endsect]
[/////////////////////////////////////]
[section:queue_op_status Queue Operation Status]
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
namespace boost
{
enum class queue_op_status { success = 0, empty, full, closed, busy }
}
[endsect]
[/////////////////////////////////////]
[section:queue_base Queue Base]
#include <boost/thread/concurrent_queues/queue_base.hpp>
namespace boost
{
template <typename ValueType, class SizeType=std::size_t>
class queue_base
{
public:
typedef ValueType value_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base() {};
// 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 push_back(BOOST_THREAD_RV_REF(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_push_back(BOOST_THREAD_RV_REF(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_push_back(BOOST_THREAD_RV_REF(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_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_pull_front(value_type& elem) = 0;
};
}
[endsect]
[/////////////////////////////////////]
[section:queue_adaptor Queue Adaptor]
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
namespace boost
{
template <typename Queue>
class queue_adaptor : public queue_base<typename Queue::value_type, typename Queue::size_type>
{
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_adaptor();
// Observers
bool empty() const;
bool full() const;
size_type size() const { return queue.size(); }
bool closed() const;
// Modifiers
void close();
void push_back(const value_type& x);
void push_back(BOOST_THREAD_RV_REF(value_type) x);
void pull_front(value_type& x);
value_type pull_front();
queue_op_status try_push_back(const value_type& x);
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
queue_op_status try_pull_front(value_type& x);
queue_op_status nonblocking_push_back(const value_type& x);
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
queue_op_status nonblocking_pull_front(value_type& x);
queue_op_status wait_push_back(const value_type& x);
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
queue_op_status wait_pull_front(value_type& x);
};
}
[endsect]
[/////////////////////////////////////]
[section:queue_views Queue Views]
#include <boost/thread/concurrent_queues/queue_views.hpp>
namespace boost
{
template <typename Queue>
class queue_back_view;
template <typename Queue>
class queue_front_view
template <class T>
using queue_back = queue_back_view<queue_base<T>>;
template <class T>
using queue_front = queue_front_view<queue_base<T>>;
}
[/////////////////////////////////////]
[section:queue_back_view Class template `queue_back_view<>`]
template <typename Queue>
class queue_back_view
{
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_back_view(Queue& q) noexcept;
// Observers
bool empty() const;
bool full() const;
size_type size() const;
bool closed() const;
// Modifiers
void close();
void push(const value_type& x);
void push(BOOST_THREAD_RV_REF(value_type) x);
queue_op_status try_push(const value_type& x);
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x);
queue_op_status nonblocking_push(const value_type& x);
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x);
queue_op_status wait_push(const value_type& x);
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x);
};
[endsect]
[/////////////////////////////////////]
[section:queue_front_view Class template `queue_front_view<>`]
template <typename Queue>
class queue_front_view
{
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_front_view(Queue& q) BOOST_NOEXCEPT;
// Observers
bool empty() const;
bool full() const;
size_type size() const;
bool closed() const;
// Modifiers
void close();
void pull(value_type& x);
value_type pull();
queue_op_status try_pull(value_type& x);
queue_op_status nonblocking_pull(value_type& x);
queue_op_status wait_pull(value_type& x);
};
[endsect]
[endsect]
[/////////////////////////////////////]
[section:sync_bounded_queue_ref Synchronized Bounded Queue]
@@ -782,13 +983,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;
@@ -830,7 +1031,7 @@ Closed queues add the following valid expressions
[/////////////////////////////////////]
[section:constructor Constructor `sync_bounded_queue(size_type)`]
[section:constructor Constructor `sync_queue(size_type)`]
explicit sync_queue();
@@ -843,21 +1044,6 @@ Closed queues add the following valid expressions
]
[endsect]
[/////////////////////////////////////]
[section:constructort Template Constructor `sync_bounded_queue(size_type, Range)`]
template <typename Range>
sync_bounded_queue(size_type max_elems, Range range);
[variablelist
[[Effects:] [Constructs an sync_queue with all the elements of the range. ]]
[[Throws:] [any exception that can be throw because of resources unavailable. ]]
]
[endsect]
[/////////////////////////////////////]
[section:full Member Function `full()`]

View File

@@ -156,7 +156,7 @@ object passed to the constructor.]]
};
}
`externally_locked_stream` cloaks a reference to an stream of type `Stream`, and actually
`externally_locked_stream` cloaks a reference to a stream of type `Stream`, and actually
provides full access to that object through the `get` member functions, provided you
pass a reference to a strict lock object.

View File

@@ -7,7 +7,9 @@
[section:tutorial Tutorial]
[@http://home.roadrunner.com/~hinnant/mutexes/locking.html Handling mutexes in C++] is an excellent tutorial. You need just replace std and ting by boost.
[@http://web.archive.org/web/20140531071228/http://home.roadrunner.com/~hinnant/mutexes/locking.html Handling mutexes in C++] is an excellent tutorial. You need just replace std and ting by boost.
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html Mutex, Lock, Condition Variable Rationale] adds rationale for the design decisions made for mutexes, locks and condition variables.

View File

@@ -63,7 +63,7 @@ Both forms of pointer dereference return a proxy object rather than a real refer
The pointer-like semantics work very well for simple accesses such as assignment and calls to member functions. However, sometimes you need to perform an operation that requires multiple accesses under protection of the same lock, and that's what the synchronize() method provides.
By calling synchronize() you obtain an strict_lock_ptr object that holds a lock on the mutex protecting the data, and which can be used to access the protected data. The lock is held until the strict_lock_ptr object is destroyed, so you can safely perform multi-part operations. The strict_lock_ptr object also acts as a pointer-to-T, just like synchronized_value does, but this time the lock is already held. For example, the following function adds a trailing slash to a path held in a synchronized_value. The use of the strict_lock_ptr object ensures that the string hasn't changed in between the query and the update.
By calling synchronize() you obtain a strict_lock_ptr object that holds a lock on the mutex protecting the data, and which can be used to access the protected data. The lock is held until the strict_lock_ptr object is destroyed, so you can safely perform multi-part operations. The strict_lock_ptr object also acts as a pointer-to-T, just like synchronized_value does, but this time the lock is already held. For example, the following function adds a trailing slash to a path held in a synchronized_value. The use of the strict_lock_ptr object ensures that the string hasn't changed in between the query and the update.
void addTrailingSlashIfMissing(boost::synchronized_value<std::string> & path)
{

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.3.0]
[version 4.8.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
[copyright 2011-14 Vicente J. Botet Escriba]
[copyright 2011-17 Vicente J. Botet Escriba]
[purpose C++ Library for launching threads and synchronizing data between them]
[category text]
[license
@@ -244,7 +244,6 @@
[include futures.qbk]
[endsect]
[include tss.qbk]
[section:sds Synchronized Data Structures]
@@ -253,6 +252,8 @@
[/include sync_streams.qbk]
[endsect]
[include parallel.qbk]
[include time.qbk]
[include emulations.qbk]

View File

@@ -21,12 +21,18 @@
{
thread::id get_id() noexcept;
template<typename TimeDuration>
void yield() noexcept; // DEPRECATED
void yield() noexcept;
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
namespace no_interruption_point // EXTENSION
{
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
}
template<typename Callable>
void at_thread_exit(Callable func); // EXTENSION
@@ -119,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
@@ -141,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
@@ -249,7 +255,7 @@ does not complete when the specified time has elapsed or reached respectively.
[endsect]
[section:destructor1 Destructor V1]
[section:destructor1 Destructor V1-2]
When the __thread__ object that represents a thread of execution is destroyed the thread becomes ['detached]. Once a thread is
detached, it will continue executing until the invocation of the function or callable object supplied on construction has completed,
@@ -258,7 +264,7 @@ object. In this case, the __thread__ object ceases to represent the now-detached
[endsect]
[section:destructor2 Destructor V2]
[section:destructor2 Destructor V3-X]
When the __thread__ object that represents a thread of execution is destroyed the program terminates if the thread is __joinable__.
@@ -274,7 +280,7 @@ You can use a thread_joiner to ensure that the thread has been joined at the thr
{
boost::thread t(my_func);
boost::thread_joiner g(t);
// do someting else
// do something else
} // here the thread_joiner destructor will join the thread before it is destroyed.
[endsect]
@@ -283,9 +289,11 @@ You can use a thread_joiner to ensure that the thread has been joined at the thr
A running thread can be ['interrupted] by invoking the __interrupt__ member function of the corresponding __thread__ object. When the
interrupted thread next executes one of the specified __interruption_points__ (or if it is currently __blocked__ whilst executing one)
with interruption enabled, then a __thread_interrupted__ exception will be thrown in the interrupted thread. If not caught,
this will cause the execution of the interrupted thread to terminate. As with any other exception, the stack will be unwound, and
destructors for objects of automatic storage duration will be executed.
with interruption enabled, then a __thread_interrupted__ exception will be thrown in the interrupted thread. Unless this exception is
caught inside the interrupted thread's thread-main function, the stack unwinding process (as with any other exception) causes the
destructors with automatic storage duration to be executed. Unlike other exceptions, when __thread_interrupted__ is propagated out of
thread-main function, this does not cause the call to `std::terminate`; the effect is as though the thread-main function has returned
normally.
If a thread wishes to avoid being interrupted, it can create an instance of __disable_interruption__. Objects of this class disable
interruption for the thread that created them on construction, and restore the interruption state to whatever it was before on
@@ -404,7 +412,7 @@ Of course all the synchronization facilities provided by Boost.Thread are also a
The `boost::this_thread` interrupt related functions behave in a degraded mode when called from a thread created using the native interface, i.e. `boost::this_thread::interruption_enabled()` returns false. As consequence the use of `boost::this_thread::disable_interruption` and `boost::this_thread::restore_interruption` will do nothing and calls to `boost::this_thread::interruption_point()` will be just ignored.
As the single way to interrupt a thread is through a __thread__ instance, `interruption_request()` wiil returns false for the native threads.
As the single way to interrupt a thread is through a __thread__ instance, `interruption_request()` will return false for the native threads.
[heading `pthread_exit` POSIX limitation]
@@ -426,12 +434,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);
@@ -450,10 +460,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;
@@ -707,7 +713,7 @@ are copied into internal storage for access by the new thread.]]]
[[Throws:] [Nothing.]]
[[Note:] [The reason to moving to std::terminate is that either implicitly detaching or joining a `joinable()` thread in its destructor could result in difficult to debug correctness (for `detach`) or performance (for `join`) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable. Join the thread before destroying or use an scoped thread.]]
[[Note:] [The reason to moving to std::terminate is that either implicitly detaching or joining a `joinable()` thread in its destructor could result in difficult to debug correctness (for `detach`) or performance (for `join`) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable. Join the thread before destroying or use a scoped thread.]]
]
@@ -752,7 +758,7 @@ corresponding successful `join()` return. ]]
[*resource_deadlock_would_occur]: if deadlock is detected or `this->get_id() == boost::this_thread::get_id()`.
[*invalid_argument]: if the thread is not joinable and `BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED` is defined.
[*invalid_argument]: if the thread is not joinable and `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined.
[/
@@ -801,7 +807,7 @@ unchanged.]]
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[/
@@ -841,7 +847,7 @@ unchanged.]]
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[/
@@ -881,7 +887,7 @@ unchanged.]]
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[/
@@ -917,7 +923,7 @@ unchanged.]]
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
]]
@@ -949,7 +955,7 @@ a default-constructed __thread_id__.]]
[[Effects:] [If `*this` refers to a thread of execution, request that the thread will be interrupted the next time it enters one of
the predefined __interruption_points__ with interruption enabled, or if it is currently __blocked__ in a call to one of the
predefined __interruption_points__ with interruption enabled .]]
predefined __interruption_points__ with interruption enabled. Otherwise do noting.]]
[[Throws:] [Nothing]]
@@ -960,7 +966,7 @@ predefined __interruption_points__ with interruption enabled .]]
[section:hardware_concurrency Static member function `hardware_concurrency()`]
unsigned hardware_concurrency() noexecpt;
unsigned hardware_concurrency() noexcept;
[variablelist
@@ -975,7 +981,7 @@ or 0 if this information is not available.]]
[section:physical_concurrency Static member function `physical_concurrency()`]
unsigned physical_concurrency() noexecpt;
unsigned physical_concurrency() noexcept;
[variablelist
@@ -1286,7 +1292,7 @@ instances of __thread_id__ `a` and `b` is the same if `a==b`, and different if `
[variablelist
[[Effects:] [Constructs a thread atrributes instance with its default values.]]
[[Effects:] [Constructs a thread attributes instance with its default values.]]
[[Throws:] [Nothing]]
@@ -1300,7 +1306,7 @@ instances of __thread_id__ `a` and `b` is the same if `a==b`, and different if `
[variablelist
[[Effects:] [Stores the stack size to be used to create a thread. This is an hint that the implementation can choose a better size if to small or too big or not aligned to a page.]]
[[Effects:] [Stores the stack size to be used to create a thread. This is a hint that the implementation can choose a better size if to small or too big or not aligned to a page.]]
[[Postconditions:] [`this-> get_stack_size()` returns the chosen stack size.]]
@@ -1489,6 +1495,11 @@ specified by `rel_time` has elapsed or the time point specified by
{
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
namespace no_interruption_point
{
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
}
}
[variablelist
@@ -1500,6 +1511,7 @@ specified by `rel_time` has elapsed or the time point specified by
do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted. ]]
[[Notes:] [`sleep_until()` is one of the predefined __interruption_points__.]]
[[Notes:] [`no_interruption_point::sleep_until()` is NOT one of the __interruption_points__.]]
]
@@ -1513,16 +1525,22 @@ do not throw exceptions. __thread_interrupted__ if the current thread of executi
{
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
namespace no_interruption_point
{
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
}
}
[variablelist
[[Effects:] [Suspends the current thread until the duration specified by
[[Effects:] [Suspends the current thread until the duration specified
by `rel_time` has elapsed.]]
[[Throws:] [Nothing if operations of chrono::duration<Rep, Period> do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted.]]
[[Notes:] [`sleep_for()` is one of the predefined __interruption_points__.]]
[[Notes:] [`no_interruption_point:: sleep_for()` is NOT one of the __interruption_points__.]]
]

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

@@ -7,9 +7,7 @@
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
#endif
#include <iostream>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
@@ -30,6 +28,12 @@
#include <boost/assert.hpp>
#include <string>
#include <iostream>
#include <cassert>
boost::future<void> p(boost::future<void> f) {
assert(f.is_ready());
return boost::make_ready_future();
}
void p1()
{
@@ -45,8 +49,9 @@ void p2()
int f1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
std::cout << BOOST_CONTEXTOF << std::endl;
return 1;
}
int f2(int i)
@@ -67,68 +72,103 @@ void submit_some(boost::executor& tp)
}
void at_th_entry(boost::basic_thread_pool& )
{
}
int main()
int test_executor_adaptor()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
{
boost::executor_adaptor < boost::basic_thread_pool > ea(4);
std::cout << BOOST_CONTEXTOF << std::endl;
submit_some( ea);
std::cout << BOOST_CONTEXTOF << std::endl;
#if 1
// fixme
// ERROR= tr1::bad_weak_ptr
{
boost::future<int> t1 = boost::async(ea, &f1);
boost::future<int> t2 = boost::async(ea, &f1);
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
std::cout << BOOST_CONTEXTOF << std::endl;
submit_some(ea);
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea3(1);
std::cout << BOOST_CONTEXTOF << std::endl;
boost::future<int> t1 = boost::async(ea3, &f1);
std::cout << BOOST_CONTEXTOF << std::endl;
boost::future<int> t2 = boost::async(ea3, &f1);
std::cout << BOOST_CONTEXTOF << std::endl;
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
#endif
std::cout << BOOST_CONTEXTOF << std::endl;
submit_some(ea);
std::cout << BOOST_CONTEXTOF << std::endl;
}
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::loop_executor > ea2;
submit_some( ea2);
ea2.underlying_executor().run_queued_closures();
}
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::basic_thread_pool > ea1(4);
boost::executor_adaptor < boost::serial_executor > ea2(ea1);
submit_some(ea2);
}
#endif
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::inline_executor > ea1;
submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::thread_executor > ea1;
submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
std::cout << BOOST_CONTEXTOF << std::endl;
#if 1
// fixme
// ERROR= tr1::bad_weak_ptr
{
boost::basic_thread_pool ea(4, at_th_entry);
boost::future<int> t1 = boost::async(ea, &f1);
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
}
#endif
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::async(&f1);
}
#if 1
// fixme
// ERROR= tr1::bad_weak_ptr
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea(1);
boost::async(ea,&f1);
}
#endif
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
std::cout << BOOST_CONTEXTOF << std::endl;
}
catch (std::exception& ex)
{
@@ -144,3 +184,24 @@ int main()
// std::cout << BOOST_CONTEXTOF << std::endl;
return 0;
}
int main()
{
return test_executor_adaptor();
#if 0 && defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
&& defined BOOST_THREAD_PROVIDES_EXECUTORS \
&& ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
boost::basic_thread_pool executor;
// compiles
boost::make_ready_future().then(&p);
// ??
boost::make_ready_future().then(executor, &p);
// doesn't compile
boost::make_ready_future().then(executor, &p);
#endif
}

View File

@@ -0,0 +1,91 @@
// Copyright (C) 2012 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
#include <boost/thread/experimental/task_region.hpp>
#include <iostream>
#if ! defined BOOST_NO_CXX11_RANGE_BASED_FOR && ! defined BOOST_NO_CXX11_LAMBDAS
int fib_task_region(int n)
{
using boost::experimental::parallel::task_region;
using boost::experimental::parallel::task_region_handle;
if (n == 0) return 0;
if (n == 1) return 1;
int n1;
int n2;
task_region([&](task_region_handle& trh)
{
trh.run([&]
{
n1 = fib_task_region(n - 1);
});
n2 = fib_task_region(n - 2);
});
return n1 + n2;
}
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
template <class Ex>
int fib_task_region_gen( Ex& ex, int n)
{
using boost::experimental::parallel::task_region;
using boost::experimental::parallel::task_region_handle_gen;
if (n == 0) return 0;
if (n == 1) return 1;
int n1;
int n2;
task_region(ex, [&](task_region_handle_gen<Ex>& trh)
{
trh.run([&]
{
n1 = fib_task_region(n - 1);
});
n2 = fib_task_region(n - 2);
});
return n1 + n2;
}
#endif
int main()
{
for (int i = 0; i<10; ++i) {
std::cout << fib_task_region(i) << " ";
}
std::cout << std::endl;
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
boost::basic_thread_pool tp;
for (int i = 0; i<10; ++i) {
std::cout << fib_task_region_gen(tp,i) << " ";
}
std::cout << std::endl;
#endif
return 0;
}
#else
int main()
{
return 0;
}
#endif

View File

@@ -4,9 +4,6 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
#endif
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
@@ -38,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;
}
@@ -78,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

@@ -4,11 +4,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
#endif
#if ! defined BOOST_NO_CXX11_DECLTYPE
//&& ! defined BOOST_NO_CXX11_DECLTYPE_N3276
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
@@ -21,6 +17,7 @@
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <string>
#include <iostream>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
int p1()
@@ -48,6 +45,7 @@ int p2(boost::future<int> f)
BOOST_ASSERT(false);
}
BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG;
return 0;
}
int p2s(boost::shared_future<int> f)
{
@@ -68,6 +66,7 @@ int p2s(boost::shared_future<int> f)
BOOST_ASSERT(false);
}
BOOST_THREAD_LOG << "P2S>" << BOOST_THREAD_END_LOG;
return 0;
}
int main()

View File

@@ -4,9 +4,6 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
#endif
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
@@ -44,10 +41,28 @@ int main()
for (int i=0; i< number_of_tests; i++)
try
{
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
boost::future<int> inner_future = outer_future.unwrap();
int ii = inner_future.get();
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
boost::future<int> inner_future = boost::async(boost::launch::async, &p2).unwrap();
inner_future.wait();
int ii = inner_future.get();
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
}
#endif
{
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
boost::future<int> inner_future = outer_future.unwrap();
inner_future.wait();
int ii = inner_future.get();
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
}
{
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
boost::future<int> inner_future = outer_future.unwrap();
int ii = inner_future.get();
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
}
}
catch (std::exception& ex)
{

View File

@@ -5,16 +5,13 @@
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
#endif
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_USES_LOG
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/future.hpp>
@@ -61,6 +58,8 @@ int p2(boost::future<int> f)
}
BOOST_THREAD_LOG
<< "P2>" << BOOST_THREAD_END_LOG;
return 0;
}
int p2s(boost::shared_future<int> f)
{
@@ -84,6 +83,7 @@ int p2s(boost::shared_future<int> f)
}
BOOST_THREAD_LOG
<< "P2>" << BOOST_THREAD_END_LOG;
return 0;
}
int main()
@@ -93,16 +93,80 @@ int main()
{
try
{
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<std::tuple<> > all0 = boost::when_all();
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
//(void) all.wait();
boost::csbl::vector<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::tuple<> > all0 = boost::when_all();
BOOST_THREAD_LOG
<< BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#endif
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::make_ready_future(1);
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
//(void) all.wait();
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<std::string> f2 = boost::make_ready_future(std::string("nnnnnnn"));;
boost::future<boost::csbl::tuple<boost::future<int>, boost::future<std::string> > > all = boost::when_all(boost::move(f1), boost::move(f2));
//(void) all.wait();
boost::csbl::tuple<boost::future<int>, boost::future<std::string> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > v;
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1b));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
}
}
catch (std::exception& ex)
{
@@ -120,16 +184,113 @@ int main()
{
try
{
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<std::tuple<> > all0 = boost::when_any();
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
//(void) all.wait();
boost::csbl::vector<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::tuple<> > all0 = boost::when_any();
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#endif
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::make_ready_future(1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<std::string> f1 = boost::make_ready_future(std::string("aaaa"));
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<std::string>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<std::string>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f2 = boost::make_ready_future(1);
boost::future<int> f1 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = boost::async(boost::launch::deferred, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#endif
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > v;
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1b));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
}
}
catch (std::exception& ex)
{
@@ -155,7 +316,6 @@ using namespace boost;
void f( boost::csbl::vector<future<int> > &//vec
, BOOST_THREAD_RV_REF(future<int>) //f
) {
//vec.push_back(boost::forward<future<int> >(f));
}
int main()
{

View File

@@ -0,0 +1,163 @@
// 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/loop_executor.hpp>
#include <boost/thread/executors/serial_executor.hpp>
#include <boost/thread/executors/inline_executor.hpp>
#include <boost/thread/executors/thread_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(200));
}
void p2()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
//boost::this_thread::sleep_for(boost::chrono::seconds(10));
}
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::generic_executor_ref tp)
{
for (int i = 0; i < 3; ++i) {
tp.submit(&p2);
}
for (int i = 0; i < 3; ++i) {
tp.submit(&p1);
}
}
void at_th_entry(boost::basic_thread_pool& )
{
}
int test_generic_executor_ref()
{
std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
{
boost::basic_thread_pool ea(4);
submit_some( ea);
{
boost::future<int> t1 = boost::async(ea, &f1);
boost::future<int> t2 = boost::async(ea, &f1);
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
submit_some(ea);
{
boost::basic_thread_pool ea3(1);
boost::future<int> t1 = boost::async(ea3, &f1);
boost::future<int> t2 = boost::async(ea3, &f1);
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
submit_some(ea);
}
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::loop_executor ea2;
submit_some( ea2);
ea2.run_queued_closures();
}
#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);
}
#endif
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::inline_executor ea1;
submit_some(ea1);
}
std::cout << BOOST_CONTEXTOF << std::endl;
{
//boost::thread_executor ea1;
//submit_some(ea1);
}
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea(4, at_th_entry);
boost::future<int> t1 = boost::async(ea, &f1);
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
}
std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea(4, at_th_entry);
boost::async(ea, &f1);
std::cout << BOOST_CONTEXTOF << std::endl;
}
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
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_generic_executor_ref();
}

View File

@@ -8,9 +8,6 @@
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
#endif
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_USES_LOG
@@ -45,6 +42,14 @@ int main()
int result = f2.get();
BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG;
}
#if ! defined BOOST_NO_CXX14_GENERIC_LAMBDAS
{
boost::future<int> f1 = boost::async(boost::launch::async, []() {return 123;});
boost::future<int> f2 = f1.then([](auto f) {return 2*f.get(); });
int result = f2.get();
BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG;
}
#endif
}
catch (std::exception& ex)
{

View File

@@ -94,6 +94,11 @@ int main()
f.get();
}
#endif
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::future<int> f = compute(-1);
f.wait();
}
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::future<int> f = compute(0);
@@ -104,11 +109,31 @@ int main()
boost::future<int&> f = compute_ref(0);
std::cout << f.get() << std::endl;
}
// {
// std::cout << __FILE__ << " "<< __LINE__ << std::endl;
// boost::future<int> f = compute(2);
// 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);
std::cout << f.get() << std::endl;
}
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::shared_future<int> f = shared_compute(0);

View File

@@ -3,12 +3,14 @@
// 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>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
//#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/executors/basic_thread_pool.hpp>

View File

@@ -3,14 +3,15 @@
// 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>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
//#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
//#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
//#endif
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/future.hpp>

View File

@@ -6,9 +6,13 @@
// adapted from the example given by Howard Hinnant in
#include <boost/config.hpp>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <iostream>
#include <boost/thread/scoped_thread.hpp>
#ifdef XXXX
@@ -18,32 +22,32 @@
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)
void producer(the_ostream & /*mos*/, boost::sync_queue<int> & sbq)
{
using namespace boost;
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));
}
}
catch(sync_queue_is_closed&)
{
mos << "closed !!!\n";
//mos << "closed !!!\n";
}
catch(...)
{
mos << "exception !!!\n";
//mos << "exception !!!\n";
}
}
void consumer(
the_ostream &mos,
the_ostream & /*mos*/,
boost::sync_queue<int> & sbq)
{
using namespace boost;
@@ -51,61 +55,60 @@ 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";
//mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(sync_queue_is_closed&)
{
mos << "closed !!!\n";
//mos << "closed !!!\n";
}
catch(...)
{
mos << "exception !!!\n";
//mos << "exception !!!\n";
}
}
void consumer2(the_ostream &mos, boost::sync_queue<int> & sbq)
void consumer2(the_ostream &/*mos*/, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
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";
//mos << i << " pull(" << r << ")\n";
}
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
mos << "exception !!!\n";
//mos << "exception !!!\n";
}
}
void consumer3(the_ostream &/*mos*/, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
queue_op_status res = sbq.wait_pull(r);
if (res==queue_op_status::closed) break;
//mos << i << " wait_pull(" << r << ")\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
//mos << "exception !!!\n";
}
}
//void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
//{
// using namespace boost;
// bool closed=false;
// try {
// for(int i=0; ;++i)
// {
// int r;
// queue_op_status res = sbq.wait_and_pull(r);
// if (res==queue_op_status::closed) break;
// mos << i << " wait_and_pull(" << r << ")\n";
// this_thread::sleep_for(chrono::milliseconds(250));
// }
// }
// catch(...)
// {
// mos << "exception !!!\n";
// }
//}
int main()
{

View File

@@ -0,0 +1,150 @@
// (C) Copyright 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)
// adapted from the example given by Howard Hinnant in
#include <boost/config.hpp>
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <iostream>
#include <boost/thread/scoped_thread.hpp>
#ifdef XXXX
#include <boost/thread/externally_locked_stream.hpp>
typedef boost::externally_locked_stream<std::ostream> the_ostream;
#else
typedef std::ostream the_ostream;
typedef std::istream the_istream;
#endif
#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>
#include <boost/type_traits.hpp>
void producer(the_ostream &/*mos*/, boost::queue_back<int> sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
sbq.push(i);
//sbq << i;
//mos << "push(" << i << ") " << sbq.size() <<"\n";
this_thread::sleep_for(chrono::milliseconds(200));
}
}
catch(sync_queue_is_closed&)
{
//mos << "closed !!!\n";
}
catch(...)
{
//mos << "exception !!!\n";
}
}
void consumer(
the_ostream &/*mos*/,
boost::queue_front<int> sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
sbq.pull(r);
//sbq >> r;
//mos << i << " pull(" << r << ") " << sbq.size() <<"\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(sync_queue_is_closed&)
{
//mos << "closed !!!\n";
}
catch(...)
{
//mos << "exception !!!\n";
}
}
void consumer2(the_ostream &/*mos*/, boost::queue_front<int> sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
queue_op_status st = sbq.try_pull(r);
if (queue_op_status::closed == st) break;
if (queue_op_status::success == st) {
//mos << i << " try_pull(" << r << ")\n";
}
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
//mos << "exception !!!\n";
}
}
void consumer3(the_ostream &/*mos*/, boost::queue_front<int> sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
queue_op_status res = sbq.wait_pull(r);
if (res==queue_op_status::closed) break;
//mos << i << " wait_pull(" << r << ")\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
//mos << "exception !!!\n";
}
}
int main()
{
using namespace boost;
#ifdef XXXX
recursive_mutex terminal_mutex;
externally_locked_stream<std::ostream> mcerr(std::cerr, terminal_mutex);
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
#else
the_ostream &mcerr = std::cout;
the_ostream &mcout = std::cerr;
//the_istream &mcin = std::cin;
#endif
queue_adaptor<sync_queue<int> > sbq;
{
mcout << "begin of main" << std::endl;
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back<int>(sbq)));
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back<int>(sbq)));
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), concurrent::queue_front<int>(sbq)));
this_thread::sleep_for(chrono::seconds(1));
mcout << "closed()" << std::endl;
sbq.close();
mcout << "closed()" << std::endl;
} // all threads joined here.
mcout << "end of main" << std::endl;
return 0;
}

View File

@@ -6,8 +6,13 @@
// adapted from the example given by Howard Hinnant in
#include <boost/config.hpp>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
//#define XXXX
#include <iostream>

View File

@@ -32,7 +32,7 @@ counter c;
void change_count()
{
std::cout << "count == " << c.increment() << std::endl;
//std::cout << "count == " << c.increment() << std::endl;
}
int main(int, char*[])

View File

@@ -39,36 +39,23 @@ void do_something_in_current_thread()
{
}
//void do_something_with_current_thread(boost::thread&& th)
//{
// th.join();
//}
int main()
{
{
int some_local_state;
int some_local_state=0;
boost::strict_scoped_thread<> t( (boost::thread(func(some_local_state))));
do_something_in_current_thread();
}
{
int some_local_state;
int some_local_state=0;
boost::thread t(( func(some_local_state) ));
boost::strict_scoped_thread<> g( (boost::move(t)) );
do_something_in_current_thread();
}
// {
// int some_local_state;
// boost::thread t(( func(some_local_state) ));
// boost::strict_scoped_thread<> g( (boost::move(t)) );
//
// do_something_in_current_thread();
// do_something_with_current_thread(boost::thread(g));
// }
{
int some_local_state;
int some_local_state=0;
boost::scoped_thread<> t( (boost::thread(func(some_local_state))));
if (t.joinable())
@@ -76,14 +63,17 @@ int main()
else
do_something_in_current_thread();
}
#if 0
{
int some_local_state;
int some_local_state=0;
boost::thread t(( func(some_local_state) ));
boost::scoped_thread<> g( (boost::move(t)) );
t.detach();
if (g.joinable())
g.detach();
do_something_in_current_thread();
}
#endif
{
boost::scoped_thread<> g( &f, 1, 2 );
do_something_in_current_thread();

107
example/serial_executor.cpp Normal file
View File

@@ -0,0 +1,107 @@
// 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)
{
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);
}
}
void at_th_entry(boost::basic_thread_pool& )
{
}
int test_executor_adaptor()
{
{
try
{
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
{
boost::basic_thread_pool ea1(4);
boost::serial_executor ea2(ea1);
submit_some(ea2);
boost::this_thread::sleep_for(boost::chrono::seconds(10));
}
#endif
}
catch (std::exception& ex)
{
std::cout << "ERROR= " << ex.what() << "" << std::endl;
return 1;
}
catch (...)
{
std::cout << " ERROR= exception thrown" << std::endl;
return 2;
}
}
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();
}

View File

@@ -0,0 +1,112 @@
// (C) Copyright 2009-2012 Anthony Williams
// (C) Copyright 2012 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)
#if __cplusplus < 201103L
int main()
{
return 0;
}
#else
#define BOOST_THREAD_VERSION 3
#include <iostream>
#include <boost/thread/scoped_thread.hpp>
#include <thread>
#include <cassert>
void do_something(int& i)
{
++i;
}
void f(int, int)
{
}
struct func
{
int& i;
func(int& i_) :
i(i_)
{
}
void operator()()
{
for (unsigned j = 0; j < 1000000; ++j)
{
do_something(i);
}
}
};
void do_something_in_current_thread()
{
}
using strict_scoped_thread = boost::strict_scoped_thread<boost::join_if_joinable, std::thread>;
using scoped_thread = boost::scoped_thread<boost::join_if_joinable, std::thread>;
int main()
{
{
int some_local_state=0;
strict_scoped_thread t( (std::thread(func(some_local_state))));
do_something_in_current_thread();
}
{
int some_local_state=0;
std::thread t(( func(some_local_state) ));
strict_scoped_thread g( (boost::move(t)) );
do_something_in_current_thread();
}
{
int some_local_state=0;
std::thread t(( func(some_local_state) ));
strict_scoped_thread g( (std::move(t)) );
do_something_in_current_thread();
}
{
int some_local_state=1;
scoped_thread t( (std::thread(func(some_local_state))));
if (t.joinable()) {
t.join();
assert( ! t.joinable() );
}
else
do_something_in_current_thread();
}
#if 0
try
{
int some_local_state=1;
std::thread t(( func(some_local_state) ));
scoped_thread g( (boost::move(t)) );
if (g.joinable()) {
// CLANG crash here
g.detach();
assert( ! g.joinable() );
}
do_something_in_current_thread();
}
catch (...) {
assert( false);
}
#endif
{
scoped_thread g( &f, 1, 2 );
do_something_in_current_thread();
}
return 0;
}
#endif

View File

@@ -0,0 +1,66 @@
// (C) Copyright 2009-2012 Anthony Williams
// (C) Copyright 2012 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)
#if __cplusplus < 201103L
int main()
{
return 0;
}
#else
#include <iostream>
#include <string>
#include <boost/thread/thread_only.hpp>
#include <boost/thread/thread_guard.hpp>
#include <thread>
void do_something(int& i)
{
++i;
}
struct func
{
int& i;
func(int& i_):i(i_){}
void operator()()
{
for(unsigned j=0;j<1000000;++j)
{
do_something(i);
}
}
private:
func& operator=(func const&);
};
void do_something_in_current_thread()
{}
using thread_guard = boost::thread_guard<boost::join_if_joinable, std::thread>;
void f()
{
int some_local_state;
func my_func(some_local_state);
std::thread t(my_func);
thread_guard g(t);
do_something_in_current_thread();
}
int main()
{
f();
return 0;
}
#endif

View File

@@ -39,7 +39,7 @@ const char* player_name(int state)
if (state == PLAYER_B)
return "PLAYER-B";
throw "bad player";
return 0;
//return 0;
}
void player(int active)
@@ -50,7 +50,7 @@ void player(int active)
while (state < GAME_OVER)
{
std::cout << player_name(active) << ": Play." << std::endl;
//std::cout << player_name(active) << ": Play." << std::endl;
state = other;
cond.notify_all();
do

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

@@ -59,6 +59,7 @@ int main()
threads.remove_thread(th);
BOOST_TEST(! threads.is_thread_in(th));
th->join();
delete th;
}
{
{

View File

@@ -3,10 +3,15 @@
// 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>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_USES_LOG
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/detail/log.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>

View File

@@ -24,6 +24,7 @@ void thread_proc()
increment();
int* p = value.get();
assert(*p == i+1);
(void)(p);
}
}

View File

@@ -3,13 +3,18 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/config.hpp>
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/detail/log.hpp>
#include <boost/thread/executors/loop_executor.hpp>
#include <boost/assert.hpp>
#include <boost/thread/thread_only.hpp>
#include <string>
void p1()

View File

@@ -41,6 +41,7 @@ namespace boost
{
}
BOOST_THREAD_MOVABLE(default_barrier_reseter)
//BOOST_THREAD_COPYABLE_AND_MOVABLE(default_barrier_reseter)
default_barrier_reseter(default_barrier_reseter const& other) BOOST_NOEXCEPT :
size_(other.size_)
@@ -71,6 +72,7 @@ namespace boost
{}
BOOST_THREAD_MOVABLE(void_functor_barrier_reseter)
//BOOST_THREAD_COPYABLE_AND_MOVABLE(void_functor_barrier_reseter)
void_functor_barrier_reseter(void_functor_barrier_reseter const& other) BOOST_NOEXCEPT :
size_(other.size_), fct_(other.fct_)
@@ -78,6 +80,7 @@ namespace boost
}
void_functor_barrier_reseter(BOOST_THREAD_RV_REF(void_functor_barrier_reseter) other) BOOST_NOEXCEPT :
size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
//size_(BOOST_THREAD_RV(other).size_), fct_(boost::move(BOOST_THREAD_RV(other).fct_))
{
}
@@ -96,6 +99,7 @@ namespace boost
{
}
BOOST_THREAD_MOVABLE(void_fct_ptr_barrier_reseter)
//BOOST_THREAD_COPYABLE_AND_MOVABLE(void_fct_ptr_barrier_reseter)
void_fct_ptr_barrier_reseter(void_fct_ptr_barrier_reseter const& other) BOOST_NOEXCEPT :
size_(other.size_), fct_(other.fct_)
@@ -112,6 +116,10 @@ namespace boost
}
};
}
//BOOST_THREAD_DCL_MOVABLE(thread_detail::default_barrier_reseter)
//BOOST_THREAD_DCL_MOVABLE(thread_detail::void_functor_barrier_reseter)
//BOOST_THREAD_DCL_MOVABLE(thread_detail::void_fct_ptr_barrier_reseter)
class barrier
{
static inline unsigned int check_counter(unsigned int count)
@@ -137,7 +145,7 @@ namespace boost
unsigned int count,
BOOST_THREAD_RV_REF(F) funct,
typename enable_if<
typename is_void<typename result_of<F>::type>::type, dummy*
typename is_void<typename result_of<F()>::type>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
@@ -152,7 +160,7 @@ namespace boost
unsigned int count,
F &funct,
typename enable_if<
typename is_void<typename result_of<F>::type>::type, dummy*
typename is_void<typename result_of<F()>::type>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
@@ -168,7 +176,7 @@ namespace boost
unsigned int count,
BOOST_THREAD_RV_REF(F) funct,
typename enable_if<
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
typename is_same<typename result_of<F()>::type, unsigned int>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
@@ -181,7 +189,7 @@ namespace boost
unsigned int count,
F& funct,
typename enable_if<
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
typename is_same<typename result_of<F()>::type, unsigned int>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
@@ -217,6 +225,7 @@ namespace boost
m_generation++;
m_count = static_cast<unsigned int>(fct_());
BOOST_ASSERT(m_count != 0);
lock.unlock();
m_cond.notify_all();
return true;
}

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

@@ -96,7 +96,6 @@ namespace boost
leavers_(0)
{
}
template <typename F>
completion_latch(std::size_t count, void(*funct)()) :
count_(count), funct_(funct), waiters_(0), leavers_(0)
{

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

@@ -0,0 +1,223 @@
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_QUEUE_BASE_HPP
#define BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_QUEUE_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_queue_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_queue_base)
inline sync_queue_base();
//template <typename Range>
//inline explicit sync_queue(Range range);
inline ~sync_queue_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_queue_base<ValueType, Queue>::sync_queue_base() :
data_(), closed_(false)
{
BOOST_ASSERT(data_.empty());
}
template <class ValueType, class Queue>
sync_queue_base<ValueType, Queue>::~sync_queue_base()
{
}
template <class ValueType, class Queue>
void sync_queue_base<ValueType, Queue>::close()
{
{
lock_guard<mutex> lk(mtx_);
closed_ = true;
}
not_empty_.notify_all();
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::closed() const
{
lock_guard<mutex> lk(mtx_);
return closed(lk);
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::closed(unique_lock<mutex>&) const
{
return closed_;
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::closed(lock_guard<mutex>&) const
{
return closed_;
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::empty() const
{
lock_guard<mutex> lk(mtx_);
return empty(lk);
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::full() const
{
return false;
}
template <class ValueType, class Queue>
typename sync_queue_base<ValueType, Queue>::size_type sync_queue_base<ValueType, Queue>::size() const
{
lock_guard<mutex> lk(mtx_);
return size(lk);
}
template <class ValueType, class Queue>
void sync_queue_base<ValueType, Queue>::throw_if_closed(unique_lock<mutex>& lk)
{
if (closed(lk))
{
BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
}
template <class ValueType, class Queue>
void sync_queue_base<ValueType, Queue>::throw_if_closed(lock_guard<mutex>& lk)
{
if (closed(lk))
{
BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
}
template <class ValueType, class Queue>
void sync_queue_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_queue_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_queue_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

@@ -0,0 +1,209 @@
#ifndef BOOST_THREAD_QUEUE_ADAPTOR_HPP
#define BOOST_THREAD_QUEUE_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/queue_base.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <typename Queue>
class queue_adaptor_copyable_only :
public boost::queue_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
queue_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(const value_type& x) { queue.push(x); }
void pull(value_type& x) { queue.pull(x); };
value_type pull() { return queue.pull(); }
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(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(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, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_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(value_type& x) { queue.pull(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue.pull(); }
queue_op_status try_pull(value_type& x) { return queue.try_pull(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(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(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, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_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(const value_type& x) { queue.push(x); }
void pull(value_type& x) { queue.pull(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue.pull(); }
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(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(const value_type& x) { return queue.wait_push(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(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__ && ! 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 queue_adaptor;
template <class Q, class T>
struct queue_adaptor<Q, T, true, true> {
typedef queue_adaptor_copyable_and_movable<Q> type;
};
template <class Q, class T>
struct queue_adaptor<Q, T, true, false> {
typedef queue_adaptor_copyable_only<Q> type;
};
template <class Q, class T>
struct queue_adaptor<Q, T, false, true> {
typedef queue_adaptor_movable_only<Q> type;
};
}
template <typename Queue>
class queue_adaptor :
public detail::queue_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 ~queue_adaptor() {};
};
}
using concurrent::queue_adaptor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,202 @@
#ifndef BOOST_THREAD_QUEUE_BASE_HPP
#define BOOST_THREAD_QUEUE_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 queue_base_copyable_only
{
public:
typedef ValueType value_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_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(const value_type& x) = 0;
virtual void pull(value_type&) = 0;
virtual value_type pull() = 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(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull(value_type&) = 0;
virtual queue_op_status wait_push(const value_type& x) = 0;
virtual queue_op_status wait_pull(ValueType& elem) = 0;
};
template <typename ValueType, class SizeType>
class queue_base_movable_only
{
public:
typedef ValueType value_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_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(value_type&) = 0;
// enable_if is_nothrow_movable<value_type>
virtual value_type pull() = 0;
virtual queue_op_status try_pull(value_type&) = 0;
virtual queue_op_status nonblocking_pull(value_type&) = 0;
virtual queue_op_status wait_pull(value_type& elem) = 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, class SizeType>
class queue_base_copyable_and_movable
{
public:
typedef ValueType value_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_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(const value_type& x) = 0;
virtual void pull(value_type&) = 0;
// enable_if is_nothrow_copy_movable<value_type>
virtual value_type pull() = 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(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull(value_type&) = 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(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, 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 queue_base;
template <class T, class ST>
struct queue_base<T, ST, true, true> {
typedef queue_base_copyable_and_movable<T, ST> type;
};
template <class T, class ST>
struct queue_base<T, ST, true, false> {
typedef queue_base_copyable_only<T, ST> type;
};
template <class T, class ST>
struct queue_base<T, ST, false, true> {
typedef queue_base_movable_only<T, ST> type;
};
}
template <typename ValueType, class SizeType=std::size_t>
class queue_base :
public detail::queue_base<ValueType, SizeType>::type
{
public:
typedef ValueType value_type;
typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base() {};
};
}
using concurrent::queue_base;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,46 @@
#ifndef BOOST_THREAD_QUEUE_OP_STATUS_HPP
#define BOOST_THREAD_QUEUE_OP_STATUS_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/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
BOOST_SCOPED_ENUM_DECLARE_BEGIN(queue_op_status)
{ success = 0, empty, full, closed, busy, timeout, not_ready }
BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)
struct sync_queue_is_closed : std::exception
{
};
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
struct no_block_tag{};
BOOST_CONSTEXPR_OR_CONST no_block_tag no_block = {};
#endif
using concurrent::queue_op_status;
using concurrent::sync_queue_is_closed;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,144 @@
#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/queue_base.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
template <typename Queue>
class queue_back_view
{
Queue* queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_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(x); }
queue_op_status try_push(const value_type& x) { return queue->try_push(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); }
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_front_view
{
Queue* queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_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 pull(value_type& x) { queue->pull(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue->pull(); }
queue_op_status try_pull(value_type& x) { return queue->try_pull(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull(x); }
queue_op_status wait_pull(value_type& x) { return queue->wait_pull(x); }
};
#if ! defined BOOST_NO_CXX11_TEMPLATE_ALIASES
template <class T>
using queue_back = queue_back_view<queue_base<T> > ;
template <class T>
using queue_front = queue_front_view<queue_base<T> > ;
#else
template <class T>
struct queue_back : queue_back_view<queue_base<T> >
{
typedef queue_back_view<queue_base<T> > base_type;
queue_back(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
};
template <class T>
struct queue_front : queue_front_view<queue_base<T> >
{
typedef queue_front_view<queue_base<T> > base_type;
queue_front(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
};
#endif
// template <class Queue>
// queue_back_view<Queue> back(Queue & q) { return queue_back_view<Queue>(q); }
// template <class Queue>
// queue_front_view<Queue> front(Queue & q) { return queue_front_view<Queue>(q); }
//#if 0
// template <class T>
// queue_back<T> back(queue_base<T> & q) { return queue_back<T>(q); }
// template <class T>
// queue_front<T> front(queue_base<T> & q) { return queue_front<T>(q); }
//#else
// template <class T>
// typename queue_back<T>::type back(queue_base<T> & q) { return typename queue_back<T>::type(q); }
// template <class T>
// typename queue_front<T>::type front(queue_base<T> & q) { return typename queue_front<T>::type(q); }
//#endif
}
using concurrent::queue_back_view;
using concurrent::queue_front_view;
using concurrent::queue_back;
using concurrent::queue_front;
//using concurrent::back;
//using concurrent::front;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,727 @@
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_BOUNDED_QUEUE_HPP
#define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_BOUNDED_QUEUE_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/mutex.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/throw_exception.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
template <typename ValueType>
class sync_bounded_queue
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
BOOST_THREAD_NO_COPYABLE(sync_bounded_queue)
explicit sync_bounded_queue(size_type max_elems);
template <typename Range>
sync_bounded_queue(size_type max_elems, Range range);
~sync_bounded_queue();
// Observers
inline bool empty() const;
inline bool full() const;
inline size_type capacity() const;
inline size_type size() const;
inline bool closed() const;
// Modifiers
inline void close();
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void push(const value_type& x);
inline void push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(const value_type& x);
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(no_block_tag, const 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 void push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status try_push_back(const value_type& x);
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status nonblocking_push_back(const value_type& x);
inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status wait_push_back(const value_type& x);
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
// Observers/Modifiers
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void pull(value_type&);
// enable_if is_nothrow_copy_movable<value_type>
inline value_type pull();
inline shared_ptr<ValueType> ptr_pull();
inline bool try_pull(value_type&);
inline bool try_pull(no_block_tag,value_type&);
inline shared_ptr<ValueType> try_pull();
#endif
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:
mutable mutex mtx_;
condition_variable not_empty_;
condition_variable not_full_;
size_type waiting_full_;
size_type waiting_empty_;
value_type* data_;
size_type in_;
size_type out_;
size_type capacity_;
bool closed_;
inline size_type inc(size_type idx) const BOOST_NOEXCEPT
{
return (idx + 1) % capacity_;
}
inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
{
return in_ == out_;
}
inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
{
return in_ == out_;
}
inline bool full(unique_lock<mutex>& ) const BOOST_NOEXCEPT
{
return (inc(in_) == out_);
}
inline bool full(lock_guard<mutex>& ) const BOOST_NOEXCEPT
{
return (inc(in_) == out_);
}
inline size_type capacity(lock_guard<mutex>& ) const BOOST_NOEXCEPT
{
return capacity_-1;
}
inline size_type size(lock_guard<mutex>& lk) const BOOST_NOEXCEPT
{
if (full(lk)) return capacity(lk);
return ((in_+capacity(lk)-out_) % capacity(lk));
}
inline void throw_if_closed(unique_lock<mutex>&);
inline bool closed(unique_lock<mutex>&) const;
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
inline shared_ptr<value_type> try_pull(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);
#endif
inline queue_op_status try_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 try_push_back(BOOST_THREAD_RV_REF(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 wait_push_back(const 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 wait_until_not_empty(unique_lock<mutex>& lk);
inline void wait_until_not_empty(unique_lock<mutex>& lk, bool&);
inline size_type wait_until_not_full(unique_lock<mutex>& lk);
inline size_type wait_until_not_full(unique_lock<mutex>& lk, bool&);
inline void notify_not_empty_if_needed(unique_lock<mutex>& lk)
{
if (waiting_empty_ > 0)
{
--waiting_empty_;
lk.unlock();
not_empty_.notify_one();
}
}
inline void notify_not_full_if_needed(unique_lock<mutex>& lk)
{
if (waiting_full_ > 0)
{
--waiting_full_;
lk.unlock();
not_full_.notify_one();
}
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void pull(value_type& elem, unique_lock<mutex>& lk)
{
elem = boost::move(data_[out_]);
out_ = inc(out_);
notify_not_full_if_needed(lk);
}
inline value_type pull(unique_lock<mutex>& lk)
{
value_type elem = boost::move(data_[out_]);
out_ = inc(out_);
notify_not_full_if_needed(lk);
return boost::move(elem);
}
inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& lk)
{
shared_ptr<value_type> res = make_shared<value_type>(boost::move(data_[out_]));
out_ = inc(out_);
notify_not_full_if_needed(lk);
return res;
}
#endif
inline void pull_front(value_type& elem, unique_lock<mutex>& lk)
{
elem = boost::move(data_[out_]);
out_ = inc(out_);
notify_not_full_if_needed(lk);
}
inline value_type pull_front(unique_lock<mutex>& lk)
{
value_type elem = boost::move(data_[out_]);
out_ = inc(out_);
notify_not_full_if_needed(lk);
return boost::move(elem);
}
inline void set_in(size_type in, unique_lock<mutex>& lk)
{
in_ = in;
notify_not_empty_if_needed(lk);
}
inline void push_at(const value_type& elem, size_type in_p_1, unique_lock<mutex>& lk)
{
data_[in_] = elem;
set_in(in_p_1, lk);
}
inline void push_at(BOOST_THREAD_RV_REF(value_type) elem, size_type in_p_1, unique_lock<mutex>& lk)
{
data_[in_] = boost::move(elem);
set_in(in_p_1, lk);
}
};
template <typename ValueType>
sync_bounded_queue<ValueType>::sync_bounded_queue(typename sync_bounded_queue<ValueType>::size_type max_elems) :
waiting_full_(0), waiting_empty_(0), data_(new value_type[max_elems + 1]), in_(0), out_(0), capacity_(max_elems + 1),
closed_(false)
{
BOOST_ASSERT_MSG(max_elems >= 1, "number of elements must be > 1");
}
// template <typename ValueType>
// template <typename Range>
// sync_bounded_queue<ValueType>::sync_bounded_queue(size_type max_elems, Range range) :
// waiting_full_(0), waiting_empty_(0), data_(new value_type[max_elems + 1]), in_(0), out_(0), capacity_(max_elems + 1),
// closed_(false)
// {
// BOOST_ASSERT_MSG(max_elems >= 1, "number of elements must be > 1");
// BOOST_ASSERT_MSG(max_elems == size(range), "number of elements must match range's size");
// try
// {
// typedef typename Range::iterator iterator_t;
// iterator_t first = boost::begin(range);
// iterator_t end = boost::end(range);
// size_type in = 0;
// for (iterator_t cur = first; cur != end; ++cur, ++in)
// {
// data_[in] = *cur;
// }
// set_in(in);
// }
// catch (...)
// {
// delete[] data_;
// }
// }
template <typename ValueType>
sync_bounded_queue<ValueType>::~sync_bounded_queue()
{
delete[] data_;
}
template <typename ValueType>
void sync_bounded_queue<ValueType>::close()
{
{
lock_guard<mutex> lk(mtx_);
closed_ = true;
}
not_empty_.notify_all();
not_full_.notify_all();
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::closed() const
{
lock_guard<mutex> lk(mtx_);
return closed_;
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::closed(unique_lock<mutex>& ) const
{
return closed_;
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::empty() const
{
lock_guard<mutex> lk(mtx_);
return empty(lk);
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::full() const
{
lock_guard<mutex> lk(mtx_);
return full(lk);
}
template <typename ValueType>
typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::capacity() const
{
lock_guard<mutex> lk(mtx_);
return capacity(lk);
}
template <typename ValueType>
typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::size() const
{
lock_guard<mutex> lk(mtx_);
return size(lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
{
if (empty(lk))
{
throw_if_closed(lk);
return false;
}
pull(elem, lk);
return true;
}
template <typename ValueType>
shared_ptr<ValueType> sync_bounded_queue<ValueType>::try_pull(unique_lock<mutex>& lk)
{
if (empty(lk))
{
throw_if_closed(lk);
return shared_ptr<ValueType>();
}
return ptr_pull(lk);
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_pull(ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return try_pull(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (empty(lk))
{
if (closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull_front(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return try_pull_front(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_pull(no_block_tag,ValueType& elem)
{
unique_lock<mutex> lk(mtx_, try_to_lock);
if (!lk.owns_lock())
{
return false;
}
return try_pull(elem, lk);
}
template <typename ValueType>
boost::shared_ptr<ValueType> sync_bounded_queue<ValueType>::try_pull()
{
unique_lock<mutex> lk(mtx_);
return try_pull(lk);
}
#endif
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::nonblocking_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_pull_front(elem, lk);
}
template <typename ValueType>
void sync_bounded_queue<ValueType>::throw_if_closed(unique_lock<mutex>&)
{
if (closed_)
{
BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
}
template <typename ValueType>
void sync_bounded_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk)
{
for (;;)
{
if (out_ != in_) break;
throw_if_closed(lk);
++waiting_empty_;
not_empty_.wait(lk);
}
}
template <typename ValueType>
void sync_bounded_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk, bool & closed)
{
for (;;)
{
if (out_ != in_) break;
if (closed_) {closed=true; return;}
++waiting_empty_;
not_empty_.wait(lk);
}
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_bounded_queue<ValueType>::pull(ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
pull(elem, lk);
}
// template <typename ValueType>
// void sync_bounded_queue<ValueType>::pull(ValueType& elem, bool & closed)
// {
// unique_lock<mutex> lk(mtx_);
// wait_until_not_empty(lk, closed);
// if (closed) {return;}
// pull(elem, lk);
// }
// enable if ValueType is nothrow movable
template <typename ValueType>
ValueType sync_bounded_queue<ValueType>::pull()
{
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
return pull(lk);
}
template <typename ValueType>
boost::shared_ptr<ValueType> sync_bounded_queue<ValueType>::ptr_pull()
{
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
return ptr_pull(lk);
}
#endif
template <typename ValueType>
void sync_bounded_queue<ValueType>::pull_front(ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
pull_front(elem, lk);
}
// enable if ValueType is nothrow movable
template <typename ValueType>
ValueType sync_bounded_queue<ValueType>::pull_front()
{
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
return pull_front(lk);
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (empty(lk) && closed(lk)) {return queue_op_status::closed;}
bool is_closed = false;
wait_until_not_empty(lk, is_closed);
if (is_closed) {return queue_op_status::closed;}
pull_front(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return wait_pull_front(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
{
throw_if_closed(lk);
size_type in_p_1 = inc(in_);
if (in_p_1 == out_) // full()
{
return false;
}
push_at(elem, in_p_1, lk);
return true;
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return try_push(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
{
if (closed(lk)) return queue_op_status::closed;
size_type in_p_1 = inc(in_);
if (in_p_1 == out_) // full()
{
return queue_op_status::full;
}
push_at(elem, in_p_1, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return try_push_back(elem, lk);
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
{
if (closed(lk)) return queue_op_status::closed;
push_at(elem, wait_until_not_full(lk), lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
return wait_push_back(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(no_block_tag, const ValueType& elem)
{
unique_lock<mutex> lk(mtx_, try_to_lock);
if (!lk.owns_lock()) return false;
return try_push(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::nonblocking_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_, try_to_lock);
if (!lk.owns_lock()) return queue_op_status::busy;
return try_push_back(elem, lk);
}
template <typename ValueType>
typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::wait_until_not_full(unique_lock<mutex>& lk)
{
for (;;)
{
throw_if_closed(lk);
size_type in_p_1 = inc(in_);
if (in_p_1 != out_) // ! full()
{
return in_p_1;
}
++waiting_full_;
not_full_.wait(lk);
}
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_bounded_queue<ValueType>::push(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
push_at(elem, wait_until_not_full(lk), lk);
}
#endif
template <typename ValueType>
void sync_bounded_queue<ValueType>::push_back(const ValueType& elem)
{
unique_lock<mutex> lk(mtx_);
push_at(elem, wait_until_not_full(lk), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
throw_if_closed(lk);
size_type in_p_1 = inc(in_);
if (in_p_1 == out_) // full()
{
return false;
}
push_at(boost::move(elem), in_p_1, lk);
return true;
}
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_);
return try_push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (closed(lk)) return queue_op_status::closed;
size_type in_p_1 = inc(in_);
if (in_p_1 == out_) // full()
{
return queue_op_status::full;
}
push_at(boost::move(elem), in_p_1, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_);
return try_push_back(boost::move(elem), lk);
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (closed(lk)) return queue_op_status::closed;
push_at(boost::move(elem), wait_until_not_full(lk), lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_bounded_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_);
return try_push_back(boost::move(elem), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_bounded_queue<ValueType>::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(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_bounded_queue<ValueType>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_push_back(boost::move(elem), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_bounded_queue<ValueType>::push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_);
push_at(boost::move(elem), wait_until_not_full(lk), lk);
}
#endif
template <typename ValueType>
void sync_bounded_queue<ValueType>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(mtx_);
push_at(boost::move(elem), wait_until_not_full(lk), lk);
}
template <typename ValueType>
sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
{
sbq.push_back(boost::move(elem));
return sbq;
}
template <typename ValueType>
sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, ValueType const&elem)
{
sbq.push_back(elem);
return sbq;
}
template <typename ValueType>
sync_bounded_queue<ValueType>& operator>>(sync_bounded_queue<ValueType>& sbq, ValueType &elem)
{
sbq.pull_front(elem);
return sbq;
}
}
using concurrent::sync_bounded_queue;
}
#include <boost/config/abi_suffix.hpp>
#endif

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

@@ -0,0 +1,369 @@
// 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_SYNC_PRIORITY_QUEUE
#define BOOST_THREAD_SYNC_PRIORITY_QUEUE
#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/vector.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/atomic.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <exception>
#include <queue>
#include <utility>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail {
template <
class Type,
class Container = csbl::vector<Type>,
class Compare = std::less<Type>
>
class priority_queue
{
private:
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)
{ }
size_type size() const
{
return _elements.size();
}
bool empty() const
{
return _elements.empty();
}
void push(Type const& element)
{
_elements.push_back(element);
std::push_heap(_elements.begin(), _elements.end(), _compare);
}
void push(BOOST_RV_REF(Type) element)
{
_elements.push_back(boost::move(element));
std::push_heap(_elements.begin(), _elements.end(), _compare);
}
void pop()
{
std::pop_heap(_elements.begin(), _elements.end(), _compare);
_elements.pop_back();
}
Type pull()
{
Type result = boost::move(_elements.front());
pop();
return boost::move(result);
}
Type const& top()
{
return _elements.front();
}
};
}
namespace concurrent
{
template <class ValueType,
class Container = csbl::vector<ValueType>,
class Compare = std::less<typename Container::value_type> >
class sync_priority_queue
: public detail::sync_queue_base<ValueType, boost::detail::priority_queue<ValueType,Container,Compare> >
{
typedef detail::sync_queue_base<ValueType, boost::detail::priority_queue<ValueType,Container,Compare> > 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;
typedef chrono::steady_clock clock;
protected:
public:
sync_priority_queue() {}
~sync_priority_queue()
{
if(!super::closed())
{
super::close();
}
}
void push(const ValueType& elem);
void push(BOOST_THREAD_RV_REF(ValueType) elem);
queue_op_status try_push(const ValueType& elem);
queue_op_status try_push(BOOST_THREAD_RV_REF(ValueType) elem);
ValueType pull();
void pull(ValueType&);
queue_op_status pull_until(const clock::time_point&, ValueType&);
queue_op_status pull_for(const clock::duration&, ValueType&);
queue_op_status try_pull(ValueType& elem);
queue_op_status wait_pull(ValueType& elem);
queue_op_status nonblocking_pull(ValueType&);
private:
void push(unique_lock<mutex>&, const ValueType& elem);
void push(lock_guard<mutex>&, const ValueType& elem);
void push(unique_lock<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem);
void push(lock_guard<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem);
queue_op_status try_push(unique_lock<mutex>&, const ValueType& elem);
queue_op_status try_push(unique_lock<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem);
ValueType pull(unique_lock<mutex>&);
ValueType pull(lock_guard<mutex>&);
void pull(unique_lock<mutex>&, ValueType&);
void pull(lock_guard<mutex>&, ValueType&);
queue_op_status try_pull(lock_guard<mutex>& lk, ValueType& elem);
queue_op_status try_pull(unique_lock<mutex>& lk, ValueType& elem);
queue_op_status wait_pull(unique_lock<mutex>& lk, ValueType& elem);
queue_op_status nonblocking_pull(unique_lock<mutex>& lk, ValueType&);
sync_priority_queue(const sync_priority_queue&);
sync_priority_queue& operator= (const sync_priority_queue&);
sync_priority_queue(BOOST_THREAD_RV_REF(sync_priority_queue));
sync_priority_queue& operator= (BOOST_THREAD_RV_REF(sync_priority_queue));
}; //end class
//////////////////////
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(unique_lock<mutex>& lk, const T& elem)
{
super::throw_if_closed(lk);
super::data_.push(elem);
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, const T& elem)
{
super::throw_if_closed(lk);
super::data_.push(elem);
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(const T& elem)
{
lock_guard<mutex> lk(super::mtx_);
push(lk, elem);
}
//////////////////////
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(unique_lock<mutex>& lk, BOOST_THREAD_RV_REF(T) elem)
{
super::throw_if_closed(lk);
super::data_.push(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, BOOST_THREAD_RV_REF(T) elem)
{
super::throw_if_closed(lk);
super::data_.push(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(BOOST_THREAD_RV_REF(T) elem)
{
lock_guard<mutex> lk(super::mtx_);
push(lk, boost::move(elem));
}
//////////////////////
template <class T, class Container,class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::try_push(const T& elem)
{
lock_guard<mutex> lk(super::mtx_);
if (super::closed(lk)) return queue_op_status::closed;
push(lk, elem);
return queue_op_status::success;
}
//////////////////////
template <class T, class Container,class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::try_push(BOOST_THREAD_RV_REF(T) elem)
{
lock_guard<mutex> lk(super::mtx_);
if (super::closed(lk)) return queue_op_status::closed;
push(lk, boost::move(elem));
return queue_op_status::success;
}
//////////////////////
template <class T,class Container, class Cmp>
T sync_priority_queue<T,Container,Cmp>::pull(unique_lock<mutex>&)
{
return super::data_.pull();
}
template <class T,class Container, class Cmp>
T sync_priority_queue<T,Container,Cmp>::pull(lock_guard<mutex>&)
{
return super::data_.pull();
}
template <class T,class Container, class Cmp>
T sync_priority_queue<T,Container,Cmp>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull(lk);
}
//////////////////////
template <class T,class Container, class Cmp>
void sync_priority_queue<T,Container,Cmp>::pull(unique_lock<mutex>&, T& elem)
{
elem = super::data_.pull();
}
template <class T,class Container, class Cmp>
void sync_priority_queue<T,Container,Cmp>::pull(lock_guard<mutex>&, T& elem)
{
elem = super::data_.pull();
}
template <class T,class Container, class Cmp>
void sync_priority_queue<T,Container,Cmp>::pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
pull(lk, elem);
}
//////////////////////
template <class T, class Cont,class Cmp>
queue_op_status
sync_priority_queue<T,Cont,Cmp>::pull_until(const clock::time_point& tp, T& elem)
{
unique_lock<mutex> lk(super::mtx_);
if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp))
return queue_op_status::timeout;
pull(lk, elem);
return queue_op_status::success;
}
//////////////////////
template <class T, class Cont,class Cmp>
queue_op_status
sync_priority_queue<T,Cont,Cmp>::pull_for(const clock::duration& dura, T& elem)
{
return pull_until(clock::now() + dura, elem);
}
//////////////////////
template <class T, class Container,class Cmp>
queue_op_status
sync_priority_queue<T,Container,Cmp>::try_pull(unique_lock<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull(lk, elem);
return queue_op_status::success;
}
template <class T, class Container,class Cmp>
queue_op_status
sync_priority_queue<T,Container,Cmp>::try_pull(lock_guard<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull(lk, elem);
return queue_op_status::success;
}
template <class T, class Container,class Cmp>
queue_op_status
sync_priority_queue<T,Container,Cmp>::try_pull(T& elem)
{
lock_guard<mutex> lk(super::mtx_);
return try_pull(lk, elem);
}
//////////////////////
template <class T,class Container, class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::wait_pull(unique_lock<mutex>& lk, T& elem)
{
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(lk, elem);
return queue_op_status::success;
}
template <class T,class Container, class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::wait_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_pull(lk, elem);
}
//////////////////////
template <class T,class Container, class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::nonblocking_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock()) return queue_op_status::busy;
return try_pull(lk, elem);
}
} //end concurrent namespace
using concurrent::sync_priority_queue;
} //end boost namespace
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,335 @@
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_QUEUE_HPP
#define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_QUEUE_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 <iostream>
#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_queue
: 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_queue)
inline sync_queue();
//template <class Range>
//inline explicit sync_queue(Range range);
inline ~sync_queue();
// Modifiers
inline void push(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 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
inline void pull(value_type&);
// enable_if is_nothrow_copy_movable<value_type>
inline value_type pull();
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:
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);
inline void pull(value_type& elem, unique_lock<mutex>& )
{
elem = boost::move(super::data_.front());
super::data_.pop_front();
}
inline value_type pull(unique_lock<mutex>& )
{
value_type e = boost::move(super::data_.front());
super::data_.pop_front();
return boost::move(e);
}
inline void push(const value_type& elem, unique_lock<mutex>& lk)
{
super::data_.push_back(elem);
super::notify_not_empty_if_needed(lk);
}
inline void push(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_queue<ValueType, Container>::sync_queue() :
super()
{
}
// template <class ValueType, class Container>
// template <class Range>
// explicit sync_queue<ValueType, Container>::sync_queue(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_queue<ValueType, Container>::~sync_queue()
{
}
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(elem, lk);
return queue_op_status::success;
}
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem, unique_lock<mutex>& lk)
{
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
if (super::empty(lk))
{
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
if (super::closed(lk)) return queue_op_status::closed;
}
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
if (has_been_closed) return queue_op_status::closed;
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
pull(elem, lk);
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
return queue_op_status::success;
}
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(elem, lk);
}
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(elem, lk);
}
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(elem, lk);
}
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);
}
// enable if ValueType is nothrow movable
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 <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push(elem, lk);
return queue_op_status::success;
}
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(elem, 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(elem, lk);
return queue_op_status::success;
}
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(elem, lk);
}
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(elem, lk);
}
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);
}
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push(boost::move(elem), lk);
return queue_op_status::success;
}
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(boost::move(elem), 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(boost::move(elem), lk);
return queue_op_status::success;
}
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(boost::move(elem), lk);
}
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(boost::move(elem), lk);
}
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);
}
template <class ValueType, class Container>
sync_queue<ValueType, Container>& operator<<(sync_queue<ValueType, Container>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
{
sbq.push(boost::move(elem));
return sbq;
}
template <class ValueType, class Container>
sync_queue<ValueType, Container>& operator<<(sync_queue<ValueType, Container>& sbq, ValueType const&elem)
{
sbq.push(elem);
return sbq;
}
template <class ValueType, class Container>
sync_queue<ValueType, Container>& operator>>(sync_queue<ValueType, Container>& sbq, ValueType &elem)
{
sbq.pull(elem);
return sbq;
}
}
using concurrent::sync_queue;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,468 @@
// 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_SYNC_TIMED_QUEUE_HPP
#define BOOST_THREAD_SYNC_TIMED_QUEUE_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/concurrent_queues/sync_priority_queue.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/chrono_io.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <class T, class Clock = chrono::steady_clock>
struct scheduled_type
{
typedef T value_type;
typedef Clock clock;
typedef typename clock::time_point time_point;
T data;
time_point time;
BOOST_THREAD_COPYABLE_AND_MOVABLE(scheduled_type)
scheduled_type(T const& pdata, time_point tp) : data(pdata), time(tp) {}
scheduled_type(BOOST_THREAD_RV_REF(T) pdata, time_point tp) : data(boost::move(pdata)), time(tp) {}
scheduled_type(scheduled_type const& other) : data(other.data), time(other.time) {}
scheduled_type& operator=(BOOST_THREAD_COPY_ASSIGN_REF(scheduled_type) other) {
data = other.data;
time = other.time;
return *this;
}
scheduled_type(BOOST_THREAD_RV_REF(scheduled_type) other) : data(boost::move(other.data)), time(other.time) {}
scheduled_type& operator=(BOOST_THREAD_RV_REF(scheduled_type) other) {
data = boost::move(other.data);
time = other.time;
return *this;
}
bool time_not_reached() const
{
return time > clock::now();
}
bool operator <(const scheduled_type<T> other) const
{
return this->time > other.time;
}
}; //end struct
} //end detail namespace
template <class T, class Clock = chrono::steady_clock>
class sync_timed_queue
: private sync_priority_queue<detail::scheduled_type<T, Clock> >
{
typedef detail::scheduled_type<T, Clock> stype;
typedef sync_priority_queue<stype> super;
public:
typedef T value_type;
typedef Clock clock;
typedef typename clock::duration duration;
typedef typename clock::time_point time_point;
typedef typename super::underlying_queue_type underlying_queue_type;
typedef typename super::size_type size_type;
typedef typename super::op_status op_status;
sync_timed_queue() : super() {};
~sync_timed_queue() {}
using super::size;
using super::empty;
using super::full;
using super::close;
using super::closed;
T pull();
void pull(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);
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);
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);
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>&);
T pull(lock_guard<mutex>&);
void pull(unique_lock<mutex>&, T& elem);
void pull(lock_guard<mutex>&, T& elem);
queue_op_status try_pull(unique_lock<mutex>&, T& elem);
queue_op_status try_pull(lock_guard<mutex>&, T& elem);
queue_op_status wait_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>&);
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>&);
bool empty_or_time_not_reached(lock_guard<mutex>&);
sync_timed_queue(const sync_timed_queue&);
sync_timed_queue& operator=(const sync_timed_queue&);
sync_timed_queue(BOOST_THREAD_RV_REF(sync_timed_queue));
sync_timed_queue& operator=(BOOST_THREAD_RV_REF(sync_timed_queue));
}; //end class
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, 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, 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, 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, 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, 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, class Clock>
bool sync_timed_queue<T, Clock>::time_not_reached(unique_lock<mutex>&)
{
return super::data_.top().time_not_reached();
}
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, class Clock>
bool sync_timed_queue<T, Clock>::wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>& lk)
{
for (;;)
{
if (super::closed(lk)) return true;
while (! super::empty(lk)) {
if (! time_not_reached(lk)) return false;
time_point tp = super::data_.top().time;
super::not_empty_.wait_until(lk, tp);
if (super::closed(lk)) return true;
}
if (super::closed(lk)) return true;
super::not_empty_.wait(lk);
}
//return false;
}
///////////////////////////
template <class T, class Clock>
T sync_timed_queue<T, Clock>::pull_when_time_reached(unique_lock<mutex>& lk)
{
while (time_not_reached(lk))
{
super::throw_if_closed(lk);
time_point tp = super::data_.top().time;
super::not_empty_.wait_until(lk,tp);
super::wait_until_not_empty(lk);
}
return pull(lk);
}
template <class T, class Clock>
template <class Duration>
queue_op_status
sync_timed_queue<T, Clock>::pull_when_time_reached_until(unique_lock<mutex>& lk, chrono::time_point<clock,Duration> const& tp, T& elem)
{
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);
if (cv_status::timeout == super::not_empty_.wait_until(lk, tpmin)) {
if (time_not_reached(lk)) return queue_op_status::not_ready;
return queue_op_status::timeout;
}
}
pull(lk, elem);
return queue_op_status::success;
}
///////////////////////////
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, 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;
return false;
}
///////////////////////////
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);
#else
return super::data_.pull().data;
#endif
}
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);
#else
return super::data_.pull().data;
#endif
}
template <class T, class Clock>
T sync_timed_queue<T, Clock>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull_when_time_reached(lk);
}
///////////////////////////
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);
#else
elem = super::data_.pull().data;
#endif
}
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);
#else
elem = super::data_.pull().data;
#endif
}
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);
elem = pull_when_time_reached(lk);
}
//////////////////////
template <class T, class Clock>
template <class Duration>
queue_op_status
sync_timed_queue<T, Clock>::pull_until(chrono::time_point<clock,Duration> const& tp, T& elem)
{
unique_lock<mutex> lk(super::mtx_);
if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp))
return queue_op_status::timeout;
return pull_when_time_reached_until(lk, tp, elem);
}
//////////////////////
template <class T, class Clock>
template <class Rep, class Period>
queue_op_status
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, class Clock>
queue_op_status sync_timed_queue<T, Clock>::try_pull(unique_lock<mutex>& lk, T& elem)
{
if ( super::empty(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
if ( time_not_reached(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::not_ready;
}
pull(lk, elem);
return queue_op_status::success;
}
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) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
if ( time_not_reached(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::not_ready;
}
pull(lk, elem);
return queue_op_status::success;
}
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, class Clock>
queue_op_status sync_timed_queue<T, Clock>::wait_pull(unique_lock<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
}
bool has_been_closed = wait_until_not_empty_time_reached_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
pull(lk, elem);
return queue_op_status::success;
}
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, class Clock>
// queue_op_status sync_timed_queue<T, Clock>::wait_pull(unique_lock<mutex> &lk, T& elem)
// {
// 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(lk, elem);
// return queue_op_status::success;
// }
// template <class T>
// 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, 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;
return try_pull(lk, elem);
}
} //end concurrent namespace
using concurrent::sync_timed_queue;
} //end boost namespace
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -10,8 +10,16 @@
#define BOOST_CSBL_DEQUE_HPP
#include <boost/config.hpp>
#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_HDR_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES
// 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_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,102 @@
// 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 csbl::vector<T> vector_type;
vector_type 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)
#if defined BOOST_THREAD_USES_BOOST_VECTOR
BOOST_NOEXCEPT_IF(vector_type::allocator_traits_type::propagate_on_container_move_assignment::value)
#endif
{
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

@@ -15,97 +15,13 @@
// default_delete
#if defined BOOST_NO_CXX11_SMART_PTR
#include <boost/thread/csbl/memory/pointer_traits.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
#include <boost/move/unique_ptr.hpp>
namespace boost
{
namespace csbl
{
namespace detail
{
template <class _Ptr1, class _Ptr2,
bool = is_same<typename remove_cv<typename pointer_traits<_Ptr1>::element_type>::type,
typename remove_cv<typename pointer_traits<_Ptr2>::element_type>::type
>::value
>
struct same_or_less_cv_qualified_imp
: is_convertible<_Ptr1, _Ptr2>
{};
template <class _Ptr1, class _Ptr2>
struct same_or_less_cv_qualified_imp<_Ptr1, _Ptr2, false>
: false_type
{};
template <class _Ptr1, class _Ptr2, bool = is_scalar<_Ptr1>::value &&
!is_pointer<_Ptr1>::value>
struct same_or_less_cv_qualified
: same_or_less_cv_qualified_imp<_Ptr1, _Ptr2>
{};
template <class _Ptr1, class _Ptr2>
struct same_or_less_cv_qualified<_Ptr1, _Ptr2, true>
: false_type
{};
}
template <class T>
struct BOOST_SYMBOL_VISIBLE default_delete
{
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() = default;
#else
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT
{}
#endif
template <class U>
BOOST_SYMBOL_VISIBLE
default_delete(const default_delete<U>&,
typename enable_if<is_convertible<U*, T*> >::type* = 0) BOOST_NOEXCEPT
{}
BOOST_SYMBOL_VISIBLE
void operator() (T* ptr) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
delete ptr;
}
};
template <class T>
struct BOOST_SYMBOL_VISIBLE default_delete<T[]>
{
public:
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() = default;
#else
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT
{}
#endif
template <class U>
BOOST_SYMBOL_VISIBLE
default_delete(const default_delete<U[]>&,
typename enable_if<detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) BOOST_NOEXCEPT
{}
template <class U>
BOOST_SYMBOL_VISIBLE
void operator() (U* ptr,
typename enable_if<detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
delete [] ptr;
}
};
using ::boost::movelib::default_delete;
}
}
#else

View File

@@ -0,0 +1,42 @@
// 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)
//
// 2014/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_SHARED_PTR_HPP
#define BOOST_CSBL_MEMORY_SHARED_PTR_HPP
#include <boost/thread/csbl/memory/config.hpp>
#if defined BOOST_NO_CXX11_SMART_PTR
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
namespace boost
{
namespace csbl
{
using ::boost::shared_ptr;
using ::boost::make_shared;
}
}
#else
#include <boost/shared_ptr.hpp>
namespace boost
{
namespace csbl
{
using std::shared_ptr;
using std::make_shared;
}
}
#endif
#endif // header

View File

@@ -1,106 +1,28 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
// Copyright (C) 2013-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)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
// Creation using interprocess::unique_ptr.
// 2014/09 Vicente J. Botet Escriba
// Adaptation to movelib::unique_ptr
#ifndef BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
#define BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
#include <boost/thread/csbl/memory/config.hpp>
// 20.8.1 class template unique_ptr:
#if defined BOOST_NO_CXX11_SMART_PTR
#include <boost/thread/csbl/memory/default_delete.hpp>
#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/move/make_unique.hpp>
namespace boost
{
namespace csbl
{
template <class T, class D = default_delete<T> > class unique_ptr :
public ::boost::interprocess::unique_ptr<T,D>
{
typedef ::boost::interprocess::unique_ptr<T,D> base_type;
BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr)
protected:
//typedef typename base_type::nat nat;
//typedef typename base_type::nullptr_t nullptr_t;
struct nat {int for_bool;};
struct nat2 {int for_nullptr;};
typedef int nat2::*nullptr_t;
using ::boost::movelib::unique_ptr;
using ::boost::movelib::make_unique;
public:
typedef typename base_type::element_type element_type;
typedef typename base_type::deleter_type deleter_type;
typedef typename base_type::pointer pointer;
unique_ptr() : base_type()
{}
explicit unique_ptr(pointer p): base_type(p)
{}
unique_ptr(pointer p
,typename interprocess::ipcdetail::if_<interprocess::ipcdetail::is_reference<D>
,D
,typename interprocess::ipcdetail::add_reference<const D>::type>::type d)
: base_type(p, d)
{}
unique_ptr(BOOST_RV_REF(unique_ptr) u)
: base_type(boost::move(static_cast<base_type&>(u)))
{}
template <class U, class E>
unique_ptr(BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u,
typename interprocess::ipcdetail::enable_if_c<
interprocess::ipcdetail::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
interprocess::ipcdetail::is_convertible<E, D>::value &&
(
!interprocess::ipcdetail::is_reference<D>::value ||
interprocess::ipcdetail::is_same<D, E>::value
)
,
nat
>::type = nat())
: base_type(boost::move(static_cast< ::boost::interprocess::unique_ptr<U,E>&>(u)))
{}
unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u)
{
this->base_type::operator=(boost::move(static_cast<base_type&>(u)));
return *this;
}
template <class U, class E>
unique_ptr& operator=(BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u)
{
this->base_type::template operator=<U,E>(boost::move(static_cast< ::boost::interprocess::unique_ptr<U,E>&>(u)));
return *this;
}
unique_ptr& operator=(nullptr_t t)
{
this->base_type::operator=(t);
return *this;
}
void swap(unique_ptr& u)
{
this->base_type::swap(u);
}
};
template <class T, class D>
class unique_ptr<T[], D> :
public ::boost::interprocess::unique_ptr<T[],D>
{
};
}
}
#else
namespace boost
{
namespace csbl
{
using ::std::unique_ptr;
}
}
#endif // BOOST_NO_CXX11_SMART_PTR
#endif // header

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

@@ -28,10 +28,14 @@ namespace boost
#if defined BOOST_THREAD_USES_BOOST_TUPLE
using ::boost::tuple;
using ::boost::get;
using ::boost::make_tuple;
//using ::boost::tuple_size;
#else
// 20.4.2, class template tuple:
using ::std::tuple;
using ::std::get;
using ::std::make_tuple;
using ::std::tuple_size;
// 20.4.2.4, tuple creation functions:
// 20.4.2.5, tuple helper classes:
// 20.4.2.6, element access:

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

@@ -12,19 +12,19 @@
#include <boost/detail/workaround.hpp>
#include <boost/thread/detail/platform.hpp>
//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
// ATTRIBUTE_MAY_ALIAS
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
//#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
#if !defined(BOOST_NO_MAY_ALIAS)
// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
// regard to violation of the strict aliasing rules.
// GCC since 3.3 and some other compilers have may_alias attribute that helps
// to alleviate optimizer issues with regard to violation of the strict aliasing rules.
#define BOOST_THREAD_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__))
#else
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS
#endif
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS BOOST_MAY_ALIAS
#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
@@ -100,8 +100,8 @@
#if !defined BOOST_THREAD_VERSION
#define BOOST_THREAD_VERSION 2
#else
#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3 && BOOST_THREAD_VERSION!=4
#error "BOOST_THREAD_VERSION must be 2, 3 or 4"
#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3 && BOOST_THREAD_VERSION!=4 && BOOST_THREAD_VERSION!=5
#error "BOOST_THREAD_VERSION must be 2, 3, 4 or 5"
#endif
#endif
@@ -239,7 +239,6 @@
! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
! defined(BOOST_NO_CXX11_DECLTYPE) && \
! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
! defined(BOOST_THREAD_NO_CXX11_DECLTYPE_N3276) && \
! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
! defined(BOOST_NO_CXX11_HDR_TUPLE)
@@ -305,6 +304,13 @@
#endif // BOOST_THREAD_VERSION>=4
#if BOOST_THREAD_VERSION>=5
//#define BOOST_THREAD_FUTURE_BLOCKING
#else
//#define BOOST_THREAD_FUTURE_BLOCKING
#define BOOST_THREAD_ASYNC_FUTURE_WAITS
#endif
// INTERRUPTIONS
#if ! defined BOOST_THREAD_PROVIDES_INTERRUPTIONS \
&& ! defined BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
@@ -354,6 +360,12 @@
#endif
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_THREAD_USES_MOVE
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_FUTURE_USES_OPTIONAL
#endif
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
# pragma warn -8008 // Condition always true/false
# pragma warn -8080 // Identifier declared but never used

View File

@@ -16,7 +16,7 @@
* makes it private.
*/
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
#if ! defined BOOST_NO_CXX11_DELETED_FUNCTIONS && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
CLASS(CLASS const&) = delete; \

View File

@@ -47,7 +47,7 @@ namespace boost
void call()
{
f();
if (impl) f();
}
};
public:

View File

@@ -47,7 +47,6 @@ namespace boost
#if ! defined(BOOST_NO_SFINAE_EXPR) && \
! defined(BOOST_NO_CXX11_DECLTYPE) && \
! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
! defined(BOOST_THREAD_NO_CXX11_DECLTYPE_N3276) && \
! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
#define BOOST_THREAD_PROVIDES_INVOKE
@@ -339,7 +338,6 @@ namespace boost
! defined BOOST_NO_CXX11_HDR_FUNCTIONAL && \
defined BOOST_MSVC
//#error
template <class Ret, class Fp>
inline
Ret invoke(BOOST_THREAD_RV_REF(Fp) f)

View File

@@ -20,8 +20,8 @@
// The invoker code is based on the one from libcxx.
//===----------------------------------------------------------------------===//
#ifndef BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP
#define BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP
#ifndef BOOST_THREAD_DETAIL_INVOKER_HPP
#define BOOST_THREAD_DETAIL_INVOKER_HPP
#include <boost/config.hpp>
@@ -51,7 +51,7 @@ namespace boost
csbl::tuple<Fp, Args...> f_;
public:
BOOST_THREAD_MOVABLE_ONLY( invoker)
BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker)
//typedef typename invoke_of<_Fp, _Args...>::type Rp;
typedef typename result_of<Fp(Args...)>::type result_type;
@@ -65,6 +65,30 @@ namespace boost
invoker(BOOST_THREAD_RV_REF(invoker) f) : f_(boost::move(BOOST_THREAD_RV(f).f_))
{}
BOOST_SYMBOL_VISIBLE
invoker( const invoker& f) : f_(f.f_)
{}
BOOST_SYMBOL_VISIBLE
invoker& operator=(BOOST_THREAD_RV_REF(invoker) f)
{
if (this != &f)
{
f_ = boost::move(BOOST_THREAD_RV(f).f_);
}
return *this;
}
BOOST_SYMBOL_VISIBLE
invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f)
{
if (this != &f)
{
f_ = f.f_;
}
return *this;
}
result_type operator()()
{
typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
@@ -75,7 +99,7 @@ namespace boost
result_type
execute(tuple_indices<Indices...>)
{
return invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
return detail::invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
}
};
@@ -89,7 +113,7 @@ namespace boost
csbl::tuple<Fp, Args...> f_;
public:
BOOST_THREAD_MOVABLE_ONLY( invoker_ret)
BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker_ret)
typedef R result_type;
template <class F, class ... As>
@@ -112,13 +136,13 @@ namespace boost
result_type
execute(tuple_indices<Indices...>)
{
return invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
return detail::invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
}
};
//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)
@@ -147,7 +171,7 @@ namespace boost
Fp fp_; \
BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
public: \
BOOST_THREAD_MOVABLE_ONLY(invoker) \
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
\
template <class F BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
@@ -160,13 +184,13 @@ namespace boost
{} \
\
BOOST_SYMBOL_VISIBLE \
invoker(BOOST_THREAD_FWD_REF(invoker) x) \
invoker(BOOST_THREAD_RV_REF(invoker) x) \
: fp_(boost::move(x.fp_)) \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
{} \
\
result_type operator()() { \
return invoke(boost::move(fp_) \
return detail::invoke(boost::move(fp_) \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \
); \
} \
@@ -179,7 +203,7 @@ namespace boost
Fp fp_; \
BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
public: \
BOOST_THREAD_MOVABLE_ONLY(invoker) \
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
\
template <class R2 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
@@ -192,7 +216,7 @@ namespace boost
{} \
\
BOOST_SYMBOL_VISIBLE \
invoker(BOOST_THREAD_FWD_REF(invoker) x) \
invoker(BOOST_THREAD_RV_REF(invoker) x) \
: fp_(x.fp_) \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
{} \
@@ -248,7 +272,7 @@ namespace boost
//::boost::tuple<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8> f_;
public:
BOOST_THREAD_MOVABLE_ONLY(invoker)
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7, T8)>::type result_type;
BOOST_SYMBOL_VISIBLE
@@ -276,7 +300,7 @@ namespace boost
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_FWD_REF(invoker) f)
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
@@ -291,7 +315,7 @@ namespace boost
result_type operator()()
{
return invoke(boost::move(fp_)
return detail::invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -317,7 +341,7 @@ namespace boost
T6 v6_;
T7 v7_;
public:
BOOST_THREAD_MOVABLE_ONLY(invoker)
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7)>::type result_type;
BOOST_SYMBOL_VISIBLE
@@ -343,7 +367,7 @@ namespace boost
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_FWD_REF(invoker) f)
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
@@ -357,7 +381,7 @@ namespace boost
result_type operator()()
{
return invoke(boost::move(fp_)
return detail::invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -381,7 +405,7 @@ namespace boost
T5 v5_;
T6 v6_;
public:
BOOST_THREAD_MOVABLE_ONLY(invoker)
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6)>::type result_type;
BOOST_SYMBOL_VISIBLE
@@ -405,7 +429,7 @@ namespace boost
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_FWD_REF(invoker) f)
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
@@ -418,7 +442,7 @@ namespace boost
result_type operator()()
{
return invoke(boost::move(fp_)
return detail::invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -440,7 +464,7 @@ namespace boost
T4 v4_;
T5 v5_;
public:
BOOST_THREAD_MOVABLE_ONLY(invoker)
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5)>::type result_type;
BOOST_SYMBOL_VISIBLE
@@ -462,7 +486,7 @@ namespace boost
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_FWD_REF(invoker) f)
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
@@ -474,7 +498,7 @@ namespace boost
result_type operator()()
{
return invoke(boost::move(fp_)
return detail::invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -494,7 +518,7 @@ namespace boost
T3 v3_;
T4 v4_;
public:
BOOST_THREAD_MOVABLE_ONLY(invoker)
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4)>::type result_type;
BOOST_SYMBOL_VISIBLE
@@ -514,7 +538,7 @@ namespace boost
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_FWD_REF(invoker) f)
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
@@ -525,7 +549,7 @@ namespace boost
result_type operator()()
{
return invoke(boost::move(fp_)
return detail::invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -543,7 +567,7 @@ namespace boost
T2 v2_;
T3 v3_;
public:
BOOST_THREAD_MOVABLE_ONLY(invoker)
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3)>::type result_type;
BOOST_SYMBOL_VISIBLE
@@ -561,7 +585,7 @@ namespace boost
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_FWD_REF(invoker) f)
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
@@ -571,7 +595,7 @@ namespace boost
result_type operator()()
{
return invoke(boost::move(fp_)
return detail::invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -587,7 +611,7 @@ namespace boost
T1 v1_;
T2 v2_;
public:
BOOST_THREAD_MOVABLE_ONLY(invoker)
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2)>::type result_type;
BOOST_SYMBOL_VISIBLE
@@ -603,7 +627,7 @@ namespace boost
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_FWD_REF(invoker) f)
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
@@ -612,7 +636,7 @@ namespace boost
result_type operator()()
{
return invoke(boost::move(fp_)
return detail::invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
@@ -626,7 +650,7 @@ namespace boost
T0 v0_;
T1 v1_;
public:
BOOST_THREAD_MOVABLE_ONLY(invoker)
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1)>::type result_type;
BOOST_SYMBOL_VISIBLE
@@ -640,7 +664,7 @@ namespace boost
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_FWD_REF(invoker) f)
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
@@ -648,7 +672,7 @@ namespace boost
result_type operator()()
{
return invoke(boost::move(fp_)
return detail::invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
);
@@ -660,7 +684,7 @@ namespace boost
Fp fp_;
T0 v0_;
public:
BOOST_THREAD_MOVABLE_ONLY(invoker)
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0)>::type result_type;
BOOST_SYMBOL_VISIBLE
@@ -672,14 +696,14 @@ namespace boost
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_FWD_REF(invoker) f)
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
return detail::invoke(boost::move(fp_)
, boost::move(v0_)
);
}
@@ -697,7 +721,7 @@ namespace boost
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_FWD_REF(invoker) f)
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(f.fp_))
{}
result_type operator()()
@@ -719,7 +743,7 @@ namespace boost
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_FWD_REF(invoker) f)
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(f.fp_)
{}
result_type operator()()

View File

@@ -80,6 +80,7 @@ namespace boost
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
@@ -93,6 +94,11 @@ namespace boost
template <typename T> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
namespace detail { \
template <typename T1, typename T2> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, false> \
{}; \
@@ -100,6 +106,7 @@ namespace boost
#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_MSVC
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
@@ -113,6 +120,11 @@ namespace boost
template <typename T> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
namespace detail { \
template <typename T1, typename T2> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, false> \
{}; \
@@ -121,6 +133,7 @@ namespace boost
#else
#if defined BOOST_THREAD_USES_MOVE
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
@@ -133,6 +146,11 @@ namespace boost
template <typename T> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
namespace detail { \
template <typename T1, typename T2> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, false> \
{}; \
@@ -140,6 +158,7 @@ namespace boost
#else
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) const TYPE&
#define BOOST_THREAD_RV_REF(TYPE) boost::detail::thread_move_t< TYPE >
#define BOOST_THREAD_RV_REF_BEG boost::detail::thread_move_t<
#define BOOST_THREAD_RV_REF_END >
@@ -157,6 +176,10 @@ struct enable_move_utility_emulation< TYPE > \
template <typename T> \
struct enable_move_utility_emulation<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
template <typename T1, typename T2> \
struct enable_move_utility_emulation<
#define BOOST_THREAD_DCL_MOVABLE_END > \
{ \
static const bool value = false; \
@@ -198,6 +221,8 @@ namespace detail
#define BOOST_THREAD_MOVABLE(TYPE)
#define BOOST_THREAD_COPYABLE(TYPE)
#else
#if defined BOOST_THREAD_USES_MOVE
@@ -220,6 +245,11 @@ namespace detail
return *static_cast<const ::boost::rv<TYPE>* >(this); \
}\
#define BOOST_THREAD_COPYABLE(TYPE) \
TYPE& operator=(TYPE &t)\
{ this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}
#else
#define BOOST_THREAD_MOVABLE(TYPE) \
@@ -233,15 +263,20 @@ namespace detail
return x; \
} \
#define BOOST_THREAD_COPYABLE(TYPE)
#endif
#endif
#define BOOST_THREAD_MOVABLE_ONLY(TYPE) \
BOOST_THREAD_NO_COPYABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
typedef int boost_move_no_copy_constructor_or_assign; \
#define BOOST_THREAD_COPYABLE_AND_MOVABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
BOOST_THREAD_COPYABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
@@ -249,6 +284,31 @@ namespace boost
{
namespace thread_detail
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#elif defined BOOST_THREAD_USES_MOVE
template <class T>
struct is_rv
: ::boost::move_detail::is_rv<T>
{};
#else
template <class T>
struct is_rv
: ::boost::integral_constant<bool, false>
{};
template <class T>
struct is_rv< ::boost::detail::thread_move_t<T> >
: ::boost::integral_constant<bool, true>
{};
template <class T>
struct is_rv< const ::boost::detail::thread_move_t<T> >
: ::boost::integral_constant<bool, true>
{};
#endif
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class Tp>
struct remove_reference : boost::remove_reference<Tp> {};

View File

@@ -13,7 +13,7 @@
#include <boost/config.hpp>
#include <boost/thread/detail/memory.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/thread/csbl/memory/shared_ptr.hpp>
#include <boost/type_traits/decay.hpp>
namespace boost
@@ -33,7 +33,7 @@ namespace boost
{
}
};
shared_ptr<impl_base> impl;
csbl::shared_ptr<impl_base> impl;
template <typename F>
struct impl_type: impl_base
{
@@ -64,7 +64,7 @@ namespace boost
}
};
public:
BOOST_THREAD_MOVABLE(nullary_function)
BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
explicit nullary_function(void (*f)()):
impl(new impl_type_ptr(f))
@@ -90,29 +90,39 @@ namespace boost
{
}
nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
#if defined BOOST_NO_CXX11_SMART_PTR
impl(BOOST_THREAD_RV(other).impl)
{
BOOST_THREAD_RV(other).impl.reset();
}
#else
impl(boost::move(other.impl))
{
}
#endif
~nullary_function()
{
}
nullary_function& operator=(nullary_function const& other) BOOST_NOEXCEPT
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
{
impl=other.impl;
return *this;
}
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
{
#if defined BOOST_NO_CXX11_SMART_PTR
impl=BOOST_THREAD_RV(other).impl;
BOOST_THREAD_RV(other).impl.reset();
#else
impl = boost::move(other.impl);
#endif
return *this;
}
void operator()()
{ impl->call();}
{ if (impl) impl->call();}
};
@@ -126,7 +136,7 @@ namespace boost
{
}
};
shared_ptr<impl_base> impl;
csbl::shared_ptr<impl_base> impl;
template <typename F>
struct impl_type: impl_base
{
@@ -158,7 +168,7 @@ namespace boost
}
};
public:
BOOST_THREAD_MOVABLE(nullary_function)
BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
nullary_function(R (*f)()):
impl(new impl_type_ptr(f))
@@ -179,10 +189,16 @@ namespace boost
{
}
nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
#if defined BOOST_NO_CXX11_SMART_PTR
impl(BOOST_THREAD_RV(other).impl)
{
BOOST_THREAD_RV(other).impl.reset();
}
#else
impl(boost::move(other.impl))
{
}
#endif
nullary_function()
: impl()
{
@@ -191,23 +207,28 @@ namespace boost
{
}
nullary_function& operator=(nullary_function const& other) BOOST_NOEXCEPT
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
{
impl=other.impl;
return *this;
}
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
{
#if defined BOOST_NO_CXX11_SMART_PTR
impl=BOOST_THREAD_RV(other).impl;
BOOST_THREAD_RV(other).impl.reset();
#else
impl = boost::move(other.impl);
#endif
return *this;
}
R operator()()
{ return impl->call();}
{ if (impl) return impl->call(); else return R();}
};
}
BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
}
#endif // header

View File

@@ -7,6 +7,7 @@
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/predef/platform.h>
#include <boost/thread/exceptions.hpp>
#ifndef BOOST_NO_IOSTREAM
@@ -71,7 +72,7 @@ namespace boost
void run2(tuple_indices<Indices...>)
{
invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...);
detail::invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...);
}
void run()
{
@@ -154,7 +155,15 @@ namespace boost
};
#endif
}
namespace thread_detail {
#ifdef BOOST_THREAD_USES_CHRONO
#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC)
typedef chrono::steady_clock internal_clock_t;
#else
typedef chrono::system_clock internal_clock_t;
#endif
#endif
}
class BOOST_THREAD_DECL thread
{
public:
@@ -172,7 +181,6 @@ namespace boost
private:
bool start_thread_noexcept();
bool start_thread_noexcept(const attributes& attr);
//public:
void start_thread()
{
if (!start_thread_noexcept())
@@ -291,7 +299,8 @@ namespace boost
template <class F>
explicit thread(F f
, typename disable_if_c<
boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
boost::thread_detail::is_rv<F>::value // todo as a thread_detail::is_rv
//boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
//|| is_same<typename decay<F>::type, thread>::value
, dummy* >::type=0
):
@@ -301,7 +310,8 @@ namespace boost
}
template <class F>
thread(attributes const& attrs, F f
, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
, typename disable_if<boost::thread_detail::is_rv<F>, dummy* >::type=0
//, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
):
thread_info(make_thread_info(f))
{
@@ -352,6 +362,8 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
if (joinable()) std::terminate();
#else
detach();
#endif
thread_info=BOOST_THREAD_RV(other).thread_info;
BOOST_THREAD_RV(other).thread_info.reset();
@@ -478,13 +490,14 @@ namespace boost
return try_join_until(chrono::steady_clock::now() + rel_time);
}
#endif
template <class Clock, class Duration>
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
bool joined= false;
do {
thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_clock_t::now();
typename Clock::duration d = ceil<nanoseconds>(t-Clock::now());
if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached
joined = try_join_until(s_now + d);
@@ -492,10 +505,10 @@ namespace boost
return true;
}
template <class Duration>
bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t)
bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
typedef time_point<thread_detail::internal_clock_t, nanoseconds> nano_sys_tmpt;
return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
#endif
@@ -510,7 +523,7 @@ namespace boost
//}
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, chrono::nanoseconds>& tp)
{
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
return do_try_join_until(rel_time.count());
@@ -531,7 +544,7 @@ namespace boost
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, chrono::nanoseconds>& tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();

View File

@@ -6,6 +6,7 @@
// (C) Copyright 2007-9 Anthony Williams
#include <list>
#include <boost/thread/csbl/memory/unique_ptr.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/lock_guard.hpp>
@@ -75,7 +76,7 @@ namespace boost
thread* create_thread(F threadfunc)
{
boost::lock_guard<shared_mutex> guard(m);
std::auto_ptr<thread> new_thread(new thread(threadfunc));
boost::csbl::unique_ptr<thread> new_thread(new thread(threadfunc));
threads.push_back(new_thread.get());
return new_thread.release();
}

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

@@ -40,19 +40,19 @@ namespace boost
typedef system::system_error base_type;
public:
thread_exception()
: base_type(0,system::system_category())
: base_type(0,system::generic_category())
{}
thread_exception(int sys_error_code)
: base_type(sys_error_code, system::system_category())
: base_type(sys_error_code, system::generic_category())
{}
thread_exception( int ev, const char * what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
: base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
thread_exception( int ev, const std::string & what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
: base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
@@ -74,18 +74,18 @@ namespace boost
typedef system::system_error base_type;
public:
condition_error()
: base_type(system::error_code(0, system::system_category()), "Condition error")
: base_type(system::error_code(0, system::generic_category()), "Condition error")
{}
condition_error( int ev )
: base_type(system::error_code(ev, system::system_category()), "Condition error")
: base_type(system::error_code(ev, system::generic_category()), "Condition error")
{
}
condition_error( int ev, const char * what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
: base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
condition_error( int ev, const std::string & what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
: base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
};

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
// Copyright (C) 2013-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)
@@ -13,8 +13,8 @@
#include <boost/thread/detail/config.hpp>
#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/thread.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/csbl/vector.hpp>
@@ -30,15 +30,14 @@ namespace executors
/// type-erasure to store the works to do
typedef executors::work work;
private:
/// the kind of stored threads are scoped threads to ensure that the threads are joined.
typedef thread thread_t;
/// A move aware vector type
typedef scoped_thread<> thread_t;
typedef csbl::vector<thread_t> thread_vector;
/// the thread safe work queue
sync_queue<work > work_queue;
/// A move aware vector
thread_vector threads;
/// the thread safe work queue
concurrent::sync_queue<work > work_queue;
public:
/**
@@ -48,23 +47,20 @@ namespace executors
*/
bool try_executing_one()
{
work task;
try
{
if (work_queue.try_pull_front(task) == queue_op_status::success)
work task;
if (work_queue.try_pull(task) == queue_op_status::success)
{
task();
return true;
}
return false;
}
catch (std::exception& )
{
return false;
}
catch (...)
{
return false;
std::terminate();
//return false;
}
}
/**
@@ -85,12 +81,29 @@ namespace executors
*/
void worker_thread()
{
while (!closed())
try
{
schedule_one_or_yield();
for(;;)
{
work task;
try
{
queue_op_status st = work_queue.wait_pull(task);
if (st == queue_op_status::closed) {
return;
}
task();
}
catch (boost::thread_interrupted&)
{
return;
}
}
}
while (try_executing_one())
catch (...)
{
std::terminate();
return;
}
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -98,37 +111,19 @@ namespace executors
void worker_thread1(AtThreadEntry& at_thread_entry)
{
at_thread_entry(*this);
while (!closed())
{
schedule_one_or_yield();
}
while (try_executing_one())
{
}
worker_thread();
}
#endif
void worker_thread2(void(*at_thread_entry)(basic_thread_pool&))
{
at_thread_entry(*this);
while (!closed())
{
schedule_one_or_yield();
}
while (try_executing_one())
{
}
worker_thread();
}
template <class AtThreadEntry>
void worker_thread3(BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry)
{
at_thread_entry(*this);
while (!closed())
{
schedule_one_or_yield();
}
while (try_executing_one())
{
}
worker_thread();
}
static void do_nothing_at_thread_entry(basic_thread_pool&) {}
@@ -141,7 +136,7 @@ namespace executors
*
* \b Throws: Whatever exception is thrown while initializing the needed resources.
*/
basic_thread_pool(unsigned const thread_count = thread::hardware_concurrency())
basic_thread_pool(unsigned const thread_count = thread::hardware_concurrency()+1)
{
try
{
@@ -235,7 +230,20 @@ namespace executors
{
// signal to all the worker threads that there will be no more submissions.
close();
// joins all the threads as the threads were scoped_threads
// joins all the threads before destroying the thread pool resources (e.g. the queue).
join();
}
/**
* \b Effects: join all the threads.
*/
void join()
{
for (unsigned i = 0; i < threads.size(); ++i)
{
threads[i].interrupt();
threads[i].join();
}
}
/**
@@ -266,38 +274,30 @@ namespace executors
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure) {
work_queue.push(boost::move(closure));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
//work w ((closure));
//work_queue.push_back(boost::move(w));
work_queue.push_back(work(closure)); // todo check why this doesn't work
submit(work(closure));
}
#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
submit(work(closure));
}
#if 0
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
}
#else
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
work_queue.push_back(work(boost::forward<Closure>(closure)));
//submit(work(boost::forward<Closure>(closure)));
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
#endif
/**
* \b Requires: This must be called from an scheduled task.
*

View File

@@ -0,0 +1,83 @@
// 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(;;)
{
try {
work task;
queue_op_status st = _workq.wait_pull(task);
if (st == queue_op_status::closed) return;
task();
}
catch (boost::thread_interrupted&)
{
return;
}
}
}
catch (...)
{
std::terminate();
return;
}
}
}; //end class
} //end detail namespace
} //end executors namespace
} //end boost namespace
#endif

View File

@@ -0,0 +1,66 @@
// Copyright (C) 2014 Ian Forbed
// 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 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/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
namespace detail
{
template <class Clock=chrono::steady_clock>
class scheduled_executor_base : public priority_executor_base<concurrent::sync_timed_queue<executors::work_pq, Clock > >
{
public:
typedef executors::work_pq work;
typedef Clock clock;
typedef typename clock::duration duration;
typedef typename clock::time_point time_point;
protected:
scheduled_executor_base() {}
public:
~scheduled_executor_base()
{
if(! this->closed())
{
this->close();
}
}
void submit_at(work w, const time_point& tp)
{
this->_workq.push(boost::move(w), tp);
}
void submit_after(work w, const duration& dura)
{
this->_workq.push(boost::move(w), dura+clock::now());
}
}; //end class
} //end detail namespace
} //end executors namespace
} //end boost namespace
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -32,43 +32,55 @@ namespace boost
executor() {}
/**
* \b Effects: Destroys the executor.
* \par Effects
* Destroys the executor.
*
* \b Synchronization: The completion of all the closures happen before the completion of the executor destructor.
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
virtual ~executor() {};
virtual ~executor() {}
/**
* \b Effects: close the \c executor for submissions.
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
virtual void close() = 0;
/**
* \b Returns: whether the pool is closed for submissions.
* \par Returns
* Whether the pool is closed for submissions.
*/
virtual bool closed() = 0;
/**
* \b Effects: The specified closure will be scheduled for execution at some point in the future.
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
* \par Synchronization
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
virtual void submit(BOOST_THREAD_RV_REF(work) closure) = 0;
// virtual void submit(work& closure) = 0;
/**
* \b Requires: \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
* \par Requires
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
*
* \b Effects: The specified closure will be scheduled for execution at some point in the future.
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
*
* \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
* \par Synchronization
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
@@ -87,23 +99,31 @@ namespace boost
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
work w = boost::move(closure);
//submit(work(boost::forward<Closure>(closure)));
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
virtual bool try_executing_one() = 0;
/**
* \b Requires: This must be called from an scheduled task.
* \par Requires
* This must be called from an scheduled task.
*
* \b Effects: reschedule functions until pred()
* \par Effects
* Reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
@@ -119,7 +139,6 @@ namespace boost
}
};
}
using executors::executor;
}

View File

@@ -97,39 +97,27 @@ namespace executors
*/
void submit(BOOST_THREAD_RV_REF(work) closure) {
return ex.submit(boost::move(closure));
//return ex.submit(boost::forward<work>(closure));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work w ((closure));
submit(boost::move(w));
//submit(work(closure));
submit(work(closure));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
submit(boost::move(w));
//submit(work(closure));
submit(work(closure));
}
#if 0
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work w =boost::move(closure);
submit(boost::move(w));
}
#else
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
submit(work(boost::forward<Closure>(closure)));
//submit(work(boost::forward<Closure>(closure)));
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
#endif
/**
* Effects: try to execute one task.

View File

@@ -0,0 +1,213 @@
// 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_GENERIC_EXECUTOR_REF_HPP
#define BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
template <class Executor>
class executor_ref : public executor
{
Executor& ex;
public:
/// type-erasure to store the works to do
typedef executors::work work;
/// executor is not copyable.
BOOST_THREAD_NO_COPYABLE(executor_ref)
executor_ref(Executor& ex_) : ex(ex_) {}
/**
* \par Effects
* Destroys the executor.
*
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
~executor_ref() {}
/**
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close() { ex.close(); }
/**
* \par Returns
* Whether the pool is closed for submissions.
*/
bool closed() { return ex.closed(); }
/**
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure) {
ex.submit(boost::move(closure));
}
// void submit(work& closure) {
// ex.submit(closure);
// }
/**
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one() { return ex.try_executing_one(); }
};
class generic_executor_ref
{
shared_ptr<executor> ex;
public:
/// type-erasure to store the works to do
typedef executors::work work;
template<typename Executor>
generic_executor_ref(Executor& ex_)
//: ex(make_shared<executor_ref<Executor> >(ex_)) // todo check why this doesn't works with C++03
: ex( new executor_ref<Executor>(ex_) )
{
}
//generic_executor_ref(generic_executor_ref const& other) noexcept {}
//generic_executor_ref& operator=(generic_executor_ref const& other) noexcept {}
/**
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close() { ex->close(); }
/**
* \par Returns
* Whether the pool is closed for submissions.
*/
bool closed() { return ex->closed(); }
/**
* \par Requires
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
*
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure)
{
ex->submit(boost::move(closure));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
//work w ((closure));
//submit(boost::move(w));
submit(work(closure));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
submit(boost::move(w));
//submit(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
// size_t num_pending_closures() const
// {
// return ex->num_pending_closures();
// }
/**
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one() { return ex->try_executing_one(); }
/**
* \par Requires
* This must be called from an scheduled task.
*
* \par Effects
* reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
{
do {
//schedule_one_or_yield();
if ( ! try_executing_one())
{
return false;
}
} while (! pred());
return true;
}
};
}
using executors::executor_ref;
using executors::generic_executor_ref;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -26,6 +26,7 @@ namespace executors
/// type-erasure to store the works to do
typedef executors::work work;
bool closed_;
mutable mutex mtx_;
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
@@ -66,16 +67,22 @@ namespace executors
*/
void close()
{
lock_guard<mutex> lk(mtx_);
closed_ = true;
}
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed()
bool closed(lock_guard<mutex>& )
{
return closed_;
}
bool closed()
{
lock_guard<mutex> lk(mtx_);
return closed(lk);
}
/**
* \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
@@ -93,21 +100,54 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
if (closed()) return;
closure();
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
try
{
closure();
}
catch (...)
{
std::terminate();
return;
}
}
#endif
void submit(void (*closure)())
{
if (closed()) return;
closure();
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
try
{
closure();
}
catch (...)
{
std::terminate();
return;
}
}
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
if (closed()) return;
closure();
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
try
{
closure();
}
catch (...)
{
std::terminate();
return;
}
}
/**

View File

@@ -14,8 +14,9 @@
#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/assert.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -31,7 +32,7 @@ namespace executors
typedef executors::work work;
private:
/// the thread safe work queue
sync_queue<work > work_queue;
concurrent::sync_queue<work > work_queue;
public:
/**
@@ -40,51 +41,39 @@ namespace executors
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one()
{
return execute_one(/*wait:*/false);
}
private:
/**
* Effects: Execute one task.
* Remark: If wait is true, waits until a task is available or the executor
* is closed. If wait is false, returns false immediately if no
* task is available.
* Returns: whether a task has been executed (if wait is true, only returns false if closed).
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool execute_one(bool wait)
{
work task;
try
{
if (work_queue.try_pull_front(task) == queue_op_status::success)
queue_op_status status = wait ?
work_queue.wait_pull(task) :
work_queue.try_pull(task);
if (status == queue_op_status::success)
{
task();
return true;
}
return false;
}
catch (std::exception& )
{
BOOST_ASSERT(!wait || status == queue_op_status::closed);
return false;
}
catch (...)
{
return false;
}
}
private:
/**
* Effects: schedule one task or yields
* Throws: whatever the current task constructor throws or the task() throws.
*/
void schedule_one_or_yield()
{
if ( ! try_executing_one())
{
this_thread::yield();
}
}
/**
* The main loop of the worker thread
*/
void worker_thread()
{
while (!closed())
{
schedule_one_or_yield();
}
while (try_executing_one())
{
std::terminate();
//return false;
}
}
@@ -112,9 +101,19 @@ namespace executors
}
/**
* loop
* The main loop of the worker thread
*/
void loop() { worker_thread(); }
void loop()
{
while (execute_one(/*wait:*/true))
{
}
BOOST_ASSERT(closed());
while (try_executing_one())
{
}
}
/**
* \b Effects: close the \c loop_executor for submissions.
* The loop will work until there is no more closures to run.
@@ -143,29 +142,29 @@ namespace executors
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure) {
work_queue.push(boost::move(closure));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work w ((closure));
work_queue.push_back(boost::move(w));
//work_queue.push(work(closure)); // todo check why this doesn't work
}
submit(work(closure));
}
#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
submit(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
void submit(BOOST_THREAD_FWD_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(work(boost::forward<Closure>(closure)));
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
/**
@@ -184,17 +183,18 @@ namespace executors
} while (! pred());
return true;
}
/**
* run queued closures
*/
void run_queued_closures()
{
sync_queue<work>::underlying_queue_type q = work_queue.underlying_queue();
while (q.empty())
while (! q.empty())
{
work task = q.front();
q.pop_front();
work& task = q.front();
task();
q.pop_front();
}
}

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