summaryrefslogtreecommitdiff
path: root/libs/thread
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2016-03-21 15:45:20 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2016-03-21 15:46:37 +0900
commit733b5d5ae2c5d625211e2985ac25728ac3f54883 (patch)
treea5b214744b256f07e1dc2bd7273035a7808c659f /libs/thread
parent08c1e93fa36a49f49325a07fe91ff92c964c2b6c (diff)
downloadboost-733b5d5ae2c5d625211e2985ac25728ac3f54883.tar.gz
boost-733b5d5ae2c5d625211e2985ac25728ac3f54883.tar.bz2
boost-733b5d5ae2c5d625211e2985ac25728ac3f54883.zip
Imported Upstream version 1.58.0upstream/1.58.0
Change-Id: If0072143aa26874812e0db6872e1efb10a3e5e94 Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'libs/thread')
-rw-r--r--libs/thread/README.md133
-rw-r--r--libs/thread/build/Jamfile.v27
-rw-r--r--libs/thread/build/has_atomic_flag_lockfree_test.cpp24
-rw-r--r--libs/thread/doc/async_executors.qbk935
-rw-r--r--libs/thread/doc/changes.qbk62
-rw-r--r--libs/thread/doc/external_locking.qbk26
-rw-r--r--libs/thread/doc/future_ref.qbk20
-rwxr-xr-xlibs/thread/doc/futures.qbk2
-rw-r--r--libs/thread/doc/mutex_concepts.qbk8
-rw-r--r--libs/thread/doc/parallel.qbk482
-rw-r--r--libs/thread/doc/scoped_thread.qbk26
-rw-r--r--libs/thread/doc/sync_queues_ref.qbk26
-rw-r--r--libs/thread/doc/synchronized_value_ref.qbk22
-rw-r--r--libs/thread/doc/thread.qbk7
-rw-r--r--libs/thread/doc/thread_ref.qbk12
-rw-r--r--libs/thread/example/default_executor.cpp61
-rw-r--r--libs/thread/example/fib_task_region.cpp91
-rw-r--r--libs/thread/example/future_fallback_to.cpp66
-rw-r--r--libs/thread/example/make_future.cpp20
-rw-r--r--libs/thread/example/producer_consumer.cpp14
-rw-r--r--libs/thread/example/producer_consumer2.cpp2
-rw-r--r--libs/thread/example/serial_executor.cpp113
-rw-r--r--libs/thread/example/serial_executor_cont.cpp113
-rw-r--r--libs/thread/example/this_executor.cpp86
-rw-r--r--libs/thread/src/future.cpp2
-rw-r--r--libs/thread/src/pthread/thread.cpp13
-rw-r--r--libs/thread/src/pthread/timeconv.inl151
-rw-r--r--libs/thread/src/win32/thread.cpp137
-rw-r--r--libs/thread/src/win32/timeconv.inl130
-rw-r--r--libs/thread/src/win32/tss_dll.cpp8
-rw-r--r--libs/thread/test/Jamfile.v275
-rw-r--r--libs/thread/test/experimental/parallel/v1/exception_list_pass.cpp23
-rw-r--r--libs/thread/test/experimental/parallel/v2/task_region_pass.cpp295
-rw-r--r--libs/thread/test/sync/futures/async/async_pass.cpp44
-rw-r--r--libs/thread/test/sync/futures/future/async_deferred_then_pass.cpp23
-rw-r--r--libs/thread/test/sync/futures/future/get_or_pass.cpp87
-rw-r--r--libs/thread/test/sync/futures/make_ready_future_pass.cpp157
-rw-r--r--libs/thread/test/sync/futures/promise/emplace_pass.cpp207
-rw-r--r--libs/thread/test/sync/futures/shared_future/then_pass.cpp24
-rw-r--r--libs/thread/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp455
-rw-r--r--libs/thread/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp60
-rw-r--r--libs/thread/test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp256
-rw-r--r--libs/thread/test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp403
-rw-r--r--libs/thread/test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp215
-rw-r--r--libs/thread/test/sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp425
-rw-r--r--libs/thread/test/sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp155
-rw-r--r--libs/thread/test/sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp216
-rw-r--r--libs/thread/test/sync/mutual_exclusion/sync_queue/single_thread_pass.cpp440
-rw-r--r--libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp2
-rw-r--r--libs/thread/test/test_10340.cpp5
-rw-r--r--libs/thread/test/test_10963.cpp44
-rw-r--r--libs/thread/test/test_10964.cpp76
-rw-r--r--libs/thread/test/test_11053.cpp70
-rwxr-xr-xlibs/thread/test/test_2309.cpp13
-rw-r--r--libs/thread/test/test_2741.cpp18
-rwxr-xr-xlibs/thread/test/test_9192.cpp5
-rw-r--r--libs/thread/test/test_9303.cpp7
-rw-r--r--libs/thread/test/test_9319.cpp21
-rw-r--r--libs/thread/test/test_9711.cpp4
-rw-r--r--libs/thread/test/test_9856.cpp29
-rw-r--r--libs/thread/test/test_condition.cpp18
-rw-r--r--libs/thread/test/test_condition_notify_all.cpp14
-rw-r--r--libs/thread/test/test_condition_notify_one.cpp16
-rw-r--r--libs/thread/test/test_condition_timed_wait_times_out.cpp14
-rw-r--r--libs/thread/test/test_futures.cpp173
-rw-r--r--libs/thread/test/test_generic_locks.cpp62
-rw-r--r--libs/thread/test/test_hardware_concurrency.cpp14
-rw-r--r--libs/thread/test/test_lock_concept.cpp64
-rw-r--r--libs/thread/test/test_move_function.cpp30
-rw-r--r--libs/thread/test/test_mutex.cpp29
-rw-r--r--libs/thread/test/test_once.cpp20
-rw-r--r--libs/thread/test/test_physical_concurrency.cpp12
-rw-r--r--libs/thread/test/test_scheduled_tp.cpp97
-rw-r--r--libs/thread/test/test_scheduler.cpp81
-rw-r--r--libs/thread/test/test_scheduling_adaptor.cpp54
-rw-r--r--libs/thread/test/test_shared_mutex.cpp27
-rw-r--r--libs/thread/test/test_shared_mutex_part_2.cpp35
-rw-r--r--libs/thread/test/test_shared_mutex_timed_locks.cpp33
-rw-r--r--libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp32
-rw-r--r--libs/thread/test/test_thread.cpp36
-rw-r--r--libs/thread/test/test_thread_exit.cpp20
-rw-r--r--libs/thread/test/test_thread_id.cpp28
-rw-r--r--libs/thread/test/test_thread_launching.cpp36
-rw-r--r--libs/thread/test/test_thread_move.cpp20
-rw-r--r--libs/thread/test/test_thread_move_return.cpp13
-rw-r--r--libs/thread/test/test_thread_return_local.cpp15
-rw-r--r--libs/thread/test/test_tss.cpp68
-rw-r--r--libs/thread/test/test_xtime.cpp24
-rw-r--r--libs/thread/test/winrt_init.cpp2
89 files changed, 5908 insertions, 1832 deletions
diff --git a/libs/thread/README.md b/libs/thread/README.md
index 81cc21eb69..ce4b25cff5 100644
--- a/libs/thread/README.md
+++ b/libs/thread/README.md
@@ -6,3 +6,136 @@ Portable C++ multi-threading. C++11, C++14.
### License
Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).
+
+### Current Jenkins CI Test Status for unstable (develop) branch
+Overall build (nightly): <a href='https://ci.nedprod.com/view/All/job/Boost.Thread%20Build/'><img src='https://ci.nedprod.com/buildStatus/icon?job=Boost.Thread%20Build'></a> Overall tests (weekly, on Sundays): <a href='https://ci.nedprod.com/view/All/job/Boost.Thread%20Test/'><img src='https://ci.nedprod.com/buildStatus/icon?job=Boost.Thread%20Test'></a>
+
+#### Build (nightly):
+<table id="configuration-matrix" width="100%" border="1">
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="6" valign="top">android-ndk</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="6" valign="top">winphone8</td>
+ </tr>
+ <tr>
+ <td/>
+ </tr>
+ <tr>
+ <td/>
+ </tr>
+ <tr>
+ <td/>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=static,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=static,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=static,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=shared,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=shared,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=shared,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="6" valign="top">arm-gcc-clang</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="6" valign="top">freebsd10-clang3.3</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=static,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=shared,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=static,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=shared,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
+ </tr>
+ <tr>
+ <td/>
+ </tr>
+ <tr>
+ <td/>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="6" valign="top">linux-gcc-clang</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.7,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.2,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.4,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.7,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.2,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.4,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.7,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.2,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.4,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.7,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.2,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.4,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
+ </tr>
+ <tr>
+ <td/>
+ </tr>
+ <tr>
+ <td/>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="6" valign="top">linux64-gcc-clang</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-analyse,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Unstable" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/yellow.png" tooltip="Unstable"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-analyse,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Unstable" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/yellow.png" tooltip="Unstable"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-analyse,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-analyse,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-analyse,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-analyse,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="6" valign="top">win8-msvc-mingw</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw32,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw64,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw32,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw64,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw32,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw64,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw32,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw64,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-10.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-10.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
+ </tr>
+ <tr>
+ <td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-analyse,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-10.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-10.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
+ </tr>
+</table>
diff --git a/libs/thread/build/Jamfile.v2 b/libs/thread/build/Jamfile.v2
index 17d44a5979..7e06cb3c40 100644
--- a/libs/thread/build/Jamfile.v2
+++ b/libs/thread/build/Jamfile.v2
@@ -63,6 +63,7 @@ project boost/thread
<toolset>gcc:<cxxflags>-Wno-variadic-macros
#<toolset>gcc:<cxxflags>-Wunused-local-typedefs
<toolset>gcc:<cxxflags>-Wunused-function
+ <toolset>gcc:<cxxflags>-Wno-unused-parameter
<toolset>darwin:<cxxflags>-Wextra
<toolset>darwin:<cxxflags>-pedantic
@@ -72,18 +73,20 @@ project boost/thread
<toolset>darwin:<cxxflags>-Wno-variadic-macros
#<toolset>darwin:<cxxflags>-Wunused-local-typedefs
<toolset>darwin:<cxxflags>-Wunused-function
+ <toolset>darwin:<cxxflags>-Wno-unused-parameter
#<toolset>pathscale:<cxxflags>-Wextra
<toolset>pathscale:<cxxflags>-Wno-long-long
<toolset>pathscale:<cxxflags>-pedantic
+ <toolset>clang:<warnings>on
<toolset>clang:<cxxflags>-Wextra
#<toolset>clang:<cxxflags>-ansi
#<toolset>clang:<cxxflags>-fpermissive
<toolset>clang:<cxxflags>-Wno-long-long
<toolset>clang:<cxxflags>-Wunused-function
<toolset>clang:<cxxflags>-Wno-variadic-macros
- <toolset>clang:<warnings>on
+ <toolset>clang:<cxxflags>-Wno-unused-parameter
#<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
#<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
@@ -116,7 +119,9 @@ project boost/thread
<toolset>intel:<cxxflags>-wd1418
<toolset>intel:<cxxflags>-wd2415
+ <toolset>msvc:<cxxflags>/wd4100
<toolset>msvc:<cxxflags>/wd4512
+ <toolset>msvc:<cxxflags>/wd6246
# : default-build <threading>multi
diff --git a/libs/thread/build/has_atomic_flag_lockfree_test.cpp b/libs/thread/build/has_atomic_flag_lockfree_test.cpp
index 3190745fdb..ca6940546b 100644
--- a/libs/thread/build/has_atomic_flag_lockfree_test.cpp
+++ b/libs/thread/build/has_atomic_flag_lockfree_test.cpp
@@ -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;
-} \ No newline at end of file
+#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;
+}
diff --git a/libs/thread/doc/async_executors.qbk b/libs/thread/doc/async_executors.qbk
index 4b22c620cb..c9311bdd5a 100644
--- a/libs/thread/doc/async_executors.qbk
+++ b/libs/thread/doc/async_executors.qbk
@@ -10,7 +10,7 @@
[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/2013/n3785.pdf [*N3785 - Executors and Schedulers revision 3]] C++1y proposal from Chris Mysen, Niklas Gustafsson, Matt Austern, Jeffrey Yasskin. The text that follows has been adapted from tis paper to show the differences.]
+[note These features are based on the [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3785.pdf [*N3785 - Executors and Schedulers revision 3]] C++1y proposal from Chris Mysen, Niklas Gustafsson, Matt Austern, Jeffrey Yasskin. The text that follows has been adapted from this paper to show the differences.]
Executors are objects that can execute units of work packaged as function objects. Boost.Thread differs from N3785 mainly in the an Executor doesn't needs to inherit from an abstract class Executor. Static polymorphism is used instead and type erasure is used internally.
@@ -158,6 +158,24 @@ In order to manage with all the clocks, there are two alternatives:
The library chose the first of those options, largely for simplicity.
]
+[heading Scheduled work]
+
+The approach of this library respect to scheduled work of the N3785 proposal is quite different. Instead of adding the scheduled operations to a specific scheduled_executor polymorphic interface, we opt by adding a specific `scheduler` class that is not an executor and knows how to manage with the scheduling of timed tasks `submit_at`/`submit_after`.
+
+
+`scheduler` provides executor factories `at`/`after` given a specific `time_point` or a `duration`. The built executors wrap a reference to this scheduler and the time at which the submitted task will be executed.
+
+If we want to schedule these operations on an existing executor (as `serial_executor` does), these classes provide a `on` factory taking another executor as parameter and wraps both instance on the returned executor.
+
+ sch.on(tp).after(seconds(i)).submit(boost::bind(fn,i));
+
+This has several advantages:
+
+* The scheduled operations are available for all the executors via wrappers.
+* The template functions could accept any chrono `time_point` and `duration` respectively as we are not working with virtual functions.
+
+In order to manage with all the clocks, this library propose generic solution. `scheduler<Clock>` know how to manage with the `submit_at`/`submit_after` `Clock::time_point`/`Clock::duration` tasks. Note that the durations on different clocks differ.
+
[heading Not Handled Exceptions]
As in N3785 and based on the same design decision than `std`/`boost::thread` if a user closure throws an exception, the executor must call the `std::terminate` function.
Note that when we combine `boost::async` and `Executors`, the exception will be caught by the closure associated to the returned future, so that the exception is stored on the returned future, as for the other `async` overloads.
@@ -182,49 +200,108 @@ An alternative is to make async return a cancelable_task but this will need also
[/
The library would provide in the future a cancelable_task that could support cancelation.
- class cancelation_state {
- std::atomic<bool> requested; std::atomic<bool> enabled; std::condition_variable* cond; std::mutex cond_mutex;
+ class cancelation_state
+ {
+ std::atomic<bool> requested;
+ std::atomic<bool> enabled;
+ std::condition_variable* cond;
+ std::mutex cond_mutex;
public:
- cancelation_state(): thread_cond(0) {} void cancel() { requested.store(true,std::memory_order_relaxed); std::lock_guard<std::mutex> lk(cond_mutex); if(cond) { cond->notify_all(); } } bool cancellation_requested() const { return requested.load(std::memory_order_relaxed); }
- void enable() { enable.store(true,std::memory_order_relaxed); } void disable() { enable.store(false,std::memory_order_relaxed); } bool cancellation_enabled() const { return enabled.load(std::memory_order_relaxed); } void set_condition_variable(std::condition_variable& cv) { std::lock_guard<std::mutex> lk(cond_mutex); cond = &cv; } void clear_condition_variable() { std::lock_guard<std::mutex> lk(cond_mutex); cond = 0; } struct clear_cv_on_destruct { ~clear_cv_on_destruct() { this_thread_interrupt_flag.clear_condition_variable(); } };
- void cancelation_point();
- void cancelable_wait(std::condition_variable& cv, std::unique_lock<std::mutex>& lk) { cancelation_point(); this_cancelable_state.set_condition_variable(cv); this_cancelable_state::clear_cv_on_destruct guard; interruption_point();
- cv.wait_for(lk, std::chrono::milliseconds(1)); this_cancelable_state.clear_condition_variable(); cancelation_point(); }
- class disable_cancelation
+ cancelation_state() :
+ thread_cond(0)
+ {
+ }
+ void cancel()
+ {
+ requested.store(true, std::memory_order_relaxed);
+ std::lock_guard < std::mutex > lk(cond_mutex);
+ if (cond)
{
- public:
- disable_cancelation(const disable_cancelation&) = delete;
- disable_cancelation& operator=(const disable_cancelation&) = delete;
- disable_cancelation(cancelable_closure& closure) noexcept;
- ~disable_cancelation() noexcept;
- };
- class restore_cancelation
+ cond->notify_all();
+ }
+ }
+ bool cancellation_requested() const
+ {
+ return requested.load(std::memory_order_relaxed);
+ }
+ void enable()
+ {
+ enable.store(true, std::memory_order_relaxed);
+ }
+ void disable()
+ {
+ enable.store(false, std::memory_order_relaxed);
+ }
+ bool cancellation_enabled() const
+ {
+ return enabled.load(std::memory_order_relaxed);
+ }
+ void set_condition_variable(std::condition_variable& cv)
+ {
+ std::lock_guard < std::mutex > lk(cond_mutex);
+ cond = &cv;
+ }
+ void clear_condition_variable()
+ {
+ std::lock_guard < std::mutex > lk(cond_mutex);
+ cond = 0;
+ }
+ struct clear_cv_on_destruct
+ {
+ ~clear_cv_on_destruct()
{
- public:
- restore_cancelation(const restore_cancelation&) = delete;
- restore_cancelation& operator=(const restore_cancelation&) = delete;
- explicit restore_cancelation(cancelable_closure& closure, disable_cancelation& disabler) noexcept;
- ~restore_cancelation() noexcept;
- };
+ this_thread_interrupt_flag.clear_condition_variable();
+ }
+ };
+ void cancelation_point();
+ void cancelable_wait(std::condition_variable& cv, std::unique_lock<std::mutex>& lk)
+ {
+ cancelation_point();
+ this_cancelable_state.set_condition_variable(cv);
+ this_cancelable_state::clear_cv_on_destruct guard;
+ interruption_point();
+ cv.wait_for(lk, std::chrono::milliseconds(1));
+ this_cancelable_state.clear_condition_variable();
+ cancelation_point();
+ }
+ class disable_cancelation
+ {
+ public:
+ disable_cancelation(const disable_cancelation&)= delete;
+ disable_cancelation& operator=(const disable_cancelation&)= delete;
+ disable_cancelation(cancelable_closure& closure)
+ noexcept ;
+ ~disable_cancelation() noexcept;
+ };
+ class restore_cancelation
+ {
+ public:
+ restore_cancelation(const restore_cancelation&) = delete;
+ restore_cancelation& operator=(const restore_cancelation&) = delete;
+ explicit restore_cancelation(cancelable_closure& closure, disable_cancelation& disabler) noexcept;
+ ~restore_cancelation() noexcept;
+ };
};
-
- template <class Closure>
- struct cancelable_closure_mixin : cancelable_closure {
- void operator() {
- cancel_point();
- this->Closure::run();
- }
+
+ template <class Closure>
+ struct cancelable_closure_mixin: cancelable_closure
+ {
+ void operator()
+ {
+ cancel_point();this->Closure::run();
+ }
};
-
- struct my_clousure : cancelable_closure_mixin<my_clousure>
+
+ struct my_clousure: cancelable_closure_mixin<my_clousure>
{
- void run() {
- while () {
- cancel_point();
- }
- }
+ void run()
+ {
+ while ()
+ {
+ cancel_point();
+ }
+ }
}
-
]
[heading Current executor]
@@ -242,33 +319,23 @@ The reason is that the user can always use a thread_local variable and reset it
}
);
+[
[heading Default executor]
The library authors share some of the concerns of the C++ standard committee (introduction of a new single shared resource, a singleton, could make it difficult to make it portable to all the environments) and that this library doesn't need to provide a default executor for the time been.
-The user can always define his default executor himself and use the `at_thread_entry ` member function to set the default constructor.
-
- thread_local default_executor_state_type default_executor_state;
- executor* default_executor() { return default_executor_state.default_executor(); }
-
- // in main
- MyDefaultExecutor myDefaultExecutor(
- // at_thread_entry
- [](MyDefaultExecutor& ex) {
- default_executor_state.set_default_executor(ex);
- }
- );
+The user can always define his default executor himself.
- basic_thread_pool pool(
- // at_thread_entry
- [&myDefaultExecutor](basic_thread_pool& pool) {
- default_executor_state.set_default_executor(myDefaultExecutor);
- }
- );
+ boost::generic_executor_ref default_executor()
+ {
+ static boost::basic_thread_pool tp(4);
+ return generic_executor_ref(tp);
+ }
[endsect]
+
[/////////////////////]
[section:ref Reference]
@@ -344,7 +411,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
[variablelist
-[[Effects:] [close the executor `e` for submissions.]]
+[[Effects:] [close the scheduler/executor `e` for submissions.]]
[[Remark:] [The worker threads will work until there is no more closures to run.]]
@@ -364,7 +431,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
[[Return type:] [`bool`.]]
-[[Return:] [whether the pool is closed for submissions.]]
+[[Return:] [whether the scheduler/executor is closed for submissions.]]
[[Throws:] [Whatever exception that can be throw while ensuring the thread safety.]]
@@ -512,7 +579,7 @@ Polymorphic adaptor of a model of Executor to an executor.
template <typename ...Args>
executor_adaptor(Args&& ... args);
- Executor& underlying_executor();
+ Executor& underlying_executor() noexcept;
void close();
bool closed();
@@ -558,14 +625,12 @@ Polymorphic adaptor of a model of Executor to an executor.
[/////////////////////////////////////]
[section:underlying_executor Function member `underlying_executor()`]
- Executor& underlying_executor();
+ Executor& underlying_executor() noexcept;
[variablelist
[[Return:] [The underlying executor instance. ]]
-[[Throws:] [Nothing.]]
-
]
@@ -587,7 +652,7 @@ Executor abstract base class.
generic_executor_ref& operator=(generic_executor_ref const&);
template <class Executor>
- executor(Executor& ex);
+ generic_executor_ref(Executor& ex);
generic_executor_ref() {};
void close() = 0;
@@ -604,29 +669,552 @@ Executor abstract base class.
[endsect]
+[//////////////////////////////////////////////////////////]
+[section: scheduler Template Class `scheduler `]
+
+Scheduler providing time related functions. Note that `scheduler` is not an Executor.
+
+ #include <boost/thread/executors/scheduler.hpp>
+ namespace boost {
+
+ template <class Clock=steady_clock>
+ class scheduler
+ {
+ public:
+ using work = boost::function<void()> ;
+ using clock = Clock;
+
+ scheduler(scheduler const&) = delete;
+ scheduler& operator=(scheduler const&) = delete;
+
+ scheduler();
+ ~scheduler();
+
+ void close();
+ bool closed();
+
+ template <class Duration, typename Closure>
+ void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
+ template <class Rep, class Period, typename Closure>
+ void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
+
+ template <class Duration>
+ at_executor<scheduler> submit_at(chrono::time_point<clock,Duration> abs_time);
+ template <class Rep, class Period>
+ at_executor<scheduler> submit_after(chrono::duration<Rep,Period> rel_time);
+
+ template <class Executor>
+ scheduler_executor_wrapper<scheduler, Executor> on(Executor& ex);
+
+ };
+ }
+
+[/////////////////////////////////////]
+[section:constructor Constructor `scheduler()`]
+
+ scheduler();
+
+[variablelist
+
+[[Effects:] [Constructs a `scheduler`. ]]
+
+[[Throws:] [Nothing. ]]
+
+]
+
+
+[endsect]
+[/////////////////////////////////////]
+[section:destructor Destructor `~scheduler()`]
+
+ ~scheduler();
+
+[variablelist
+
+[[Effects:] [Destroys the scheduler.]]
+
+[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_at Template Function Member `submit_at()`]
+
+ template <class Clock, class Duration, typename Closure>
+ void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Schedule a `closure` to be executed at `abs_time`. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_after Template Function Member `submit_after()`]
+
+ template <class Rep, class Period, typename Closure>
+ void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Schedule a `closure` to be executed after `rel_time`. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+
+[endsect]
+
+[endsect]
+
+[//////////////////////////////////////////////////////////]
+[section:at_executor Template Class `at_executor`]
+
+
+ #include <boost/thread/executors/scheduler.hpp>
+ namespace boost {
+
+ template <class Scheduler>
+ class at_executor
+ {
+ public:
+ using work = Scheduler::work;
+ using clock = Scheduler::clock;
+
+ at_executor(at_executor const&) = default;
+ at_executor(at_executor &&) = default;
+ at_executor& operator=(at_executor const&) = default;
+ at_executor& operator=(at_executor &&) = default;
+
+ at_executor(Scheduler& sch, clock::time_point const& tp);
+ ~at_executor();
+
+ void close();
+ bool closed();
+
+ Scheduler& underlying_scheduler();
+
+ template <class Closure>
+ void submit(Closure&& closure);
+ template <class Duration, typename Work>
+ void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
+ template <class Rep, class Period, typename Work>
+ void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
+
+ template <class Executor>
+ resubmit_at_executor<Scheduler, Executor> on(Executor& ex);
+
+ };
+ }
+
+[/////////////////////////////////////]
+[section:constructor Constructor `at_executor(Scheduler&)`]
+
+ at_executor(Scheduler& sch, clock::time_point const& tp);
+
+[variablelist
+
+[[Effects:] [Constructs a `at_executor`. ]]
+
+[[Throws:] [Nothing. ]]
+
+]
+
+
+[endsect]
+[/////////////////////////////////////]
+[section:destructor Destructor `~at_executor()`]
+
+ ~at_executor();
+
+[variablelist
+
+[[Effects:] [Destroys the `at_executor`.]]
+
+[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:underlying_scheduler Function member `underlying_scheduler()`]
+
+ Scheduler& underlying_scheduler() noexcept;
+
+[variablelist
+
+[[Return:] [The underlying scheduler instance. ]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_at Template Function Member `submit()`]
+
+ template <typename Closure>
+ void submit(Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Schedule the `closure` to be executed at the `abs_time` given at construction time. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_at Template Function Member `submit_at()`]
+
+ template <class Clock, class Duration, typename Closure>
+ void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Schedule a `closure` to be executed at `abs_time`. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_after Template Function Member `submit_after()`]
+
+ template <class Rep, class Period, typename Closure>
+ void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Schedule a `closure` to be executed after `rel_time`. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+
+[endsect]
+
+[endsect]
+
-[/
[//////////////////////////////////////////////////////////]
-[section:scheduled_executor Template Class `scheduled_executor`]
+[section:scheduler_executor_wrapper Template Class `scheduler_executor_wrapper`]
+
+ #include <boost/thread/executors/scheduler.hpp>
+ namespace boost {
+
+ template <class Scheduler, class Executor>
+ class scheduler_executor_wrapper
+ {
+ public:
+ using work = Scheduler::work;
+ using clock = Scheduler::clock;
+
+ scheduler_executor_wrapper(scheduler_executor_wrapper const&) = default;
+ scheduler_executor_wrapper(scheduler_executor_wrapper &&) = default;
+ scheduler_executor_wrapper& operator=(scheduler_executor_wrapper const&) = default;
+ scheduler_executor_wrapper& operator=(scheduler_executor_wrapper &&) = default;
+
+ scheduler_executor_wrapper(Scheduler& sch, Executor& ex);
+
+ ~scheduler_executor_wrapper();
+
+ void close();
+ bool closed();
+
+ Executor& underlying_executor();
+ Scheduler& underlying_scheduler();
+
+ template <class Closure>
+ void submit(Closure&& closure);
+ template <class Duration, typename Work>
+ void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
+ template <class Rep, class Period, typename Work>
+ void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
+
+ template <class Duration>
+ resubmit_at_executor<Scheduler, Executor> at(chrono::time_point<clock,Duration> abs_time);
+ template <class Rep, class Period>
+ resubmit_at_executor<Scheduler, Executor> after(chrono::duration<Rep,Period> rel_time);
+
+ };
+ }
+
+[/////////////////////////////////////]
+[section:constructor Constructor `scheduler_executor_wrapper(Scheduler&, Executor&)`]
+
+ scheduler_executor_wrapper(Scheduler& sch, Executor& ex);
+
+[variablelist
+
+[[Effects:] [Constructs a `scheduler_executor_wrapper`. ]]
+
+[[Throws:] [Nothing. ]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:destructor Destructor `~scheduler_executor_wrapper()`]
+
+ ~scheduler_executor_wrapper();
+
+[variablelist
+
+[[Effects:] [Destroys the `scheduler_executor_wrapper`.]]
+
+[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:underlying_scheduler Function member `underlying_scheduler()`]
+
+ Scheduler& underlying_scheduler() noexcept;
+
+[variablelist
+
+[[Return:] [The underlying scheduler instance. ]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:underlying_executor Function member `underlying_executor()`]
+
+ Executor& underlying_executor() noexcept;
+
+[variablelist
+
+[[Return:] [The underlying executor instance. ]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_at Template Function Member `submit()`]
+
+ template <typename Closure>
+ void submit(Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Submit the `closure` on the underlying executor. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_at Template Function Member `submit_at()`]
+
+ template <class Clock, class Duration, typename Closure>
+ void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Resubmit the `closure` to be executed on the underlying executor at `abs_time`. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_after Template Function Member `submit_after()`]
+
+ template <class Rep, class Period, typename Closure>
+ void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Resubmit the `closure` to be executed on the underlying executor after `rel_time`. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[endsect]
+
+
+[//////////////////////////////////////////////////////////]
+[section:resubmit_at_executor Template Class `resubmit_at_executor`]
+
+`Executor` wrapping an `Scheduler`, an `Executor` and a `time_point` providing an `Executor` interface.
+
+ #include <boost/thread/executors/scheduler.hpp>
+ namespace boost {
+
+ template <class Scheduler, class Executor>
+ class resubmit_at_executor
+ {
+ public:
+ using work = Scheduler::work;
+ using clock = Scheduler::clock;
+
+ resubmit_at_executor(resubmit_at_executor const&) = default;
+ resubmit_at_executor(resubmit_at_executor &&) = default;
+ resubmit_at_executor& operator=(resubmit_at_executor const&) = default;
+ resubmit_at_executor& operator=(resubmit_at_executor &&) = default;
+
+ template <class Duration>
+ resubmit_at_executor(Scheduler& sch, Executor& ex, clock::time_point<Duration> const& tp);
+ ~resubmit_at_executor();
+
+ void close();
+ bool closed();
+
+ Executor& underlying_executor();
+ Scheduler& underlying_scheduler();
+
+ template <class Closure>
+ void submit(Closure&& closure);
+ template <class Duration, typename Work>
+ void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
+ template <class Rep, class Period, typename Work>
+ void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
+
+ };
+ }
+
+
+[/////////////////////////////////////]
+[section:constructor Constructor `resubmit_at_executor(Scheduler&, Executor&, clock::time_point<Duration>)`]
+
+ template <class Duration>
+ resubmit_at_executor(Scheduler& sch, Executor& ex, clock::time_point<Duration> const& tp);
+
+[variablelist
+
+[[Effects:] [Constructs a `resubmit_at_executor`. ]]
+
+[[Throws:] [Nothing. ]]
+
+]
+
+
+[endsect]
+[/////////////////////////////////////]
+[section:destructor Destructor `~resubmit_at_executor()`]
+
+ ~resubmit_at_executor();
+
+[variablelist
+
+[[Effects:] [Destroys the executor_adaptor.]]
+
+[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:underlying_executor Function member `underlying_executor()`]
+
+ Executor& underlying_executor() noexcept;
+
+[variablelist
+
+[[Return:] [The underlying executor instance. ]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:underlying_scheduler Function member `underlying_scheduler()`]
+
+ Scheduler& underlying_scheduler() noexcept;
+
+[variablelist
+
+[[Return:] [The underlying scheduler instance. ]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_at Template Function Member `submit()`]
+
+ template <typename Closure>
+ void submit(Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Resubmit the `closure` to be executed on the underlying executor at the `abs_time` given at construction time. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_at Template Function Member `submit_at()`]
+
+ template <class Clock, class Duration, typename Closure>
+ void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Resubmit the `closure` to be executed on the underlying executor at `abs_time`. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_after Template Function Member `submit_after()`]
+
+ template <class Rep, class Period, typename Closure>
+ void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Resubmit the `closure` to be executed on the underlying executor after `rel_time`. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[endsect]
+
+
+[//////////////////////////////////////////////////////////]
+[/
+[section:scheduled_executor_ref Template Class `scheduled_executor_ref`]
Executor providing time related functions.
- #include <boost/thread/scheduled_executor.hpp>
+ #include <boost/thread/executors/scheduled_executor_ref.hpp>
namespace boost {
template <class Executor>
- class scheduled_executor
+ class scheduled_executor_ref
{
Executor& ex;
public:
typedef executor::work work;
- scheduled_executor(scheduled_executor const&) = delete;
- scheduled_executor& operator=(scheduled_executor const&) = delete;
+ scheduled_executor_ref(scheduled_executor_ref const&) = delete;
+ scheduled_executor_ref& operator=(scheduled_executor_ref const&) = delete;
template <class Rep, class Period>
- scheduled_executor(Executor& ex, chrono::duration<Rep, Period> granularity=chrono::milliseconds(100));
+ scheduled_executor_ref(Executor& ex, chrono::duration<Rep, Period> granularity=chrono::milliseconds(100));
- Executor& underlying_executor();
+ Executor& underlying_executor() noexcept;
void close();
bool closed();
@@ -640,10 +1228,6 @@ Executor providing time related functions.
template <typename Pred>
bool reschedule_until(Pred const& pred);
- template <class Clock, class Duration>
- void submit_at(chrono::time_point<Clock,Duration> abs_time, work&& closure);
- template <class Rep, class Period>
- void submit_after(chrono::duration<Rep,Period> rel_time, work&& closure);
template <class Clock, class Duration, typename Closure>
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
template <class Rep, class Period, typename Closure>
@@ -652,14 +1236,14 @@ Executor providing time related functions.
}
[/////////////////////////////////////]
-[section:constructor Constructor `scheduled_executor(Executor&, chrono::duration<Rep, Period>)`]
+[section:constructor Constructor `scheduled_executor_ref(Executor&, chrono::duration<Rep, Period>)`]
template <class Rep, class Period>
- scheduled_executor(Executor& ex, chrono::duration<Rep, Period> granularity=chrono::milliseconds(100));
+ scheduled_executor_ref(Executor& ex, chrono::duration<Rep, Period> granularity=chrono::milliseconds(100));
[variablelist
-[[Effects:] [Constructs a scheduled_executor. ]]
+[[Effects:] [Constructs a scheduled_executor_ref. ]]
[[Throws:] [Nothing. ]]
@@ -668,9 +1252,9 @@ Executor providing time related functions.
[endsect]
[/////////////////////////////////////]
-[section:destructor Destructor `~scheduled_executor()`]
+[section:destructor Destructor `~scheduled_executor_ref()`]
- ~scheduled_executor();
+ ~scheduled_executor_ref();
[variablelist
@@ -684,29 +1268,74 @@ Executor providing time related functions.
[/////////////////////////////////////]
[section:underlying_executor Function member `underlying_executor()`]
- Executor& underlying_executor();
+ Executor& underlying_executor() noexcept;
[variablelist
[[Return:] [The underlying executor instance. ]]
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_at Template Function Member `submit()`]
+
+ template <typename Closure>
+ void submit(Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Resubmit the `closure` to be executed on the underlying executor. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:submit_at Template Function Member `submit_at()`]
+
+ template <class Clock, class Duration, typename Closure>
+ void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Schedule a `closure` to be executed at `abs_time`. ]]
+
[[Throws:] [Nothing.]]
]
[endsect]
+[/////////////////////////////////////]
+[section:submit_after Template Function Member `submit_after()`]
+
+ template <class Rep, class Period, typename Closure>
+ void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
+
+[variablelist
+
+[[Effects:] [Schedule a `closure` to be executed after `rel_time`. ]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
[endsect]
]
[//////////////////////////////////////////////////////////]
-[section:serial_executor Class `serial_executor`]
+[section:serial_executor Template Class `serial_executor`]
A serial executor ensuring that there are no two work units that executes concurrently.
#include <boost/thread/serial_executor.hpp>
namespace boost {
+ template <class Executor>
class serial_executor
{
public:
@@ -716,7 +1345,7 @@ A serial executor ensuring that there are no two work units that executes concur
template <class Executor>
serial_executor(Executor& ex);
- generic_executor_ref underlying_executor();
+ Executor& underlying_executor() noexcept;
void close();
bool closed();
@@ -764,7 +1393,7 @@ A serial executor ensuring that there are no two work units that executes concur
[/////////////////////////////////////]
[section:underlying_executor Function member `underlying_executor()`]
- generic_executor_ref underlying_executor();
+ generic_executor_ref& underlying_executor() noexcept;
[variablelist
@@ -780,6 +1409,84 @@ A serial executor ensuring that there are no two work units that executes concur
[endsect]
[//////////////////////////////////////////////////////////]
+[section:generic_serial_executor Class `generic_serial_executor`]
+
+A serial executor ensuring that there are no two work units that executes concurrently.
+
+ #include <boost/thread/generic_serial_executor.hpp>
+ namespace boost {
+ class generic_serial_executor
+ {
+ public:
+ generic_serial_executor(generic_serial_executor const&) = delete;
+ generic_serial_executor& operator=(generic_serial_executor const&) = delete;
+
+ template <class Executor>
+ generic_serial_executor(Executor& ex);
+
+ generic_executor_ref& underlying_executor() noexcept;
+
+ void close();
+ bool closed();
+
+ template <typename Closure>
+ void submit(Closure&& closure);
+
+ bool try_executing_one();
+ template <typename Pred>
+ bool reschedule_until(Pred const& pred);
+
+ };
+ }
+
+[/////////////////////////////////////]
+[section:constructor Constructor `generic_serial_executor(Executor&)`]
+
+ template <class Executor>
+ generic_serial_executor(Executor& ex);
+
+[variablelist
+
+[[Effects:] [Constructs a serial_executor. ]]
+
+[[Throws:] [Nothing. ]]
+
+]
+
+
+[endsect]
+[/////////////////////////////////////]
+[section:destructor Destructor `~serial_executor()`]
+
+ ~generic_serial_executor();
+
+[variablelist
+
+[[Effects:] [Destroys the serial_executor.]]
+
+[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
+
+]
+
+[endsect]
+[/////////////////////////////////////]
+[section:underlying_executor Function member `underlying_executor()`]
+
+ Executor& underlying_executor() noexcept;
+
+[variablelist
+
+[[Return:] [The underlying executor instance. ]]
+
+]
+
+
+[endsect]
+
+[endsect]
+
+
+[//////////////////////////////////////////////////////////]
[section:inline_executor Class `inline_executor`]
A serial executor ensuring that there are no two work units that executes concurrently.
@@ -848,7 +1555,7 @@ A serial executor ensuring that there are no two work units that executes concur
A thread pool with up to a fixed number of threads.
- #include <boost/thread/work.hpp>
+ #include <boost/thread/executors/basic_thread_pool.hpp>
namespace boost {
class basic_thread_pool
{
@@ -892,7 +1599,7 @@ A thread pool with up to a fixed number of threads.
[/////////////////////////////////////]
[section:destructor Destructor `~basic_thread_pool()`]
- virtual ~basic_thread_pool();
+ ~basic_thread_pool();
[variablelist
@@ -905,6 +1612,64 @@ A thread pool with up to a fixed number of threads.
[endsect]
+[///////////////////////////////////////]
+[section:thread_executor Class `thread_executor`]
+
+A thread_executor with a threads for each task.
+
+ #include <boost/thread/executors/thread_executor.hpp>
+ namespace boost {
+ class thread_executor
+ {
+ public:
+
+ thread_executor(thread_executor const&) = delete;
+ thread_executor& operator=(thread_executor const&) = delete;
+
+ thread_executor();
+ template <class AtThreadEntry>
+ basic_thread_pool( unsigned const thread_count, AtThreadEntry at_thread_entry);
+ ~thread_executor();
+
+ void close();
+ bool closed();
+
+ template <typename Closure>
+ void submit(Closure&& closure);
+
+ };
+ }
+
+[/////////////////////////////////////]
+[section:constructor Constructor `thread_executor()`]
+
+[variablelist
+
+[[Effects:] [creates a thread_executor. ]]
+
+[[Throws:] [Whatever exception is thrown while initializing the needed resources. ]]
+
+]
+
+
+[endsect]
+[/////////////////////////////////////]
+[section:destructor Destructor `~thread_executor()`]
+
+ ~thread_executor();
+
+[variablelist
+
+[[Effects:] [Waits for closures (if any) to complete, then joins and destroys the threads.]]
+
+[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
+
+]
+[endsect]
+
+[endsect]
+
+
[/////////////////////////////////]
[section:loop_executor Class `loop_executor`]
diff --git a/libs/thread/doc/changes.qbk b/libs/thread/doc/changes.qbk
index 970f37f463..e158388b7b 100644
--- a/libs/thread/doc/changes.qbk
+++ b/libs/thread/doc/changes.qbk
@@ -8,6 +8,61 @@
[section:changes History]
+[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:]
@@ -24,6 +79,7 @@
* [@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.
@@ -557,9 +613,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.
@@ -567,9 +620,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 extensions related to fork-join as:
- * [@http://svn.boost.org/trac/boost/ticket/9600 #9600] Async: Add task_region/task_run.
-
# And some additional extensions related to futures as:
* [@http://svn.boost.org/trac/boost/ticket/8517 #8517] Async: Add a variadic shared_future::then.
diff --git a/libs/thread/doc/external_locking.qbk b/libs/thread/doc/external_locking.qbk
index a485f3633a..9c7b1ee46f 100644
--- a/libs/thread/doc/external_locking.qbk
+++ b/libs/thread/doc/external_locking.qbk
@@ -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) {
diff --git a/libs/thread/doc/future_ref.qbk b/libs/thread/doc/future_ref.qbk
index 9fb73c1737..d63e1aee32 100644
--- a/libs/thread/doc/future_ref.qbk
+++ b/libs/thread/doc/future_ref.qbk
@@ -1020,7 +1020,7 @@ There are not too much tests yet, so it is possible that you can find out some t
void swap(shared_future& other);
// retrieving the value
- see below get();
+ see below get() const;
exception_ptr get_exception_ptr(); // EXTENSION
@@ -1066,9 +1066,9 @@ There are not too much tests yet, so it is possible that you can find out some t
[///////////////////////////////////]
[section:get Member function `get()`]
- const R& get();
- R& get();
- void get();
+ const R& get() const;
+ R& get() const;
+ void get() const;
[variablelist
@@ -2362,7 +2362,7 @@ All `R` types must be the same. If any of the `future<R>` or `shared_future<R>`
[section:make_ready_future Non-member function `make_ready_future()` EXTENSION]
template <typename T>
- future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
+ future<V> make_ready_future(T&& value); // EXTENSION
future<void> make_ready_future(); // EXTENSION
template <typename T>
future<T> make_ready_future(exception_ptr ex); // DEPRECATED
@@ -2371,11 +2371,15 @@ All `R` types must be the same. If any of the `future<R>` or `shared_future<R>`
[variablelist
+[[Remark:][
+where `V` is determined as follows: Let `U` be `decay_t<T>`. Then `V` is `X&`
+if `U` equals `reference_wrapper<X>`, otherwise `V` is `U`.
+]]
[[Effects:] [
-- value prototype: The value that is passed into the function is moved to the shared state of the returned function if it is an rvalue.
-Otherwise the value is copied to the shared state of the returned function.
+- value prototype: The value that is passed into the function is moved to the shared state of the returned future if it is an rvalue.
+Otherwise the value is copied to the shared state of the returned future.
-- exception: The exception that is passed into the function is copied to the shared state of the returned function.
+- exception: The exception that is passed into the function is copied to the shared state of the returned future.
.]]
diff --git a/libs/thread/doc/futures.qbk b/libs/thread/doc/futures.qbk
index 5a5bdfa2e6..f05bde5550 100755
--- a/libs/thread/doc/futures.qbk
+++ b/libs/thread/doc/futures.qbk
@@ -93,7 +93,7 @@ the result is ready, it is returned from __unique_future_get__ by rvalue-referen
appropriate for the type.
On the other hand, many instances of __shared_future__ may reference the same result. Instances can be freely copied and assigned,
-and __shared_future_get__ returns a non `const` reference so that multiple calls to __shared_future_get__ are safe. You can move an
+and __shared_future_get__ returns a `const` reference so that multiple calls to __shared_future_get__ are safe. You can move an
instance of __unique_future__ into an instance of __shared_future__, thus transferring ownership of the associated asynchronous
result, but not vice-versa.
diff --git a/libs/thread/doc/mutex_concepts.qbk b/libs/thread/doc/mutex_concepts.qbk
index 78ec58849f..825d22c23e 100644
--- a/libs/thread/doc/mutex_concepts.qbk
+++ b/libs/thread/doc/mutex_concepts.qbk
@@ -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);
diff --git a/libs/thread/doc/parallel.qbk b/libs/thread/doc/parallel.qbk
new file mode 100644
index 0000000000..7acee567a1
--- /dev/null
+++ b/libs/thread/doc/parallel.qbk
@@ -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]
diff --git a/libs/thread/doc/scoped_thread.qbk b/libs/thread/doc/scoped_thread.qbk
index f98f525003..f92b076764 100644
--- a/libs/thread/doc/scoped_thread.qbk
+++ b/libs/thread/doc/scoped_thread.qbk
@@ -21,18 +21,18 @@
class scoped_thread;
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
-[section:motovation Motivation]
+[section:motivation Motivation]
Based on the scoped_thread class defined in C++ Concurrency in Action Boost.Thread defines a thread wrapper class that instead of calling terminate if the thread is joinable on destruction, call a specific action given as template parameter.
-While the scoped_thread class defined in C++ Concurrency in Action is closer to strict_scoped_thread class that doesn't allows any change in the wrapped thread, Boost.Thread provides a class scoped_thread that provides the same non-deprecated interface than __thread.
+While the scoped_thread class defined in C++ Concurrency in Action is closer to strict_scoped_thread class that doesn't allows any change in the wrapped thread, Boost.Thread provides a class scoped_thread that provides the same non-deprecated interface as __thread.
[endsect]
[section:tutorial Tutorial]
-Scoped Threads are wrappers around a thread that allows the user to state what to do at destruction time. One of the common uses is to join the thread at destruction time so this is the default behavior. This is the single difference respect to a thread. While thread call std::terminate() on the destructor is the thread is joinable, strict_scoped_thread<> or scoped_thread<> join the thread if joinable.
+Scoped Threads are wrappers around a thread that allows the user to state what to do at destruction time. One of the common uses is to join the thread at destruction time so this is the default behavior. This is the single difference respect to a thread. While thread call std::terminate() on the destructor if the thread is joinable, strict_scoped_thread<> or scoped_thread<> join the thread if joinable.
-The difference between strict_scoped_thread and scoped_thread is that the strict_scoped_thread hides completely the owned thread and so the user can do nothing with the owned thread other than the specific action given as parameter, while scoped_thread provide the same interface than __thread and forwards all the operations.
+The difference between strict_scoped_thread and scoped_thread is that the strict_scoped_thread hides completely the owned thread and so the user can do nothing with the owned thread other than the specific action given as parameter, while scoped_thread provide the same interface as __thread and forwards all the operations.
boost::strict_scoped_thread<> t1((boost::thread(f)));
//t1.detach(); // compile fails
@@ -114,15 +114,15 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
};
-RAI __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
+RAII __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
CallableThread: A callable `void(thread&)`.
The default is a `join_if_joinable`.
-`std/boost::thread` destructor terminates the program if the __thread is not joinable.
-This wrapper can be used to join the thread before destroying it seems a natural need.
+Thread destructor terminates the program if the __thread is joinable.
+This wrapper can be used to join the thread before destroying it.
[heading Example]
@@ -233,13 +233,13 @@ This wrapper can be used to join the thread before destroying it seems a natural
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
-RAI __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
+RAII __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
CallableThread: A callable void(thread&).
The default is join_if_joinable.
-thread std::thread destructor terminates the program if the thread is not joinable.
-Having a wrapper that can join the thread before destroying it seems a natural need.
+Thread destructor terminates the program if the thread is joinable.
+This wrapper can be used to join the thread before destroying it.
Remark: `scoped_thread` is not a __thread as __thread is not designed to be derived from as a polymorphic type.
@@ -312,9 +312,9 @@ any) to `*this`.
[variablelist
-[[Effects:] [move the thread to own `t_`.]]
+[[Effects:] [Transfers ownership of the thread managed by `other` (if any) to the newly constructed scoped_thread instance.]]
-[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
+[[Postconditions:] [other.get_id()==thread::id() and get_id() returns the value of other.get_id() prior to the construction.]]
[[Throws:] [Nothing]]
@@ -329,7 +329,7 @@ any) to `*this`.
[variablelist
-[[Effects:] [Construct a internal thread in place.]]
+[[Effects:] [Construct an internal thread in place.]]
[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
diff --git a/libs/thread/doc/sync_queues_ref.qbk b/libs/thread/doc/sync_queues_ref.qbk
index a46f34fc5f..eba795fc30 100644
--- a/libs/thread/doc/sync_queues_ref.qbk
+++ b/libs/thread/doc/sync_queues_ref.qbk
@@ -181,7 +181,7 @@ where
[variablelist
-[[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety.]]
+[[Requires:] [Q::value_type is no throw move constructible. This is needed to ensure the exception safety.]]
[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element.]]
@@ -206,7 +206,7 @@ where
[variablelist
-[/[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety. ]]
+[/[Requires:] [Q::value_type is no throw move assignable. This is needed to ensure the exception safety. ]]
[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element into a shared_ptr.]]
@@ -314,7 +314,7 @@ where
[variablelist
-[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
+[[Effects:] [If the queue is not empty pulls the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
@@ -393,7 +393,7 @@ where
[endsect]
[/////////////////////////////////////]
-[section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve());`]
+[section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve);`]
[variablelist
@@ -427,7 +427,7 @@ where
[variablelist
-[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
+[[Effects:] [If the queue is not empty pulls the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
@@ -636,12 +636,12 @@ Closed queues add the following valid expressions
namespace boost
{
- template <typename ValueType>
+ template <typename ValueType, class SizeType=std::size_t>
class queue_base
{
public:
typedef ValueType value_type;
- typedef std::size_t size_type;
+ typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base() {};
@@ -671,7 +671,7 @@ Closed queues add the following valid expressions
virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
- virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
+ virtual queue_op_status wait_pull_front(value_type& elem) = 0;
};
}
@@ -685,11 +685,11 @@ Closed queues add the following valid expressions
namespace boost
{
template <typename Queue>
- class queue_adaptor : public queue_base<typename Queue::value_type>
+ class queue_adaptor : public queue_base<typename Queue::value_type, typename Queue::size_type>
{
public:
typedef typename Queue::value_type value_type;
- typedef std::size_t size_type;
+ typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
@@ -1002,13 +1002,13 @@ Closed queues add the following valid expressions
namespace boost
{
- template <typename ValueType>
+ template <typename ValueType, class Container = csbl::devector<ValueType>>
class sync_queue
{
public:
typedef ValueType value_type;
- typedef csbl::deque<ValueType> underlying_queue_type;
- typedef std::size_t size_type;
+ typedef Container underlying_queue_type;
+ typedef typename Container::size_type size_type;
sync_queue(sync_queue const&) = delete;
sync_queue& operator=(sync_queue const&) = delete;
diff --git a/libs/thread/doc/synchronized_value_ref.qbk b/libs/thread/doc/synchronized_value_ref.qbk
index 20b304c807..2826282e18 100644
--- a/libs/thread/doc/synchronized_value_ref.qbk
+++ b/libs/thread/doc/synchronized_value_ref.qbk
@@ -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()`.]]
diff --git a/libs/thread/doc/thread.qbk b/libs/thread/doc/thread.qbk
index 6d33eb5d86..9605234daf 100644
--- a/libs/thread/doc/thread.qbk
+++ b/libs/thread/doc/thread.qbk
@@ -8,10 +8,10 @@
[library Thread
[quickbook 1.5]
- [version 4.4.0]
+ [version 4.5.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
- [copyright 2011-14 Vicente J. Botet Escriba]
+ [copyright 2011-15 Vicente J. Botet Escriba]
[purpose C++ Library for launching threads and synchronizing data between them]
[category text]
[license
@@ -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]
diff --git a/libs/thread/doc/thread_ref.qbk b/libs/thread/doc/thread_ref.qbk
index 9709d5453c..a1e86426f0 100644
--- a/libs/thread/doc/thread_ref.qbk
+++ b/libs/thread/doc/thread_ref.qbk
@@ -125,7 +125,7 @@ the user to set the platform specific attributes. Boost.Thread stay in the middl
thread::attributes which allows to set at least in a portable way the stack size as follows:
boost::thread::attributes attrs;
- attrs.set_size(4096*10);
+ attrs.set_stack_size(4096*10);
boost::thread deep_thought_2(attrs, find_the_question, 42);
Even for this simple attribute there could be portable issues as some platforms could require that the stack size
@@ -147,7 +147,7 @@ Next follows how the user could set the stack size and the scheduling policy on
// ... window version
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
// ... pthread version
- pthread_attr_setschedpolicy(attr.get_native_handle(), SCHED_RR);
+ pthread_attr_setschedpolicy(attr.native_handle(), SCHED_RR);
#else
#error "Boost threads unavailable on this platform"
#endif
@@ -432,12 +432,14 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
class attributes; // EXTENSION
thread() noexcept;
+ ~thread();
+
thread(const thread&) = delete;
thread& operator=(const thread&) = delete;
+ // move support
thread(thread&&) noexcept;
thread& operator=(thread&&) noexcept;
- ~thread();
template <class F>
explicit thread(F f);
@@ -456,10 +458,6 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
template <class F, class ...Args>
explicit thread(attributes& attrs, F&& f, Args&&... args);
- // move support
- thread(thread && x) noexcept;
- thread& operator=(thread && x) noexcept;
-
void swap(thread& x) noexcept;
class id;
diff --git a/libs/thread/example/default_executor.cpp b/libs/thread/example/default_executor.cpp
new file mode 100644
index 0000000000..ccdb387675
--- /dev/null
+++ b/libs/thread/example/default_executor.cpp
@@ -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;
+
+}
diff --git a/libs/thread/example/fib_task_region.cpp b/libs/thread/example/fib_task_region.cpp
new file mode 100644
index 0000000000..1540dc2948
--- /dev/null
+++ b/libs/thread/example/fib_task_region.cpp
@@ -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
diff --git a/libs/thread/example/future_fallback_to.cpp b/libs/thread/example/future_fallback_to.cpp
index d1a3c52fd8..7301b0ae57 100644
--- a/libs/thread/example/future_fallback_to.cpp
+++ b/libs/thread/example/future_fallback_to.cpp
@@ -35,31 +35,83 @@ int p1()
int main()
{
- const int number_of_tests = 100;
+ const int number_of_tests = 200;
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
+
+ {
+ for (int i=0; i< number_of_tests; i++)
+ try
+ {
+ BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
+ boost::future<int> f1 = boost::async(boost::launch::async, &p1);
+ BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
+ f1.wait();
+ BOOST_ASSERT(f1.get()==1);
+ BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
+ }
+ catch (std::exception& ex)
+ {
+ std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
+ BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
+ return 1;
+ }
+ catch (...)
+ {
+ std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
+ BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
+ return 2;
+ }
+ }
+
{
for (int i=0; i< number_of_tests; i++)
try
{
- //boost::future<int> f1 = boost::async(boost::launch::async, &p1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(&p1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f2 = f1.fallback_to(-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f2.wait();
+ //std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
BOOST_ASSERT(f2.get()==1);
+ //std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
+ BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
+ }
+ catch (std::exception& ex)
+ {
+ std::cout << __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_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 << "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;
}
@@ -75,18 +127,20 @@ int main()
boost::future<int> f2 = f1.fallback_to(-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f2.wait();
+ //std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
BOOST_ASSERT(f2.get()==-1);
+ //std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
- std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
+ std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
- std::cout << " ERRORRRRR exception thrown" << std::endl;
+ std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
diff --git a/libs/thread/example/make_future.cpp b/libs/thread/example/make_future.cpp
index 399bb46f53..3b427e39fa 100644
--- a/libs/thread/example/make_future.cpp
+++ b/libs/thread/example/make_future.cpp
@@ -104,6 +104,26 @@ int main()
boost::future<int&> f = compute_ref(0);
std::cout << f.get() << std::endl;
}
+#if __cplusplus > 201103L
+ {
+ std::cout << __FILE__ << " "<< __LINE__ << std::endl;
+ int i = 0;
+ boost::future<int&> f = boost::make_ready_future(std::ref(i));
+ std::cout << f.get() << std::endl;
+ }
+#endif
+ {
+ std::cout << __FILE__ << " "<< __LINE__ << std::endl;
+ int i = 0;
+ boost::future<int&> f = boost::make_ready_future(boost::ref(i));
+ std::cout << f.get() << std::endl;
+ }
+ {
+ std::cout << __FILE__ << " "<< __LINE__ << std::endl;
+ const int i = 0;
+ boost::future<int const&> f = boost::make_ready_future(boost::cref(i));
+ std::cout << f.get() << std::endl;
+ }
// {
// std::cout << __FILE__ << " "<< __LINE__ << std::endl;
// boost::future<int> f = compute(2);
diff --git a/libs/thread/example/producer_consumer.cpp b/libs/thread/example/producer_consumer.cpp
index fb6e16b35e..51979b6c70 100644
--- a/libs/thread/example/producer_consumer.cpp
+++ b/libs/thread/example/producer_consumer.cpp
@@ -22,7 +22,7 @@
typedef std::ostream the_ostream;
typedef std::istream the_istream;
#endif
-#include <boost/thread/sync_queue.hpp>
+#include <boost/thread/concurrent_queues/sync_queue.hpp>
void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
{
@@ -30,9 +30,9 @@ void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
try {
for(int i=0; ;++i)
{
- sbq.push_back(i);
+ sbq.push(i);
//sbq << i;
- mos << "push_back(" << i << ") "<< sbq.size()<<"\n";
+ mos << "push(" << i << ") "<< sbq.size()<<"\n";
this_thread::sleep_for(chrono::milliseconds(200));
}
}
@@ -55,7 +55,7 @@ void consumer(
for(int i=0; ;++i)
{
int r;
- sbq.pull_front(r);
+ sbq.pull(r);
//sbq >> r;
mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
@@ -78,7 +78,7 @@ void consumer2(the_ostream &mos, boost::sync_queue<int> & sbq)
for(int i=0; ;++i)
{
int r;
- queue_op_status st = sbq.try_pull_front(r);
+ queue_op_status st = sbq.try_pull(r);
if (queue_op_status::closed == st) break;
if (queue_op_status::success == st) {
mos << i << " pull(" << r << ")\n";
@@ -98,9 +98,9 @@ void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
for(int i=0; ;++i)
{
int r;
- queue_op_status res = sbq.wait_pull_front(r);
+ queue_op_status res = sbq.wait_pull(r);
if (res==queue_op_status::closed) break;
- mos << i << " wait_pull_front(" << r << ")\n";
+ mos << i << " wait_pull(" << r << ")\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
diff --git a/libs/thread/example/producer_consumer2.cpp b/libs/thread/example/producer_consumer2.cpp
index 110cbbab32..9e3ad976c1 100644
--- a/libs/thread/example/producer_consumer2.cpp
+++ b/libs/thread/example/producer_consumer2.cpp
@@ -21,7 +21,7 @@
typedef std::ostream the_ostream;
typedef std::istream the_istream;
#endif
-#include <boost/thread/sync_queue.hpp>
+#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
#include <boost/thread/concurrent_queues/queue_views.hpp>
#include <boost/static_assert.hpp>
diff --git a/libs/thread/example/serial_executor.cpp b/libs/thread/example/serial_executor.cpp
new file mode 100644
index 0000000000..ad25e822ee
--- /dev/null
+++ b/libs/thread/example/serial_executor.cpp
@@ -0,0 +1,113 @@
+// Copyright (C) 2015 Vicente J. Botet Escriba
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config.hpp>
+#if ! defined BOOST_NO_CXX11_DECLTYPE
+#define BOOST_RESULT_OF_USE_DECLTYPE
+#endif
+
+#define BOOST_THREAD_VERSION 4
+#define BOOST_THREAD_PROVIDES_EXECUTORS
+//#define BOOST_THREAD_USES_LOG
+#define BOOST_THREAD_USES_LOG_THREAD_ID
+#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
+
+#include <boost/thread/caller_context.hpp>
+#include <boost/thread/executors/basic_thread_pool.hpp>
+#include <boost/thread/executors/serial_executor.hpp>
+#include <boost/thread/executors/executor.hpp>
+#include <boost/thread/executors/executor_adaptor.hpp>
+#include <boost/thread/executor.hpp>
+#include <boost/thread/future.hpp>
+#include <boost/assert.hpp>
+#include <string>
+#include <iostream>
+
+void p1()
+{
+ std::cout << BOOST_CONTEXTOF << std::endl;
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(30));
+ std::cout << BOOST_CONTEXTOF << std::endl;
+}
+
+void p2()
+{
+ std::cout << BOOST_CONTEXTOF << std::endl;
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
+ std::cout << BOOST_CONTEXTOF << std::endl;
+}
+
+int f1()
+{
+ // std::cout << BOOST_CONTEXTOF << std::endl;
+ boost::this_thread::sleep_for(boost::chrono::seconds(1));
+ return 1;
+}
+int f2(int i)
+{
+ // std::cout << BOOST_CONTEXTOF << std::endl;
+ boost::this_thread::sleep_for(boost::chrono::seconds(2));
+ return i + 1;
+}
+
+void submit_some(boost::serial_executor& tp)
+{
+ std::cout << BOOST_CONTEXTOF << std::endl;
+ for (int i = 0; i < 3; ++i) {
+ std::cout << BOOST_CONTEXTOF << std::endl;
+ tp.submit(&p2);
+ }
+ for (int i = 0; i < 3; ++i) {
+ std::cout << BOOST_CONTEXTOF << std::endl;
+ tp.submit(&p1);
+ }
+ std::cout << BOOST_CONTEXTOF << std::endl;
+
+}
+
+
+void at_th_entry(boost::basic_thread_pool& )
+{
+
+}
+
+int test_executor_adaptor()
+{
+ // std::cout << BOOST_CONTEXTOF << std::endl;
+ {
+ try
+ {
+
+#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ // std::cout << BOOST_CONTEXTOF << std::endl;
+ {
+ boost::basic_thread_pool ea1(4);
+ boost::serial_executor ea2(ea1);
+ submit_some(ea2);
+ boost::this_thread::sleep_for(boost::chrono::seconds(10));
+ }
+#endif
+ // std::cout << BOOST_CONTEXTOF << std::endl;
+ }
+ catch (std::exception& ex)
+ {
+ std::cout << "ERROR= " << ex.what() << "" << std::endl;
+ return 1;
+ }
+ catch (...)
+ {
+ std::cout << " ERROR= exception thrown" << std::endl;
+ return 2;
+ }
+ }
+ // std::cout << BOOST_CONTEXTOF << std::endl;
+ return 0;
+}
+
+
+int main()
+{
+ return test_executor_adaptor();
+}
diff --git a/libs/thread/example/serial_executor_cont.cpp b/libs/thread/example/serial_executor_cont.cpp
new file mode 100644
index 0000000000..1883b07182
--- /dev/null
+++ b/libs/thread/example/serial_executor_cont.cpp
@@ -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();
+}
diff --git a/libs/thread/example/this_executor.cpp b/libs/thread/example/this_executor.cpp
new file mode 100644
index 0000000000..feeebf854f
--- /dev/null
+++ b/libs/thread/example/this_executor.cpp
@@ -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;
+
+}
diff --git a/libs/thread/src/future.cpp b/libs/thread/src/future.cpp
index 0b990c1011..4aeac94a1b 100644
--- a/libs/thread/src/future.cpp
+++ b/libs/thread/src/future.cpp
@@ -7,7 +7,7 @@
#ifndef BOOST_NO_EXCEPTIONS
-#include <boost/thread/future_error_code.hpp>
+#include <boost/thread/futures/future_error_code.hpp>
#include <string>
namespace boost
diff --git a/libs/thread/src/pthread/thread.cpp b/libs/thread/src/pthread/thread.cpp
index 4eab832b40..bbd25493f5 100644
--- a/libs/thread/src/pthread/thread.cpp
+++ b/libs/thread/src/pthread/thread.cpp
@@ -36,8 +36,6 @@
#include <set>
#include <vector>
-#include "./timeconv.inl"
-
namespace boost
{
namespace detail
@@ -98,13 +96,10 @@ namespace boost
}
delete current_node;
}
- for(std::map<void const*,tss_data_node>::iterator next=thread_info->tss_data.begin(),
- current,
- end=thread_info->tss_data.end();
- next!=end;)
+ while (!thread_info->tss_data.empty())
{
- current=next;
- ++next;
+ std::map<void const*,detail::tss_data_node>::iterator current
+ = thread_info->tss_data.begin();
if(current->second.func && (current->second.value!=0))
{
(*current->second.func)(current->second.value);
@@ -164,7 +159,7 @@ namespace boost
static void* thread_proxy(void* param)
{
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
- thread_info->self.reset();
+ //thread_info->self.reset();
detail::set_current_thread_data(thread_info.get());
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
BOOST_TRY
diff --git a/libs/thread/src/pthread/timeconv.inl b/libs/thread/src/pthread/timeconv.inl
deleted file mode 100644
index d81f31ba2e..0000000000
--- a/libs/thread/src/pthread/timeconv.inl
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-// Copyright (C) 2009 Anthony Williams
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-// boostinspect:nounnamed
-
-#include <boost/assert.hpp>
-
-namespace {
-const int MILLISECONDS_PER_SECOND = 1000;
-const int NANOSECONDS_PER_SECOND = 1000000000;
-const int NANOSECONDS_PER_MILLISECOND = 1000000;
-
-const int MICROSECONDS_PER_SECOND = 1000000;
-const int NANOSECONDS_PER_MICROSECOND = 1000;
-
-#if defined BOOST_THREAD_USES_DATETIME
-inline void to_time(int milliseconds, boost::xtime& xt)
-{
- int res = 0;
- res = boost::xtime_get(&xt, boost::TIME_UTC_);
- BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
-
- xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
- xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
- NANOSECONDS_PER_MILLISECOND);
-
- if (xt.nsec >= NANOSECONDS_PER_SECOND)
- {
- ++xt.sec;
- xt.nsec -= NANOSECONDS_PER_SECOND;
- }
-}
-#endif
-#if defined(BOOST_HAS_PTHREADS)
-#if defined BOOST_THREAD_USES_DATETIME
-inline void to_timespec(const boost::xtime& xt, timespec& ts)
-{
- ts.tv_sec = static_cast<int>(xt.sec);
- ts.tv_nsec = static_cast<int>(xt.nsec);
- if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
- {
- ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
- ts.tv_nsec %= NANOSECONDS_PER_SECOND;
- }
-}
-#endif
-inline void to_time(int milliseconds, timespec& ts)
-{
-#if defined BOOST_THREAD_USES_DATETIME
- boost::xtime xt;
- to_time(milliseconds, xt);
- to_timespec(xt, ts);
-#else
- ts.tv_sec += (milliseconds / MILLISECONDS_PER_SECOND);
- ts.tv_nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
- NANOSECONDS_PER_MILLISECOND);
-
- if (ts.tv_nsec >= NANOSECONDS_PER_SECOND)
- {
- ++ts.tv_sec;
- ts.tv_nsec -= NANOSECONDS_PER_SECOND;
- }
-#endif
-}
-
-#if defined BOOST_THREAD_USES_DATETIME
-inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)
-{
- boost::xtime cur;
- int res = 0;
- res = boost::xtime_get(&cur, boost::TIME_UTC_);
- BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
-
- if (boost::xtime_cmp(xt, cur) <= 0)
- {
- ts.tv_sec = 0;
- ts.tv_nsec = 0;
- }
- else
- {
- ts.tv_sec = xt.sec - cur.sec;
- ts.tv_nsec = xt.nsec - cur.nsec;
-
- if( ts.tv_nsec < 0 )
- {
- ts.tv_sec -= 1;
- ts.tv_nsec += NANOSECONDS_PER_SECOND;
- }
- if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
- {
- ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
- ts.tv_nsec %= NANOSECONDS_PER_SECOND;
- }
- }
-}
-#endif
-#endif
-
-#if defined BOOST_THREAD_USES_DATETIME
-inline void to_duration(boost::xtime xt, int& milliseconds)
-{
- boost::xtime cur;
- int res = 0;
- res = boost::xtime_get(&cur, boost::TIME_UTC_);
- BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
-
- if (boost::xtime_cmp(xt, cur) <= 0)
- milliseconds = 0;
- else
- {
- if (cur.nsec > xt.nsec)
- {
- xt.nsec += NANOSECONDS_PER_SECOND;
- --xt.sec;
- }
- milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
- (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
- NANOSECONDS_PER_MILLISECOND);
- }
-}
-
-inline void to_microduration(boost::xtime xt, int& microseconds)
-{
- boost::xtime cur;
- int res = 0;
- res = boost::xtime_get(&cur, boost::TIME_UTC_);
- BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
-
- if (boost::xtime_cmp(xt, cur) <= 0)
- microseconds = 0;
- else
- {
- if (cur.nsec > xt.nsec)
- {
- xt.nsec += NANOSECONDS_PER_SECOND;
- --xt.sec;
- }
- microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
- (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) /
- NANOSECONDS_PER_MICROSECOND);
- }
-}
-#endif
-}
-
-// Change Log:
-// 1 Jun 01 Initial creation.
diff --git a/libs/thread/src/win32/thread.cpp b/libs/thread/src/win32/thread.cpp
index ed2c10bfaf..f23cf29a1d 100644
--- a/libs/thread/src/win32/thread.cpp
+++ b/libs/thread/src/win32/thread.cpp
@@ -44,7 +44,7 @@
#include <wrl\ftm.h>
#include <windows.system.threading.h>
#pragma comment(lib, "runtimeobject.lib")
-#endif
+#endif
namespace boost
{
@@ -198,7 +198,7 @@ namespace boost
namespace detail
{
std::atomic_uint threadCount;
-
+
bool win32::scoped_winrt_thread::start(thread_func address, void *parameter, unsigned int *thrdId)
{
Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IThreadPoolStatics> threadPoolFactory;
@@ -220,7 +220,7 @@ namespace boost
m_completionHandle = completionHandle;
// Create new work item.
- Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem =
+ Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem =
Microsoft::WRL::Callback<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::System::Threading::IWorkItemHandler, Microsoft::WRL::FtmBase>>
([address, parameter, completionHandle](ABI::Windows::Foundation::IAsyncAction *)
{
@@ -274,13 +274,10 @@ namespace boost
}
boost::detail::heap_delete(current_node);
}
- for(std::map<void const*,detail::tss_data_node>::iterator next=current_thread_data->tss_data.begin(),
- current,
- end=current_thread_data->tss_data.end();
- next!=end;)
+ while (!current_thread_data->tss_data.empty())
{
- current=next;
- ++next;
+ std::map<void const*,detail::tss_data_node>::iterator current
+ = current_thread_data->tss_data.begin();
if(current->second.func && (current->second.value!=0))
{
(*current->second.func)(current->second.value);
@@ -346,7 +343,7 @@ namespace boost
return true;
#endif
}
-
+
bool thread::start_thread_noexcept(const attributes& attr)
{
#if BOOST_PLAT_WINDOWS_RUNTIME
@@ -367,7 +364,7 @@ namespace boost
return true;
#endif
}
-
+
thread::thread(detail::thread_data_ptr data):
thread_info(data)
{}
@@ -529,11 +526,10 @@ namespace boost
unsigned thread::physical_concurrency() BOOST_NOEXCEPT
{
-#if BOOST_PLAT_WINDOWS_RUNTIME
+#if BOOST_PLAT_WINDOWS_RUNTIME || (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
return hardware_concurrency();
#else
unsigned cores = 0;
-#if !(defined(__MINGW32__) || defined (__MINGW64__))
DWORD size = 0;
GetLogicalProcessorInformation(NULL, &size);
@@ -550,7 +546,6 @@ namespace boost
if (buffer[i].Relationship == RelationProcessorCore)
++cores;
}
-#endif
return cores;
#endif
}
@@ -633,10 +628,60 @@ namespace boost
}
}
-
+#ifndef UNDER_CE
+#if !BOOST_PLAT_WINDOWS_RUNTIME
+ namespace detail_
+ {
+ typedef struct _REASON_CONTEXT {
+ ULONG Version;
+ DWORD Flags;
+ union {
+ LPWSTR SimpleReasonString;
+ struct {
+ HMODULE LocalizedReasonModule;
+ ULONG LocalizedReasonId;
+ ULONG ReasonStringCount;
+ LPWSTR *ReasonStrings;
+ } Detailed;
+ } Reason;
+ } REASON_CONTEXT, *PREASON_CONTEXT;
+ static REASON_CONTEXT default_reason_context={0/*POWER_REQUEST_CONTEXT_VERSION*/, 0x00000001/*POWER_REQUEST_CONTEXT_SIMPLE_STRING*/, (LPWSTR)L"generic"};
+ typedef BOOL (WINAPI *setwaitabletimerex_t)(HANDLE, const LARGE_INTEGER *, LONG, PTIMERAPCROUTINE, LPVOID, PREASON_CONTEXT, ULONG);
+ static inline BOOL WINAPI SetWaitableTimerEx_emulation(HANDLE hTimer, const LARGE_INTEGER *lpDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext, ULONG TolerableDelay)
+ {
+ return SetWaitableTimer(hTimer, lpDueTime, lPeriod, pfnCompletionRoutine, lpArgToCompletionRoutine, FALSE);
+ }
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 6387) // MSVC sanitiser warns that GetModuleHandleA() might fail
+#endif
+ static inline setwaitabletimerex_t SetWaitableTimerEx()
+ {
+ static setwaitabletimerex_t setwaitabletimerex_impl;
+ if(setwaitabletimerex_impl)
+ return setwaitabletimerex_impl;
+ void (*addr)()=(void (*)()) GetProcAddress(
+#if !defined(BOOST_NO_ANSI_APIS)
+ GetModuleHandleA("KERNEL32.DLL"),
+#else
+ GetModuleHandleW(L"KERNEL32.DLL"),
+#endif
+ "SetWaitableTimerEx");
+ if(addr)
+ setwaitabletimerex_impl=(setwaitabletimerex_t) addr;
+ else
+ setwaitabletimerex_impl=&SetWaitableTimerEx_emulation;
+ return setwaitabletimerex_impl;
+ }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+ }
+#endif
+#endif
bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
{
- detail::win32::handle handles[3]={0};
+ detail::win32::handle handles[4]={0};
unsigned handle_count=0;
unsigned wait_handle_index=~0U;
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
@@ -659,32 +704,24 @@ namespace boost
#ifndef UNDER_CE
#if !BOOST_PLAT_WINDOWS_RUNTIME
- unsigned const min_timer_wait_period=20;
-
+ // Preferentially use coalescing timers for better power consumption and timer accuracy
if(!target_time.is_sentinel())
{
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
- if(time_left.milliseconds > min_timer_wait_period)
+ timer_handle=CreateWaitableTimer(NULL,false,NULL);
+ if(timer_handle!=0)
{
- // for a long-enough timeout, use a waitable timer (which tracks clock changes)
- timer_handle=CreateWaitableTimer(NULL,false,NULL);
- if(timer_handle!=0)
+ ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
+ if(time_left.milliseconds/20>tolerable) // 5%
+ tolerable=time_left.milliseconds/20;
+ LARGE_INTEGER due_time=get_due_time(target_time);
+ bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
+ if(set_time_succeeded)
{
- LARGE_INTEGER due_time=get_due_time(target_time);
-
- bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
- if(set_time_succeeded)
- {
- timeout_index=handle_count;
- handles[handle_count++]=timer_handle;
- }
+ timeout_index=handle_count;
+ handles[handle_count++]=timer_handle;
}
}
- else if(!target_time.relative)
- {
- // convert short absolute-time timeouts into relative ones, so we don't race against clock changes
- target_time=detail::timeout(time_left.milliseconds);
- }
}
#endif
#endif
@@ -751,32 +788,24 @@ namespace boost
#ifndef UNDER_CE
#if !BOOST_PLAT_WINDOWS_RUNTIME
- unsigned const min_timer_wait_period=20;
-
+ // Preferentially use coalescing timers for better power consumption and timer accuracy
if(!target_time.is_sentinel())
{
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
- if(time_left.milliseconds > min_timer_wait_period)
+ timer_handle=CreateWaitableTimer(NULL,false,NULL);
+ if(timer_handle!=0)
{
- // for a long-enough timeout, use a waitable timer (which tracks clock changes)
- timer_handle=CreateWaitableTimer(NULL,false,NULL);
- if(timer_handle!=0)
+ ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
+ if(time_left.milliseconds/20>tolerable) // 5%
+ tolerable=time_left.milliseconds/20;
+ LARGE_INTEGER due_time=get_due_time(target_time);
+ bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
+ if(set_time_succeeded)
{
- LARGE_INTEGER due_time=get_due_time(target_time);
-
- bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
- if(set_time_succeeded)
- {
- timeout_index=handle_count;
- handles[handle_count++]=timer_handle;
- }
+ timeout_index=handle_count;
+ handles[handle_count++]=timer_handle;
}
}
- else if(!target_time.relative)
- {
- // convert short absolute-time timeouts into relative ones, so we don't race against clock changes
- target_time=detail::timeout(time_left.milliseconds);
- }
}
#endif
#endif
diff --git a/libs/thread/src/win32/timeconv.inl b/libs/thread/src/win32/timeconv.inl
deleted file mode 100644
index c6467832a7..0000000000
--- a/libs/thread/src/win32/timeconv.inl
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-// boostinspect:nounnamed
-
-namespace {
-const int MILLISECONDS_PER_SECOND = 1000;
-const int NANOSECONDS_PER_SECOND = 1000000000;
-const int NANOSECONDS_PER_MILLISECOND = 1000000;
-
-const int MICROSECONDS_PER_SECOND = 1000000;
-const int NANOSECONDS_PER_MICROSECOND = 1000;
-
-inline void to_time(int milliseconds, boost::xtime& xt)
-{
- int res = 0;
- res = boost::xtime_get(&xt, boost::TIME_UTC_);
- assert(res == boost::TIME_UTC_);
-
- xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
- xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
- NANOSECONDS_PER_MILLISECOND);
-
- if (xt.nsec >= NANOSECONDS_PER_SECOND)
- {
- ++xt.sec;
- xt.nsec -= NANOSECONDS_PER_SECOND;
- }
-}
-
-#if defined(BOOST_HAS_PTHREADS)
-inline void to_timespec(const boost::xtime& xt, timespec& ts)
-{
- ts.tv_sec = static_cast<int>(xt.sec);
- ts.tv_nsec = static_cast<int>(xt.nsec);
- if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
- {
- ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
- ts.tv_nsec %= NANOSECONDS_PER_SECOND;
- }
-}
-
-inline void to_time(int milliseconds, timespec& ts)
-{
- boost::xtime xt;
- to_time(milliseconds, xt);
- to_timespec(xt, ts);
-}
-
-inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)
-{
- boost::xtime cur;
- int res = 0;
- res = boost::xtime_get(&cur, boost::TIME_UTC_);
- assert(res == boost::TIME_UTC_);
-
- if (boost::xtime_cmp(xt, cur) <= 0)
- {
- ts.tv_sec = 0;
- ts.tv_nsec = 0;
- }
- else
- {
- ts.tv_sec = xt.sec - cur.sec;
- ts.tv_nsec = xt.nsec - cur.nsec;
-
- if( ts.tv_nsec < 0 )
- {
- ts.tv_sec -= 1;
- ts.tv_nsec += NANOSECONDS_PER_SECOND;
- }
- if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
- {
- ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
- ts.tv_nsec %= NANOSECONDS_PER_SECOND;
- }
- }
-}
-#endif
-
-inline void to_duration(boost::xtime xt, int& milliseconds)
-{
- boost::xtime cur;
- int res = 0;
- res = boost::xtime_get(&cur, boost::TIME_UTC_);
- assert(res == boost::TIME_UTC_);
-
- if (boost::xtime_cmp(xt, cur) <= 0)
- milliseconds = 0;
- else
- {
- if (cur.nsec > xt.nsec)
- {
- xt.nsec += NANOSECONDS_PER_SECOND;
- --xt.sec;
- }
- milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
- (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
- NANOSECONDS_PER_MILLISECOND);
- }
-}
-
-inline void to_microduration(boost::xtime xt, int& microseconds)
-{
- boost::xtime cur;
- int res = 0;
- res = boost::xtime_get(&cur, boost::TIME_UTC_);
- assert(res == boost::TIME_UTC_);
-
- if (boost::xtime_cmp(xt, cur) <= 0)
- microseconds = 0;
- else
- {
- if (cur.nsec > xt.nsec)
- {
- xt.nsec += NANOSECONDS_PER_SECOND;
- --xt.sec;
- }
- microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
- (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) /
- NANOSECONDS_PER_MICROSECOND);
- }
-}
-}
-
-// Change Log:
-// 1 Jun 01 Initial creation.
diff --git a/libs/thread/src/win32/tss_dll.cpp b/libs/thread/src/win32/tss_dll.cpp
index 2dc019f4bb..e0b73e0fc1 100644
--- a/libs/thread/src/win32/tss_dll.cpp
+++ b/libs/thread/src/win32/tss_dll.cpp
@@ -73,5 +73,13 @@ namespace boost
}
}
+#else //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
+
+#ifdef _MSC_VER
+// Prevent LNK4221 warning with link=static
+namespace boost { namespace link_static_warning_inhibit {
+ extern __declspec(dllexport) void foo() { }
+} }
+#endif
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
diff --git a/libs/thread/test/Jamfile.v2 b/libs/thread/test/Jamfile.v2
index 37cc72c508..22f526501e 100644
--- a/libs/thread/test/Jamfile.v2
+++ b/libs/thread/test/Jamfile.v2
@@ -34,6 +34,7 @@ project
<toolset>gcc:<cxxflags>-Wno-variadic-macros
#<toolset>gcc:<cxxflags>-Wunused-local-typedefs
<toolset>gcc:<cxxflags>-Wunused-function
+ <toolset>gcc:<cxxflags>-Wno-unused-parameter
<toolset>darwin:<cxxflags>-Wextra
<toolset>darwin:<cxxflags>-pedantic
@@ -43,18 +44,20 @@ project
<toolset>darwin:<cxxflags>-Wno-variadic-macros
#<toolset>darwin:<cxxflags>-Wunused-local-typedefs
<toolset>darwin:<cxxflags>-Wunused-function
+ <toolset>darwin:<cxxflags>-Wno-unused-parameter
#<toolset>pathscale:<cxxflags>-Wextra
<toolset>pathscale:<cxxflags>-Wno-long-long
<toolset>pathscale:<cxxflags>-pedantic
+ <toolset>clang:<warnings>on
<toolset>clang:<cxxflags>-Wextra
#<toolset>clang:<cxxflags>-pedantic
- <toolset>clang:<warnings>on
<toolset>clang:<cxxflags>-Wno-long-long
#<toolset>clang:<cxxflags>-ansi
#<toolset>clang:<cxxflags>-fpermissive # doesn't work
<toolset>clang:<cxxflags>-Wunused-function
+ <toolset>clang:<cxxflags>-Wno-unused-parameter
#<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
#<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
@@ -97,6 +100,10 @@ project
<toolset>intel:<cxxflags>-wd593,981
<toolset>intel:<cxxflags>-wd1418
<toolset>intel:<cxxflags>-wd2415
+
+ <toolset>msvc:<cxxflags>/wd4100
+ <toolset>msvc:<cxxflags>/wd4512
+ <toolset>msvc:<cxxflags>/wd6246
;
rule thread-run ( sources )
@@ -115,7 +122,7 @@ rule thread-test ( sources )
sources = $(sources) winrt_init.cpp ;
return
[ run $(sources) ../build//boost_thread : : :
- <library>/boost/test//boost_unit_test_framework/<link>static
+ <library>/boost/test//boost_unit_test_framework
]
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
: : :
@@ -286,8 +293,11 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run test_7328.cpp ]
[ thread-run test_7571.cpp ]
[ thread-run test_9319.cpp ]
- [ thread-run test_9711.cpp ]
-
+ #[ thread-run test_9711.cpp ] This is an invalid use of ::then deferred.
+ [ thread-run test_9856.cpp ]
+ [ thread-compile test_10963.cpp : : test_10963_c ]
+ [ thread-run test_10964.cpp ]
+ [ thread-test test_11053.cpp ]
;
@@ -349,6 +359,7 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2-noit ./sync/futures/promise/set_rvalue_pass.cpp : promise__set_rvalue_p ]
[ thread-run2-noit ./sync/futures/promise/set_value_const_pass.cpp : promise__set_value_const_p ]
[ thread-run2-noit ./sync/futures/promise/set_value_void_pass.cpp : promise__set_value_void_p ]
+ [ thread-run2-noit ./sync/futures/promise/emplace_pass.cpp : promise__emplace_p ]
[ thread-run2-noit ./sync/futures/promise/use_allocator_pass.cpp : promise__use_allocator_p ]
[ thread-run2-noit ./sync/futures/promise/set_exception_at_thread_exit_pass.cpp : promise__set_exception_at_thread_exit_p ]
[ thread-run2-noit ./sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp : promise__set_lvalue_at_thread_exit_p ]
@@ -357,6 +368,12 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2-noit ./sync/futures/promise/set_value_at_thread_exit_void_pass.cpp : promise__set_value_at_thread_exit_void_p ]
;
+ #explicit ts_make_ready_future ;
+ test-suite ts_make_ready_future
+ :
+ [ thread-run2-noit ./sync/futures/make_ready_future_pass.cpp : make_ready_future_p ]
+ ;
+
#explicit ts_future ;
test-suite ts_future
:
@@ -669,18 +686,49 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2-noit ./sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp : sync_queue__multi_thread_p ]
;
+ test-suite ts_sync_deque
+ :
+ [ thread-run2-noit ./sync/mutual_exclusion/sync_deque/single_thread_pass.cpp : sync_deque__single_thread_p ]
+ [ thread-run2-noit ./sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp : sync_deque__multi_thread_p ]
+ ;
+
test-suite ts_sync_bounded_queue
:
[ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp : sync_bounded_q_single_thread_p ]
[ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp : sync_bounded_q_multi_thread_p ]
;
+ test-suite ts_sync_pq
+ :
+ [ thread-run2-noit ./sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp : sync_pq_single_thread_p ]
+ [ thread-run2-noit ./sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp : sync_pq_multi_thread_p ]
+ ;
+
+ test-suite ts_sync_tq
+ :
+ [ thread-run2-noit ./sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp : sync_tq_single_thread_p ]
+ #[ thread-run2-noit ./sync/mutual_exclusion/sync_pq/tq_multi_thread_pass.cpp : sync_tq_multi_thread_p ]
+ ;
+
+ test-suite ts_scheduler
+ :
+ [ thread-run2-noit ./test_scheduled_tp.cpp : test_scheduled_tp_p ]
+ [ thread-run2-noit ./test_scheduling_adaptor.cpp : test_scheduling_adaptor_p ]
+ [ thread-run2-noit ./test_scheduler.cpp : test_scheduler_p ]
+ ;
+
test-suite ts_queue_views
:
[ thread-run2-noit ./sync/mutual_exclusion/queue_views/single_thread_pass.cpp : queue_views__single_thread_p ]
#[ thread-run2-noit ./sync/mutual_exclusion/queue_views/multi_thread_pass.cpp : queue_views__multi_thread_p ]
;
+ test-suite ts_deque_views
+ :
+ [ thread-run2-noit ./sync/mutual_exclusion/deque_views/single_thread_pass.cpp : deque_views__single_thread_p ]
+ #[ thread-run2-noit ./sync/mutual_exclusion/deque_views/multi_thread_pass.cpp : deque_views__multi_thread_p ]
+ ;
+
#explicit ts_this_thread ;
test-suite ts_this_thread
:
@@ -761,11 +809,13 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2 ../example/user_scheduler.cpp : ex_user_scheduler ]
[ thread-run2 ../example/executor.cpp : ex_executor ]
[ thread-run2 ../example/generic_executor_ref.cpp : ex_generic_executor_ref ]
+ [ thread-run2 ../example/serial_executor.cpp : ex_serial_executor ]
+ [ thread-run2 ../example/serial_executor_cont.cpp : ex_serial_executor_cont ]
[ thread-run2 ../example/future_when_all.cpp : ex_future_when_all ]
[ thread-run2 ../example/parallel_accumulate.cpp : ex_parallel_accumulate ]
[ thread-run2 ../example/parallel_quick_sort.cpp : ex_parallel_quick_sort ]
[ thread-run2 ../example/with_lock_guard.cpp : ex_with_lock_guard ]
-
+ [ thread-run2 ../example/fib_task_region.cpp : ex_fib_task_region ]
;
#explicit ts_shared_upwards ;
@@ -883,10 +933,25 @@ rule thread-compile ( sources : reqs * : name )
#[ thread-run ../example/perf_condition_variable.cpp ]
#[ thread-run ../example/perf_shared_mutex.cpp ]
;
+
+
+ #explicit ts_exception_list ;
+ test-suite ts_exception_list
+ :
+ [ thread-run2-noit ./experimental/parallel/v1/exception_list_pass.cpp : exception_list_p ]
+ ;
+
+ #explicit ts_task_region ;
+ test-suite ts_task_region
+ :
+ [ thread-run2-noit ./experimental/parallel/v2/task_region_pass.cpp : task_region_p ]
+ ;
explicit ts_ ;
test-suite ts_
:
+ [ thread-run2 ../example/this_executor.cpp : ex_this_executor ]
+ [ thread-run2 ../example/default_executor.cpp : ex_default_executor ]
;
}
diff --git a/libs/thread/test/experimental/parallel/v1/exception_list_pass.cpp b/libs/thread/test/experimental/parallel/v1/exception_list_pass.cpp
new file mode 100644
index 0000000000..de79412ae5
--- /dev/null
+++ b/libs/thread/test/experimental/parallel/v1/exception_list_pass.cpp
@@ -0,0 +1,23 @@
+// Copyright (C) 2014 Vicente J. Botet Escriba
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// <boost/thread/experimental/parallel/v1/exception_list.hpp>
+
+
+#define BOOST_THREAD_VERSION 4
+#include <boost/config.hpp>
+#if ! defined BOOST_NO_CXX11_DECLTYPE
+#define BOOST_RESULT_OF_USE_DECLTYPE
+#endif
+
+#include <boost/thread/experimental/parallel/v1/exception_list.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+
+int main()
+{
+ return boost::report_errors();
+}
diff --git a/libs/thread/test/experimental/parallel/v2/task_region_pass.cpp b/libs/thread/test/experimental/parallel/v2/task_region_pass.cpp
new file mode 100644
index 0000000000..814ef28e5b
--- /dev/null
+++ b/libs/thread/test/experimental/parallel/v2/task_region_pass.cpp
@@ -0,0 +1,295 @@
+// 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)
+
+// <boost/thread/experimental/parallel/v1/exception_list.hpp>
+
+
+#define BOOST_THREAD_VERSION 4
+#define BOOST_THREAD_PROVIDES_EXECUTORS
+#include <boost/config.hpp>
+#if ! defined BOOST_NO_CXX11_DECLTYPE
+#define BOOST_RESULT_OF_USE_DECLTYPE
+#endif
+
+#include <boost/thread/experimental/parallel/v2/task_region.hpp>
+#include <string>
+
+#include <boost/detail/lightweight_test.hpp>
+
+#if ! defined BOOST_NO_CXX11_LAMBDAS && defined(BOOST_THREAD_PROVIDES_INVOKE)
+using boost::experimental::parallel::v2::task_region;
+using boost::experimental::parallel::v2::task_region_handle;
+using boost::experimental::parallel::v1::exception_list;
+
+void run_no_exception()
+{
+ std::string s("test");
+ bool parent_flag = false;
+ bool task1_flag = false;
+ bool task2_flag = false;
+ bool task21_flag = false;
+ bool task3_flag = false;
+ task_region([&](task_region_handle& trh)
+ {
+ parent_flag = true;
+ trh.run([&]()
+ {
+ task1_flag = true;
+ std::cout << "task1: " << s << std::endl;
+ });
+ trh.run([&]()
+ {
+ task2_flag = true;
+ std::cout << "task2" << std::endl;
+ task_region([&](task_region_handle& trh)
+ {
+ trh.run([&]()
+ {
+ task21_flag = true;
+ std::cout << "task2.1" << std::endl;
+ });
+ });
+ });
+ int i = 0, j = 10, k = 20;
+ trh.run([=, &task3_flag]()
+ {
+ task3_flag = true;
+ std::cout << "task3: " << i << " " << j << " " << k << std::endl;
+ });
+ std::cout << "parent" << std::endl;
+ });
+ BOOST_TEST(parent_flag);
+ BOOST_TEST(task1_flag);
+ BOOST_TEST(task2_flag);
+ BOOST_TEST(task21_flag);
+ BOOST_TEST(task3_flag);
+}
+
+void run_no_exception_wait()
+{
+ std::string s("test");
+ bool parent_flag = false;
+ bool wait_flag = false;
+ bool task1_flag = false;
+ bool task2_flag = false;
+ bool task21_flag = false;
+ bool task3_flag = false;
+ task_region([&](task_region_handle& trh)
+ {
+ parent_flag = true;
+ trh.run([&]()
+ {
+ task1_flag = true;
+ std::cout << "task1: " << s << std::endl;
+ });
+ trh.run([&]()
+ {
+ task2_flag = true;
+ std::cout << "task2" << std::endl;
+ task_region([&](task_region_handle& trh)
+ {
+ trh.run([&]()
+ {
+ task21_flag = true;
+ std::cout << "task2.1" << std::endl;
+ });
+ });
+ });
+ int i = 0, j = 10, k = 20;
+ trh.run([=, &task3_flag]()
+ {
+ task3_flag = true;
+ std::cout << "task3: " << i << " " << j << " " << k << std::endl;
+ });
+ std::cout << "before" << std::endl;
+ trh.wait();
+ wait_flag = true;
+ std::cout << "parent" << std::endl;
+ });
+ BOOST_TEST(parent_flag);
+ BOOST_TEST(wait_flag);
+ BOOST_TEST(task1_flag);
+ BOOST_TEST(task2_flag);
+ BOOST_TEST(task21_flag);
+ BOOST_TEST(task3_flag);
+}
+
+void run_exception_1()
+{
+ try
+ {
+ task_region([](task_region_handle& trh)
+ {
+ trh.run([]()
+ {
+ std::cout << "task1" << std::endl;
+ throw 1;
+ });
+ boost::this_thread::sleep_for(boost::chrono::seconds(1));
+ trh.run([]()
+ {
+ std::cout << "task3" << std::endl;
+ });
+#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
+ BOOST_TEST(false);
+#endif
+ });
+ BOOST_TEST(false);
+ }
+ catch (exception_list const& e)
+ {
+ BOOST_TEST_EQ(e.size(), 1u);
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+}
+
+void run_exception()
+{
+ try
+ {
+ task_region([](task_region_handle& trh)
+ {
+ trh.run([]()
+ {
+ std::cout << "task1" << std::endl;
+ throw 1;
+ });
+ trh.run([]()
+ {
+ std::cout << "task2" << std::endl;
+ throw 2;
+ });
+ boost::this_thread::sleep_for(boost::chrono::seconds(1));
+ trh.run([]()
+ {
+ std::cout << "task3" << std::endl;
+ throw 3;
+ });
+ std::cout << "parent" << std::endl;
+ throw 100;
+ });
+ BOOST_TEST(false);
+ }
+ catch (exception_list const& el)
+ {
+ BOOST_TEST(el.size() >= 1u);
+ for (boost::exception_ptr const& e: el)
+ {
+ try {
+ boost::rethrow_exception(e);
+ }
+ catch (boost::exception&)
+ {
+ BOOST_TEST(true);
+ }
+ catch (int i) // this doesn't works yet
+ {
+ BOOST_TEST((i == 1) || (i == 2) || (i == 3));
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+ }
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+}
+
+
+void run_nested_exception()
+{
+ std::string s("test");
+ bool parent_flag = false;
+ bool task1_flag = false;
+ bool task2_flag = false;
+ bool task21_flag = false;
+ bool task3_flag = false;
+ try
+ {
+ task_region([&](task_region_handle& trh)
+ {
+ parent_flag = true;
+ trh.run([&]()
+ {
+ task1_flag = true;
+ std::cout << "task1: " << s << std::endl;
+ });
+ trh.run([&]()
+ {
+ task2_flag = true;
+ std::cout << "task2" << std::endl;
+ task_region([&](task_region_handle& trh)
+ {
+ trh.run([&]()
+ {
+ task21_flag = true;
+ std::cout << "task2.1" << std::endl;
+ throw 21;
+ });
+ });
+ });
+ int i = 0, j = 10, k = 20;
+ trh.run([=, &task3_flag]()
+ {
+ task3_flag = true;
+ std::cout << "task3: " << i << " " << j << " " << k << std::endl;
+ });
+ std::cout << "parent" << std::endl;
+ });
+ }
+ catch (exception_list const& el)
+ {
+ BOOST_TEST(el.size() == 1u);
+ for (boost::exception_ptr const& e: el)
+ {
+ try {
+ boost::rethrow_exception(e);
+ }
+ catch (int i) // this doesn't works yet
+ {
+ BOOST_TEST_EQ(i, 21);
+ }
+ catch (boost::exception&)
+ {
+ BOOST_TEST(true);
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+ }
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+ BOOST_TEST(parent_flag);
+ BOOST_TEST(task1_flag);
+ BOOST_TEST(task2_flag);
+ BOOST_TEST(task21_flag);
+}
+
+
+int main()
+{
+ run_no_exception();
+ run_no_exception_wait();
+ run_exception();
+ run_exception_1();
+ run_nested_exception();
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return boost::report_errors();
+}
+#endif
diff --git a/libs/thread/test/sync/futures/async/async_pass.cpp b/libs/thread/test/sync/futures/async/async_pass.cpp
index add6282cf6..86fdfdbec6 100644
--- a/libs/thread/test/sync/futures/async/async_pass.cpp
+++ b/libs/thread/test/sync/futures/async/async_pass.cpp
@@ -85,7 +85,7 @@ public:
return *this;
}
- int operator()()
+ int operator()() const
{
boost::this_thread::sleep_for(ms(200));
return 3;
@@ -167,6 +167,48 @@ struct check_timer {
int main()
{
+ {
+ try {
+ boost::async(f0);
+ } catch (std::exception& ex)
+ {
+ std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
+ BOOST_TEST(false && "exception thrown");
+ }
+ catch (...)
+ {
+ BOOST_TEST(false && "exception thrown");
+ }
+ }
+ {
+ try {
+ boost::async(boost::launch::async, f0);
+ } catch (std::exception& ex)
+ {
+ std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
+ BOOST_TEST(false && "exception thrown");
+ }
+ catch (...)
+ {
+ BOOST_TEST(false && "exception thrown");
+ }
+ }
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
+ {
+ try {
+ boost::async(boost::launch::deferred, f0);
+ } catch (std::exception& ex)
+ {
+ std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
+ BOOST_TEST(false && "exception thrown");
+ }
+ catch (...)
+ {
+ BOOST_TEST(false && "exception thrown");
+ }
+ }
+#endif
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
try
diff --git a/libs/thread/test/sync/futures/future/async_deferred_then_pass.cpp b/libs/thread/test/sync/futures/future/async_deferred_then_pass.cpp
index e17e912cea..b400074cdd 100644
--- a/libs/thread/test/sync/futures/future/async_deferred_then_pass.cpp
+++ b/libs/thread/test/sync/futures/future/async_deferred_then_pass.cpp
@@ -53,6 +53,29 @@ int main()
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
+ try
+ {
+ boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
+ BOOST_TEST(f1.valid());
+ {
+ boost::future<int> f2 = f1.then(&p2);
+ BOOST_TEST(f2.valid());
+ }
+ BOOST_TEST(! f1.valid());
+ }
+ catch (std::exception& ex)
+ {
+ BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
+ BOOST_TEST(false);
+ }
+ catch (...)
+ {
+ BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
+ BOOST_TEST(false);
+ }
+ }
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ {
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
BOOST_TEST(f1.valid());
boost::future<int> f2 = f1.then(&p2);
diff --git a/libs/thread/test/sync/futures/future/get_or_pass.cpp b/libs/thread/test/sync/futures/future/get_or_pass.cpp
index a2bd652226..64409455bf 100644
--- a/libs/thread/test/sync/futures/future/get_or_pass.cpp
+++ b/libs/thread/test/sync/futures/future/get_or_pass.cpp
@@ -17,6 +17,7 @@
#include <boost/thread/future.hpp>
#include <boost/thread/thread.hpp>
+#include <boost/core/ref.hpp>
#include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_USES_CHRONO
@@ -128,49 +129,49 @@ int main()
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
}
}
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// {
-// typedef int& T;
-// {
-// boost::promise<T> p;
-// boost::future<T> f = p.get_future();
-//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
-// boost::thread(func3, boost::move(p)).detach();
-//#else
-// int j=5;
-// p.set_value(j);
-//#endif
-// BOOST_TEST(f.valid());
-// int k=4;
-// BOOST_TEST(f.get_or(k) == 5);
-//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
-// BOOST_TEST(!f.valid());
-//#endif
-// }
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// {
-// boost::promise<T> p;
-// boost::future<T> f = p.get_future();
-//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
-// boost::thread(func4, boost::move(p)).detach();
-//#else
-// p.set_exception(boost::make_exception_ptr(3.5));
-//#endif
-// try
-// {
-// BOOST_TEST(f.valid());
-// int j=4;
-// BOOST_TEST(f.get_or(j) == 4);
-// }
-// catch (...)
-// {
-// BOOST_TEST(false);
-// }
-//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
-// BOOST_TEST(!f.valid());
-//#endif
-// }
-// }
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ {
+ typedef int& T;
+ {
+ boost::promise<T> p;
+ boost::future<T> f = p.get_future();
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ boost::thread(func3, boost::move(p)).detach();
+#else
+ int j=5;
+ p.set_value(j);
+#endif
+ BOOST_TEST(f.valid());
+ int k=4;
+ BOOST_TEST(f.get_or(boost::ref(k)) == 5);
+#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ BOOST_TEST(!f.valid());
+#endif
+ }
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ {
+ boost::promise<T> p;
+ boost::future<T> f = p.get_future();
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ boost::thread(func4, boost::move(p)).detach();
+#else
+ p.set_exception(boost::make_exception_ptr(3.5));
+#endif
+ try
+ {
+ BOOST_TEST(f.valid());
+ int j=4;
+ BOOST_TEST(f.get_or(boost::ref(j)) == 4);
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ BOOST_TEST(!f.valid());
+#endif
+ }
+ }
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
diff --git a/libs/thread/test/sync/futures/make_ready_future_pass.cpp b/libs/thread/test/sync/futures/make_ready_future_pass.cpp
new file mode 100644
index 0000000000..dfce3cde74
--- /dev/null
+++ b/libs/thread/test/sync/futures/make_ready_future_pass.cpp
@@ -0,0 +1,157 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Copyright (C) 2011,2014 Vicente J. Botet Escriba
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// <boost/thread/future.hpp>
+
+// class promise<R>
+
+// future<void> make_ready_future();
+// template <class T>
+// future<decay_t<T>> make_ready_future(T&&);
+// template <class T>
+// future<T> make_ready_future(remove_reference_t<T>&);
+// template <class T>
+// future<T> make_ready_future(remove_reference_t<T>&&);
+// template <class T, class ...Args>
+// future<T> make_ready_future(Args&& ... args);
+
+#define BOOST_THREAD_VERSION 3
+
+#include <boost/thread/future.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/static_assert.hpp>
+
+struct A
+{
+ A() :
+ value(0)
+ {
+ }
+ A(int i) :
+ value(i)
+ {
+ }
+ A(int i, int j) :
+ value(i+j)
+ {
+ }
+ int value;
+};
+
+A make(int i) {
+ return A(i);
+}
+A make(int i, int j) {
+ return A(i, j);
+}
+
+struct movable2
+{
+ int value_;
+ BOOST_THREAD_MOVABLE_ONLY(movable2)
+ movable2() : value_(1){}
+ movable2(int i) : value_(i){}
+ movable2(int i, int j) : value_(i+j){}
+
+ //Move constructor and assignment
+ movable2(BOOST_RV_REF(movable2) m)
+ { value_ = m.value_; m.value_ = 0; }
+
+ movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m)
+ { value_ = m.value_; m.value_ = 0; return *this; }
+
+ bool moved() const //Observer
+ { return !value_; }
+
+ int value() const //Observer
+ { return value_; }
+};
+
+
+movable2 move_return_function2(int i) {
+ return movable2(i);
+}
+
+int main()
+{
+#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false));
+ BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true));
+ BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == true));
+ BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == false));
+#endif
+
+ {
+ boost::future<void> f = boost::make_ready_future();
+ f.wait();
+ }
+ {
+ typedef A T;
+ T i;
+ boost::future<T> f = boost::make_ready_future(i);
+ BOOST_TEST(f.get().value==0);
+ }
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ {
+ typedef A T;
+ boost::future<T> f = boost::make_ready_future<T>();
+ BOOST_TEST(f.get().value==0);
+ }
+ {
+ typedef A T;
+ boost::future<T> f = boost::make_ready_future<T>(1);
+ BOOST_TEST(f.get().value==1);
+ }
+ {
+ typedef A T;
+ boost::future<T> f = boost::make_ready_future<T>(1,2);
+ BOOST_TEST(f.get().value==3);
+ }
+ {
+ typedef A T;
+ T i;
+ boost::future<T&> f = boost::make_ready_future<T&>(i);
+ BOOST_TEST(f.get().value==0);
+ }
+#endif
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+// sync/futures/make_ready_future_pass.cpp:125:65: erreur: conversion from Ôboost::future<boost::rv<movable2> >Õ to non-scalar type Ôboost::future<movable2>Õ requested
+ {
+ typedef movable2 T;
+ T i;
+ boost::future<T> f = boost::make_ready_future(boost::move(i));
+ BOOST_TEST_EQ(f.get().value(),1);
+ }
+#endif
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ {
+ typedef movable2 T;
+ boost::future<T> f = boost::make_ready_future<T>();
+ BOOST_TEST(f.get().value()==1);
+ }
+ {
+ typedef movable2 T;
+ boost::future<T> f = boost::make_ready_future<T>(1);
+ BOOST_TEST(f.get().value()==1);
+ }
+ {
+ typedef movable2 T;
+ boost::future<T> f = boost::make_ready_future<T>(1,2);
+ BOOST_TEST(f.get().value()==3);
+ }
+#endif
+
+ return boost::report_errors();
+}
+
diff --git a/libs/thread/test/sync/futures/promise/emplace_pass.cpp b/libs/thread/test/sync/futures/promise/emplace_pass.cpp
new file mode 100644
index 0000000000..6a1a352925
--- /dev/null
+++ b/libs/thread/test/sync/futures/promise/emplace_pass.cpp
@@ -0,0 +1,207 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Copyright (C) 2011,2014 Vicente J. Botet Escriba
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// <boost/thread/future.hpp>
+
+// class promise<R>
+
+// template <class ...Args>
+// void promise::emplace(Args&& ... args);
+
+#define BOOST_THREAD_VERSION 3
+
+#include <boost/thread/future.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/static_assert.hpp>
+
+struct A
+{
+ A() :
+ value(0)
+ {
+ }
+ A(int i) :
+ value(i)
+ {
+ }
+ A(int i, int j) :
+ value(i+j)
+ {
+ }
+ BOOST_THREAD_MOVABLE_ONLY(A)
+
+ A(BOOST_THREAD_RV_REF(A) rhs)
+ {
+ if(rhs.value==0)
+ throw 9;
+ else
+ {
+ value=rhs.value;
+ rhs.value=0;
+ }
+ }
+ A& operator=(BOOST_THREAD_RV_REF(A) rhs)
+ {
+ if(rhs.value==0)
+ throw 9;
+ else
+ {
+ value=rhs.value;
+ rhs.value=0;
+ }
+ return *this;
+ }
+ int value;
+};
+
+A make(int i) {
+ return A(i);
+}
+A make(int i, int j) {
+ return A(i, j);
+}
+
+struct movable2
+{
+ int value_;
+ BOOST_THREAD_MOVABLE_ONLY(movable2)
+ movable2() : value_(1){}
+ movable2(int i) : value_(i){}
+ movable2(int i, int j) : value_(i+j){}
+
+ //Move constructor and assignment
+ movable2(BOOST_RV_REF(movable2) m)
+ { value_ = m.value_; m.value_ = 0; }
+
+ movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m)
+ { value_ = m.value_; m.value_ = 0; return *this; }
+
+ bool moved() const //Observer
+ { return !value_; }
+
+ int value() const //Observer
+ { return value_; }
+};
+
+
+movable2 move_return_function2(int i) {
+ return movable2(i);
+}
+
+int main()
+{
+#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false));
+ BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true));
+ BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == false));
+ BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == true));
+#endif
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ {
+ typedef A T;
+ T i;
+ boost::promise<T> p;
+ boost::future<T> f = p.get_future();
+ p.emplace();
+ try
+ {
+ T a = f.get(); (void)a;
+ BOOST_TEST(false);
+ }
+ catch (int j)
+ {
+ BOOST_TEST(j == 9);
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+ }
+ {
+ typedef A T;
+ boost::promise<T> p;
+ boost::future<T> f = p.get_future();
+ p.emplace(3);
+ BOOST_TEST(f.get().value == 3);
+ try
+ {
+ T j(3);
+ p.set_value(boost::move(j));
+ BOOST_TEST(false);
+ }
+ catch (const boost::future_error& e)
+ {
+ BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+
+ }
+ {
+ boost::promise<movable2> p;
+ boost::future<movable2> f = p.get_future();
+ p.emplace(3);
+ BOOST_TEST(f.get().value_ == 3);
+ try
+ {
+ p.emplace(3);
+ BOOST_TEST(false);
+ }
+ catch (const boost::future_error& e)
+ {
+ BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+
+ }
+ {
+ boost::promise<A> p;
+ boost::future<A> f = p.get_future();
+ p.emplace(1,2);
+ BOOST_TEST(f.get().value == 3);
+ try
+ {
+ p.emplace(1,2);
+ BOOST_TEST(false);
+ }
+ catch (const boost::future_error& e)
+ {
+ BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+
+ }
+ {
+ typedef A T;
+ boost::promise<T> p;
+ boost::future<T> f = p.get_future();
+ p.emplace(3);
+ boost::promise<T> p2(boost::move(p));
+ BOOST_TEST(f.get().value == 3);
+
+ }
+#endif
+
+ return boost::report_errors();
+}
+
diff --git a/libs/thread/test/sync/futures/shared_future/then_pass.cpp b/libs/thread/test/sync/futures/shared_future/then_pass.cpp
index 4739135bfd..b7d95bc663 100644
--- a/libs/thread/test/sync/futures/shared_future/then_pass.cpp
+++ b/libs/thread/test/sync/futures/shared_future/then_pass.cpp
@@ -75,6 +75,30 @@ int main()
{
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
BOOST_TEST(f1.valid());
+ boost::future<int> f2 = f1.then(&p2);
+ boost::future<int> f3 = f1.then(&p2);
+ BOOST_TEST(f2.valid());
+ BOOST_TEST(f3.valid());
+ try
+ {
+ BOOST_TEST(f2.get()==2);
+ BOOST_TEST(f3.get()==2);
+ }
+ catch (std::exception& ex)
+ {
+ BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
+ BOOST_TEST(false);
+ }
+ catch (...)
+ {
+ BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
+ BOOST_TEST(false);
+ }
+ }
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+ {
+ boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
+ BOOST_TEST(f1.valid());
boost::future<void> f2 = f1.then(&p3);
BOOST_TEST(f2.valid());
try
diff --git a/libs/thread/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp b/libs/thread/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp
new file mode 100644
index 0000000000..96e8e268d7
--- /dev/null
+++ b/libs/thread/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp
@@ -0,0 +1,455 @@
+// Copyright (C) 2014 Vicente J. Botet Escriba
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// <boost/thread/sync_deque.hpp>
+
+// class sync_deque<T>
+
+// sync_deque();
+
+#define BOOST_THREAD_VERSION 4
+//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
+
+#include <boost/thread/concurrent_queues/sync_deque.hpp>
+#include <boost/thread/concurrent_queues/deque_adaptor.hpp>
+#include <boost/thread/concurrent_queues/deque_views.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/static_assert.hpp>
+
+class non_copyable
+{
+ BOOST_THREAD_MOVABLE_ONLY(non_copyable)
+ int val;
+public:
+ non_copyable(int v) : val(v){}
+ non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
+ non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
+ bool operator==(non_copyable const& x) const {return val==x.val;}
+ template <typename OSTREAM>
+ friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x )
+ {
+ os << x.val;
+ return os;
+ }
+
+};
+
+#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
+BOOST_STATIC_ASSERT( ! boost::is_copy_constructible<non_copyable>::value );
+BOOST_STATIC_ASSERT( boost::has_move_emulation_enabled<non_copyable>::value );
+#endif
+
+int main()
+{
+
+ {
+ // default queue invariants
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_back<int> q(sq);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // default queue invariants
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_front<int> q(sq);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+
+
+ {
+ // empty queue try_pull fails
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_front<int> q(sq);
+ int i;
+ BOOST_TEST( boost::queue_op_status::empty == q.try_pull(i));
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue push rvalue/copyable succeeds
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_back<int> q(sq);
+ q.push(1);
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue push lvalue/copyable succeeds
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_back<int> q(sq);
+ int i;
+ q.push(i);
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+
+
+#if 0
+ {
+ // empty queue push rvalue/non_copyable succeeds
+ boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
+ boost::deque_back<non_copyable> q(sq);
+ q.push(non_copyable(1));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+ {
+ // empty queue push rvalue/non_copyable succeeds
+ boost::deque_adaptor<boost::sync_deque<non_copyable> > q;
+ //boost::sync_deque<non_copyable> q;
+ //boost::deque_back<non_copyable> q(sq);
+ non_copyable nc(1);
+ q.push_back(boost::move(nc));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+
+ {
+ // empty queue push rvalue succeeds
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_back<int> q(sq);
+ q.push(1);
+ q.push(2);
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 2u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue push lvalue succeeds
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_back<int> q(sq);
+ int i;
+ q.push(i);
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue try_push rvalue/copyable succeeds
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_back<int> q(sq);
+ BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue try_push rvalue/copyable succeeds
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_back<int> q(sq);
+ BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+
+#if 0
+ {
+ // empty queue try_push rvalue/non-copyable succeeds
+ boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
+ boost::deque_back<non_copyable> q(sq);
+ non_copyable nc(1);
+ BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc)));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+
+ {
+ // empty queue try_push lvalue succeeds
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_back<int> q(sq);
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue try_push rvalue succeeds
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_back<int> q(sq);
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+
+
+#if 0
+ {
+ // empty queue nonblocking_push_back rvalue/non-copyable succeeds
+ boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
+ boost::deque_back<non_copyable> q(sq);
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+ {
+ // empty queue nonblocking_push_back rvalue/non-copyable succeeds
+ boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
+ boost::deque_back<non_copyable> q(sq);
+ non_copyable nc(1);
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_front<int> q(sq);
+ sq.push_back(1);
+ int i;
+ q.pull(i);
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
+ boost::deque_front<non_copyable> q(sq);
+ non_copyable nc1(1);
+ sq.push_back(boost::move(nc1));
+ non_copyable nc2(2);
+ q.pull(nc2);
+ BOOST_TEST_EQ(nc1, nc2);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_front<int> q(sq);
+ sq.push_back(1);
+ int i = q.pull();
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
+ boost::deque_front<non_copyable> q(sq);
+ non_copyable nc1(1);
+ sq.push_back(boost::move(nc1));
+ non_copyable nc = q.pull();
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue try_pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_front<int> q(sq);
+ sq.push_back(1);
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.try_pull(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue try_pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
+ boost::deque_front<non_copyable> q(sq);
+ non_copyable nc1(1);
+ sq.push_back(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue nonblocking_pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_front<int> q(sq);
+ sq.push_back(1);
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue nonblocking_pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
+ boost::deque_front<non_copyable> q(sq);
+ non_copyable nc1(1);
+ sq.push_back(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue wait_pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
+ boost::deque_front<non_copyable> q(sq);
+ non_copyable nc1(1);
+ sq.push_back(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue wait_pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_front<int> q(sq);
+ sq.push_back(1);
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue wait_pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
+ boost::deque_front<non_copyable> q(sq);
+ non_copyable nc1(1);
+ sq.push_back(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+
+ {
+ // closed invariants
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_back<int> q(sq);
+ q.close();
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ {
+ // closed invariants
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_front<int> q(sq);
+ q.close();
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ {
+ // closed queue push fails
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_back<int> q(sq);
+ q.close();
+ try {
+ q.push(1);
+ BOOST_TEST(false);
+ } catch (...) {
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ }
+ {
+ // 1-element closed queue pull succeed
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_front<int> q(sq);
+ sq.push_back(1);
+ q.close();
+ int i;
+ q.pull(i);
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ {
+ // 1-element closed queue wait_pull_front succeed
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_front<int> q(sq);
+ sq.push_back(1);
+ q.close();
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ {
+ // closed empty queue wait_pull_front fails
+ boost::deque_adaptor<boost::sync_deque<int> > sq;
+ boost::deque_front<int> q(sq);
+ q.close();
+ BOOST_TEST(q.empty());
+ BOOST_TEST(q.closed());
+ int i;
+ BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i));
+ BOOST_TEST(q.empty());
+ BOOST_TEST(q.closed());
+ }
+ return boost::report_errors();
+}
+
diff --git a/libs/thread/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp b/libs/thread/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp
index 141c23a4fc..41cf1cf3a2 100644
--- a/libs/thread/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp
+++ b/libs/thread/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp
@@ -12,7 +12,7 @@
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
-#include <boost/thread/sync_queue.hpp>
+#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
#include <boost/thread/concurrent_queues/queue_views.hpp>
@@ -117,7 +117,7 @@ int main()
//boost::sync_queue<non_copyable> q;
//boost::queue_back<non_copyable> q(sq);
non_copyable nc(1);
- q.push_back(boost::move(nc));
+ q.push(boost::move(nc));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -206,7 +206,7 @@ int main()
#if 0
{
- // empty queue nonblocking_push_back rvalue/non-copyable succeeds
+ // empty queue nonblocking_push rvalue/non-copyable succeeds
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_back<non_copyable> q(sq);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
@@ -217,7 +217,7 @@ int main()
}
#endif
{
- // empty queue nonblocking_push_back rvalue/non-copyable succeeds
+ // empty queue nonblocking_push rvalue/non-copyable succeeds
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_back<non_copyable> q(sq);
non_copyable nc(1);
@@ -228,10 +228,10 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue pull_front succeed
+ // 1-element queue pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
- sq.push_back(1);
+ sq.push(1);
int i;
q.pull(i);
BOOST_TEST_EQ(i, 1);
@@ -241,11 +241,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue pull_front succeed
+ // 1-element queue pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
- sq.push_back(boost::move(nc1));
+ sq.push(boost::move(nc1));
non_copyable nc2(2);
q.pull(nc2);
BOOST_TEST_EQ(nc1, nc2);
@@ -255,10 +255,10 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue pull_front succeed
+ // 1-element queue pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
- sq.push_back(1);
+ sq.push(1);
int i = q.pull();
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
@@ -267,11 +267,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue pull_front succeed
+ // 1-element queue pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
- sq.push_back(boost::move(nc1));
+ sq.push(boost::move(nc1));
non_copyable nc = q.pull();
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
@@ -280,10 +280,10 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue try_pull_front succeed
+ // 1-element queue try_pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
- sq.push_back(1);
+ sq.push(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.try_pull(i));
BOOST_TEST_EQ(i, 1);
@@ -293,11 +293,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue try_pull_front succeed
+ // 1-element queue try_pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
- sq.push_back(boost::move(nc1));
+ sq.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
BOOST_TEST_EQ(nc, nc1);
@@ -307,10 +307,10 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue nonblocking_pull_front succeed
+ // 1-element queue nonblocking_pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
- sq.push_back(1);
+ sq.push(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i));
BOOST_TEST_EQ(i, 1);
@@ -320,11 +320,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue nonblocking_pull_front succeed
+ // 1-element queue nonblocking_pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
- sq.push_back(boost::move(nc1));
+ sq.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
BOOST_TEST_EQ(nc, nc1);
@@ -334,11 +334,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue wait_pull_front succeed
+ // 1-element queue wait_pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
- sq.push_back(boost::move(nc1));
+ sq.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
BOOST_TEST_EQ(nc, nc1);
@@ -348,10 +348,10 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue wait_pull_front succeed
+ // 1-element queue wait_pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
- sq.push_back(1);
+ sq.push(1);
int i;
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
BOOST_TEST_EQ(i, 1);
@@ -361,11 +361,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue wait_pull_front succeed
+ // 1-element queue wait_pull succeed
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
boost::queue_front<non_copyable> q(sq);
non_copyable nc1(1);
- sq.push_back(boost::move(nc1));
+ sq.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
BOOST_TEST_EQ(nc, nc1);
@@ -414,7 +414,7 @@ int main()
// 1-element closed queue pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
- sq.push_back(1);
+ sq.push(1);
q.close();
int i;
q.pull(i);
@@ -425,10 +425,10 @@ int main()
BOOST_TEST(q.closed());
}
{
- // 1-element closed queue wait_pull_front succeed
+ // 1-element closed queue wait_pull succeed
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
- sq.push_back(1);
+ sq.push(1);
q.close();
int i;
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
@@ -439,7 +439,7 @@ int main()
BOOST_TEST(q.closed());
}
{
- // closed empty queue wait_pull_front fails
+ // closed empty queue wait_pull fails
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_front<int> q(sq);
q.close();
diff --git a/libs/thread/test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp b/libs/thread/test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp
new file mode 100644
index 0000000000..703c54f40b
--- /dev/null
+++ b/libs/thread/test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp
@@ -0,0 +1,256 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// <boost/thread/concurrent_queues/sync_deque.hpp>
+
+// class sync_deque<T>
+
+// push || pull;
+
+#include <boost/config.hpp>
+#if ! defined BOOST_NO_CXX11_DECLTYPE
+#define BOOST_RESULT_OF_USE_DECLTYPE
+#endif
+
+#define BOOST_THREAD_VERSION 4
+
+#include <boost/thread/concurrent_queues/sync_deque.hpp>
+#include <boost/thread/future.hpp>
+#include <boost/thread/barrier.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+template <typename ValueType>
+struct call_push_back
+{
+ boost::sync_deque<ValueType> *q_;
+ boost::barrier *go_;
+
+ call_push_back(boost::sync_deque<ValueType> *q, boost::barrier *go) :
+ q_(q), go_(go)
+ {
+ }
+ typedef void result_type;
+ void operator()()
+ {
+ go_->count_down_and_wait();
+ q_->push_back(42);
+ }
+};
+
+template <typename ValueType>
+struct call_pull_front
+{
+ boost::sync_deque<ValueType> *q_;
+ boost::barrier *go_;
+
+ call_pull_front(boost::sync_deque<ValueType> *q, boost::barrier *go) :
+ q_(q), go_(go)
+ {
+ }
+ typedef ValueType result_type;
+ ValueType operator()()
+ {
+ go_->count_down_and_wait();
+ return q_->pull_front();
+ }
+};
+
+template <typename ValueType>
+struct call_wait_pull_front
+{
+ boost::sync_deque<ValueType> *q_;
+ boost::barrier *go_;
+
+ call_wait_pull_front(boost::sync_deque<ValueType> *q, boost::barrier *go) :
+ q_(q), go_(go)
+ {
+ }
+ typedef boost::queue_op_status result_type;
+ boost::queue_op_status operator()(ValueType& v)
+ {
+ go_->wait();
+ return q_->wait_pull_front(v);
+ }
+};
+
+void test_concurrent_push_back_and_pull_front_on_empty_queue()
+{
+ boost::sync_deque<int> q;
+
+ boost::barrier go(2);
+
+ boost::future<void> push_done;
+ boost::future<int> pull_done;
+
+ try
+ {
+ push_done=boost::async(boost::launch::async,
+ call_push_back<int>(&q,&go));
+ pull_done=boost::async(boost::launch::async,
+ call_pull_front<int>(&q,&go));
+
+ push_done.get();
+ BOOST_TEST_EQ(pull_done.get(), 42);
+ BOOST_TEST(q.empty());
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+}
+
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+void test_concurrent_push_back_and_wait_pull_front_on_empty_queue()
+{
+ boost::sync_deque<int> q;
+ const unsigned int n = 3;
+ boost::barrier go(n);
+
+ boost::future<boost::queue_op_status> pull_done[n];
+ int results[n];
+
+ try
+ {
+ for (unsigned int i =0; i< n; ++i)
+ pull_done[i]=boost::async(boost::launch::async,
+ call_wait_pull_front<int>(&q,&go),
+ boost::ref(results[i]));
+
+ for (unsigned int i =0; i< n; ++i)
+ q.push_back(42);
+
+ for (unsigned int i = 0; i < n; ++i) {
+ BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success);
+ BOOST_TEST_EQ(results[i], 42);
+ }
+ BOOST_TEST(q.empty());
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+}
+
+void test_concurrent_wait_pull_front_and_close_on_empty_queue()
+{
+ boost::sync_deque<int> q;
+ const unsigned int n = 3;
+ boost::barrier go(n);
+
+ boost::future<boost::queue_op_status> pull_done[n];
+ int results[n];
+
+ try
+ {
+ for (unsigned int i =0; i< n; ++i)
+ pull_done[i]=boost::async(boost::launch::async,
+ call_wait_pull_front<int>(&q,&go),
+ boost::ref(results[i]));
+
+ q.close();
+
+ for (unsigned int i = 0; i < n; ++i) {
+ BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed);
+ }
+ BOOST_TEST(q.empty());
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+}
+#endif
+
+void test_concurrent_push_back_on_empty_queue()
+{
+ boost::sync_deque<int> q;
+ const unsigned int n = 3;
+ boost::barrier go(n);
+ boost::future<void> push_done[n];
+
+ try
+ {
+ for (unsigned int i =0; i< n; ++i)
+ push_done[i]=boost::async(boost::launch::async,
+ call_push_back<int>(&q,&go));
+
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+ try
+ {
+ for (unsigned int i = 0; i < n; ++i)
+ push_done[i].get();
+
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+ try
+ {
+ BOOST_TEST(!q.empty());
+ for (unsigned int i =0; i< n; ++i)
+ BOOST_TEST_EQ(q.pull_front(), 42);
+ BOOST_TEST(q.empty());
+
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+}
+
+void test_concurrent_pull_front_on_queue()
+{
+ boost::sync_deque<int> q;
+ const unsigned int n = 3;
+ boost::barrier go(n);
+
+ boost::future<int> pull_done[n];
+
+ try
+ {
+ for (unsigned int i =0; i< n; ++i)
+ q.push_back(42);
+
+ for (unsigned int i =0; i< n; ++i)
+ pull_done[i]=boost::async(boost::launch::async,
+#if ! defined BOOST_NO_CXX11_LAMBDAS
+ [&q,&go]() -> int
+ {
+ go.wait();
+ return q.pull_front();
+ }
+#else
+ call_pull_front<int>(&q,&go)
+#endif
+ );
+
+ for (unsigned int i = 0; i < n; ++i)
+ BOOST_TEST_EQ(pull_done[i].get(), 42);
+ BOOST_TEST(q.empty());
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+}
+
+int main()
+{
+ test_concurrent_push_back_and_pull_front_on_empty_queue();
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ test_concurrent_push_back_and_wait_pull_front_on_empty_queue();
+ test_concurrent_wait_pull_front_and_close_on_empty_queue();
+#endif
+ test_concurrent_push_back_on_empty_queue();
+ test_concurrent_pull_front_on_queue();
+ return boost::report_errors();
+}
+
diff --git a/libs/thread/test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp b/libs/thread/test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp
new file mode 100644
index 0000000000..5170bcf614
--- /dev/null
+++ b/libs/thread/test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp
@@ -0,0 +1,403 @@
+// Copyright (C) 2013,2015 Vicente J. Botet Escriba
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// <boost/thread/concurrent_queues/sync_deque.hpp>
+
+// class sync_deque<T>
+
+// sync_deque();
+
+#define BOOST_THREAD_VERSION 4
+
+#include <boost/thread/concurrent_queues/sync_deque.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+class non_copyable
+{
+ BOOST_THREAD_MOVABLE_ONLY(non_copyable)
+ int val;
+public:
+ non_copyable(int v) : val(v){}
+ non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
+ non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
+ bool operator==(non_copyable const& x) const {return val==x.val;}
+ template <typename OSTREAM>
+ friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x )
+ {
+ os << x.val;
+ return os;
+ }
+
+};
+
+
+
+int main()
+{
+
+ {
+ // default queue invariants
+ boost::sync_deque<int> q;
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue try_pull fails
+ boost::sync_deque<int> q;
+ int i;
+ BOOST_TEST( boost::queue_op_status::empty == q.try_pull_front(i));
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue push rvalue/copyable succeeds
+ boost::sync_deque<int> q;
+ q.push_back(1);
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue push lvalue/copyable succeeds
+ boost::sync_deque<int> q;
+ int i;
+ q.push_back(i);
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ {
+ // empty queue push rvalue/non_copyable succeeds
+ boost::sync_deque<non_copyable> q;
+ q.push_back(non_copyable(1));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+ {
+ // empty queue push rvalue/non_copyable succeeds
+ boost::sync_deque<non_copyable> q;
+ non_copyable nc(1);
+ q.push_back(boost::move(nc));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+
+ {
+ // empty queue push rvalue succeeds
+ boost::sync_deque<int> q;
+ q.push_back(1);
+ q.push_back(2);
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 2u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue push lvalue succeeds
+ boost::sync_deque<int> q;
+ int i;
+ q.push_back(i);
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue try_push rvalue/copyable succeeds
+ boost::sync_deque<int> q;
+ BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue try_push rvalue/copyable succeeds
+ boost::sync_deque<int> q;
+ BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ {
+ // empty queue try_push rvalue/non-copyable succeeds
+ boost::sync_deque<non_copyable> q;
+ BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable(1)));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+ {
+ // empty queue try_push rvalue/non-copyable succeeds
+ boost::sync_deque<non_copyable> q;
+ non_copyable nc(1);
+ BOOST_TEST(boost::queue_op_status::success == q.try_push_back(boost::move(nc)));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+
+ {
+ // empty queue try_push lvalue succeeds
+ boost::sync_deque<int> q;
+ int i=1;
+ BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue try_push rvalue succeeds
+ boost::sync_deque<int> q;
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(1));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ {
+ // empty queue nonblocking_push_back rvalue/non-copyable succeeds
+ boost::sync_deque<non_copyable> q;
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(non_copyable(1)));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+ {
+ // empty queue nonblocking_push_back rvalue/non-copyable succeeds
+ boost::sync_deque<non_copyable> q;
+ non_copyable nc(1);
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(boost::move(nc)));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue pull_front succeed
+ boost::sync_deque<int> q;
+ q.push_back(1);
+ int i;
+ q.pull_front(i);
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue pull_front succeed
+ boost::sync_deque<non_copyable> q;
+ non_copyable nc1(1);
+ q.push_back(boost::move(nc1));
+ non_copyable nc2(2);
+ q.pull_front(nc2);
+ BOOST_TEST_EQ(nc1, nc2);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue pull_front succeed
+ boost::sync_deque<int> q;
+ q.push_back(1);
+ int i = q.pull_front();
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue pull_front succeed
+ boost::sync_deque<non_copyable> q;
+ non_copyable nc1(1);
+ q.push_back(boost::move(nc1));
+ non_copyable nc = q.pull_front();
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue try_pull_front succeed
+ boost::sync_deque<int> q;
+ q.push_back(1);
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue try_pull_front succeed
+ boost::sync_deque<non_copyable> q;
+ non_copyable nc1(1);
+ q.push_back(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue nonblocking_pull_front succeed
+ boost::sync_deque<int> q;
+ q.push_back(1);
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue nonblocking_pull_front succeed
+ boost::sync_deque<non_copyable> q;
+ non_copyable nc1(1);
+ q.push_back(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue wait_pull_front succeed
+ boost::sync_deque<non_copyable> q;
+ non_copyable nc1(1);
+ q.push_back(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue wait_pull_front succeed
+ boost::sync_deque<int> q;
+ q.push_back(1);
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue wait_pull_front succeed
+ boost::sync_deque<non_copyable> q;
+ non_copyable nc1(1);
+ q.push_back(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+
+ {
+ // closed invariants
+ boost::sync_deque<int> q;
+ q.close();
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ {
+ // closed queue push fails
+ boost::sync_deque<int> q;
+ q.close();
+ try {
+ q.push_back(1);
+ BOOST_TEST(false);
+ } catch (...) {
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ }
+ {
+ // 1-element closed queue pull succeed
+ boost::sync_deque<int> q;
+ q.push_back(1);
+ q.close();
+ int i;
+ q.pull_front(i);
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ {
+ // 1-element closed queue wait_pull_front succeed
+ boost::sync_deque<int> q;
+ q.push_back(1);
+ q.close();
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ {
+ // closed empty queue wait_pull_front fails
+ boost::sync_deque<int> q;
+ q.close();
+ BOOST_TEST(q.empty());
+ BOOST_TEST(q.closed());
+ int i;
+ BOOST_TEST(boost::queue_op_status::closed == q.wait_pull_front(i));
+ BOOST_TEST(q.empty());
+ BOOST_TEST(q.closed());
+ }
+
+ return boost::report_errors();
+}
+
diff --git a/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp b/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp
new file mode 100644
index 0000000000..d8e82c2e68
--- /dev/null
+++ b/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp
@@ -0,0 +1,215 @@
+// 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)
+//
+
+#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 <exception>
+
+#include <boost/thread/thread.hpp>
+#include <boost/thread/barrier.hpp>
+#include <boost/thread/concurrent_queues/sync_priority_queue.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+
+typedef boost::concurrent::sync_priority_queue<int> sync_pq;
+
+int call_pull(sync_pq* q, boost::barrier* go)
+{
+ go->wait();
+ return q->pull();
+
+}
+
+void call_push(sync_pq* q, boost::barrier* go, int val)
+{
+ go->wait();
+ q->push(val);
+}
+
+void test_pull(const int n)
+{
+ sync_pq pq;
+ BOOST_TEST(pq.empty());
+ for(int i = 0; i < n; i++)
+ {
+ pq.push(i);
+ }
+ BOOST_TEST(!pq.empty());
+ BOOST_TEST_EQ(pq.size(), std::size_t(n));
+ pq.close();
+ BOOST_TEST(pq.closed());
+ boost::barrier b(n);
+ boost::thread_group tg;
+ for(int i = 0; i < n; i++)
+ {
+ tg.create_thread(boost::bind(call_pull, &pq, &b));
+ }
+ tg.join_all();
+ BOOST_TEST(pq.empty());
+}
+
+void test_push(const int n)
+{
+ sync_pq pq;
+ BOOST_TEST(pq.empty());
+
+ boost::barrier b(n);
+ boost::thread_group tg;
+ for(int i = 0; i < n; i++)
+ {
+ tg.create_thread(boost::bind(call_push, &pq, &b, i));
+ }
+ tg.join_all();
+ BOOST_TEST(!pq.empty());
+ BOOST_TEST_EQ(pq.size(), std::size_t(n));
+}
+
+void test_both(const int n)
+{
+ sync_pq pq;
+ BOOST_TEST(pq.empty());
+
+ boost::barrier b(2*n);
+ boost::thread_group tg;
+ for(int i = 0; i < n; i++)
+ {
+ tg.create_thread(boost::bind(call_pull, &pq, &b));
+ tg.create_thread(boost::bind(call_push, &pq, &b, i));
+ }
+ tg.join_all();
+ BOOST_TEST(pq.empty());
+ BOOST_TEST_EQ(pq.size(), std::size_t(0));
+}
+
+void push_range(sync_pq* q, const int begin, const int end)
+{
+ for(int i = begin; i < end; i++)
+ q->push(i);
+}
+
+void atomic_pull(sync_pq* q, boost::atomic<int>* sum)
+{
+ while(1)
+ {
+ try{
+ const int val = q->pull();
+ sum->fetch_add(val);
+ }
+ catch(std::exception& e ){
+ break;
+ }
+ }
+}
+
+/**
+ * This test computes the sum of the first N integers upto $limit using
+ * $n threads for the push operation and $n threads for the pull and count
+ * operation. The push operation push a range of numbers on the queue while
+ * the pull operation pull from the queue and increments an atomic int.
+ * At the end of execution the value of atomic<int> $sum should be the same
+ * as n*(n+1)/2 as this is the closed form solution to this problem.
+ */
+void compute_sum(const int n)
+{
+ const int limit = 1000;
+ sync_pq pq;
+ BOOST_TEST(pq.empty());
+ boost::atomic<int> sum(0);
+ boost::thread_group tg1;
+ boost::thread_group tg2;
+ for(int i = 0; i < n; i++)
+ {
+ tg1.create_thread(boost::bind(push_range, &pq, i*(limit/n)+1, (i+1)*(limit/n)+1));
+ tg2.create_thread(boost::bind(atomic_pull, &pq, &sum));
+ }
+ tg1.join_all();
+ pq.close(); //Wait until all enqueuing is done before closing.
+ BOOST_TEST(pq.closed());
+ tg2.join_all();
+ BOOST_TEST(pq.empty());
+ BOOST_TEST_EQ(sum.load(), limit*(limit+1)/2);
+}
+
+void move_between_queues(sync_pq* q1, sync_pq* q2)
+{
+ while(1){
+ try{
+ const int val = q1->pull();
+ q2->push(val);
+ }
+ catch(std::exception& e){
+ break;
+ }
+ }
+}
+
+/**
+ * This test computes the sum of the first N integers upto $limit by moving
+ * numbers between 2 sync_priority_queues. A range of numbers are pushed onto
+ * one queue by $n threads while $n threads pull from this queue and push onto
+ * another sync_pq. At the end the main thread ensures the the values in the
+ * second queue are in proper order and then sums all the values from this
+ * queue. The sum should match n*(n+1)/2, the closed form solution to this
+ * problem.
+ */
+void sum_with_moving(const int n)
+{
+ const int limit = 1000;
+ sync_pq pq1;
+ sync_pq pq2;
+ BOOST_TEST(pq1.empty());
+ BOOST_TEST(pq2.empty());
+ boost::thread_group tg1;
+ boost::thread_group tg2;
+ for(int i = 0; i < n; i++)
+ {
+ tg1.create_thread(boost::bind(push_range, &pq1, i*(limit/n)+1, (i+1)*(limit/n)+1));
+ tg2.create_thread(boost::bind(move_between_queues, &pq1, &pq2));
+ }
+ tg1.join_all();
+ pq1.close(); //Wait until all enqueuing is done before closing.
+ BOOST_TEST(pq1.closed());
+ tg2.join_all();
+ BOOST_TEST(pq1.empty());
+ BOOST_TEST(!pq2.empty());
+ int sum = 0;
+ for(int i = 1000; i > 0; i--){
+ const int val = pq2.pull();
+ BOOST_TEST_EQ(i,val);
+ sum += val;
+ }
+ BOOST_TEST(pq2.empty());
+ BOOST_TEST_EQ(sum, limit*(limit+1)/2);
+}
+
+int main()
+{
+ for(int i = 1; i <= 64; i *= 2)
+ {
+ test_pull(i);
+ test_push(i);
+ test_both(i);
+ }
+ //These numbers must divide 1000
+ compute_sum(1);
+ compute_sum(4);
+ compute_sum(10);
+ compute_sum(25);
+ compute_sum(50);
+ sum_with_moving(1);
+ sum_with_moving(4);
+ sum_with_moving(10);
+ sum_with_moving(25);
+ sum_with_moving(50);
+ return boost::report_errors();
+}
diff --git a/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp b/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp
new file mode 100644
index 0000000000..cc1ae90c60
--- /dev/null
+++ b/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp
@@ -0,0 +1,425 @@
+// 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)
+//
+
+#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 <iostream>
+
+#include <boost/thread.hpp>
+#include <boost/chrono.hpp>
+#include <boost/thread/concurrent_queues/sync_priority_queue.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+using namespace boost::chrono;
+
+typedef boost::concurrent::sync_priority_queue<int> sync_pq;
+
+class non_copyable
+{
+ BOOST_THREAD_MOVABLE_ONLY(non_copyable)
+ int val;
+public:
+ non_copyable(int v) : val(v){}
+ non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
+ non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
+ bool operator==(non_copyable const& x) const {return val==x.val;}
+ template <typename OSTREAM>
+ friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x )
+ {
+ os << x.val;
+ return os;
+ }
+ bool operator <(const non_copyable& other) const
+ {
+ return val < other.val;
+ }
+};
+
+
+void test_pull_for()
+{
+ sync_pq pq;
+ steady_clock::time_point start = steady_clock::now();
+ int val;
+ boost::queue_op_status st = pq.pull_for(milliseconds(500), val);
+ steady_clock::duration diff = steady_clock::now() - start;
+ BOOST_TEST(boost::queue_op_status::timeout == st);
+ BOOST_TEST(diff < milliseconds(550) && diff > milliseconds(500));
+}
+
+void test_pull_until()
+{
+ sync_pq pq;
+ steady_clock::time_point start = steady_clock::now();
+ int val;
+ boost::queue_op_status st = pq.pull_until(start + milliseconds(500), val);
+ steady_clock::duration diff = steady_clock::now() - start;
+ BOOST_TEST(boost::queue_op_status::timeout == st);
+ BOOST_TEST(diff < milliseconds(550) && diff > milliseconds(500));
+}
+
+void test_nonblocking_pull()
+{
+ sync_pq pq;
+ steady_clock::time_point start = steady_clock::now();
+ int val;
+ boost::queue_op_status st = pq.nonblocking_pull(val);
+ steady_clock::duration diff = steady_clock::now() - start;
+ BOOST_TEST(boost::queue_op_status::empty == st);
+ BOOST_TEST(diff < milliseconds(5));
+}
+
+void test_pull_for_when_not_empty()
+{
+ sync_pq pq;
+ pq.push(1);
+ steady_clock::time_point start = steady_clock::now();
+ int val;
+ boost::queue_op_status st = pq.pull_for(milliseconds(500), val);
+ steady_clock::duration diff = steady_clock::now() - start;
+ BOOST_TEST(boost::queue_op_status::success == st);
+ BOOST_TEST(1 == val);
+ BOOST_TEST(diff < milliseconds(5));
+}
+
+void test_pull_until_when_not_empty()
+{
+ sync_pq pq;
+ pq.push(1);
+ steady_clock::time_point start = steady_clock::now();
+ int val;
+ boost::queue_op_status st = pq.pull_until(start + milliseconds(500), val);
+ steady_clock::duration diff = steady_clock::now() - start;
+ BOOST_TEST(boost::queue_op_status::success == st);
+ BOOST_TEST(1 == val);
+ BOOST_TEST(diff < milliseconds(5));
+}
+
+int main()
+{
+ sync_pq pq;
+ BOOST_TEST(pq.empty());
+ BOOST_TEST(!pq.closed());
+ BOOST_TEST_EQ(pq.size(), std::size_t(0));
+
+ for(int i = 1; i <= 5; i++){
+ pq.push(i);
+ BOOST_TEST(!pq.empty());
+ BOOST_TEST_EQ(pq.size(), std::size_t(i));
+ }
+
+ for(int i = 6; i <= 10; i++){
+ boost::queue_op_status succ = pq.try_push(i);
+ BOOST_TEST(succ == boost::queue_op_status::success );
+ BOOST_TEST(!pq.empty());
+ BOOST_TEST_EQ(pq.size(), std::size_t(i));
+ }
+
+ for(int i = 10; i > 5; i--){
+ int val = pq.pull();
+ BOOST_TEST_EQ(val, i);
+ }
+
+// for(int i = 5; i > 0; i--){
+// boost::optional<int> val = pq.try_pull();
+// BOOST_TEST(val);
+// BOOST_TEST_EQ(*val, i);
+// }
+
+// BOOST_TEST(pq.empty());
+ pq.close();
+ BOOST_TEST(pq.closed());
+
+ test_pull_for();
+ test_pull_until();
+ test_nonblocking_pull();
+
+ test_pull_for_when_not_empty();
+ //test_pull_until_when_not_empty();
+
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ {
+ // empty queue try_push rvalue/non-copyable succeeds
+ boost::concurrent::sync_priority_queue<non_copyable> q;
+ BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1)));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ //fixme
+ // empty queue try_push rvalue/non-copyable succeeds
+ boost::concurrent::sync_priority_queue<non_copyable> q;
+ non_copyable nc(1);
+ BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc)));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+
+ {
+ // empty queue try_push lvalue succeeds
+ boost::concurrent::sync_priority_queue<int> q;
+ int i=1;
+ BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+#if 0
+ {
+ // empty queue try_push rvalue succeeds
+ boost::concurrent::sync_priority_queue<int> q;
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue nonblocking_push rvalue/non-copyable succeeds
+ boost::concurrent::sync_priority_queue<non_copyable> q;
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // empty queue nonblocking_push rvalue/non-copyable succeeds
+ boost::concurrent::sync_priority_queue<non_copyable> q;
+ non_copyable nc(1);
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
+ BOOST_TEST(! q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 1u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+
+ {
+ // 1-element queue pull succeed
+ boost::concurrent::sync_priority_queue<int> q;
+ q.push(1);
+ int i;
+ i=q.pull();
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ {
+ // 1-element queue pull succeed
+ boost::concurrent::sync_priority_queue<non_copyable> q;
+ non_copyable nc1(1);
+ q.push(boost::move(nc1));
+ non_copyable nc2(2);
+ nc2=q.pull();
+ BOOST_TEST_EQ(nc1, nc2);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+
+ {
+ // 1-element queue pull succeed
+ boost::concurrent::sync_priority_queue<int> q;
+ q.push(1);
+ int i = q.pull();
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ {
+ // 1-element queue pull succeed
+ boost::concurrent::sync_priority_queue<non_copyable> q;
+ non_copyable nc1(1);
+ q.push(boost::move(nc1));
+ non_copyable nc = q.pull();
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+
+ {
+ // 1-element queue try_pull succeed
+ boost::concurrent::sync_priority_queue<int> q;
+ q.push(1);
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.try_pull(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ {
+ // 1-element queue try_pull succeed
+ boost::concurrent::sync_priority_queue<non_copyable> q;
+ non_copyable nc1(1);
+ q.push(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+ {
+ // 1-element queue nonblocking_pull succeed
+ boost::concurrent::sync_priority_queue<int> q;
+ q.push(1);
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ {
+ // 1-element queue nonblocking_pull succeed
+ boost::concurrent::sync_priority_queue<non_copyable> q;
+ non_copyable nc1(1);
+ q.push(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+ {
+ // 1-element queue wait_pull succeed
+ boost::concurrent::sync_priority_queue<non_copyable> q;
+ non_copyable nc1(1);
+ q.push(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+ {
+ // 1-element queue wait_pull succeed
+ boost::concurrent::sync_priority_queue<int> q;
+ q.push(1);
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ {
+ // 1-element queue wait_pull succeed
+ boost::concurrent::sync_priority_queue<non_copyable> q;
+ non_copyable nc1(1);
+ q.push(boost::move(nc1));
+ non_copyable nc(2);
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
+ BOOST_TEST_EQ(nc, nc1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(! q.closed());
+ }
+#endif
+
+ {
+ // closed invariants
+ boost::concurrent::sync_priority_queue<int> q;
+ q.close();
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ {
+ // closed queue push fails
+ boost::concurrent::sync_priority_queue<int> q;
+ q.close();
+ try {
+ q.push(1);
+ BOOST_TEST(false); // fixme
+ } catch (...) {
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ }
+ {
+ // 1-element closed queue pull succeed
+ boost::concurrent::sync_priority_queue<int> q;
+ q.push(1);
+ q.close();
+ int i;
+ i=q.pull();
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ {
+ // 1-element closed queue wait_pull succeed
+ boost::concurrent::sync_priority_queue<int> q;
+ q.push(1);
+ q.close();
+ int i;
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
+ BOOST_TEST_EQ(i, 1);
+ BOOST_TEST(q.empty());
+ BOOST_TEST(! q.full());
+ BOOST_TEST_EQ(q.size(), 0u);
+ BOOST_TEST(q.closed());
+ }
+ {
+ // closed empty queue wait_pull fails
+ boost::concurrent::sync_priority_queue<int> q;
+ q.close();
+ BOOST_TEST(q.empty());
+ BOOST_TEST(q.closed());
+ int i;
+ BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i));
+ BOOST_TEST(q.empty());
+ BOOST_TEST(q.closed());
+ }
+ return boost::report_errors();
+}
diff --git a/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp b/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp
new file mode 100644
index 0000000000..dd4dfc17fb
--- /dev/null
+++ b/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp
@@ -0,0 +1,155 @@
+// 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)
+//
+
+#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.hpp>
+#include <boost/chrono.hpp>
+#include <boost/function.hpp>
+#include <boost/thread/concurrent_queues/sync_timed_queue.hpp>
+#include <boost/thread/executors/work.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost::chrono;
+
+typedef boost::concurrent::sync_timed_queue<int> sync_tq;
+
+void test_all()
+{
+ sync_tq pq;
+ BOOST_TEST(pq.empty());
+ BOOST_TEST(!pq.closed());
+ BOOST_TEST_EQ(pq.size(), std::size_t(0));
+
+ for(int i = 1; i <= 5; i++){
+ pq.push(i, milliseconds(i*100));
+ BOOST_TEST(!pq.empty());
+ BOOST_TEST_EQ(pq.size(), std::size_t(i));
+ }
+
+ for(int i = 6; i <= 10; i++){
+ pq.push(i,steady_clock::now() + milliseconds(i*100));
+ BOOST_TEST(!pq.empty());
+ BOOST_TEST_EQ(pq.size(), std::size_t(i));
+ }
+
+ for(int i = 1; i <= 10; i++){
+ int val = pq.pull();
+ BOOST_TEST_EQ(val, i);
+ }
+
+ int val;
+ boost::queue_op_status st = pq.nonblocking_pull(val);
+ BOOST_TEST(boost::queue_op_status::empty == st);
+
+ BOOST_TEST(pq.empty());
+ pq.close();
+ BOOST_TEST(pq.closed());
+}
+
+void test_all_with_try()
+{
+ sync_tq pq;
+ BOOST_TEST(pq.empty());
+ BOOST_TEST(!pq.closed());
+ BOOST_TEST_EQ(pq.size(), std::size_t(0));
+
+ for(int i = 1; i <= 5; i++){
+ boost::queue_op_status st = pq.try_push(i, milliseconds(i*100));
+ BOOST_TEST(st == boost::queue_op_status::success );
+ BOOST_TEST(!pq.empty());
+ BOOST_TEST_EQ(pq.size(), std::size_t(i));
+ }
+
+ for(int i = 6; i <= 10; i++){
+ boost::queue_op_status st = pq.try_push(i,steady_clock::now() + milliseconds(i*100));
+ BOOST_TEST(st == boost::queue_op_status::success );
+ BOOST_TEST(!pq.empty());
+ BOOST_TEST_EQ(pq.size(), std::size_t(i));
+ }
+
+ for(int i = 1; i <= 10; i++){
+ int val=0;
+ boost::queue_op_status st = pq.wait_pull(val);
+ BOOST_TEST(st == boost::queue_op_status::success );
+ BOOST_TEST_EQ(val, i);
+ }
+
+ int val;
+ boost::queue_op_status st = pq.nonblocking_pull(val);
+ BOOST_TEST(st == boost::queue_op_status::empty );
+
+ BOOST_TEST(pq.empty());
+ pq.close();
+ BOOST_TEST(pq.closed());
+}
+
+void func(steady_clock::time_point pushed, steady_clock::duration dur)
+{
+ BOOST_TEST(pushed + dur <= steady_clock::now());
+}
+void func2()
+{
+ BOOST_TEST(false);
+}
+
+/**
+ * This test ensures that when items come of the front of the queue
+ * that at least $dur has elapsed.
+ */
+void test_deque_times()
+{
+ boost::concurrent::sync_timed_queue<boost::function<void()> > tq;
+ for(int i = 0; i < 10; i++)
+ {
+ steady_clock::duration d = milliseconds(i*100);
+ boost::function<void()> fn = boost::bind(func, steady_clock::now(), d);
+ tq.push(fn, d);
+ }
+ while(!tq.empty())
+ {
+ boost::function<void()> fn = tq.pull();
+ fn();
+ }
+}
+
+/**
+ * This test ensures that when items come of the front of the queue
+ * that at least $dur has elapsed.
+ */
+#if 0
+void test_deque_times2()
+{
+ boost::concurrent::sync_timed_queue<boost::executors::work> tq;
+ for(int i = 0; i < 10; i++)
+ {
+ steady_clock::duration d = milliseconds(i*100);
+ tq.push(func2, d);
+ }
+ while(!tq.empty())
+ {
+ boost::executors::work fn = tq.pull();
+ fn();
+ }
+}
+#endif
+
+int main()
+{
+ test_all();
+ test_all_with_try();
+ test_deque_times();
+ //test_deque_times2(); // rt fails
+ return boost::report_errors();
+}
diff --git a/libs/thread/test/sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp b/libs/thread/test/sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp
index 0d6d1025d3..556ca68e97 100644
--- a/libs/thread/test/sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp
+++ b/libs/thread/test/sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp
@@ -15,7 +15,6 @@
#endif
#define BOOST_THREAD_VERSION 4
-//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/future.hpp>
@@ -23,50 +22,13 @@
#include <boost/detail/lightweight_test.hpp>
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
-struct call_push
-{
- boost::sync_queue<int> *q_;
- boost::barrier *go_;
-
- call_push(boost::sync_queue<int> *q, boost::barrier *go) :
- q_(q), go_(go)
- {
- }
- typedef void result_type;
- void operator()()
- {
- go_->count_down_and_wait();
- q_->push(42);
-
- }
-};
-
-struct call_pull
-{
- boost::sync_queue<int> *q_;
- boost::barrier *go_;
-
- call_pull(boost::sync_queue<int> *q, boost::barrier *go) :
- q_(q), go_(go)
- {
- }
- typedef int result_type;
- int operator()()
- {
- go_->count_down_and_wait();
- return q_->pull();
- }
-};
-#endif
-
template <typename ValueType>
-struct call_push_back
+struct call_push
{
boost::sync_queue<ValueType> *q_;
boost::barrier *go_;
- call_push_back(boost::sync_queue<ValueType> *q, boost::barrier *go) :
+ call_push(boost::sync_queue<ValueType> *q, boost::barrier *go) :
q_(q), go_(go)
{
}
@@ -74,17 +36,17 @@ struct call_push_back
void operator()()
{
go_->count_down_and_wait();
- q_->push_back(42);
+ q_->push(42);
}
};
template <typename ValueType>
-struct call_pull_front
+struct call_pull
{
boost::sync_queue<ValueType> *q_;
boost::barrier *go_;
- call_pull_front(boost::sync_queue<ValueType> *q, boost::barrier *go) :
+ call_pull(boost::sync_queue<ValueType> *q, boost::barrier *go) :
q_(q), go_(go)
{
}
@@ -92,17 +54,17 @@ struct call_pull_front
ValueType operator()()
{
go_->count_down_and_wait();
- return q_->pull_front();
+ return q_->pull();
}
};
template <typename ValueType>
-struct call_wait_pull_front
+struct call_wait_pull
{
boost::sync_queue<ValueType> *q_;
boost::barrier *go_;
- call_wait_pull_front(boost::sync_queue<ValueType> *q, boost::barrier *go) :
+ call_wait_pull(boost::sync_queue<ValueType> *q, boost::barrier *go) :
q_(q), go_(go)
{
}
@@ -110,11 +72,10 @@ struct call_wait_pull_front
boost::queue_op_status operator()(ValueType& v)
{
go_->wait();
- return q_->wait_pull_front(v);
+ return q_->wait_pull(v);
}
};
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
void test_concurrent_push_and_pull_on_empty_queue()
{
boost::sync_queue<int> q;
@@ -127,127 +88,9 @@ void test_concurrent_push_and_pull_on_empty_queue()
try
{
push_done=boost::async(boost::launch::async,
-#if ! defined BOOST_NO_CXX11_LAMBDAS
- [&q,&go]()
- {
- go.wait();
- q.push(42);
- }
-#else
- call_push(&q,&go)
-#endif
- );
- pull_done=boost::async(boost::launch::async,
-#if ! defined BOOST_NO_CXX11_LAMBDAS
- [&q,&go]() -> int
- {
- go.wait();
- return q.pull();
- }
-#else
- call_pull(&q,&go)
-#endif
- );
-
- push_done.get();
- BOOST_TEST_EQ(pull_done.get(), 42);
- BOOST_TEST(q.empty());
- }
- catch (...)
- {
- BOOST_TEST(false);
- }
-}
-
-void test_concurrent_push_on_empty_queue()
-{
- boost::sync_queue<int> q;
- const unsigned int n = 3;
- boost::barrier go(n);
- boost::future<void> push_done[n];
-
- try
- {
- for (unsigned int i =0; i< n; ++i)
- push_done[i]=boost::async(boost::launch::async,
-#if ! defined BOOST_NO_CXX11_LAMBDAS
- [&q,&go]()
- {
- go.wait();
- q.push(42);
- }
-#else
- call_push(&q,&go)
-#endif
- );
-
- for (unsigned int i = 0; i < n; ++i)
- push_done[i].get();
-
- BOOST_TEST(!q.empty());
- for (unsigned int i =0; i< n; ++i)
- BOOST_TEST_EQ(q.pull(), 42);
- BOOST_TEST(q.empty());
-
- }
- catch (...)
- {
- BOOST_TEST(false);
- }
-}
-
-void test_concurrent_pull_on_queue()
-{
- boost::sync_queue<int> q;
- const unsigned int n = 3;
- boost::barrier go(n);
-
- boost::future<int> pull_done[n];
-
- try
- {
- for (unsigned int i =0; i< n; ++i)
- q.push(42);
-
- for (unsigned int i =0; i< n; ++i)
- pull_done[i]=boost::async(boost::launch::async,
-#if ! defined BOOST_NO_CXX11_LAMBDAS
- [&q,&go]() -> int
- {
- go.wait();
- return q.pull();
- }
-#else
- call_pull(&q,&go)
-#endif
- );
-
- for (unsigned int i = 0; i < n; ++i)
- BOOST_TEST_EQ(pull_done[i].get(), 42);
- BOOST_TEST(q.empty());
- }
- catch (...)
- {
- BOOST_TEST(false);
- }
-}
-#endif
-
-void test_concurrent_push_back_and_pull_front_on_empty_queue()
-{
- boost::sync_queue<int> q;
-
- boost::barrier go(2);
-
- boost::future<void> push_done;
- boost::future<int> pull_done;
-
- try
- {
- push_done=boost::async(boost::launch::async,
- call_push_back<int>(&q,&go));
+ call_push<int>(&q,&go));
pull_done=boost::async(boost::launch::async,
- call_pull_front<int>(&q,&go));
+ call_pull<int>(&q,&go));
push_done.get();
BOOST_TEST_EQ(pull_done.get(), 42);
@@ -260,7 +103,7 @@ void test_concurrent_push_back_and_pull_front_on_empty_queue()
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
-void test_concurrent_push_back_and_wait_pull_front_on_empty_queue()
+void test_concurrent_push_and_wait_pull_on_empty_queue()
{
boost::sync_queue<int> q;
const unsigned int n = 3;
@@ -273,11 +116,11 @@ void test_concurrent_push_back_and_wait_pull_front_on_empty_queue()
{
for (unsigned int i =0; i< n; ++i)
pull_done[i]=boost::async(boost::launch::async,
- call_wait_pull_front<int>(&q,&go),
+ call_wait_pull<int>(&q,&go),
boost::ref(results[i]));
for (unsigned int i =0; i< n; ++i)
- q.push_back(42);
+ q.push(42);
for (unsigned int i = 0; i < n; ++i) {
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success);
@@ -291,7 +134,7 @@ void test_concurrent_push_back_and_wait_pull_front_on_empty_queue()
}
}
-void test_concurrent_wait_pull_front_and_close_on_empty_queue()
+void test_concurrent_wait_pull_and_close_on_empty_queue()
{
boost::sync_queue<int> q;
const unsigned int n = 3;
@@ -304,7 +147,7 @@ void test_concurrent_wait_pull_front_and_close_on_empty_queue()
{
for (unsigned int i =0; i< n; ++i)
pull_done[i]=boost::async(boost::launch::async,
- call_wait_pull_front<int>(&q,&go),
+ call_wait_pull<int>(&q,&go),
boost::ref(results[i]));
q.close();
@@ -321,7 +164,7 @@ void test_concurrent_wait_pull_front_and_close_on_empty_queue()
}
#endif
-void test_concurrent_push_back_on_empty_queue()
+void test_concurrent_push_on_empty_queue()
{
boost::sync_queue<int> q;
const unsigned int n = 3;
@@ -332,7 +175,7 @@ void test_concurrent_push_back_on_empty_queue()
{
for (unsigned int i =0; i< n; ++i)
push_done[i]=boost::async(boost::launch::async,
- call_push_back<int>(&q,&go));
+ call_push<int>(&q,&go));
}
catch (...)
@@ -353,7 +196,7 @@ void test_concurrent_push_back_on_empty_queue()
{
BOOST_TEST(!q.empty());
for (unsigned int i =0; i< n; ++i)
- BOOST_TEST_EQ(q.pull_front(), 42);
+ BOOST_TEST_EQ(q.pull(), 42);
BOOST_TEST(q.empty());
}
@@ -363,7 +206,7 @@ void test_concurrent_push_back_on_empty_queue()
}
}
-void test_concurrent_pull_front_on_queue()
+void test_concurrent_pull_on_queue()
{
boost::sync_queue<int> q;
const unsigned int n = 3;
@@ -374,7 +217,7 @@ void test_concurrent_pull_front_on_queue()
try
{
for (unsigned int i =0; i< n; ++i)
- q.push_back(42);
+ q.push(42);
for (unsigned int i =0; i< n; ++i)
pull_done[i]=boost::async(boost::launch::async,
@@ -382,10 +225,10 @@ void test_concurrent_pull_front_on_queue()
[&q,&go]() -> int
{
go.wait();
- return q.pull_front();
+ return q.pull();
}
#else
- call_pull_front<int>(&q,&go)
+ call_pull<int>(&q,&go)
#endif
);
@@ -401,18 +244,13 @@ void test_concurrent_pull_front_on_queue()
int main()
{
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
test_concurrent_push_and_pull_on_empty_queue();
- test_concurrent_push_on_empty_queue();
- test_concurrent_pull_on_queue();
-#endif
- test_concurrent_push_back_and_pull_front_on_empty_queue();
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
- test_concurrent_push_back_and_wait_pull_front_on_empty_queue();
- test_concurrent_wait_pull_front_and_close_on_empty_queue();
+ test_concurrent_push_and_wait_pull_on_empty_queue();
+ test_concurrent_wait_pull_and_close_on_empty_queue();
#endif
- test_concurrent_push_back_on_empty_queue();
- test_concurrent_pull_front_on_queue();
+ test_concurrent_push_on_empty_queue();
+ test_concurrent_pull_on_queue();
return boost::report_errors();
}
diff --git a/libs/thread/test/sync/mutual_exclusion/sync_queue/single_thread_pass.cpp b/libs/thread/test/sync/mutual_exclusion/sync_queue/single_thread_pass.cpp
index 0d788d88ca..8f47ec82ad 100644
--- a/libs/thread/test/sync/mutual_exclusion/sync_queue/single_thread_pass.cpp
+++ b/libs/thread/test/sync/mutual_exclusion/sync_queue/single_thread_pass.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Vicente J. Botet Escriba
+// Copyright (C) 2013,2015 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -10,7 +10,6 @@
// sync_queue();
#define BOOST_THREAD_VERSION 4
-//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/sync_queue.hpp>
@@ -47,79 +46,8 @@ int main()
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- {
- // empty queue try_pull fails
- boost::sync_queue<int> q;
- int i;
- BOOST_TEST(! q.try_pull(i));
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
- {
- // empty queue try_pull fails
- boost::sync_queue<int> q;
- BOOST_TEST(! q.try_pull());
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
- {
- // empty queue push rvalue/copyable succeeds
- boost::sync_queue<int> q;
- q.push(1);
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
- {
- // empty queue push lvalue/copyable succeeds
- boost::sync_queue<int> q;
- int i;
- q.push(i);
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
-#endif
-
- {
- // empty queue try_pull fails
- boost::sync_queue<int> q;
- int i;
- BOOST_TEST( boost::queue_op_status::empty == q.try_pull_front(i));
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
- {
- // empty queue push rvalue/copyable succeeds
- boost::sync_queue<int> q;
- q.push_back(1);
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
- {
- // empty queue push lvalue/copyable succeeds
- boost::sync_queue<int> q;
- int i;
- q.push_back(i);
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
-#if 0
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue push rvalue/non_copyable succeeds
boost::sync_queue<non_copyable> q;
@@ -164,68 +92,7 @@ int main()
{
// empty queue try_push rvalue/copyable succeeds
boost::sync_queue<int> q;
- BOOST_TEST(q.try_push(1));
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
- {
- // empty queue try_push rvalue/copyable succeeds
- boost::sync_queue<int> q;
- BOOST_TEST(q.try_push(1));
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
-#endif
-#if 0
- {
- // empty queue push rvalue/non_copyable succeeds
- boost::sync_queue<non_copyable> q;
- q.push_back(non_copyable(1));
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
-#endif
- {
- // empty queue push rvalue/non_copyable succeeds
- boost::sync_queue<non_copyable> q;
- non_copyable nc(1);
- q.push_back(boost::move(nc));
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
-
- {
- // empty queue push rvalue succeeds
- boost::sync_queue<int> q;
- q.push_back(1);
- q.push_back(2);
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 2u);
- BOOST_TEST(! q.closed());
- }
- {
- // empty queue push lvalue succeeds
- boost::sync_queue<int> q;
- int i;
- q.push_back(i);
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
- {
- // empty queue try_push rvalue/copyable succeeds
- boost::sync_queue<int> q;
- BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
+ BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -234,60 +101,18 @@ int main()
{
// empty queue try_push rvalue/copyable succeeds
boost::sync_queue<int> q;
- BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
-#if 0
- {
- // empty queue try_push rvalue/non-copyable succeeds
- boost::sync_queue<non_copyable> q;
- BOOST_TEST(q.try_push(non_copyable()));
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
-#endif
- {
- // empty queue try_push rvalue/non-copyable succeeds
- boost::sync_queue<non_copyable> q;
- non_copyable nc(1);
- BOOST_TEST(q.try_push(boost::move(nc)));
+ BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
- {
- // empty queue try_push lvalue succeeds
- boost::sync_queue<int> q;
- int i=1;
- BOOST_TEST(q.try_push(i));
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
- {
- // empty queue try_push rvalue succeeds
- boost::sync_queue<int> q;
- BOOST_TEST(q.try_push(boost::no_block, 1));
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
-#endif
-#if 0
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
- BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable()));
+ BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -298,7 +123,7 @@ int main()
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
non_copyable nc(1);
- BOOST_TEST(boost::queue_op_status::success == q.try_push_back(boost::move(nc)));
+ BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -309,7 +134,7 @@ int main()
// empty queue try_push lvalue succeeds
boost::sync_queue<int> q;
int i=1;
- BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i));
+ BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -318,19 +143,18 @@ int main()
{
// empty queue try_push rvalue succeeds
boost::sync_queue<int> q;
- BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(1));
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
-#if 0
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
- // empty queue try_push rvalue/non-copyable succeeds
+ // empty queue nonblocking_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
- BOOST_TEST(q.try_push(boost::no_block, non_copyable(1)));
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -338,10 +162,10 @@ int main()
}
#endif
{
- // empty queue try_push rvalue/non-copyable succeeds
+ // empty queue nonblocking_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
non_copyable nc(1);
- BOOST_TEST(q.try_push(boost::no_block, boost::move(nc)));
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
@@ -400,7 +224,7 @@ int main()
boost::sync_queue<int> q;
q.push(1);
int i;
- BOOST_TEST(q.try_pull(i));
+ BOOST_TEST(boost::queue_op_status::success == q.try_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -413,7 +237,7 @@ int main()
non_copyable nc1(1);
q.push(boost::move(nc1));
non_copyable nc(2);
- BOOST_TEST(q.try_pull(nc));
+ BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -421,11 +245,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue try_pull succeed
+ // 1-element queue nonblocking_pull succeed
boost::sync_queue<int> q;
q.push(1);
int i;
- BOOST_TEST(q.try_pull(boost::no_block, i));
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -433,177 +257,12 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue try_pull succeed
+ // 1-element queue nonblocking_pull succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push(boost::move(nc1));
non_copyable nc(2);
- BOOST_TEST(q.try_pull(boost::no_block, nc));
- BOOST_TEST_EQ(nc, nc1);
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
- {
- // 1-element queue try_pull succeed
- boost::sync_queue<int> q;
- q.push(1);
- boost::shared_ptr<int> i = q.try_pull();
- BOOST_TEST_EQ(*i, 1);
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
-
- {
- // closed invariants
- boost::sync_queue<int> q;
- q.close();
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(q.closed());
- }
- {
- // closed queue push fails
- boost::sync_queue<int> q;
- q.close();
- try {
- q.push(1);
- BOOST_TEST(false);
- } catch (...) {
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(q.closed());
- }
- }
- {
- // closed empty queue try_pull_front closed
- boost::sync_queue<int> q;
- q.close();
- int i;
- BOOST_TEST(boost::queue_op_status::closed == q.try_pull_front(i));
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(q.closed());
- }
- {
- // closed empty queue nonblocking_pull_front closed
- boost::sync_queue<int> q;
- q.close();
- int i;
- BOOST_TEST(boost::queue_op_status::closed == q.nonblocking_pull_front(i));
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(q.closed());
- }
- {
- // 1-element closed queue pull succeed
- boost::sync_queue<int> q;
- q.push(1);
- q.close();
- int i;
- q.pull(i);
- BOOST_TEST_EQ(i, 1);
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(q.closed());
- }
-#endif
-#if 0
- {
- // empty queue nonblocking_push_back rvalue/non-copyable succeeds
- boost::sync_queue<non_copyable> q;
- BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(non_copyable(1)));
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
-#endif
- {
- // empty queue nonblocking_push_back rvalue/non-copyable succeeds
- boost::sync_queue<non_copyable> q;
- non_copyable nc(1);
- BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(boost::move(nc)));
- BOOST_TEST(! q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 1u);
- BOOST_TEST(! q.closed());
- }
- {
- // 1-element queue pull_front succeed
- boost::sync_queue<int> q;
- q.push_back(1);
- int i;
- q.pull_front(i);
- BOOST_TEST_EQ(i, 1);
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
- {
- // 1-element queue pull_front succeed
- boost::sync_queue<non_copyable> q;
- non_copyable nc1(1);
- q.push_back(boost::move(nc1));
- non_copyable nc2(2);
- q.pull_front(nc2);
- BOOST_TEST_EQ(nc1, nc2);
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
- {
- // 1-element queue pull_front succeed
- boost::sync_queue<int> q;
- q.push_back(1);
- int i = q.pull_front();
- BOOST_TEST_EQ(i, 1);
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
- {
- // 1-element queue pull_front succeed
- boost::sync_queue<non_copyable> q;
- non_copyable nc1(1);
- q.push_back(boost::move(nc1));
- non_copyable nc = q.pull_front();
- BOOST_TEST_EQ(nc, nc1);
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
- {
- // 1-element queue try_pull_front succeed
- boost::sync_queue<int> q;
- q.push_back(1);
- int i;
- BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(i));
- BOOST_TEST_EQ(i, 1);
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
- {
- // 1-element queue try_pull_front succeed
- boost::sync_queue<non_copyable> q;
- non_copyable nc1(1);
- q.push_back(boost::move(nc1));
- non_copyable nc(2);
- BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(nc));
+ BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -611,37 +270,12 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue nonblocking_pull_front succeed
- boost::sync_queue<int> q;
- q.push_back(1);
- int i;
- BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(i));
- BOOST_TEST_EQ(i, 1);
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
- {
- // 1-element queue nonblocking_pull_front succeed
+ // 1-element queue wait_pull succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
- q.push_back(boost::move(nc1));
- non_copyable nc(2);
- BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(nc));
- BOOST_TEST_EQ(nc, nc1);
- BOOST_TEST(q.empty());
- BOOST_TEST(! q.full());
- BOOST_TEST_EQ(q.size(), 0u);
- BOOST_TEST(! q.closed());
- }
- {
- // 1-element queue wait_pull_front succeed
- boost::sync_queue<non_copyable> q;
- non_copyable nc1(1);
- q.push_back(boost::move(nc1));
+ q.push(boost::move(nc1));
non_copyable nc(2);
- BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -649,11 +283,11 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue wait_pull_front succeed
+ // 1-element queue wait_pull succeed
boost::sync_queue<int> q;
- q.push_back(1);
+ q.push(1);
int i;
- BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -661,12 +295,12 @@ int main()
BOOST_TEST(! q.closed());
}
{
- // 1-element queue wait_pull_front succeed
+ // 1-element queue wait_pull succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
- q.push_back(boost::move(nc1));
+ q.push(boost::move(nc1));
non_copyable nc(2);
- BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -688,7 +322,7 @@ int main()
boost::sync_queue<int> q;
q.close();
try {
- q.push_back(1);
+ q.push(1);
BOOST_TEST(false);
} catch (...) {
BOOST_TEST(q.empty());
@@ -700,10 +334,10 @@ int main()
{
// 1-element closed queue pull succeed
boost::sync_queue<int> q;
- q.push_back(1);
+ q.push(1);
q.close();
int i;
- q.pull_front(i);
+ q.pull(i);
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -711,12 +345,12 @@ int main()
BOOST_TEST(q.closed());
}
{
- // 1-element closed queue wait_pull_front succeed
+ // 1-element closed queue wait_pull succeed
boost::sync_queue<int> q;
- q.push_back(1);
+ q.push(1);
q.close();
int i;
- BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
+ BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
BOOST_TEST_EQ(i, 1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
@@ -724,13 +358,13 @@ int main()
BOOST_TEST(q.closed());
}
{
- // closed empty queue wait_pull_front fails
+ // closed empty queue wait_pull fails
boost::sync_queue<int> q;
q.close();
BOOST_TEST(q.empty());
BOOST_TEST(q.closed());
int i;
- BOOST_TEST(boost::queue_op_status::closed == q.wait_pull_front(i));
+ BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i));
BOOST_TEST(q.empty());
BOOST_TEST(q.closed());
}
diff --git a/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp b/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp
index 58ec01ab4b..2da08c2f48 100644
--- a/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp
+++ b/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp
@@ -72,7 +72,7 @@ void test_bind() {
BOOST_TEST(c == 345);
}
-#if defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
void test_bind_non_const() {
std::cout << "c++11 variadic templates disabled" << std::endl;
}
diff --git a/libs/thread/test/test_10340.cpp b/libs/thread/test/test_10340.cpp
index 50d2aa0d07..5311e8210d 100644
--- a/libs/thread/test/test_10340.cpp
+++ b/libs/thread/test/test_10340.cpp
@@ -1,3 +1,8 @@
+// Copyright (C) 2014 Vicente Botet
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
#define BOOST_THREAD_VERSION 4
#include <boost/thread/future.hpp>
diff --git a/libs/thread/test/test_10963.cpp b/libs/thread/test/test_10963.cpp
new file mode 100644
index 0000000000..b918b55d32
--- /dev/null
+++ b/libs/thread/test/test_10963.cpp
@@ -0,0 +1,44 @@
+// Copyright (C) 2014 Vicente Botet
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_THREAD_VERSION 4
+#include <boost/config.hpp>
+#if ! defined BOOST_NO_CXX11_DECLTYPE
+#define BOOST_RESULT_OF_USE_DECLTYPE
+#endif
+
+#include <boost/thread/future.hpp>
+#include <boost/static_assert.hpp>
+
+
+struct TestCallback
+{
+ typedef boost::future<void> result_type;
+
+ result_type operator()(boost::future<void> future) const
+ {
+ future.get();
+ return boost::make_ready_future();
+ }
+
+ result_type operator()(boost::future<boost::future<void> > future) const
+ {
+ future.get();
+ return boost::make_ready_future();
+ }
+};
+
+int main()
+{
+#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS
+ boost::promise<void> test_promise;
+ boost::future<void> test_future(test_promise.get_future());
+ auto f1 = test_future.then(TestCallback());
+ BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
+ auto f2 = f1.then(TestCallback());
+ BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<boost::future<void> > >::value);
+#endif
+ return 0;
+}
diff --git a/libs/thread/test/test_10964.cpp b/libs/thread/test/test_10964.cpp
new file mode 100644
index 0000000000..b8cc7b5c05
--- /dev/null
+++ b/libs/thread/test/test_10964.cpp
@@ -0,0 +1,76 @@
+// Copyright (C) 2015 Vicente Botet
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_THREAD_VERSION 4
+#include <boost/config.hpp>
+#if ! defined BOOST_NO_CXX11_DECLTYPE
+#define BOOST_RESULT_OF_USE_DECLTYPE
+#endif
+
+#include <boost/thread/future.hpp>
+#include <boost/static_assert.hpp>
+
+struct TestCallback
+{
+ typedef boost::future<void> result_type;
+
+ result_type operator()(boost::future<void> future) const
+ {
+ future.get();
+ return boost::make_ready_future();
+ }
+
+ result_type operator()(boost::future<boost::future<void> > future) const
+ {
+ future.get();
+ return boost::make_ready_future();
+ }
+};
+
+void p1()
+{
+}
+
+int main()
+{
+#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS
+ std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
+ {
+ auto f1 = boost::make_ready_future().then(TestCallback());
+ BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
+ f1.wait();
+ }
+ std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
+ {
+ auto f1 = boost::make_ready_future().then(TestCallback());
+ BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
+ auto f2 = f1.unwrap();
+ BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
+ f2.wait();
+ }
+ std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
+ {
+ auto f1 = boost::make_ready_future().then(TestCallback());
+ BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
+ auto f2 = f1.unwrap();
+ BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
+ auto f3 = f2.then(TestCallback());
+ BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
+ f3.wait();
+ }
+ std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
+ {
+ boost::make_ready_future().then(
+ TestCallback()).unwrap().then(TestCallback()).get();
+ }
+ std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
+ {
+ boost::future<void> f = boost::async(p1);
+ f.then(
+ TestCallback()).unwrap().then(TestCallback()).get();
+ }
+#endif
+ return 0;
+}
diff --git a/libs/thread/test/test_11053.cpp b/libs/thread/test/test_11053.cpp
new file mode 100644
index 0000000000..a8b6dfa976
--- /dev/null
+++ b/libs/thread/test/test_11053.cpp
@@ -0,0 +1,70 @@
+// Copyright (C) 2015 Vicente Botet
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_THREAD_VERSION 4
+#include <boost/thread.hpp>
+#include <boost/thread/tss.hpp>
+#include <boost/shared_ptr.hpp>
+#include <iostream>
+
+struct A
+{
+ void DoWork()
+ {
+ std::cout << "A: doing work\n";
+ if (!m_ptr.get())
+ m_ptr.reset(new WorkSpace());
+ // do not very much
+ for (size_t i = 0; i < 10; ++i)
+ m_ptr->a += 10;
+ }
+
+private:
+ struct WorkSpace
+ {
+ int a;
+ WorkSpace() : a(0) {}
+ };
+ boost::thread_specific_ptr<WorkSpace> m_ptr;
+};
+
+struct B
+{
+ void DoWork()
+ {
+ std::cout << "B: doing work\n";
+ if (!m_ptr.get())
+ m_ptr.reset(new A());
+ m_ptr->DoWork();
+ }
+private:
+ boost::thread_specific_ptr<A> m_ptr;
+};
+
+struct C
+{
+ void DoWork()
+ {
+ std::cout << "C: doing work\n";
+ if (!m_ptr.get())
+ m_ptr.reset(new B());
+ m_ptr->DoWork();
+ }
+private:
+ boost::thread_specific_ptr<B> m_ptr;
+};
+
+int main(int ac, char** av)
+{
+ std::cout << "test starting\n";
+ boost::shared_ptr<C> p_C(new C);
+ boost::thread cWorker(&C::DoWork, p_C);
+ cWorker.join();
+ std::cout << "test stopping\n";
+ return 0;
+}
+
+
+
diff --git a/libs/thread/test/test_2309.cpp b/libs/thread/test/test_2309.cpp
index 1385a174a8..09d92c30a2 100755
--- a/libs/thread/test/test_2309.cpp
+++ b/libs/thread/test/test_2309.cpp
@@ -5,7 +5,7 @@
#define BOOST_THREAD_VERSION 2
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
-
+#define BOOST_TEST_MODULE Boost.Threads: 2309
#include <boost/test/unit_test.hpp>
#include <iostream>
@@ -40,7 +40,7 @@
}
}
- void test()
+ BOOST_AUTO_TEST_CASE(test)
{
try
{
@@ -61,14 +61,5 @@
}
}
-boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test_framework::test_suite* tests =
- BOOST_TEST_SUITE("Boost.Threads: 2309");
-
- tests->add(BOOST_TEST_CASE(&test));
-
- return tests;
-}
diff --git a/libs/thread/test/test_2741.cpp b/libs/thread/test/test_2741.cpp
index 409a51f7b8..793e68cdcf 100644
--- a/libs/thread/test/test_2741.cpp
+++ b/libs/thread/test/test_2741.cpp
@@ -3,7 +3,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
-
+#define BOOST_TEST_MODULE Boost.Threads: thread attributes test suite
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread_only.hpp>
@@ -29,7 +29,7 @@ void simple_thread()
test_value = 999;
}
-void test_native_handle()
+BOOST_AUTO_TEST_CASE(test_native_handle)
{
boost::thread_attributes attrs;
@@ -51,7 +51,7 @@ void test_native_handle()
}
-void test_stack_size()
+BOOST_AUTO_TEST_CASE(test_stack_size)
{
boost::thread_attributes attrs;
@@ -70,18 +70,8 @@ void do_test_creation_with_attrs()
BOOST_CHECK_EQUAL(test_value, 999);
}
-void test_creation_with_attrs()
+BOOST_AUTO_TEST_CASE(test_creation_with_attrs)
{
timed_test(&do_test_creation_with_attrs, 1);
}
-boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: thread attributes test suite");
-
- test->add(BOOST_TEST_CASE(test_native_handle));
- test->add(BOOST_TEST_CASE(test_stack_size));
- test->add(BOOST_TEST_CASE(test_creation_with_attrs));
-
- return test;
-}
diff --git a/libs/thread/test/test_9192.cpp b/libs/thread/test/test_9192.cpp
index ddc8b92667..c7aad7dd83 100755
--- a/libs/thread/test/test_9192.cpp
+++ b/libs/thread/test/test_9192.cpp
@@ -1,3 +1,8 @@
+// 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/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/thread.hpp>
diff --git a/libs/thread/test/test_9303.cpp b/libs/thread/test/test_9303.cpp
index a49758a1a2..19bfc3eeb2 100644
--- a/libs/thread/test/test_9303.cpp
+++ b/libs/thread/test/test_9303.cpp
@@ -1,3 +1,8 @@
+// Copyright (C) 2014 Vicente Botet
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
#define BOOST_THREAD_VERSION 4
#include <iostream>
#include <fstream>
@@ -81,7 +86,7 @@
#if defined EXAMPLE_3
//! Doesn't compile in C++03.
- //! error: variable ‘boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)> example’ has initializer but incomplete type
+ //! error: variable âboost::packaged_task<std::basic_string<char>(std::basic_string<char>&)> exampleâ has initializer but incomplete type
{
boost::packaged_task<std::string(std::string&)> example(string_with_params);
diff --git a/libs/thread/test/test_9319.cpp b/libs/thread/test/test_9319.cpp
index 173f427296..9e5c1d9350 100644
--- a/libs/thread/test/test_9319.cpp
+++ b/libs/thread/test/test_9319.cpp
@@ -24,18 +24,37 @@ void foo(IntPromise p)
void bar(boost::future<int> fooResult)
{
+ try {
std::cout << "bar" << std::endl;
int i = fooResult.get(); // Code hangs on this line (Due to future already being locked by the set_value call)
std::cout << "i: " << i << std::endl;
+ } catch(...) {
+ std::cout << __FILE__ << ":" << __LINE__ << std::endl;
+ }
}
int main()
{
+ std::cout << __FILE__ << ":" << __LINE__ << std::endl;
+ try {
IntPromise p(new boost::promise<int>());
boost::thread t(boost::bind(foo, p));
boost::future<int> f1 = p->get_future();
- //f1.then(launch::deferred, boost::bind(bar, _1));
f1.then(boost::launch::deferred, &bar);
t.join();
+ } catch(...) {
+ return 1;
+ }
+ std::cout << __FILE__ << ":" << __LINE__ << std::endl;
+ try {
+ IntPromise p(new boost::promise<int>());
+ boost::thread t(boost::bind(foo, p));
+ boost::future<int> f1 = p->get_future();
+ f1.then(boost::launch::async, &bar);
+ t.join();
+ } catch(...) {
+ return 2;
+ }
+ std::cout << __FILE__ << ":" << __LINE__ << std::endl;
}
diff --git a/libs/thread/test/test_9711.cpp b/libs/thread/test/test_9711.cpp
index a2095f6635..d8fd8e3e81 100644
--- a/libs/thread/test/test_9711.cpp
+++ b/libs/thread/test/test_9711.cpp
@@ -1,3 +1,7 @@
+// Copyright (C) 2014 Vicente Botet
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
diff --git a/libs/thread/test/test_9856.cpp b/libs/thread/test/test_9856.cpp
new file mode 100644
index 0000000000..918d232d5b
--- /dev/null
+++ b/libs/thread/test/test_9856.cpp
@@ -0,0 +1,29 @@
+#include "boost/atomic.hpp"
+#include "boost/thread.hpp"
+#include <iostream>
+
+using namespace boost;
+
+int main() {
+ atomic<size_t> total(0), failures(0);
+
+#pragma omp parallel shared(total, failures) num_threads(1000)
+ {
+ mutex mtx;
+ condition_variable cond;
+ unique_lock<mutex> lk(mtx);
+ for (int i = 0; i < 500; i++) {
+ ++total;
+ if (cv_status::timeout != cond.wait_for(lk, chrono::milliseconds(10)))
+ ++failures;
+ }
+ }
+ if(failures)
+ std::cout << "There were " << failures << " failures out of " << total << " timed waits." << std::endl;
+ if((100*failures)/total>10)
+ {
+ std::cerr << "This exceeds 10%, so failing the test." << std::endl;
+ return 1;
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/libs/thread/test/test_condition.cpp b/libs/thread/test/test_condition.cpp
index f37a955502..64d0871b7e 100644
--- a/libs/thread/test/test_condition.cpp
+++ b/libs/thread/test/test_condition.cpp
@@ -7,7 +7,7 @@
#define BOOST_THREAD_VERSION 2
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
-
+#define BOOST_TEST_MODULE Boost.Threads: condition test suite
#include <boost/thread/detail/config.hpp>
#include <boost/thread/condition.hpp>
@@ -156,7 +156,7 @@ void do_test_condition_waits()
BOOST_CHECK_EQUAL(data.awoken, 5);
}
-void test_condition_waits()
+BOOST_AUTO_TEST_CASE(test_condition_waits)
{
// We should have already tested notify_one here, so
// a timed test with the default execution_monitor::use_condition
@@ -176,20 +176,8 @@ void do_test_condition_wait_is_a_interruption_point()
}
-void test_condition_wait_is_a_interruption_point()
+BOOST_AUTO_TEST_CASE(test_condition_wait_is_a_interruption_point)
{
timed_test(&do_test_condition_wait_is_a_interruption_point, 1);
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: condition test suite");
-
- test->add(BOOST_TEST_CASE(&test_condition_waits));
- test->add(BOOST_TEST_CASE(&test_condition_wait_is_a_interruption_point));
-
- return test;
-}
-
-
diff --git a/libs/thread/test/test_condition_notify_all.cpp b/libs/thread/test/test_condition_notify_all.cpp
index 944f945545..017ff28d1e 100644
--- a/libs/thread/test/test_condition_notify_all.cpp
+++ b/libs/thread/test/test_condition_notify_all.cpp
@@ -4,7 +4,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
-
+#define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_all test suite
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread_only.hpp>
@@ -202,7 +202,7 @@ void do_test_notify_all_following_notify_one_wakes_all_threads()
thread3.join();
}
-void test_condition_notify_all()
+BOOST_AUTO_TEST_CASE(test_condition_notify_all)
{
timed_test(&do_test_condition_notify_all_wakes_from_wait, timeout_seconds);
timed_test(&do_test_condition_notify_all_wakes_from_wait_with_predicate, timeout_seconds);
@@ -213,14 +213,4 @@ void test_condition_notify_all()
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: condition test suite");
-
- test->add(BOOST_TEST_CASE(&test_condition_notify_all));
-
- return test;
-}
-
diff --git a/libs/thread/test/test_condition_notify_one.cpp b/libs/thread/test/test_condition_notify_one.cpp
index 5bd5f7e437..23fe74dfcf 100644
--- a/libs/thread/test/test_condition_notify_one.cpp
+++ b/libs/thread/test/test_condition_notify_one.cpp
@@ -5,6 +5,8 @@
#define BOOST_THREAD_VERSION 2
+#define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_one test suite
+
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread_only.hpp>
@@ -135,7 +137,7 @@ void do_test_multiple_notify_one_calls_wakes_multiple_threads()
thread3.join();
}
-void test_condition_notify_one()
+BOOST_AUTO_TEST_CASE(test_condition_notify_one)
{
timed_test(&do_test_condition_notify_one_wakes_from_wait, timeout_seconds, execution_monitor::use_mutex);
timed_test(&do_test_condition_notify_one_wakes_from_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
@@ -144,15 +146,3 @@ void test_condition_notify_one()
timed_test(&do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
timed_test(&do_test_multiple_notify_one_calls_wakes_multiple_threads, timeout_seconds, execution_monitor::use_mutex);
}
-
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: condition test suite");
-
- test->add(BOOST_TEST_CASE(&test_condition_notify_one));
-
- return test;
-}
-
diff --git a/libs/thread/test/test_condition_timed_wait_times_out.cpp b/libs/thread/test/test_condition_timed_wait_times_out.cpp
index 3632286ee5..8e19cd7bf0 100644
--- a/libs/thread/test/test_condition_timed_wait_times_out.cpp
+++ b/libs/thread/test/test_condition_timed_wait_times_out.cpp
@@ -5,6 +5,8 @@
#define BOOST_THREAD_VERSION 2
+#define BOOST_TEST_MODULE Boost.Threads: condition_variable test suite
+
#include <boost/thread/detail/config.hpp>
#include <boost/thread/condition.hpp>
@@ -152,7 +154,7 @@ void do_test_cv_any_timed_wait_relative_times_out()
}
-void test_timed_wait_times_out()
+BOOST_AUTO_TEST_CASE(test_timed_wait_times_out)
{
timed_test(&do_test_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
timed_test(&do_test_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
@@ -164,14 +166,4 @@ void test_timed_wait_times_out()
timed_test(&do_test_cv_any_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: condition test suite");
-
- test->add(BOOST_TEST_CASE(&test_timed_wait_times_out));
-
- return test;
-}
-
diff --git a/libs/thread/test/test_futures.cpp b/libs/thread/test/test_futures.cpp
index a6aad6361e..33698bae97 100644
--- a/libs/thread/test/test_futures.cpp
+++ b/libs/thread/test/test_futures.cpp
@@ -5,6 +5,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
+#define BOOST_TEST_MODULE Boost.Threads: futures test suite
#include <boost/thread/thread_only.hpp>
#include <boost/thread/mutex.hpp>
@@ -93,7 +94,7 @@ void set_promise_exception_thread(boost::promise<int>* p)
}
-void test_store_value_from_thread()
+BOOST_AUTO_TEST_CASE(test_store_value_from_thread)
{
LOG;
try {
@@ -122,8 +123,7 @@ void test_store_value_from_thread()
}
}
-
-void test_store_exception()
+BOOST_AUTO_TEST_CASE(test_store_exception)
{
LOG;
boost::promise<int> pi3;
@@ -145,7 +145,7 @@ void test_store_exception()
BOOST_CHECK(fi3.get_state()==boost::future_state::ready);
}
-void test_initial_state()
+BOOST_AUTO_TEST_CASE(test_initial_state)
{
LOG;
boost::unique_future<int> fi;
@@ -166,7 +166,7 @@ void test_initial_state()
}
}
-void test_waiting_future()
+BOOST_AUTO_TEST_CASE(test_waiting_future)
{
LOG;
boost::promise<int> pi;
@@ -181,7 +181,7 @@ void test_waiting_future()
BOOST_CHECK(i==0);
}
-void test_cannot_get_future_twice()
+BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice)
{
LOG;
boost::promise<int> pi;
@@ -198,7 +198,7 @@ void test_cannot_get_future_twice()
}
}
-void test_set_value_updates_future_state()
+BOOST_AUTO_TEST_CASE(test_set_value_updates_future_state)
{
LOG;
boost::promise<int> pi;
@@ -213,7 +213,7 @@ void test_set_value_updates_future_state()
BOOST_CHECK(fi.get_state()==boost::future_state::ready);
}
-void test_set_value_can_be_retrieved()
+BOOST_AUTO_TEST_CASE(test_set_value_can_be_retrieved)
{
LOG;
boost::promise<int> pi;
@@ -231,7 +231,7 @@ void test_set_value_can_be_retrieved()
BOOST_CHECK(fi.get_state()==boost::future_state::ready);
}
-void test_set_value_can_be_moved()
+BOOST_AUTO_TEST_CASE(test_set_value_can_be_moved)
{
LOG;
// boost::promise<int> pi;
@@ -249,7 +249,7 @@ void test_set_value_can_be_moved()
// BOOST_CHECK(fi.get_state()==boost::future_state::ready);
}
-void test_future_from_packaged_task_is_waiting()
+BOOST_AUTO_TEST_CASE(test_future_from_packaged_task_is_waiting)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -262,7 +262,7 @@ void test_future_from_packaged_task_is_waiting()
BOOST_CHECK(i==0);
}
-void test_invoking_a_packaged_task_populates_future()
+BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_populates_future)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -279,7 +279,7 @@ void test_invoking_a_packaged_task_populates_future()
BOOST_CHECK(i==42);
}
-void test_invoking_a_packaged_task_twice_throws()
+BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_twice_throws)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -297,7 +297,7 @@ void test_invoking_a_packaged_task_twice_throws()
}
-void test_cannot_get_future_twice_from_task()
+BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice_from_task)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -313,7 +313,7 @@ void test_cannot_get_future_twice_from_task()
}
}
-void test_task_stores_exception_if_function_throws()
+BOOST_AUTO_TEST_CASE(test_task_stores_exception_if_function_throws)
{
LOG;
boost::packaged_task<int> pt(throw_runtime_error);
@@ -341,7 +341,7 @@ void test_task_stores_exception_if_function_throws()
}
-void test_void_promise()
+BOOST_AUTO_TEST_CASE(test_void_promise)
{
LOG;
boost::promise<void> p;
@@ -354,7 +354,7 @@ void test_void_promise()
f.get();
}
-void test_reference_promise()
+BOOST_AUTO_TEST_CASE(test_reference_promise)
{
LOG;
boost::promise<int&> p;
@@ -371,7 +371,7 @@ void test_reference_promise()
void do_nothing()
{}
-void test_task_returning_void()
+BOOST_AUTO_TEST_CASE(test_task_returning_void)
{
LOG;
boost::packaged_task<void> pt(do_nothing);
@@ -392,7 +392,7 @@ int& return_ref()
return global_ref_target;
}
-void test_task_returning_reference()
+BOOST_AUTO_TEST_CASE(test_task_returning_reference)
{
LOG;
boost::packaged_task<int&> pt(return_ref);
@@ -408,7 +408,7 @@ void test_task_returning_reference()
BOOST_CHECK(&i==&global_ref_target);
}
-void test_shared_future()
+BOOST_AUTO_TEST_CASE(test_shared_future)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -428,7 +428,7 @@ void test_shared_future()
BOOST_CHECK(i==42);
}
-void test_copies_of_shared_future_become_ready_together()
+BOOST_AUTO_TEST_CASE(test_copies_of_shared_future_become_ready_together)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -467,7 +467,7 @@ void test_copies_of_shared_future_become_ready_together()
BOOST_CHECK(i==42);
}
-void test_shared_future_can_be_move_assigned_from_unique_future()
+BOOST_AUTO_TEST_CASE(test_shared_future_can_be_move_assigned_from_unique_future)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -483,7 +483,7 @@ void test_shared_future_can_be_move_assigned_from_unique_future()
BOOST_CHECK(sf.get_state()==boost::future_state::waiting);
}
-void test_shared_future_void()
+BOOST_AUTO_TEST_CASE(test_shared_future_void)
{
LOG;
boost::packaged_task<void> pt(do_nothing);
@@ -501,7 +501,7 @@ void test_shared_future_void()
sf.get();
}
-void test_shared_future_ref()
+BOOST_AUTO_TEST_CASE(test_shared_future_ref)
{
LOG;
boost::promise<int&> p;
@@ -515,7 +515,7 @@ void test_shared_future_ref()
BOOST_CHECK(&f.get()==&i);
}
-void test_can_get_a_second_future_from_a_moved_promise()
+BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_promise)
{
LOG;
boost::promise<int> pi;
@@ -533,7 +533,7 @@ void test_can_get_a_second_future_from_a_moved_promise()
BOOST_CHECK(fi2.get()==42);
}
-void test_can_get_a_second_future_from_a_moved_void_promise()
+BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_void_promise)
{
LOG;
boost::promise<void> pi;
@@ -549,7 +549,7 @@ void test_can_get_a_second_future_from_a_moved_void_promise()
BOOST_CHECK(fi2.is_ready());
}
-void test_unique_future_for_move_only_udt()
+BOOST_AUTO_TEST_CASE(test_unique_future_for_move_only_udt)
{
LOG;
boost::promise<X> pt;
@@ -560,7 +560,7 @@ void test_unique_future_for_move_only_udt()
BOOST_CHECK(res.i==42);
}
-void test_unique_future_for_string()
+BOOST_AUTO_TEST_CASE(test_unique_future_for_string)
{
LOG;
boost::promise<std::string> pt;
@@ -611,7 +611,7 @@ void do_nothing_callback(boost::promise<int>& /*pi*/)
++callback_called;
}
-void test_wait_callback()
+BOOST_AUTO_TEST_CASE(test_wait_callback)
{
LOG;
callback_called=0;
@@ -626,7 +626,7 @@ void test_wait_callback()
BOOST_CHECK(callback_called==1);
}
-void test_wait_callback_with_timed_wait()
+BOOST_AUTO_TEST_CASE(test_wait_callback_with_timed_wait)
{
LOG;
callback_called=0;
@@ -665,7 +665,7 @@ void wait_callback_for_task(boost::packaged_task<int>& pt)
}
-void test_wait_callback_for_packaged_task()
+BOOST_AUTO_TEST_CASE(test_wait_callback_for_packaged_task)
{
LOG;
callback_called=0;
@@ -680,7 +680,7 @@ void test_wait_callback_for_packaged_task()
BOOST_CHECK(callback_called==1);
}
-void test_packaged_task_can_be_moved()
+BOOST_AUTO_TEST_CASE(test_packaged_task_can_be_moved)
{
LOG;
boost::packaged_task<int> pt(make_int);
@@ -708,7 +708,7 @@ void test_packaged_task_can_be_moved()
BOOST_CHECK(fi.is_ready());
}
-void test_destroying_a_promise_stores_broken_promise()
+BOOST_AUTO_TEST_CASE(test_destroying_a_promise_stores_broken_promise)
{
LOG;
boost::unique_future<int> f;
@@ -728,7 +728,7 @@ void test_destroying_a_promise_stores_broken_promise()
}
}
-void test_destroying_a_packaged_task_stores_broken_promise()
+BOOST_AUTO_TEST_CASE(test_destroying_a_packaged_task_stores_broken_promise)
{
LOG;
boost::unique_future<int> f;
@@ -754,7 +754,7 @@ int make_int_slowly()
return 42;
}
-void test_wait_for_either_of_two_futures_1()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_1)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -772,7 +772,7 @@ void test_wait_for_either_of_two_futures_1()
BOOST_CHECK(f1.get()==42);
}
-void test_wait_for_either_of_two_futures_2()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_2)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -790,7 +790,7 @@ void test_wait_for_either_of_two_futures_2()
BOOST_CHECK(f2.get()==42);
}
-void test_wait_for_either_of_three_futures_1()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_1)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -811,7 +811,7 @@ void test_wait_for_either_of_three_futures_1()
BOOST_CHECK(f1.get()==42);
}
-void test_wait_for_either_of_three_futures_2()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_2)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -832,7 +832,7 @@ void test_wait_for_either_of_three_futures_2()
BOOST_CHECK(f2.get()==42);
}
-void test_wait_for_either_of_three_futures_3()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_3)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -853,7 +853,7 @@ void test_wait_for_either_of_three_futures_3()
BOOST_CHECK(f3.get()==42);
}
-void test_wait_for_either_of_four_futures_1()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_1)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -877,7 +877,7 @@ void test_wait_for_either_of_four_futures_1()
BOOST_CHECK(f1.get()==42);
}
-void test_wait_for_either_of_four_futures_2()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_2)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -901,7 +901,7 @@ void test_wait_for_either_of_four_futures_2()
BOOST_CHECK(f2.get()==42);
}
-void test_wait_for_either_of_four_futures_3()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_3)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -925,7 +925,7 @@ void test_wait_for_either_of_four_futures_3()
BOOST_CHECK(f3.get()==42);
}
-void test_wait_for_either_of_four_futures_4()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_4)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -949,7 +949,7 @@ void test_wait_for_either_of_four_futures_4()
BOOST_CHECK(f4.get()==42);
}
-void test_wait_for_either_of_five_futures_1()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_1)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -976,7 +976,7 @@ void test_wait_for_either_of_five_futures_1()
BOOST_CHECK(f1.get()==42);
}
-void test_wait_for_either_of_five_futures_2()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_2)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -1002,7 +1002,7 @@ void test_wait_for_either_of_five_futures_2()
BOOST_CHECK(!f5.is_ready());
BOOST_CHECK(f2.get()==42);
}
-void test_wait_for_either_of_five_futures_3()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_3)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -1028,7 +1028,7 @@ void test_wait_for_either_of_five_futures_3()
BOOST_CHECK(!f5.is_ready());
BOOST_CHECK(f3.get()==42);
}
-void test_wait_for_either_of_five_futures_4()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_4)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -1054,7 +1054,7 @@ void test_wait_for_either_of_five_futures_4()
BOOST_CHECK(!f5.is_ready());
BOOST_CHECK(f4.get()==42);
}
-void test_wait_for_either_of_five_futures_5()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_5)
{
LOG;
boost::packaged_task<int> pt(make_int_slowly);
@@ -1081,7 +1081,7 @@ void test_wait_for_either_of_five_futures_5()
BOOST_CHECK(f5.get()==42);
}
-void test_wait_for_either_invokes_callbacks()
+BOOST_AUTO_TEST_CASE(test_wait_for_either_invokes_callbacks)
{
LOG;
callback_called=0;
@@ -1098,7 +1098,7 @@ void test_wait_for_either_invokes_callbacks()
BOOST_CHECK(fi.get()==42);
}
-void test_wait_for_any_from_range()
+BOOST_AUTO_TEST_CASE(test_wait_for_any_from_range)
{
LOG;
unsigned const count=10;
@@ -1133,7 +1133,7 @@ void test_wait_for_any_from_range()
}
}
-void test_wait_for_all_from_range()
+BOOST_AUTO_TEST_CASE(test_wait_for_all_from_range)
{
LOG;
unsigned const count=10;
@@ -1153,7 +1153,7 @@ void test_wait_for_all_from_range()
}
}
-void test_wait_for_all_two_futures()
+BOOST_AUTO_TEST_CASE(test_wait_for_all_two_futures)
{
LOG;
unsigned const count=2;
@@ -1173,7 +1173,7 @@ void test_wait_for_all_two_futures()
}
}
-void test_wait_for_all_three_futures()
+BOOST_AUTO_TEST_CASE(test_wait_for_all_three_futures)
{
LOG;
unsigned const count=3;
@@ -1193,7 +1193,7 @@ void test_wait_for_all_three_futures()
}
}
-void test_wait_for_all_four_futures()
+BOOST_AUTO_TEST_CASE(test_wait_for_all_four_futures)
{
LOG;
unsigned const count=4;
@@ -1213,7 +1213,7 @@ void test_wait_for_all_four_futures()
}
}
-void test_wait_for_all_five_futures()
+BOOST_AUTO_TEST_CASE(test_wait_for_all_five_futures)
{
LOG;
unsigned const count=5;
@@ -1232,68 +1232,3 @@ void test_wait_for_all_five_futures()
BOOST_CHECK(futures[j].is_ready());
}
}
-
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: futures test suite");
-
- test->add(BOOST_TEST_CASE(test_initial_state));
- test->add(BOOST_TEST_CASE(test_waiting_future));
- test->add(BOOST_TEST_CASE(test_cannot_get_future_twice));
- test->add(BOOST_TEST_CASE(test_set_value_updates_future_state));
- test->add(BOOST_TEST_CASE(test_set_value_can_be_retrieved));
- test->add(BOOST_TEST_CASE(test_set_value_can_be_moved));
- test->add(BOOST_TEST_CASE(test_store_value_from_thread));
- test->add(BOOST_TEST_CASE(test_store_exception));
- test->add(BOOST_TEST_CASE(test_future_from_packaged_task_is_waiting));
- test->add(BOOST_TEST_CASE(test_invoking_a_packaged_task_populates_future));
- test->add(BOOST_TEST_CASE(test_invoking_a_packaged_task_twice_throws));
- test->add(BOOST_TEST_CASE(test_cannot_get_future_twice_from_task));
- test->add(BOOST_TEST_CASE(test_task_stores_exception_if_function_throws));
- test->add(BOOST_TEST_CASE(test_void_promise));
- test->add(BOOST_TEST_CASE(test_reference_promise));
- test->add(BOOST_TEST_CASE(test_task_returning_void));
- test->add(BOOST_TEST_CASE(test_task_returning_reference));
- test->add(BOOST_TEST_CASE(test_shared_future));
- test->add(BOOST_TEST_CASE(test_copies_of_shared_future_become_ready_together));
- test->add(BOOST_TEST_CASE(test_shared_future_can_be_move_assigned_from_unique_future));
- test->add(BOOST_TEST_CASE(test_shared_future_void));
- test->add(BOOST_TEST_CASE(test_shared_future_ref));
- test->add(BOOST_TEST_CASE(test_can_get_a_second_future_from_a_moved_promise));
- test->add(BOOST_TEST_CASE(test_can_get_a_second_future_from_a_moved_void_promise));
- test->add(BOOST_TEST_CASE(test_unique_future_for_move_only_udt));
- test->add(BOOST_TEST_CASE(test_unique_future_for_string));
- test->add(BOOST_TEST_CASE(test_wait_callback));
- test->add(BOOST_TEST_CASE(test_wait_callback_with_timed_wait));
- test->add(BOOST_TEST_CASE(test_wait_callback_for_packaged_task));
- test->add(BOOST_TEST_CASE(test_packaged_task_can_be_moved));
- test->add(BOOST_TEST_CASE(test_destroying_a_promise_stores_broken_promise));
- test->add(BOOST_TEST_CASE(test_destroying_a_packaged_task_stores_broken_promise));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_two_futures_1));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_two_futures_2));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_1));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_2));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_3));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_1));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_2));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_3));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_4));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_1));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_2));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_3));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_4));
- test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_5));
- test->add(BOOST_TEST_CASE(test_wait_for_either_invokes_callbacks));
- test->add(BOOST_TEST_CASE(test_wait_for_any_from_range));
- test->add(BOOST_TEST_CASE(test_wait_for_all_from_range));
- test->add(BOOST_TEST_CASE(test_wait_for_all_two_futures));
- test->add(BOOST_TEST_CASE(test_wait_for_all_three_futures));
- test->add(BOOST_TEST_CASE(test_wait_for_all_four_futures));
- test->add(BOOST_TEST_CASE(test_wait_for_all_five_futures));
-
- return test;
-}
-
-
diff --git a/libs/thread/test/test_generic_locks.cpp b/libs/thread/test/test_generic_locks.cpp
index f7c5608951..22aed6e65b 100644
--- a/libs/thread/test/test_generic_locks.cpp
+++ b/libs/thread/test/test_generic_locks.cpp
@@ -5,13 +5,15 @@
#define BOOST_THREAD_VERSION 2
+#define BOOST_TEST_MODULE Boost.Threads: generic locks test suite
+
#include <boost/test/unit_test.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread_only.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/condition_variable.hpp>
-void test_lock_two_uncontended()
+BOOST_AUTO_TEST_CASE(test_lock_two_uncontended)
{
boost::mutex m1,m2;
@@ -87,7 +89,7 @@ void lock_pair(boost::mutex* m1,boost::mutex* m2)
l2(*m2,boost::adopt_lock);
}
-void test_lock_two_other_thread_locks_in_order()
+BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_order)
{
boost::mutex m1,m2;
wait_data locked;
@@ -106,7 +108,7 @@ void test_lock_two_other_thread_locks_in_order()
t.join();
}
-void test_lock_two_other_thread_locks_in_opposite_order()
+BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_opposite_order)
{
boost::mutex m1,m2;
wait_data locked;
@@ -125,7 +127,7 @@ void test_lock_two_other_thread_locks_in_opposite_order()
t.join();
}
-void test_lock_five_uncontended()
+BOOST_AUTO_TEST_CASE(test_lock_five_uncontended)
{
boost::mutex m1,m2,m3,m4,m5;
@@ -176,7 +178,7 @@ void lock_five(boost::mutex* m1,boost::mutex* m2,boost::mutex* m3,boost::mutex*
m5->unlock();
}
-void test_lock_five_other_thread_locks_in_order()
+BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_order)
{
boost::mutex m1,m2,m3,m4,m5;
wait_data locked;
@@ -195,7 +197,7 @@ void test_lock_five_other_thread_locks_in_order()
t.join();
}
-void test_lock_five_other_thread_locks_in_different_order()
+BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_different_order)
{
boost::mutex m1,m2,m3,m4,m5;
wait_data locked;
@@ -224,7 +226,7 @@ void lock_n(boost::mutex* mutexes,unsigned count)
}
-void test_lock_ten_other_thread_locks_in_different_order()
+BOOST_AUTO_TEST_CASE(test_lock_ten_other_thread_locks_in_different_order)
{
unsigned const num_mutexes=10;
@@ -285,7 +287,7 @@ namespace boost
-void test_lock_five_in_range()
+BOOST_AUTO_TEST_CASE(test_lock_five_in_range)
{
unsigned const num_mutexes=5;
dummy_mutex mutexes[num_mutexes];
@@ -350,7 +352,7 @@ public:
};
-void test_lock_five_in_range_custom_iterator()
+BOOST_AUTO_TEST_CASE(test_lock_five_in_range_custom_iterator)
{
unsigned const num_mutexes=5;
dummy_mutex mutexes[num_mutexes];
@@ -368,7 +370,7 @@ class dummy_mutex2:
{};
-void test_lock_ten_in_range_inherited_mutex()
+BOOST_AUTO_TEST_CASE(test_lock_ten_in_range_inherited_mutex)
{
unsigned const num_mutexes=10;
dummy_mutex2 mutexes[num_mutexes];
@@ -381,7 +383,7 @@ void test_lock_ten_in_range_inherited_mutex()
}
}
-void test_try_lock_two_uncontended()
+BOOST_AUTO_TEST_CASE(test_try_lock_two_uncontended)
{
dummy_mutex m1,m2;
@@ -391,7 +393,7 @@ void test_try_lock_two_uncontended()
BOOST_CHECK(m1.is_locked);
BOOST_CHECK(m2.is_locked);
}
-void test_try_lock_two_first_locked()
+BOOST_AUTO_TEST_CASE(test_try_lock_two_first_locked)
{
dummy_mutex m1,m2;
m1.lock();
@@ -407,7 +409,7 @@ void test_try_lock_two_first_locked()
BOOST_CHECK(!l1.owns_lock());
BOOST_CHECK(!l2.owns_lock());
}
-void test_try_lock_two_second_locked()
+BOOST_AUTO_TEST_CASE(test_try_lock_two_second_locked)
{
dummy_mutex m1,m2;
m2.lock();
@@ -424,7 +426,7 @@ void test_try_lock_two_second_locked()
BOOST_CHECK(!l2.owns_lock());
}
-void test_try_lock_three()
+BOOST_AUTO_TEST_CASE(test_try_lock_three)
{
int const num_mutexes=3;
@@ -469,7 +471,7 @@ void test_try_lock_three()
}
}
-void test_try_lock_four()
+BOOST_AUTO_TEST_CASE(test_try_lock_four)
{
int const num_mutexes=4;
@@ -517,7 +519,7 @@ void test_try_lock_four()
}
}
-void test_try_lock_five()
+BOOST_AUTO_TEST_CASE(test_try_lock_five)
{
int const num_mutexes=5;
@@ -568,31 +570,3 @@ void test_try_lock_five()
}
}
-
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: generic locks test suite");
-
- test->add(BOOST_TEST_CASE(&test_lock_two_uncontended));
- test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_order));
- test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_opposite_order));
- test->add(BOOST_TEST_CASE(&test_lock_five_uncontended));
- test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_order));
- test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_different_order));
- test->add(BOOST_TEST_CASE(&test_lock_five_in_range));
- test->add(BOOST_TEST_CASE(&test_lock_five_in_range_custom_iterator));
- test->add(BOOST_TEST_CASE(&test_lock_ten_in_range_inherited_mutex));
- test->add(BOOST_TEST_CASE(&test_lock_ten_other_thread_locks_in_different_order));
- test->add(BOOST_TEST_CASE(&test_try_lock_two_uncontended));
- test->add(BOOST_TEST_CASE(&test_try_lock_two_first_locked));
- test->add(BOOST_TEST_CASE(&test_try_lock_two_second_locked));
- test->add(BOOST_TEST_CASE(&test_try_lock_three));
- test->add(BOOST_TEST_CASE(&test_try_lock_four));
- test->add(BOOST_TEST_CASE(&test_try_lock_five));
-
- return test;
-}
-
-
diff --git a/libs/thread/test/test_hardware_concurrency.cpp b/libs/thread/test/test_hardware_concurrency.cpp
index 487aa536be..1d4376c27e 100644
--- a/libs/thread/test/test_hardware_concurrency.cpp
+++ b/libs/thread/test/test_hardware_concurrency.cpp
@@ -2,22 +2,16 @@
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE Boost.Threads: hardware_concurrency test suite
+
#include <boost/thread/thread_only.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread/mutex.hpp>
-void test_hardware_concurrency_is_non_zero()
+BOOST_AUTO_TEST_CASE(test_hardware_concurrency_is_non_zero)
{
BOOST_CHECK(boost::thread::hardware_concurrency()!=0);
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: hardware concurrency test suite");
-
- test->add(BOOST_TEST_CASE(test_hardware_concurrency_is_non_zero));
- return test;
-}
-
diff --git a/libs/thread/test/test_lock_concept.cpp b/libs/thread/test/test_lock_concept.cpp
index ac152bf68a..78e70120f0 100644
--- a/libs/thread/test/test_lock_concept.cpp
+++ b/libs/thread/test/test_lock_concept.cpp
@@ -4,8 +4,10 @@
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
+#define BOOST_TEST_MODULE Boost.Threads: lock_concept test suite
#include <boost/test/unit_test.hpp>
+#include <boost/test/test_case_template.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/lock_types.hpp>
@@ -438,22 +440,30 @@ void test_lock_is_scoped_lock_concept_for_mutex()
test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()();
}
+typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
+ boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock;
-BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_lock_concept,Mutex)
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_lock_concept,Mutex,mutex_types_with_scoped_lock)
{
typedef typename Mutex::scoped_lock Lock;
test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();
}
-BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_unique_lock_is_scoped_lock,Mutex)
+typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
+ boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,Mutex,all_mutex_types)
{
typedef boost::unique_lock<Mutex> Lock;
test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();
}
-BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_try_lock_concept,Mutex)
+typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
+ boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,Mutex,mutex_types_with_scoped_try_lock)
{
typedef typename Mutex::scoped_try_lock Lock;
@@ -534,7 +544,7 @@ struct dummy_shared_mutex
};
-void test_shared_lock()
+BOOST_AUTO_TEST_CASE(test_shared_lock)
{
typedef boost::shared_mutex Mutex;
typedef boost::shared_lock<Mutex> Lock;
@@ -564,27 +574,27 @@ void test_shared_lock()
BOOST_CHECK(dummy.shared_timed_locked_absolute);
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: lock concept test suite");
-
- typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
- boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock;
-
- test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types_with_scoped_lock));
-
- typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
- boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock;
-
- test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,mutex_types_with_scoped_try_lock));
-
- typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
- boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types;
-
- test->add(BOOST_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,all_mutex_types));
- test->add(BOOST_TEST_CASE(&test_shared_lock));
-
- return test;
-}
+//boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
+//{
+// boost::unit_test::test_suite* test =
+// BOOST_TEST_SUITE("Boost.Threads: lock concept test suite");
+//
+// typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
+// boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock;
+//
+// test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types_with_scoped_lock));
+//
+// typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
+// boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock;
+//
+// test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,mutex_types_with_scoped_try_lock));
+//
+// typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
+// boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types;
+//
+// test->add(BOOST_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,all_mutex_types));
+// test->add(BOOST_TEST_CASE(&test_shared_lock));
+//
+// return test;
+//}
diff --git a/libs/thread/test/test_move_function.cpp b/libs/thread/test/test_move_function.cpp
index 6eb145231b..1fef7a3bb6 100644
--- a/libs/thread/test/test_move_function.cpp
+++ b/libs/thread/test/test_move_function.cpp
@@ -4,6 +4,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
+#define BOOST_TEST_MODULE Boost.Threads: move function test suite
#include <boost/thread/thread_only.hpp>
#include <boost/test/unit_test.hpp>
@@ -13,7 +14,7 @@
void do_nothing()
{}
-void test_thread_move_from_lvalue_on_construction()
+BOOST_AUTO_TEST_CASE(test_thread_move_from_lvalue_on_construction)
{
boost::thread src(do_nothing);
boost::thread::id src_id=src.get_id();
@@ -24,7 +25,7 @@ void test_thread_move_from_lvalue_on_construction()
dest.join();
}
-void test_thread_move_from_lvalue_on_assignment()
+BOOST_AUTO_TEST_CASE(test_thread_move_from_lvalue_on_assignment)
{
boost::thread src(do_nothing);
boost::thread::id src_id=src.get_id();
@@ -41,14 +42,14 @@ boost::thread start_thread()
return boost::thread(do_nothing);
}
-void test_thread_move_from_rvalue_on_construction()
+BOOST_AUTO_TEST_CASE(test_thread_move_from_rvalue_on_construction)
{
boost::thread x(start_thread());
BOOST_CHECK(x.get_id()!=boost::thread::id());
x.join();
}
-void test_thread_move_from_rvalue_using_explicit_move()
+BOOST_AUTO_TEST_CASE(test_thread_move_from_rvalue_using_explicit_move)
{
//boost::thread x(boost::move(start_thread()));
boost::thread x=start_thread();
@@ -56,7 +57,7 @@ void test_thread_move_from_rvalue_using_explicit_move()
x.join();
}
-void test_unique_lock_move_from_lvalue_on_construction()
+BOOST_AUTO_TEST_CASE(test_unique_lock_move_from_lvalue_on_construction)
{
boost::mutex m;
boost::unique_lock<boost::mutex> l(m);
@@ -76,7 +77,7 @@ boost::unique_lock<boost::mutex> get_lock(boost::mutex& m)
}
-void test_unique_lock_move_from_rvalue_on_construction()
+BOOST_AUTO_TEST_CASE(test_unique_lock_move_from_rvalue_on_construction)
{
boost::mutex m;
boost::unique_lock<boost::mutex> l(get_lock(m));
@@ -117,7 +118,7 @@ namespace boost
BOOST_THREAD_DCL_MOVABLE(user_test_ns::nc)
}
-void test_move_for_user_defined_type_unaffected()
+BOOST_AUTO_TEST_CASE(test_move_for_user_defined_type_unaffected)
{
user_test_ns::nc src;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
@@ -128,19 +129,6 @@ void test_move_for_user_defined_type_unaffected()
BOOST_CHECK(user_test_ns::move_called);
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: thread move test suite");
-
- test->add(BOOST_TEST_CASE(test_thread_move_from_lvalue_on_construction));
- test->add(BOOST_TEST_CASE(test_thread_move_from_rvalue_on_construction));
- test->add(BOOST_TEST_CASE(test_thread_move_from_rvalue_using_explicit_move));
- test->add(BOOST_TEST_CASE(test_thread_move_from_lvalue_on_assignment));
- test->add(BOOST_TEST_CASE(test_unique_lock_move_from_lvalue_on_construction));
- test->add(BOOST_TEST_CASE(test_unique_lock_move_from_rvalue_on_construction));
- test->add(BOOST_TEST_CASE(test_move_for_user_defined_type_unaffected));
- return test;
-}
+
diff --git a/libs/thread/test/test_mutex.cpp b/libs/thread/test/test_mutex.cpp
index c10125a280..e6ac24e271 100644
--- a/libs/thread/test/test_mutex.cpp
+++ b/libs/thread/test/test_mutex.cpp
@@ -5,6 +5,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
+#define BOOST_TEST_MODULE Boost.Threads: mutex test suite
#include <boost/thread/detail/config.hpp>
@@ -15,6 +16,8 @@
#include <boost/thread/thread_time.hpp>
#include <boost/thread/condition.hpp>
+#define BOOST_TEST_MODULE Boost.Threads: mutex test suite
+
#include <boost/test/unit_test.hpp>
#define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only
@@ -270,7 +273,7 @@ void do_test_mutex()
test_lock<boost::mutex>()();
}
-void test_mutex()
+BOOST_AUTO_TEST_CASE(test_mutex)
{
timed_test(&do_test_mutex, 3);
}
@@ -281,7 +284,7 @@ void do_test_try_mutex()
test_trylock<boost::try_mutex>()();
}
-void test_try_mutex()
+BOOST_AUTO_TEST_CASE(test_try_mutex)
{
timed_test(&do_test_try_mutex, 3);
}
@@ -293,7 +296,7 @@ void do_test_timed_mutex()
test_timedlock<boost::timed_mutex>()();
}
-void test_timed_mutex()
+BOOST_AUTO_TEST_CASE(test_timed_mutex)
{
timed_test(&do_test_timed_mutex, 3);
}
@@ -304,7 +307,7 @@ void do_test_recursive_mutex()
test_recursive_lock<boost::recursive_mutex>()();
}
-void test_recursive_mutex()
+BOOST_AUTO_TEST_CASE(test_recursive_mutex)
{
timed_test(&do_test_recursive_mutex, 3);
}
@@ -316,7 +319,7 @@ void do_test_recursive_try_mutex()
test_recursive_lock<boost::recursive_try_mutex>()();
}
-void test_recursive_try_mutex()
+BOOST_AUTO_TEST_CASE(test_recursive_try_mutex)
{
timed_test(&do_test_recursive_try_mutex, 3);
}
@@ -329,24 +332,10 @@ void do_test_recursive_timed_mutex()
test_recursive_lock<boost::recursive_timed_mutex>()();
}
-void test_recursive_timed_mutex()
+BOOST_AUTO_TEST_CASE(test_recursive_timed_mutex)
{
timed_test(&do_test_recursive_timed_mutex, 3);
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: mutex test suite");
-
- test->add(BOOST_TEST_CASE(&test_mutex));
- test->add(BOOST_TEST_CASE(&test_try_mutex));
- test->add(BOOST_TEST_CASE(&test_timed_mutex));
- test->add(BOOST_TEST_CASE(&test_recursive_mutex));
- test->add(BOOST_TEST_CASE(&test_recursive_try_mutex));
- test->add(BOOST_TEST_CASE(&test_recursive_timed_mutex));
-
- return test;
-}
diff --git a/libs/thread/test/test_once.cpp b/libs/thread/test/test_once.cpp
index 35eaa1017d..0232e59af8 100644
--- a/libs/thread/test/test_once.cpp
+++ b/libs/thread/test/test_once.cpp
@@ -5,6 +5,7 @@
#define BOOST_THREAD_VERSION 2
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
+#define BOOST_TEST_MODULE Boost.Threads: once test suite
#include <boost/test/unit_test.hpp>
#include <boost/thread/thread.hpp>
@@ -43,7 +44,7 @@ void call_once_thread()
BOOST_CHECK_EQUAL(my_once_value, 1);
}
-void test_call_once()
+BOOST_AUTO_TEST_CASE(test_call_once)
{
LOG;
@@ -102,7 +103,7 @@ void call_once_with_functor()
BOOST_CHECK_EQUAL(my_once_value, 1);
}
-void test_call_once_arbitrary_functor()
+BOOST_AUTO_TEST_CASE(test_call_once_arbitrary_functor)
{
LOG;
@@ -163,7 +164,7 @@ void call_once_with_exception()
}
}
-void test_call_once_retried_on_exception()
+BOOST_AUTO_TEST_CASE(test_call_once_retried_on_exception)
{
LOG;
unsigned const num_threads=20;
@@ -189,16 +190,3 @@ void test_call_once_retried_on_exception()
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: call_once test suite");
-
- test->add(BOOST_TEST_CASE(test_call_once));
- test->add(BOOST_TEST_CASE(test_call_once_arbitrary_functor));
- test->add(BOOST_TEST_CASE(test_call_once_retried_on_exception));
-
- return test;
-}
-
-
diff --git a/libs/thread/test/test_physical_concurrency.cpp b/libs/thread/test/test_physical_concurrency.cpp
index 20b5dc0282..6a8bbc8f7c 100644
--- a/libs/thread/test/test_physical_concurrency.cpp
+++ b/libs/thread/test/test_physical_concurrency.cpp
@@ -3,22 +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_TEST_MODULE Boost.Threads: physical_concurrency test suite
+
#include <boost/thread/thread_only.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread/mutex.hpp>
-void test_physical_concurrency_is_non_zero()
+BOOST_AUTO_TEST_CASE(test_physical_concurrency_is_non_zero)
{
BOOST_CHECK(boost::thread::physical_concurrency()!=0);
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: physical concurrency test suite");
- test->add(BOOST_TEST_CASE(test_physical_concurrency_is_non_zero));
- return test;
-}
diff --git a/libs/thread/test/test_scheduled_tp.cpp b/libs/thread/test/test_scheduled_tp.cpp
new file mode 100644
index 0000000000..b4503a8bf9
--- /dev/null
+++ b/libs/thread/test/test_scheduled_tp.cpp
@@ -0,0 +1,97 @@
+// 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)
+//
+
+#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/bind.hpp>
+#include <boost/chrono.hpp>
+#include <boost/chrono/chrono_io.hpp>
+#include <boost/function.hpp>
+#include <boost/thread/executors/scheduled_thread_pool.hpp>
+#include <iostream>
+
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost::chrono;
+
+typedef boost::scheduled_thread_pool scheduled_tp;
+
+void fn(int x)
+{
+ std::cout << x << std::endl;
+}
+
+void func(steady_clock::time_point pushed, steady_clock::duration dur)
+{
+ BOOST_TEST(pushed + dur < steady_clock::now());
+}
+void func2(scheduled_tp* tp, steady_clock::duration d)
+{
+ boost::function<void()> fn = boost::bind(func,steady_clock::now(),d);
+ tp->submit_after(fn, d);
+}
+
+
+
+void test_timing(const int n)
+{
+ //This function should take n seconds to execute.
+ boost::scheduled_thread_pool se(4);
+
+ for(int i = 1; i <= n; i++)
+ {
+ se.submit_after(boost::bind(fn,i), milliseconds(i*100));
+ }
+ boost::this_thread::sleep_for(boost::chrono::seconds(10));
+ //dtor is called here so all task will have to be executed before we return
+}
+
+void test_deque_timing()
+{
+ boost::scheduled_thread_pool se(4);
+ for(int i = 0; i < 10; i++)
+ {
+ steady_clock::duration d = milliseconds(i*100);
+ boost::function<void()> fn = boost::bind(func,steady_clock::now(),d);
+ se.submit_after(fn,d);
+ }
+}
+
+void test_deque_multi(const int n)
+{
+ scheduled_tp se(4);
+ boost::thread_group tg;
+ for(int i = 0; i < n; i++)
+ {
+ steady_clock::duration d = milliseconds(i*100);
+ //boost::function<void()> fn = boost::bind(func,steady_clock::now(),d);
+ //tg.create_thread(boost::bind(boost::mem_fn(&scheduled_tp::submit_after), &se, fn, d));
+ tg.create_thread(boost::bind(func2, &se, d));
+ }
+ tg.join_all();
+ //dtor is called here so execution will block untill all the closures
+ //have been completed.
+}
+
+int main()
+{
+ steady_clock::time_point start = steady_clock::now();
+ test_timing(5);
+ steady_clock::duration diff = steady_clock::now() - start;
+ BOOST_TEST(diff > milliseconds(500));
+ test_deque_timing();
+ test_deque_multi(4);
+ test_deque_multi(8);
+ test_deque_multi(16);
+ return boost::report_errors();
+}
diff --git a/libs/thread/test/test_scheduler.cpp b/libs/thread/test/test_scheduler.cpp
new file mode 100644
index 0000000000..5847ff0100
--- /dev/null
+++ b/libs/thread/test/test_scheduler.cpp
@@ -0,0 +1,81 @@
+// 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)
+//
+
+#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/executors/scheduler.hpp>
+#include <boost/thread/executors/basic_thread_pool.hpp>
+#include <boost/chrono/chrono_io.hpp>
+#include <iostream>
+
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost::chrono;
+
+
+typedef boost::executors::basic_thread_pool thread_pool;
+
+void fn(int x)
+{
+ //std::cout << "[" << __LINE__ << "] " << steady_clock::now() << std::endl;
+ std::cout << x << std::endl;
+}
+
+void test_scheduler(const int n, boost::scheduler<>& sch)
+{
+ for(int i = 1; i <= n; i++)
+ {
+ sch.submit_after(boost::bind(fn,i), seconds(i));
+ sch.submit_after(boost::bind(fn,i), milliseconds(i*100));
+ }
+}
+
+void test_after(const int n, boost::scheduler<>& sch)
+{
+ for(int i = 1; i <= n; i++)
+ {
+ sch.after(seconds(i)).submit(boost::bind(fn,i));
+ sch.after(milliseconds(i*100)).submit(boost::bind(fn,i));
+ }
+}
+
+void test_at(const int n, boost::scheduler<>& sch)
+{
+ for(int i = 1; i <= n; i++)
+ {
+ sch.at(steady_clock::now()+seconds(i)).submit(boost::bind(fn,i));
+ sch.at(steady_clock::now()+milliseconds(i*100)).submit(boost::bind(fn,i));
+ }
+}
+
+void test_on(const int n, boost::scheduler<>& sch, thread_pool& tp)
+{
+ for(int i = 1; i <= n; i++)
+ {
+ sch.on(tp).after(seconds(i)).submit(boost::bind(fn,i));
+ sch.on(tp).after(milliseconds(i*100)).submit(boost::bind(fn,i));
+ }
+}
+
+int main()
+{
+ thread_pool tp(4);
+ boost::scheduler<> sch;
+ test_scheduler(5, sch);
+ test_after(5, sch);
+ test_at(5, sch);
+ test_on(5, sch, tp);
+ boost::this_thread::sleep_for(boost::chrono::seconds(10));
+
+ return boost::report_errors();
+}
diff --git a/libs/thread/test/test_scheduling_adaptor.cpp b/libs/thread/test/test_scheduling_adaptor.cpp
new file mode 100644
index 0000000000..ba43551fe6
--- /dev/null
+++ b/libs/thread/test/test_scheduling_adaptor.cpp
@@ -0,0 +1,54 @@
+// 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)
+//
+
+#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/function.hpp>
+#include <boost/thread/executors/executor.hpp>
+#include <boost/thread/executors/basic_thread_pool.hpp>
+#include <boost/thread/executors/scheduling_adaptor.hpp>
+#include <boost/chrono/chrono_io.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost::chrono;
+
+
+typedef boost::executors::basic_thread_pool thread_pool;
+
+void fn(int x)
+{
+ //std::cout << "[" << __LINE__ << "] " << steady_clock::now() << std::endl;
+ std::cout << x << std::endl;
+}
+
+void test_timing(const int n)
+{
+ thread_pool tp(4);
+ boost::scheduling_adpator<thread_pool> sa(tp);
+ for(int i = 1; i <= n; i++)
+ {
+ sa.submit_after(boost::bind(fn,i),seconds(i));
+ sa.submit_after(boost::bind(fn,i), milliseconds(i*100));
+ }
+ boost::this_thread::sleep_for(boost::chrono::seconds(10));
+}
+
+int main()
+{
+ steady_clock::time_point start = steady_clock::now();
+ test_timing(5);
+ steady_clock::duration diff = steady_clock::now() - start;
+ BOOST_TEST(diff > seconds(5));
+ return boost::report_errors();
+}
diff --git a/libs/thread/test/test_shared_mutex.cpp b/libs/thread/test/test_shared_mutex.cpp
index ca10e30006..f7779e90a7 100644
--- a/libs/thread/test/test_shared_mutex.cpp
+++ b/libs/thread/test/test_shared_mutex.cpp
@@ -5,6 +5,7 @@
#define BOOST_THREAD_VERSION 2
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
+#define BOOST_TEST_MODULE Boost.Threads: shared_mutex test suite
#include <boost/test/unit_test.hpp>
#include <boost/thread/thread.hpp>
@@ -18,7 +19,7 @@
BOOST_CHECK_EQUAL(value,expected_value); \
}
-void test_multiple_readers()
+BOOST_AUTO_TEST_CASE(test_multiple_readers)
{
std::cout << __LINE__ << std::endl;
unsigned const number_of_threads=10;
@@ -66,7 +67,7 @@ void test_multiple_readers()
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,number_of_threads);
}
-void test_only_one_writer_permitted()
+BOOST_AUTO_TEST_CASE(test_only_one_writer_permitted)
{
std::cout << __LINE__ << std::endl;
unsigned const number_of_threads=10;
@@ -109,7 +110,7 @@ void test_only_one_writer_permitted()
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
}
-void test_reader_blocks_writer()
+BOOST_AUTO_TEST_CASE(test_reader_blocks_writer)
{
std::cout << __LINE__ << std::endl;
boost::thread_group pool;
@@ -156,7 +157,7 @@ void test_reader_blocks_writer()
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
}
-void test_unlocking_writer_unblocks_all_readers()
+BOOST_AUTO_TEST_CASE(test_unlocking_writer_unblocks_all_readers)
{
std::cout << __LINE__ << std::endl;
boost::thread_group pool;
@@ -208,7 +209,7 @@ void test_unlocking_writer_unblocks_all_readers()
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count);
}
-void test_unlocking_last_reader_only_unblocks_one_writer()
+BOOST_AUTO_TEST_CASE(test_unlocking_last_reader_only_unblocks_one_writer)
{
std::cout << __LINE__ << std::endl;
boost::thread_group pool;
@@ -277,19 +278,3 @@ void test_unlocking_last_reader_only_unblocks_one_writer()
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_readers,reader_count);
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_writers,1u);
}
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite");
-
- test->add(BOOST_TEST_CASE(&test_multiple_readers));
- test->add(BOOST_TEST_CASE(&test_only_one_writer_permitted));
- test->add(BOOST_TEST_CASE(&test_reader_blocks_writer));
- test->add(BOOST_TEST_CASE(&test_unlocking_writer_unblocks_all_readers));
- test->add(BOOST_TEST_CASE(&test_unlocking_last_reader_only_unblocks_one_writer));
-
- return test;
-}
-
-
diff --git a/libs/thread/test/test_shared_mutex_part_2.cpp b/libs/thread/test/test_shared_mutex_part_2.cpp
index 3f213b6b76..a0b5282c79 100644
--- a/libs/thread/test/test_shared_mutex_part_2.cpp
+++ b/libs/thread/test/test_shared_mutex_part_2.cpp
@@ -4,6 +4,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
+#define BOOST_TEST_MODULE Boost.Threads: shared_mutex_part2 test suite
#include <boost/test/unit_test.hpp>
#include <boost/thread/thread.hpp>
@@ -49,7 +50,7 @@ public:
};
-void test_only_one_upgrade_lock_permitted()
+BOOST_AUTO_TEST_CASE(test_only_one_upgrade_lock_permitted)
{
unsigned const number_of_threads=2;
@@ -91,7 +92,7 @@ void test_only_one_upgrade_lock_permitted()
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
}
-void test_can_lock_upgrade_if_currently_locked_shared()
+BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_if_currently_locked_shared)
{
boost::thread_group pool;
@@ -140,7 +141,7 @@ void test_can_lock_upgrade_if_currently_locked_shared()
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count+1);
}
-void test_can_lock_upgrade_to_unique_if_currently_locked_upgrade()
+BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_to_unique_if_currently_locked_upgrade)
{
boost::shared_mutex mtx;
boost::upgrade_lock<boost::shared_mutex> l(mtx);
@@ -148,7 +149,7 @@ void test_can_lock_upgrade_to_unique_if_currently_locked_upgrade()
BOOST_CHECK(ul.owns_lock());
}
-void test_if_other_thread_has_write_lock_try_lock_shared_returns_false()
+BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_shared_returns_false)
{
boost::shared_mutex rw_mutex;
@@ -171,7 +172,7 @@ void test_if_other_thread_has_write_lock_try_lock_shared_returns_false()
writer.join();
}
-void test_if_other_thread_has_write_lock_try_lock_upgrade_returns_false()
+BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_upgrade_returns_false)
{
boost::shared_mutex rw_mutex;
@@ -194,7 +195,7 @@ void test_if_other_thread_has_write_lock_try_lock_upgrade_returns_false()
writer.join();
}
-void test_if_no_thread_has_lock_try_lock_shared_returns_true()
+BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_shared_returns_true)
{
boost::shared_mutex rw_mutex;
bool const try_succeeded=rw_mutex.try_lock_shared();
@@ -205,7 +206,7 @@ void test_if_no_thread_has_lock_try_lock_shared_returns_true()
}
}
-void test_if_no_thread_has_lock_try_lock_upgrade_returns_true()
+BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_upgrade_returns_true)
{
boost::shared_mutex rw_mutex;
bool const try_succeeded=rw_mutex.try_lock_upgrade();
@@ -216,7 +217,7 @@ void test_if_no_thread_has_lock_try_lock_upgrade_returns_true()
}
}
-void test_if_other_thread_has_shared_lock_try_lock_shared_returns_true()
+BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_shared_returns_true)
{
boost::shared_mutex rw_mutex;
@@ -239,7 +240,7 @@ void test_if_other_thread_has_shared_lock_try_lock_shared_returns_true()
writer.join();
}
-void test_if_other_thread_has_shared_lock_try_lock_upgrade_returns_true()
+BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_upgrade_returns_true)
{
boost::shared_mutex rw_mutex;
@@ -262,7 +263,7 @@ void test_if_other_thread_has_shared_lock_try_lock_upgrade_returns_true()
writer.join();
}
-void test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false()
+BOOST_AUTO_TEST_CASE(test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false)
{
boost::shared_mutex rw_mutex;
@@ -285,18 +286,4 @@ void test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false()
writer.join();
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite");
-
- test->add(BOOST_TEST_CASE(&test_only_one_upgrade_lock_permitted));
- test->add(BOOST_TEST_CASE(&test_can_lock_upgrade_if_currently_locked_shared));
- test->add(BOOST_TEST_CASE(&test_can_lock_upgrade_to_unique_if_currently_locked_upgrade));
- test->add(BOOST_TEST_CASE(&test_if_other_thread_has_write_lock_try_lock_shared_returns_false));
- test->add(BOOST_TEST_CASE(&test_if_no_thread_has_lock_try_lock_shared_returns_true));
- test->add(BOOST_TEST_CASE(&test_if_other_thread_has_shared_lock_try_lock_shared_returns_true));
-
- return test;
-}
diff --git a/libs/thread/test/test_shared_mutex_timed_locks.cpp b/libs/thread/test/test_shared_mutex_timed_locks.cpp
index 5eea1a1ac2..c29c4260c8 100644
--- a/libs/thread/test/test_shared_mutex_timed_locks.cpp
+++ b/libs/thread/test/test_shared_mutex_timed_locks.cpp
@@ -4,6 +4,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
+#define BOOST_TEST_MODULE Boost.Threads: shared_mutex_timed_locks test suite
#include <boost/test/unit_test.hpp>
#include <boost/thread/thread_only.hpp>
@@ -18,7 +19,7 @@
}
-void test_timed_lock_shared_times_out_if_write_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_shared_times_out_if_write_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -54,7 +55,7 @@ void test_timed_lock_shared_times_out_if_write_lock_held()
writer.join();
}
-void test_timed_lock_shared_succeeds_if_no_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_no_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -83,7 +84,7 @@ void test_timed_lock_shared_succeeds_if_no_lock_held()
}
-void test_timed_lock_shared_succeeds_if_read_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_read_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -119,7 +120,7 @@ void test_timed_lock_shared_succeeds_if_read_lock_held()
reader.join();
}
-void test_timed_lock_times_out_if_write_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_write_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -155,7 +156,7 @@ void test_timed_lock_times_out_if_write_lock_held()
writer.join();
}
-void test_timed_lock_succeeds_if_no_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_succeeds_if_no_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -184,7 +185,7 @@ void test_timed_lock_succeeds_if_no_lock_held()
}
-void test_timed_lock_times_out_if_read_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_read_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -220,7 +221,7 @@ void test_timed_lock_times_out_if_read_lock_held()
reader.join();
}
-void test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -252,21 +253,3 @@ void test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held()
reader.join();
}
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite");
-
- test->add(BOOST_TEST_CASE(&test_timed_lock_shared_times_out_if_write_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_shared_succeeds_if_no_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_shared_succeeds_if_read_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_times_out_if_write_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_times_out_if_read_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_succeeds_if_no_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held));
-
- return test;
-}
-
-
diff --git a/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp b/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp
index fd6690c72f..95dad08258 100644
--- a/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp
+++ b/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp
@@ -4,6 +4,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
+#define BOOST_TEST_MODULE Boost.Threads: shared_mutex_locks_chrono test suite
#include <boost/test/unit_test.hpp>
#include <boost/thread/thread.hpp>
@@ -20,7 +21,7 @@
}
-void test_timed_lock_shared_times_out_if_write_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_shared_times_out_if_write_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -56,7 +57,7 @@ void test_timed_lock_shared_times_out_if_write_lock_held()
writer.join();
}
-void test_timed_lock_shared_succeeds_if_no_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_no_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -85,7 +86,7 @@ void test_timed_lock_shared_succeeds_if_no_lock_held()
}
-void test_timed_lock_shared_succeeds_if_read_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_read_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -121,7 +122,7 @@ void test_timed_lock_shared_succeeds_if_read_lock_held()
reader.join();
}
-void test_timed_lock_times_out_if_write_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_write_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -157,7 +158,7 @@ void test_timed_lock_times_out_if_write_lock_held()
writer.join();
}
-void test_timed_lock_succeeds_if_no_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_succeeds_if_no_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -186,7 +187,7 @@ void test_timed_lock_succeeds_if_no_lock_held()
}
-void test_timed_lock_times_out_if_read_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_read_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -222,7 +223,7 @@ void test_timed_lock_times_out_if_read_lock_held()
reader.join();
}
-void test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held()
+BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held)
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
@@ -254,23 +255,6 @@ void test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held()
reader.join();
}
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite");
-
- test->add(BOOST_TEST_CASE(&test_timed_lock_shared_times_out_if_write_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_shared_succeeds_if_no_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_shared_succeeds_if_read_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_times_out_if_write_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_times_out_if_read_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_succeeds_if_no_lock_held));
- test->add(BOOST_TEST_CASE(&test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held));
-
- return test;
-}
-
#else
#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
#endif
diff --git a/libs/thread/test/test_thread.cpp b/libs/thread/test/test_thread.cpp
index f6a2cb7ae4..fa9e556afd 100644
--- a/libs/thread/test/test_thread.cpp
+++ b/libs/thread/test/test_thread.cpp
@@ -16,6 +16,8 @@
#include <boost/ref.hpp>
#include <boost/utility.hpp>
+#define BOOST_TEST_MODULE Boost.Threads: thread test suite
+
#include <boost/test/unit_test.hpp>
#define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only
@@ -40,7 +42,7 @@ void comparison_thread(boost::thread::id parent)
BOOST_CHECK(my_id != no_thread_id);
}
-void test_sleep()
+BOOST_AUTO_TEST_CASE(test_sleep)
{
boost::xtime xt = delay(3);
boost::thread::sleep(xt);
@@ -58,7 +60,7 @@ void do_test_creation()
BOOST_CHECK_EQUAL(test_value, 999);
}
-void test_creation()
+BOOST_AUTO_TEST_CASE(test_creation)
{
timed_test(&do_test_creation, 1);
}
@@ -70,7 +72,7 @@ void do_test_id_comparison()
thrd.join();
}
-void test_id_comparison()
+BOOST_AUTO_TEST_CASE(test_id_comparison)
{
timed_test(&do_test_id_comparison, 1);
}
@@ -94,7 +96,7 @@ void do_test_thread_interrupts_at_interruption_point()
BOOST_CHECK(!failed);
}
-void test_thread_interrupts_at_interruption_point()
+BOOST_AUTO_TEST_CASE(test_thread_interrupts_at_interruption_point)
{
timed_test(&do_test_thread_interrupts_at_interruption_point, 1);
}
@@ -119,7 +121,7 @@ void do_test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point()
BOOST_CHECK(!failed);
}
-void test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point()
+BOOST_AUTO_TEST_CASE(test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point)
{
timed_test(&do_test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point, 1);
}
@@ -148,7 +150,7 @@ void do_test_creation_through_reference_wrapper()
BOOST_CHECK_EQUAL(f.value, 999u);
}
-void test_creation_through_reference_wrapper()
+BOOST_AUTO_TEST_CASE(test_creation_through_reference_wrapper)
{
timed_test(&do_test_creation_through_reference_wrapper, 1);
}
@@ -197,12 +199,12 @@ void do_test_timed_join()
BOOST_CHECK(!thrd.joinable());
}
-void test_timed_join()
+BOOST_AUTO_TEST_CASE(test_timed_join)
{
timed_test(&do_test_timed_join, 10);
}
-void test_swap()
+BOOST_AUTO_TEST_CASE(test_swap)
{
boost::thread t(simple_thread);
boost::thread t2(simple_thread);
@@ -218,21 +220,3 @@ void test_swap()
BOOST_CHECK(t2.get_id()==id2);
}
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: thread test suite");
-
- test->add(BOOST_TEST_CASE(test_sleep));
- test->add(BOOST_TEST_CASE(test_creation));
- test->add(BOOST_TEST_CASE(test_id_comparison));
- test->add(BOOST_TEST_CASE(test_thread_interrupts_at_interruption_point));
- test->add(BOOST_TEST_CASE(test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point));
- test->add(BOOST_TEST_CASE(test_creation_through_reference_wrapper));
- test->add(BOOST_TEST_CASE(test_timed_join));
- test->add(BOOST_TEST_CASE(test_swap));
-
- return test;
-}
-
diff --git a/libs/thread/test/test_thread_exit.cpp b/libs/thread/test/test_thread_exit.cpp
index abd18a85b4..539a50acde 100644
--- a/libs/thread/test/test_thread_exit.cpp
+++ b/libs/thread/test/test_thread_exit.cpp
@@ -12,6 +12,8 @@
#include <memory>
#include <string>
+#define BOOST_TEST_MODULE Boost.Threads: thread exit test suite
+
#include <boost/test/unit_test.hpp>
boost::thread::id exit_func_thread_id;
@@ -27,7 +29,7 @@ void tf1()
BOOST_CHECK(exit_func_thread_id!=boost::this_thread::get_id());
}
-void test_thread_exit_func_runs_when_thread_exits()
+BOOST_AUTO_TEST_CASE(test_thread_exit_func_runs_when_thread_exits)
{
exit_func_thread_id=boost::thread::id();
boost::thread t(tf1);
@@ -51,7 +53,7 @@ void tf2()
}
-void test_can_use_function_object_for_exit_func()
+BOOST_AUTO_TEST_CASE(test_can_use_function_object_for_exit_func)
{
exit_func_thread_id=boost::thread::id();
boost::thread t(tf2);
@@ -59,17 +61,3 @@ void test_can_use_function_object_for_exit_func()
t.join();
BOOST_CHECK(exit_func_thread_id==t_id);
}
-
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: futures test suite");
-
- test->add(BOOST_TEST_CASE(test_thread_exit_func_runs_when_thread_exits));
- test->add(BOOST_TEST_CASE(test_can_use_function_object_for_exit_func));
-
- return test;
-}
-
-
diff --git a/libs/thread/test/test_thread_id.cpp b/libs/thread/test/test_thread_id.cpp
index 0a9725ec08..96b98016a7 100644
--- a/libs/thread/test/test_thread_id.cpp
+++ b/libs/thread/test/test_thread_id.cpp
@@ -2,6 +2,9 @@
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE Boost.Threads: thread::get_id test suite
+
#include <boost/thread/thread_only.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/bind.hpp>
@@ -9,20 +12,20 @@
void do_nothing()
{}
-void test_thread_id_for_default_constructed_thread_is_default_constructed_id()
+BOOST_AUTO_TEST_CASE(test_thread_id_for_default_constructed_thread_is_default_constructed_id)
{
boost::thread t;
BOOST_CHECK(t.get_id()==boost::thread::id());
}
-void test_thread_id_for_running_thread_is_not_default_constructed_id()
+BOOST_AUTO_TEST_CASE(test_thread_id_for_running_thread_is_not_default_constructed_id)
{
boost::thread t(do_nothing);
BOOST_CHECK(t.get_id()!=boost::thread::id());
t.join();
}
-void test_different_threads_have_different_ids()
+BOOST_AUTO_TEST_CASE(test_different_threads_have_different_ids)
{
boost::thread t(do_nothing);
boost::thread t2(do_nothing);
@@ -31,7 +34,7 @@ void test_different_threads_have_different_ids()
t2.join();
}
-void test_thread_ids_have_a_total_order()
+BOOST_AUTO_TEST_CASE(test_thread_ids_have_a_total_order)
{
boost::thread t(do_nothing);
boost::thread t2(do_nothing);
@@ -126,7 +129,7 @@ void get_thread_id(boost::thread::id* id)
*id=boost::this_thread::get_id();
}
-void test_thread_id_of_running_thread_returned_by_this_thread_get_id()
+BOOST_AUTO_TEST_CASE(test_thread_id_of_running_thread_returned_by_this_thread_get_id)
{
boost::thread::id id;
boost::thread t(boost::bind(get_thread_id,&id));
@@ -134,18 +137,3 @@ void test_thread_id_of_running_thread_returned_by_this_thread_get_id()
t.join();
BOOST_CHECK(id==t_id);
}
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: thread move test suite");
-
- test->add(BOOST_TEST_CASE(test_thread_id_for_default_constructed_thread_is_default_constructed_id));
- test->add(BOOST_TEST_CASE(test_thread_id_for_running_thread_is_not_default_constructed_id));
- test->add(BOOST_TEST_CASE(test_different_threads_have_different_ids));
- test->add(BOOST_TEST_CASE(test_thread_ids_have_a_total_order));
- test->add(BOOST_TEST_CASE(test_thread_id_of_running_thread_returned_by_this_thread_get_id));
- return test;
-}
-
-
diff --git a/libs/thread/test/test_thread_launching.cpp b/libs/thread/test/test_thread_launching.cpp
index 656a46ebf4..7c0d3f9f00 100644
--- a/libs/thread/test/test_thread_launching.cpp
+++ b/libs/thread/test/test_thread_launching.cpp
@@ -4,6 +4,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 3
+#define BOOST_TEST_MODULE Boost.Threads: thread launching test suite
#include <boost/thread/thread_only.hpp>
#include <boost/test/unit_test.hpp>
@@ -19,7 +20,7 @@ void normal_function()
normal_function_called=true;
}
-void test_thread_function_no_arguments()
+BOOST_AUTO_TEST_CASE(test_thread_function_no_arguments)
{
boost::thread function(normal_function);
function.join();
@@ -33,7 +34,7 @@ void normal_function_one_arg(int i)
nfoa_res=i;
}
-void test_thread_function_one_argument()
+BOOST_AUTO_TEST_CASE(test_thread_function_one_argument)
{
boost::thread function(normal_function_one_arg,42);
function.join();
@@ -52,7 +53,7 @@ struct callable_no_args
bool callable_no_args::called=false;
-void test_thread_callable_object_no_arguments()
+BOOST_AUTO_TEST_CASE(test_thread_callable_object_no_arguments)
{
callable_no_args func;
boost::thread callable(func);
@@ -74,7 +75,7 @@ struct callable_noncopyable_no_args:
bool callable_noncopyable_no_args::called=false;
-void test_thread_callable_object_ref_no_arguments()
+BOOST_AUTO_TEST_CASE(test_thread_callable_object_ref_no_arguments)
{
callable_noncopyable_no_args func;
@@ -98,7 +99,7 @@ struct callable_one_arg
bool callable_one_arg::called=false;
int callable_one_arg::called_arg=0;
-void test_thread_callable_object_one_argument()
+BOOST_AUTO_TEST_CASE(test_thread_callable_object_one_argument)
{
callable_one_arg func;
boost::thread callable(func,42);
@@ -140,7 +141,7 @@ std::string callable_multiple_arg::called_three_arg1;
std::vector<int> callable_multiple_arg::called_three_arg2;
int callable_multiple_arg::called_three_arg3;
-void test_thread_callable_object_multiple_arguments()
+BOOST_AUTO_TEST_CASE(test_thread_callable_object_multiple_arguments)
{
std::vector<int> x;
for(unsigned i=0;i<7;++i)
@@ -196,7 +197,7 @@ struct X
};
-void test_thread_member_function_no_arguments()
+BOOST_AUTO_TEST_CASE(test_thread_member_function_no_arguments)
{
X x;
@@ -206,29 +207,10 @@ void test_thread_member_function_no_arguments()
}
-void test_thread_member_function_one_argument()
+BOOST_AUTO_TEST_CASE(test_thread_member_function_one_argument)
{
X x;
boost::thread function(&X::f1,&x,42);
function.join();
BOOST_CHECK_EQUAL(42,x.arg_value);
}
-
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: thread launching test suite");
-
- test->add(BOOST_TEST_CASE(test_thread_function_no_arguments));
- test->add(BOOST_TEST_CASE(test_thread_function_one_argument));
- test->add(BOOST_TEST_CASE(test_thread_callable_object_no_arguments));
- test->add(BOOST_TEST_CASE(test_thread_callable_object_ref_no_arguments));
- test->add(BOOST_TEST_CASE(test_thread_callable_object_one_argument));
- test->add(BOOST_TEST_CASE(test_thread_callable_object_multiple_arguments));
- test->add(BOOST_TEST_CASE(test_thread_member_function_no_arguments));
- test->add(BOOST_TEST_CASE(test_thread_member_function_one_argument));
- return test;
-}
-
-
diff --git a/libs/thread/test/test_thread_move.cpp b/libs/thread/test/test_thread_move.cpp
index fe01b62fdf..e86db8cad5 100644
--- a/libs/thread/test/test_thread_move.cpp
+++ b/libs/thread/test/test_thread_move.cpp
@@ -2,6 +2,9 @@
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MODULE Boost.Threads: thread move test suite
+
#include <boost/thread/thread_only.hpp>
#include <boost/test/unit_test.hpp>
@@ -10,7 +13,7 @@ void do_nothing(boost::thread::id* my_id)
*my_id=boost::this_thread::get_id();
}
-void test_move_on_construction()
+BOOST_AUTO_TEST_CASE(test_move_on_construction)
{
boost::thread::id the_id;
boost::thread x=boost::thread(do_nothing,&the_id);
@@ -24,7 +27,7 @@ boost::thread make_thread(boost::thread::id* the_id)
return boost::thread(do_nothing,the_id);
}
-void test_move_from_function_return()
+BOOST_AUTO_TEST_CASE(test_move_from_function_return)
{
boost::thread::id the_id;
boost::thread x=make_thread(&the_id);
@@ -33,7 +36,7 @@ void test_move_from_function_return()
BOOST_CHECK_EQUAL(the_id,x_id);
}
-void test_move_assign()
+BOOST_AUTO_TEST_CASE(test_move_assign)
{
boost::thread::id the_id;
boost::thread x(do_nothing,&the_id);
@@ -44,15 +47,4 @@ void test_move_assign()
BOOST_CHECK_EQUAL(the_id,y_id);
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: thread move test suite");
-
- test->add(BOOST_TEST_CASE(test_move_on_construction));
- test->add(BOOST_TEST_CASE(test_move_from_function_return));
- test->add(BOOST_TEST_CASE(test_move_assign));
- return test;
-}
-
diff --git a/libs/thread/test/test_thread_move_return.cpp b/libs/thread/test/test_thread_move_return.cpp
index e9e4512b86..f714fb0a57 100644
--- a/libs/thread/test/test_thread_move_return.cpp
+++ b/libs/thread/test/test_thread_move_return.cpp
@@ -4,6 +4,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_USES_MOVE
+#define BOOST_TEST_MODULE Boost.Threads: thread move return test suite
#include <boost/thread/thread_only.hpp>
#include <boost/test/unit_test.hpp>
@@ -19,7 +20,7 @@ boost::thread make_thread_move_return(boost::thread::id* the_id)
return boost::move(t);
}
-void test_move_from_function_move_return()
+BOOST_AUTO_TEST_CASE(test_move_from_function_move_return)
{
boost::thread::id the_id;
boost::thread x=make_thread_move_return(&the_id);
@@ -28,13 +29,3 @@ void test_move_from_function_move_return()
BOOST_CHECK_EQUAL(the_id,x_id);
}
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: thread move test suite");
-
- test->add(BOOST_TEST_CASE(test_move_from_function_move_return));
- return test;
-}
-
-
diff --git a/libs/thread/test/test_thread_return_local.cpp b/libs/thread/test/test_thread_return_local.cpp
index 46e84a7e29..6ffd1083ae 100644
--- a/libs/thread/test/test_thread_return_local.cpp
+++ b/libs/thread/test/test_thread_return_local.cpp
@@ -5,6 +5,8 @@
#define BOOST_THREAD_USES_MOVE
+#define BOOST_TEST_MODULE Boost.Threads: thread return local test suite
+
#include <boost/thread/thread_only.hpp>
#include <boost/test/unit_test.hpp>
@@ -19,7 +21,7 @@ boost::thread make_thread_return_local(boost::thread::id* the_id)
return boost::move(t);
}
-void test_move_from_function_return_local()
+BOOST_AUTO_TEST_CASE(test_move_from_function_return_local)
{
boost::thread::id the_id;
boost::thread x=make_thread_return_local(&the_id);
@@ -27,14 +29,3 @@ void test_move_from_function_return_local()
x.join();
BOOST_CHECK_EQUAL(the_id,x_id);
}
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: thread move test suite");
-
- test->add(BOOST_TEST_CASE(test_move_from_function_return_local));
- return test;
-}
-
-
diff --git a/libs/thread/test/test_tss.cpp b/libs/thread/test/test_tss.cpp
index 595b15620e..c833a9fd03 100644
--- a/libs/thread/test/test_tss.cpp
+++ b/libs/thread/test/test_tss.cpp
@@ -7,6 +7,7 @@
#define BOOST_THREAD_VERSION 2
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
+#define BOOST_TEST_MODULE Boost.Threads: tss test suite
#include <boost/thread/detail/config.hpp>
#include <boost/predef/platform.h>
@@ -73,7 +74,7 @@ void test_tss_thread()
#if BOOST_PLAT_WINDOWS_RUNTIME
typedef std::shared_ptr<std::thread> native_thread_t;
- void test_tss_thread_native()
+ BOOST_AUTO_TEST_CASE(test_tss_thread_native)
{
test_tss_thread();
}
@@ -208,7 +209,7 @@ void do_test_tss()
BOOST_CHECK_EQUAL(tss_total, 5);
}
-void test_tss()
+BOOST_AUTO_TEST_CASE(test_tss)
{
timed_test(&do_test_tss, 2);
}
@@ -224,6 +225,7 @@ void tss_void_custom_cleanup(void* d)
}
boost::thread_specific_ptr<void> tss_void(tss_void_custom_cleanup);
+
void test_tss_void_thread()
{
tss_void.reset(new tss_value_t());
@@ -300,10 +302,10 @@ void do_test_tss_void()
// BOOST_CHECK_EQUAL(tss_total, 5);
}
-void test_tss_void()
-{
- timed_test(&do_test_tss_void, 2);
-}
+//BOOST_AUTO_TEST_CASE(test_tss_void)
+//{
+// timed_test(&do_test_tss_void, 2);
+//}
boost::thread_specific_ptr<void> tss_void_with_cleanup(tss_void_custom_cleanup);
@@ -331,7 +333,7 @@ void do_test_tss_void_with_custom_cleanup()
}
-void test_tss_void_with_custom_cleanup()
+BOOST_AUTO_TEST_CASE(test_tss_void_with_custom_cleanup)
{
timed_test(&do_test_tss_void_with_custom_cleanup, 2);
}
@@ -373,7 +375,7 @@ void do_test_tss_with_custom_cleanup()
}
-void test_tss_with_custom_cleanup()
+BOOST_AUTO_TEST_CASE(test_tss_with_custom_cleanup)
{
timed_test(&do_test_tss_with_custom_cleanup, 2);
}
@@ -450,12 +452,12 @@ void do_test_tss_does_no_cleanup_with_null_cleanup_function()
}
}
-void test_tss_does_no_cleanup_after_release()
+BOOST_AUTO_TEST_CASE(test_tss_does_no_cleanup_after_release)
{
timed_test(&do_test_tss_does_no_cleanup_after_release, 2);
}
-void test_tss_does_no_cleanup_with_null_cleanup_function()
+BOOST_AUTO_TEST_CASE(test_tss_does_no_cleanup_with_null_cleanup_function)
{
timed_test(&do_test_tss_does_no_cleanup_with_null_cleanup_function, 2);
}
@@ -472,14 +474,14 @@ void thread_with_local_tss_ptr()
}
-void test_tss_does_not_call_cleanup_after_ptr_destroyed()
+BOOST_AUTO_TEST_CASE(test_tss_does_not_call_cleanup_after_ptr_destroyed)
{
boost::thread t(thread_with_local_tss_ptr);
t.join();
BOOST_CHECK(!tss_cleanup_called);
}
-void test_tss_cleanup_not_called_for_null_pointer()
+BOOST_AUTO_TEST_CASE(test_tss_cleanup_not_called_for_null_pointer)
{
boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup);
local_tss.reset(new Dummy);
@@ -491,34 +493,16 @@ void test_tss_cleanup_not_called_for_null_pointer()
BOOST_CHECK(!tss_cleanup_called);
}
-void test_tss_at_the_same_adress()
-{
- for(int i=0; i<2; i++)
- {
- boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup);
- local_tss.reset(new Dummy);
- tss_cleanup_called=false;
- BOOST_CHECK(tss_cleanup_called);
- tss_cleanup_called=false;
- BOOST_CHECK(!tss_cleanup_called);
- }
-}
-
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: tss test suite");
-
- test->add(BOOST_TEST_CASE(test_tss));
- test->add(BOOST_TEST_CASE(test_tss_with_custom_cleanup));
- test->add(BOOST_TEST_CASE(test_tss_does_no_cleanup_after_release));
- test->add(BOOST_TEST_CASE(test_tss_does_no_cleanup_with_null_cleanup_function));
- test->add(BOOST_TEST_CASE(test_tss_does_not_call_cleanup_after_ptr_destroyed));
- test->add(BOOST_TEST_CASE(test_tss_cleanup_not_called_for_null_pointer));
- //test->add(BOOST_TEST_CASE(test_tss_void));
- test->add(BOOST_TEST_CASE(test_tss_void_with_custom_cleanup));
+//BOOST_AUTO_TEST_CASE(test_tss_at_the_same_adress)
+//{
+// for(int i=0; i<2; i++)
+// {
+// boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup);
+// local_tss.reset(new Dummy);
+// tss_cleanup_called=false;
+// BOOST_CHECK(tss_cleanup_called);
+// tss_cleanup_called=false;
+// BOOST_CHECK(!tss_cleanup_called);
+// }
+//}
-
- return test;
-}
diff --git a/libs/thread/test/test_xtime.cpp b/libs/thread/test/test_xtime.cpp
index f7d79a0987..4988d1f860 100644
--- a/libs/thread/test/test_xtime.cpp
+++ b/libs/thread/test/test_xtime.cpp
@@ -6,6 +6,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 2
+#define BOOST_TEST_MODULE Boost.Threads: xtime test suite
#include <boost/thread/detail/config.hpp>
@@ -15,7 +16,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
-void test_xtime_cmp()
+BOOST_AUTO_TEST_CASE(test_xtime_cmp)
{
boost::xtime xt1, xt2, cur;
BOOST_CHECK_EQUAL(
@@ -39,7 +40,7 @@ void test_xtime_cmp()
BOOST_CHECK(boost::xtime_cmp(cur, cur) == 0);
}
-void test_xtime_get()
+BOOST_AUTO_TEST_CASE(test_xtime_get)
{
boost::xtime orig, cur, old;
BOOST_CHECK_EQUAL(
@@ -58,7 +59,7 @@ void test_xtime_get()
}
}
-void test_xtime_mutex_backwards_compatibility()
+BOOST_AUTO_TEST_CASE(test_xtime_mutex_backwards_compatibility)
{
boost::timed_mutex m;
BOOST_CHECK(m.timed_lock(boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10))));
@@ -82,7 +83,7 @@ bool predicate()
}
-void test_xtime_condvar_backwards_compatibility()
+BOOST_AUTO_TEST_CASE(test_xtime_condvar_backwards_compatibility)
{
boost::condition_variable cond;
boost::condition_variable_any cond_any;
@@ -94,18 +95,3 @@ void test_xtime_condvar_backwards_compatibility()
cond_any.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)));
cond_any.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)),predicate);
}
-
-
-
-boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
-{
- boost::unit_test::test_suite* test =
- BOOST_TEST_SUITE("Boost.Threads: xtime test suite");
-
- test->add(BOOST_TEST_CASE(&test_xtime_cmp));
- test->add(BOOST_TEST_CASE(&test_xtime_get));
- test->add(BOOST_TEST_CASE(&test_xtime_mutex_backwards_compatibility));
- test->add(BOOST_TEST_CASE(&test_xtime_condvar_backwards_compatibility));
-
- return test;
-}
diff --git a/libs/thread/test/winrt_init.cpp b/libs/thread/test/winrt_init.cpp
index 99edd8b51d..b6d0864baa 100644
--- a/libs/thread/test/winrt_init.cpp
+++ b/libs/thread/test/winrt_init.cpp
@@ -1,3 +1,5 @@
+// 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)