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

Compare commits

..

2 Commits

Author SHA1 Message Date
Daniel James
52b9d23065 Thread: rollback change in #8070 as this includes a regression on windows XP.
From [84946], by viboes.



[SVN r84968]
2013-07-07 11:46:48 +00:00
Daniel James
44e74f866c Create a maintenance branch for Boost 1.54.0
[SVN r84945]
2013-07-03 21:01:45 +00:00
234 changed files with 4992 additions and 27959 deletions

40
.gitignore vendored
View File

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

View File

@@ -1,8 +0,0 @@
thread
======
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).

View File

@@ -36,7 +36,6 @@ import os ;
import feature ;
import indirect ;
import path ;
import configure ;
project boost/thread
: source-location ../src
@@ -78,19 +77,19 @@ project boost/thread
<toolset>pathscale:<cxxflags>-pedantic
<toolset>clang:<cxxflags>-Wextra
<toolset>clang:<cxxflags>-pedantic
#<toolset>clang:<cxxflags>-ansi
#<toolset>clang:<cxxflags>-fpermissive
<toolset>clang:<cxxflags>-Wno-long-long
<toolset>clang:<cxxflags>-Wunused-function
<toolset>clang:<cxxflags>-Wno-variadic-macros
<toolset>clang:<warnings>on
#<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
#<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
#<toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option
#<toolset>gcc-mingw-4.6.3:<cxxflags>-fdiagnostics-show-option
#<toolset>gcc-mingw-4.7.0:<cxxflags>-fdiagnostics-show-option
#<toolset>gcc-mingw-4.8.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.6.3:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.7.0:<cxxflags>-fdiagnostics-show-option
<toolset>gcc-mingw-4.8.0:<cxxflags>-fdiagnostics-show-option
#<toolset>gcc:<cxxflags>-Wno-missing-field-initializers
<toolset>darwin-4.6.2:<cxxflags>-Wno-delete-non-virtual-dtor
@@ -141,8 +140,6 @@ local rule default_threadapi ( )
feature.feature threadapi : pthread win32 : propagated ;
feature.set-default threadapi : [ default_threadapi ] ;
exe has_atomic_flag_lockfree : ../build/has_atomic_flag_lockfree_test.cpp ;
rule tag ( name : type ? : property-set )
{
local result = $(name) ;
@@ -239,10 +236,10 @@ rule usage-requirements ( properties * )
}
}
#if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties) || <toolset-vacpp:version>12.1.0.1 in $(properties) || <toolset-vacpp:version>12.1 in $(properties)
#{
if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties) || <toolset-vacpp:version>12.1.0.1 in $(properties) || <toolset-vacpp:version>12.1 in $(properties)
{
result += <library>/boost/chrono//boost_chrono ;
#}
}
return $(result) ;
}
@@ -267,15 +264,16 @@ rule requirements ( properties * )
}
}
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
if ! [ configure.builds has_atomic_flag_lockfree
: $(properties) : "lockfree boost::atomic_flag" ] {
result += <library>/boost/atomic//boost_atomic ;
}
} else {
result += <define>BOOST_THREAD_USES_CHRONO ;
result += <library>/boost/chrono//boost_chrono ;
}
if <toolset>pgi in $(properties) || <toolset>vacpp in $(properties)
{
result += <library>/boost/atomic//boost_atomic ;
}
return $(result) ;
}

View File

@@ -1,13 +0,0 @@
// 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"
int main(int argc, char *argv[])
{
BOOST_STATIC_ASSERT(BOOST_ATOMIC_FLAG_LOCK_FREE);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,11 @@
[/
(C) Copyright 2007-8 Anthony Williams.
(C) Copyright 2013 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
]
[section:barriers Barriers -- EXTENSION]
[section:barriers Barriers]
A barrier is a simple concept. Also known as a ['rendezvous], it is a synchronization point between multiple threads. The barrier is
configured for a particular number of threads (`n`), and as threads reach the barrier they must wait until all `n` threads have
@@ -23,18 +22,14 @@ arrived. Once the `n`-th thread has reached the barrier, all the waiting threads
barrier& operator=(barrier const&) = delete;
barrier(unsigned int count);
template <typename F>
barrier(unsigned int count, F&&);
~barrier();
bool wait();
void count_down_and_wait();
};
Instances of __barrier__ are not copyable or movable.
[section Constructor `barrier(unsigned int)`]
[heading Constructor]
barrier(unsigned int count);
@@ -46,24 +41,7 @@ Instances of __barrier__ are not copyable or movable.
]
[endsect]
[section Constructor `barrier(unsigned int, F&&)`]
barrier(unsigned int count, F&& completion);
[variablelist
[[Requires:] [The result type of the completion function call `completion()` is `void` or `unsigned int`.]]
[[Effects:] [Construct a barrier for `count` threads and a completion function `completion`.]]
[[Throws:] [__thread_resource_error__ if an error occurs.]]
]
[endsect]
[section Destructor `~barrier()`]
[heading Destructor]
~barrier();
@@ -77,55 +55,24 @@ Instances of __barrier__ are not copyable or movable.
]
[endsect]
[section Member Function `wait()`]
[heading Member function `wait`]
bool wait();
[variablelist
[[Effects:] [Block until `count` threads have called `wait` or `count_down_and_wait` on `*this`. When the `count`-th thread calls `wait`, the barrier is reset and all waiting threads are unblocked.
The reset depends on whether the barrier was constructed with a completion function or not. If there is no completion function or if the completion function result is void, the reset consists in restoring the original count. Otherwise the rest consist in assigning the result of the completion function (which must not be 0).]]
[[Effects:] [Block until `count` threads have called `wait` on `*this`. When the `count`-th thread calls `wait`, all waiting threads
are unblocked, and the barrier is reset. ]]
[[Returns:] [`true` for exactly one thread from each batch of waiting threads, `false` otherwise.]]
[[Throws:] [
- __thread_resource_error__ if an error occurs.
- __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.
]]
[[Throws:] [__thread_resource_error__ if an error occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
[[Notes:] [`wait()` is an ['interruption point].]]
]
[endsect]
[section Member Function `count_down_and_wait()`]
void count_down_and_wait();
[variablelist
[[Effects:] [Block until `count` threads have called `wait` or `count_down_and_wait` on `*this`. When the `count`-th thread calls `wait`, the barrier is reset and all waiting threads are unblocked.
The reset depends on whether the barrier was constructed with a completion function or not. If there is no completion function or if the completion function result is void, the reset consists in restoring the original count. Otherwise the rest consist in assigning the result of the completion function (which must not be 0).]]
[[Throws:] [
- __thread_resource_error__ if an error occurs.
- __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.
]]
[[Notes:] [`count_down_and_wait()` is an ['interruption point].]]
]
[endsect]
[endsect]
[endsect]

View File

@@ -1,6 +1,6 @@
[/
(C) Copyright 2007-11 Anthony Williams.
(C) Copyright 2011-14 Vicente J. Botet Escriba.
(C) Copyright 2011-13 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
@@ -8,171 +8,23 @@
[section:changes History]
[heading Version 4.4.0 - boost 1.57]
[*Know Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/2442 #2442] Application statically linked with Boost.Thread crashes when Google Desktop is installed (Windows XP)
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
* [@http://svn.boost.org/trac/boost/ticket/4833 #4833] MinGW/test_tss_lib: Support of automatic tss cleanup for native threading API not available
* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue
* [@http://svn.boost.org/trac/boost/ticket/8600 #8600] wait_for_any hangs, if called with multiple copies of shared_future referencing same task
* [@http://svn.boost.org/trac/boost/ticket/9118 #9118] Seg fault on thread join when llvm and libc++ are used
* [@http://svn.boost.org/trac/boost/ticket/9309 #9309] test_latch fails often on clang-darwin-tot11
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
* [@http://svn.boost.org/trac/boost/ticket/10537 #10537] Application crash on throw exception
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last snapshot.
[*Sever limitations:]
There are some severe bugs that prevent the use of the library on concrete contexts, in particular:
* on thread specific storage that prevent the library to be used with dynamic libraries,
[*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/6227 #6227] Synchro: Use of variadic templates on Generic Locking Algorithms on compilers providing them
* [@http://svn.boost.org/trac/boost/ticket/10298 #10298] Synchro: Added queue views.
* [@http://svn.boost.org/trac/boost/ticket/10300 #10300] Async: Added generic_executor_ref.
* [@http://svn.boost.org/trac/boost/ticket/10552 #10552] Add make_valid_future
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/6782 #6782] call_once uses incorrect barrier intrinsic on Visual Studio
* [@http://svn.boost.org/trac/boost/ticket/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
* [@http://svn.boost.org/trac/boost/ticket/7665 #7665] this_thread::sleep_for no longer uses steady_clock in thread
* [@http://svn.boost.org/trac/boost/ticket/9307 #9307] future::fallback_to assert with ERRORRRRR boost: mutex lock failed in pthread_mutex_lock: Invalid argument
* [@http://svn.boost.org/trac/boost/ticket/9308 #9308] future::async fails with terminate called throwing an exception when called with a lambda - clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9425 #9425] Boost promise & future does not use supplied allocator for value storage
* [@http://svn.boost.org/trac/boost/ticket/9558 #9558] future continuations unit test hangs in get()/pthread_cond_wait() on Mac 10.7/32-bit/x86/darwin-4.2.1
* [@http://svn.boost.org/trac/boost/ticket/9787 #9787] [windows] Small duration value passed down to basic_timed_mutex::try_lock_until and condition_variable::wait_until can cause infinite or near infinite wait for win32
* [@http://svn.boost.org/trac/boost/ticket/9880 #9880] [windows] boost::condition_variable.timed_wait() exception if system time < 1970
* [@http://svn.boost.org/trac/boost/ticket/10159 #10159] GCC 4.4 error sorry, unimplemented
* [@http://svn.boost.org/trac/boost/ticket/10196 #10196] thread_specific_ptr does not support void*
* [@http://svn.boost.org/trac/boost/ticket/10296 #10296] Boost.Thread 1.56 rc1 does not compile on Mingw
* [@http://svn.boost.org/trac/boost/ticket/10297 #10297] Boost.Thread 1.56 rc1 hangs when built with clang on armhf
* [@http://svn.boost.org/trac/boost/ticket/10340 #10340] No boost::promise<T>::set_value(const T&) overload present in C++03 mode
* [@http://svn.boost.org/trac/boost/ticket/10425 #10425] Missing documentation for when_all/when_any.
* [@http://svn.boost.org/trac/boost/ticket/10426 #10426] Take in account the deferred futures in when_all.
* [@http://svn.boost.org/trac/boost/ticket/10427 #10427] Take in account the deferred and ready futures in when_any.
* [@http://svn.boost.org/trac/boost/ticket/10428 #10428] Adapt to new unique_ptr interface in Boost.Move
* [@http://svn.boost.org/trac/boost/ticket/10465 #10465] Missing implementation of when_all/when_any when the result is a tuple.
* [@http://svn.boost.org/trac/boost/ticket/10476 #10476] classes using BOOST_THREAD_MOVABLE_ONLY<T> dont satisfy is_copy_constructible<T>::value == false
* [@http://svn.boost.org/trac/boost/ticket/10478 #10478] Data race in boost/thread/future.hpp
* [@http://svn.boost.org/trac/boost/ticket/10529 #10529] The pthread/condition_variable_any constructor reports incorrect error code for pthread_cond_init
* [@http://svn.boost.org/trac/boost/ticket/10563 #10563] shared_future<R>::then should be const
[heading Version 4.3.0 - boost 1.56]
[*Know Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/2442 #2442] Application statically linked with Boost.Thread crashes when Google Desktop is installed (Windows XP)
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
* [@http://svn.boost.org/trac/boost/ticket/4833 #4833] MinGW/test_tss_lib: Support of automatic tss cleanup for native threading API not available
* [@http://svn.boost.org/trac/boost/ticket/6782 #6782] call_once uses incorrect barrier intrinsic on Visual Studio
* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue
* [@http://svn.boost.org/trac/boost/ticket/8600 #8600] wait_for_any hangs, if called with multiple copies of shared_future referencing same task
* [@http://svn.boost.org/trac/boost/ticket/9307 #9307] future::fallback_to assert with ERRORRRRR boost: mutex lock failed in pthread_mutex_lock: Invalid argument
* [@http://svn.boost.org/trac/boost/ticket/9308 #9308] future::async fails with terminate called throwing an exception when called with a lambda - clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
* [@http://svn.boost.org/trac/boost/ticket/9425 #9425] Boost promise & future does not use supplied allocator for value storage
* [@http://svn.boost.org/trac/boost/ticket/9558 #9558] future continuations unit test hangs in get()/pthread_cond_wait() on Mac 10.7/32-bit/x86/darwin-4.2.1
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last snapshot.
[*Sever limitations:]
There are some severe bugs that prevent the use of the library on concrete contexts, in particular:
* on thread specific storage that prevent the library to be used with dynamic libraries,
* The experimental features of boost::future have some severe holes that make the program crash unexpectedly.
[*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/7446 #7446] Async: Add when_any.
* [@http://svn.boost.org/trac/boost/ticket/7447 #7447] Async: Add when_all.
* [@http://svn.boost.org/trac/boost/ticket/7448 #7448] Async: Add async taking a scheduler parameter.
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Synchro: Add concurrent queue
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Synchro: Add a latch class.
* [@http://svn.boost.org/trac/boost/ticket/8513 #8513] Async: Add a basic thread_pool executor.
* [@http://svn.boost.org/trac/boost/ticket/8516 #8516] Async: Add future/shared_future::then taking a scheduler as parameter.
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/8070 #8070] prefer GetTickCount64 over GetTickCount
* [@http://svn.boost.org/trac/boost/ticket/9333 #9333] ex_scoped_thread compile fails on msvc-12.0
* [@http://svn.boost.org/trac/boost/ticket/9366 #9366] async(Executor, ...) fails to compile with msvc-10,11,12
* [@http://svn.boost.org/trac/boost/ticket/9402 #9402] test_excutor regression on msvc-10,11,12
* [@http://svn.boost.org/trac/boost/ticket/9404 #9404] ex_make_future regression error
* [@http://svn.boost.org/trac/boost/ticket/9471 #9471] Synchronization documentation nits
* [@http://svn.boost.org/trac/boost/ticket/9535 #9535] Missing exception safety might result in crash
* [@http://svn.boost.org/trac/boost/ticket/9618 #9618] try_join_for problem: program is not terminate.
* [@http://svn.boost.org/trac/boost/ticket/9673 #9673] thread compilation with MingW/gcc on Windows gives errors
* [@http://svn.boost.org/trac/boost/ticket/9708 #9708] boost::condition_variable::timed_wait unexpectedly wakes up while should wait infinite
* [@http://svn.boost.org/trac/boost/ticket/9711 #9711] future continuation called twice
[/
[heading Version 4.2.0 - boost 1.55]
[*Know Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/2442 #2442] Application statically linked with Boost.Thread crashes when Google Desktop is installed (Windows XP)
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
* [@http://svn.boost.org/trac/boost/ticket/4833 #4833] MinGW/test_tss_lib: Support of automatic tss cleanup for native threading API not available
* [@http://svn.boost.org/trac/boost/ticket/6782 #6782] call_once uses incorrect barrier intrinsic on Visual Studio
* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue
* [@http://svn.boost.org/trac/boost/ticket/8600 #8600] wait_for_any hangs, if called with multiple copies of shared_future referencing same task
* [@http://svn.boost.org/trac/boost/ticket/9307 #9307] future::fallback_to assert with ERRORRRRR boost: mutex lock failed in pthread_mutex_lock: Invalid argument
* [@http://svn.boost.org/trac/boost/ticket/9308 #9308] future::async fails with terminate called throwing an exception when called with a lambda - clang-darwin-asan11
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
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 trunk regression test] to see the current state.
[*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,
* The experimental features of boost::future have some severe holes that make the program crash unexpectedly.
[*New Features:]
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Synchro: Update class barrier with a completion function.
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Synchro:Add externally locked streams.
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Synchro:Add concurrent queue.
* [@http://svn.boost.org/trac/boost/ticket/8515 #8515] Async: Add shared_future::then.
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Synchro: Update class barrier with a completion function
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Synchro: Add a latch class.
* [@http://svn.boost.org/trac/boost/ticket/8615 #8615] Async: Replace make_future/make_shared_future by make_ready_future.
* [@http://svn.boost.org/trac/boost/ticket/8627 #8627] Async: Add future<>::unwrap and unwrapping constructor.
* [@http://svn.boost.org/trac/boost/ticket/8627 #8627] Async: Add future<>::unwrap.
* [@http://svn.boost.org/trac/boost/ticket/8677 #8677] Async: Add future<>::get_or.
* [@http://svn.boost.org/trac/boost/ticket/8678 #8678] Async: Add future<>::fallback_to.
* [@http://svn.boost.org/trac/boost/ticket/8891 #8891] upgrade_to_unique_lock: missing mutex() function.
* [@http://svn.boost.org/trac/boost/ticket/8955 #8955] Request for more efficient way to get exception_ptr from future.
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/7461 #7461] detail::win32::ReleaseSemaphore may be called with count_to_release equal to 0
* [@http://svn.boost.org/trac/boost/ticket/8070 #8070] prefer GetTickCount64 over GetTickCount
* [@http://svn.boost.org/trac/boost/ticket/8768 #8768] win32 condition_variable::wait_until infinite wait in rare cases.
* [@http://svn.boost.org/trac/boost/ticket/8817 #8817] Boost Thread Windows CE _createthreadex handling breaks mingw w64.
* [@http://svn.boost.org/trac/boost/ticket/8943 #8943] Failed to compile code using boost::call_once with Intel C++ Composer XE 2013 on Windows.
* [@http://svn.boost.org/trac/boost/ticket/8931 #8931] Typos in external_locking reference.
* [@http://svn.boost.org/trac/boost/ticket/9029 #9029] Misprint in documentation.
* [@http://svn.boost.org/trac/boost/ticket/9037 #9037] gcc -Wshadow gives warnings in condition_variable{,_fwd}.hpp.
* [@http://svn.boost.org/trac/boost/ticket/9041 #9041] Boost.Thread DSO's may need to link with Boost.Atomic.
* [@http://svn.boost.org/trac/boost/ticket/9048 #9048] boost::scoped_thread useless ctor with variadic template arguments.
* [@http://svn.boost.org/trac/boost/ticket/9079 #9079] Condition variable will wait forever for some timepoint values (Win).
]
[heading Version 4.1.0 - boost 1.54]
@@ -564,14 +416,26 @@ The following features will be included in next releases.
* [@http://svn.boost.org/trac/boost/ticket/7589 #7589] Synchro: Add polymorphic lockables.
# Add some features based on C++ proposals, in particular
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Synchro: Add externally locked streams.
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Add externally locked streams
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Add concurrent queue
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Sync: Add a latch class
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Sync: Add a completion_latch class
* [@http://svn.boost.org/trac/boost/ticket/8513 #8513] Async: Add a basic thread_pool executor.
* [@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.
# Add some of the extension proposed in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3428.pdf A Standardized Representation of Asynchronous Operations] or extension to them, in particular
* [@http://svn.boost.org/trac/boost/ticket/7446 #7446] Async: Add when_any.
* [@http://svn.boost.org/trac/boost/ticket/7447 #7447] Async: Add when_all.
* [@http://svn.boost.org/trac/boost/ticket/7448 #7448] Async: Add async taking a scheduler parameter.
* [@http://svn.boost.org/trac/boost/ticket/8515 #8515] Async: Add shared_future::then.
* [@http://svn.boost.org/trac/boost/ticket/8516 #8516] Async: Add future/shared_future::then taking a scheduler as parameter.
* [@http://svn.boost.org/trac/boost/ticket/8627 #8627] Async: Add future<>::unwrap.
# And some additional extensions related to futures as:
* [@http://svn.boost.org/trac/boost/ticket/8677 #8677] Async: Add future<>::get_or.
* [@http://svn.boost.org/trac/boost/ticket/8678 #8678] Async: Add future<>::fallback_to.
* [@http://svn.boost.org/trac/boost/ticket/8517 #8517] Async: Add a variadic shared_future::then.

View File

@@ -1,5 +1,5 @@
[/
(C) Copyright 2011-2013 Vicente J. Botet Escriba.
(C) Copyright 2011-12 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
@@ -9,7 +9,7 @@
[section:cpp11 C++11 standard Thread library]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 - Standard for Programming Language C++]]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 standard]]
[table C++11 standard Conformance
@@ -73,23 +73,24 @@
[[30.6.9] [Class template packaged_task] [Yes] [-] [-]]
]
[/
[table Extension
[[Section] [Description] [Comments]]
[[30.3.1.5.x] [interrupt] [-]]
[[30.3.2.x] [Interruption] [-]]
[[30.3.2.y] [at_thread_exit] [-]]
[[30.4.3.x] [Generic locking algorithms begin/end] [-]]
[[30.x] [Barriers] [-]]
[[30.y] [Thread Local Storage] [-]]
[[30.z] [Class thread_group] [-]]
]
[/
[[30.x] [Thread Local Storage] [-]]
[[30.y] [Class thread_group] [-]]
]
[endsect]
[section:cxx14 C++14 standard Thread library - accepted changes]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.html Working Draft, Standard for Programming Language C++]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.html C++14 on-going standard]]
[table [@http://isocpp.org/files/papers/N3659.html N3659 Shared locking in C++ revision 2] Conformance
@@ -101,36 +102,12 @@
[endsect]
[section:cxx1y C++14 TS Extensions for Concurrency V1 ]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4107.html N4107-Extensions for Concurrency]]
[table Improvements to std::future<T> and related APIs]
[[Section] [Description] [Status] [Comments]]
[[2.1] [ - ] [ - ] [ - ]]
[[2.2] [Class template future] [Partial] [ - ]]
[[2.2] [then] [ Partial ] [ without implicit unwrapping #10550 and blocking #10551 ]]
[[2.2] [is_ready] [ Yes ] [ - ]]
[[2.3] [Class template shared_future] [Partial] [ - ]]
[[2.3] [then] [ Partial ] [ Without implicit unwrapping #10550 and blocking #10551 ]]
[[2.3] [is_ready] [ Yes ] [ - ]]
[[2.4] [Function template when_all] [Partial] [ interface not complete #10426 and blocking #10551 ]]
[[2.5] [Function template when_any] [Partial] [ interface not complete #10427 and blocking #10551 ]]
[[2.6] [Function template when_any_back] [No] [ #XXXX ]]
[[2.7] [Function template make_ready_future] [Yes] [ - ]]
]
[endsect]
[section:cxx1y C++1z TS Concurrency - On going proposals]
[section:cxx1y C++1y TS Concurrency - On going proposals]
[section:latch C++ Latches and Barriers]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3600 C++ Latches and Barriers]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3817.html N3817 C++ Latches and Barriers]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3659 C++ Latches and Barriers]]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3666.html N3659 C++ Latches and Barriers]]
[table C++ Latches and Barriers Conformance
[[Section] [Description] [Status] [Comments]]
@@ -147,84 +124,105 @@
[[Section] [Description] [Status] [Comments]]
[[X.1] [Conceptual interface] [Partial] [ The interface provided has some differences respect to this proposal. All the functions having a queue_op_status are not provided. No lock-free concrete classes ]]
[[X.1.1] [Basic Operations] [Partial] [ - ]]
[[X.1.1.1] [push] [yes] [ renamed push_back. ]]
[[X.1.1.2] [value_pop] [no] [ renamed pull_front with two flavors. ]]
[[X.1.1.1] [push] [yes] [ - ]]
[[X.1.1.2] [value_pop] [no] [ renamed pull with two flavors + a ptr_pull that returns a sharted_ptr<>. ]]
[[X.1.2] [Non-waiting operations] [ - ] [ - ]]
[[X.1.2.1] [try_push] [yes] [ renamed try_push_back ]]
[[X.1.2.2] [try_pop] [yes] [ renamed try_pull_back ]]
[[X.1.2.1] [try_push] [Partial] [ return bool instead ]]
[[X.1.2.2] [try_pop] [Partial] [ renamed try_pull, returns null ]]
[[X.1.3] [Non-blocking operations] [ - ] [ - ]]
[[X.1.3.1] [nonblocking_push] [Yes] [ renamed nonblocking_push_back ]]
[[X.1.3.2] [nonblocking_pop] [Yes] [ renamed nonblocking_pull_front ]]
[[X.1.3.1] [nonblocking_push] [Partial] [ renamed try_push(no_block, ]]
[[X.1.3.2] [nonblocking_pop] [Partial] [ renamed try_pop(no_block, ]]
[[X.1.4] [Push-front operations] [No] [ - ]]
[[X.1.5] [Closed queues] [Partial] [ - ]]
[[X.1.5.1] [close] [Yes] [ - ]]
[[X.1.5.2] [is_closed] [Yes] [ renamed closed ]]
[[X.1.5.3] [wait_push] [Yes] [ renamed wait_push_back ]]
[[X.1.5.4] [wait_pop] [Yes] [ renamed wait_pull_front ]]
[[X.1.5.2] [is_closed] [Yes] [ - ]]
[[X.1.5.3] [wait_push] [Partial] [ - ]]
[[X.1.5.4] [wait_pop] [Partial] [ - ]]
[[X.1.5.5] [wait_push_front] [no] [ - ]]
[[X.1.5.6] [wait_pop_back] [no] [ - ]]
[[X.1.5.6] [wait_pop] [Partial] [ - ]]
[[X.1.5.6] [open] [no] [ - ]]
[[X.1.6] [Empty and Full Queues] [Yes] [ - ]]
[[X.1.6.1] [is_empty] [Yes] [ - ]]
[[X.1.6.2] [is_full] [Yes] [ Added capacity ]]
[[X.1.7] [Queue Names] [No] [ Not considered a must for the time been. ]]
[[X.1.7] [Queue Names] [No] [ Not considere a must for the time been. ]]
[[X.1.8] [Element Type Requirements] [Yes?] [ - ]]
[[X.1.9] [Exception Handling] [Yes?] [ - ]]
[[X.1.10] [Queue Ordering] [Yes?] [ - ]]
[[X.1.11] [Lock-Free Implementations] [No] [ waiting to stabilize the lock-based interface. Will use Boost.LockFree once it is Boost.Move aware. ]]
[[X.1.11] [Lock-Free Implementations] [No] [ waiting to stabilize the lock-based interface. Will use Boost.LockFree once it is Move aware. ]]
[[X.2] [Concrete queues] [Partial] [ - ]]
[[X.2.1] [Locking Buffer Queue] [Partial] [ classes sync_queue and a sync_bounded_queue. ]]
[[X.2.1] [Lock-Free Buffer Queue] [No] [ waiting to stabilize the lock-based interface. Will use Boost.LockFree once it is Boost.Move aware. ]]
[[X.2.1] [Lock-Free Buffer Queue] [No] [ - ]]
[[X.3] [Additional Conceptual Tools] [No] [ - ]]
[[X.3.1] [Fronts and Backs] [No] [ - ]]
[[X.3.2] [Streaming Iterators] [No] [ - ]]
[[X.3.2] [Streaming Iterators] [No] [ - ]]
[[X.3.3] [Storage Iterators] [No] [ - ]]
[[X.3.4] [Binary Interfaces] [No] [ - ]]
[[X.3.4] [Managed Indirection] [No] [ - ]]
]
[endsect]
[section:executors Asynchronous Executors]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3785.pdf N3785 Executors and Schedulers]]
While Boost.Thread implementation of executors would not use dynamic polymorphism, it is worth comparing with the current trend on the standard.
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3378.pdf N3378 A preliminary proposal for work executors]]
[table Asynchronous Executors
[[Section] [Description] [Status] [Comments]]
[[V.1.1] [Class executor] [Yes] [ - ]]
[[V.1.1] [add] [Yes] [ renamed with a function template submit ]]
[[V.1.1] [num_of_pendin_closures] [No] [ ]]
[[V.1.2] [Class sceduled_executor] [No] [ - ]]
[[V.1.2] [add_at] [No] [ renamed with a function template submit_at ]]
[[V.1.2] [add_after] [No] [ renamed with a function template submit_after ]]
[[V.2] [Concrete executor classes] [No] [ - ]]
[[V.2.1] [thread_pool] [Yes] [ static version Basic_thread_pool, dynamic one execduler_adaptor<basic_thread_pool> ]]
[[V.2.2] [serial_executor] [yes] [ - ]]
[[V.2.3] [loop_executor] [Yes] [ static version loop_scheduler, dynamic one execduler_adaptor<loop_scheduler> ]]
[[V.2.4] [inline_executor] [Yes] [ static version inline_executor, dynamic one execduler_adaptor<inline_executor> ]]
[[V.2.5] [thread_executor] [Yes] [ static version thread_executor, dynamic one execduler_adaptor<thread_executor> ]]
]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3784.pdf N3784-Improvements to `std::future<T> and Related APIs]]
[table `async, future/shared_future::then`and Executors
[[Section] [Description] [Status] [Comments]]
[[30.6.6] [`future<T>::then`] [Yes] [ ]]
[[30.6.7] [`shared_future<T>::then`] [Yes] [ ]]
[[30.6.8] [`async`] [Yes] [ - ]]
[[30.X.1] [Class executor] [No] [ - ]]
[[30.X.1.1] [add] [No] [ renamed with a function template submit ]]
[[30.X.1.1] [num_of_pendin_closures] [??] [ ]]
[[30.X.2] [Class sceduled_executor] [No] [ - ]]
[[30.X.2.1] [add_at] [No] [ renamed with a function template submit_at ]]
[[30.X.2.2] [add_after] [No] [ renamed with a function template submit_after ]]
[[30.X.3] [Executor utilities functions] [No] [ - ]]
[[30.X.3.1] [default_executor] [No] [ - ]]
[[30.X.3.2] [set_default_executor] [No] [ - ]]
[[30.X.3.3] [singleton_inline_executor] [No] [ - ]]
[[30.X.4] [Concrete executor classes] [No] [ - ]]
[[30.X.4.1] [loop_executor] [No] [ - ]]
[[30.X.4.1] [serial_executor] [No] [ - ]]
[[30.X.4.1] [thread_pool] [No] [ #8513 ]]
]
[endsect]
[section:async A Standardized Representation of Asynchronous Operations]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3558.pdf N3558 A Standardized Representation of Asynchronous Operations]]
[note These functions are based on the [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3634.pdf [*N3634 - Improvements to std::future<T> and related APIs]] C++1y proposal by N. Gustafsson, A. Laksberg, H. Sutter, S. Mithani.]
[table Improvements to std::future<T> and related APIs]
[[Section] [Description] [Status] [Comments]]
[[30.6.6] [Class template future] [Partial] [ - ]]
[[30.6.6.1] [then] [Partial] [ executor interface missing #8516 ]]
[[30.6.6.2] [unwrap] [Yes] [ - ]]
[[30.6.6.3] [ready] [Partial] [ is_ready ]]
[[30.6.7] [Class template shared_future] [Partial] [ - ]]
[[30.6.7.1] [then] [Yes] [ executor interface missing #8516 ]]
[[30.6.7.2] [unwrap] [No] [ #XXXX ]]
[[30.6.7.3] [ready] [Partial] [ is_ready ]]
[[30.6.X] [Function template when_any] [No] [ #7446 ]]
[[30.6.X] [Function template when_all] [No] [ #7447 ]]
[[30.6.X] [Function template make_ready_future] [Yes] [ - ]]
[[30.6.8] [Function template async ] [No] [ executor interface missing #7448 ]]
]
[endsect]
[section:stream_mutex C++ Stream Mutexes - C++ Stream Guards]
While Boost.Thread implementation of stream mutexes differ in the approach, it is worth comparing with the current trend on the standard.
[note These functions are based on [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3535.html [*N3535 - C++ Stream Mutexes]] by Lawrence Crowl.]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3535.html N3535 - C++ Stream Mutexes]. This has been replaced already by N3678 - C++ Stream Guards.]
[note This proposal has been replaced already by [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html N3678 - C++ Stream Guards], which has been replaced by [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html N3665 - Uninterleaved String Output Streaming] and [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html N3750 - C++ Ostream Buffers]]
[table C++ Stream Mutexes Conformance
[table C++ C++ Stream MutexesConformance
[[Section] [Description] [Status] [Comments]]
[[X.1] [Class template stream_mutex] [Partial] [ Renamed externally_locked_stream<> ]]
[[X.2.1] [constructor] [Partial] [ externally_locked_stream needs a mutex in addition as argument. ]]
[[X.1] [Class template stream_mutex] [Partial] [ externally_locked_stream<> ]]
[[X.2.1] [constructor] [Partial] [ externally_locked_stream needs a mutex in addition as argumement. ]]
[[X.2.2] [lock] [yes] [ - ]]
[[X.2.3] [unlock] [yes] [ - ]]
[[X.2.4] [try_lock] [yes] [ - ]]
@@ -234,10 +232,12 @@ While Boost.Thread implementation of stream mutexes differ in the approach, it i
[[X.2.1] [stream_guard] [Yes] [ - ]]
[[X.2.2] [~stream_guard] [Yes] [ - ]]
[[X.2.3] [bypass] [Yes] [ - ]]
[[X.3] [Stream Operators] [Yes] [-]]
[[X.4] [Predefined Objects] [No] [-]]
[[X.3] [Stream Operators] [Yes] [.]]
[[X.4] [Predefined Objects] [No] [.]]
]
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html N3678 - C++ Stream Guards]]
[endsect]

View File

@@ -78,28 +78,20 @@ When `BOOST_THREAD_VERSION>3` && defined BOOST_THREAD_PLATFORM_PTHREAD define `
[endsect]
[section:move Boost.Atomic]
Boost.Thread uses by default an Boost.Atomic in POSIX platforms to implement call_once..
[section:thread_eq `boost::thread::oprator==` deprecated]
Define `BOOST_THREAD_USES_ATOMIC ` if you want to use Boost.Atomic.
Define `BOOST_THREAD_DONT_USE_ATOMIC ` if you don't want to use Boost.Atomic or if it is not supported in your platform.
The following nested typedefs are deprecated:
[endsect]
[section:thread_eq `boost::thread::operator==` deprecated]
The following operators are deprecated:
* `boost::thread::operator==`
* `boost::thread::operator!=`
* `boost::thread::oprator==`
* `boost::thread::oprator!=`
When `BOOST_THREAD_PROVIDES_THREAD_EQ` is defined Boost.Thread provides these deprecated feature.
Use instead
* `boost::thread::id::operator==`
* `boost::thread::id::operator!=`
* `boost::thread::id::oprator==`
* `boost::thread::id::oprator!=`
[warning This is a breaking change respect to version 1.x.]
@@ -304,12 +296,8 @@ When `BOOST_THREAD_VERSION>=4` define `BOOST_THREAD_DONT_PROVIDE_SIGNATURE_PACKA
C++11 thread constructor accep a variable number of rvalue argumentshas. When `BOOST_THREAD_PROVIDES_VARIADIC_THREAD ` is defined Boost.Thread provides this C++ feature if the following are not defined
* BOOST_NO_SFINAE_EXPR
* BOOST_NO_CXX11_VARIADIC_TEMPLATES
* BOOST_NO_CXX11_DECLTYPE
* BOOST_NO_CXX11_DECLTYPE_N3276
* BOOST_NO_CXX11_RVALUE_REFERENCES
* BOOST_NO_CXX11_TRAILING_RESULT_TYPES
* BOOST_NO_CXX11_RVALUE_REFERENCES
* BOOST_NO_CXX11_HDR_TUPLE

View File

@@ -1,5 +1,5 @@
[/
/ Copyright (c) 2008,2012,2014 Vicente J. Botet Escriba
/ Copyright (c) 2008,2012 Vicente J. Botet Escriba
/
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -8,7 +8,7 @@
[section External Locking -- `strict_lock` and `externally_locked` classes]
[note This tutorial is an adaptation of the paper by Andrei Alexandrescu "Multithreading and the C++ Type System"
[note This tutorial is an adaptation of the paper of Andrei Alexandrescu "Multithreading and the C++ Type System"
to the Boost library.]
[/
@@ -163,7 +163,7 @@ Obviously, the caller-ensured locking approach has a safety problem. BankAccount
To conclude, if in designing a multi-threaded class you settle on internal locking, you expose yourself to inefficiency or deadlocks. On the other hand, if you rely on caller-provided locking, you make your class error-prone and difficult to use. Finally, external locking completely avoids the issue by leaving it all to the client code.
[endsect]
]
[section Locks as permits]
[section Locks as Permits]
So what to do? Ideally, the BankAccount class should do the following:
@@ -182,9 +182,9 @@ For now, let's make a couple of enhancements to the `lock_guard` class template
We'll call the enhanced version `strict_lock`. Essentially, a `strict_lock`'s role is only to live on the stack as an automatic variable.
`strict_lock` must adhere to a non-copy and non-alias policy.
`strict_lock` disables copying by making the copy constructor and the assignment operator private.
[/
While we're at it, let's disable operator new and operator delete.
[/
`strict_lock` are not intended to be allocated on the heap.
`strict_lock` avoids aliasing by using a slightly less orthodox and less well-known technique: disable address taking.
]
@@ -217,7 +217,7 @@ Silence can be sometimes louder than words-what's forbidden to do with a `strict
* You can create a `strict_lock<T>` only starting from a valid T object. Notice that there is no other way you can create a `strict_lock<T>`.
BankAccount myAccount("John Doe", "123-45-6789");
strict_lock<BankAccount> myLock(myAccount); // ok
strict_locerk<BankAccount> myLock(myAccount); // ok
* You cannot copy `strict_lock`s to one another. In particular, you cannot pass `strict_lock`s by value to functions or have them returned by functions:
@@ -293,7 +293,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n
}
};
Now, if you want the benefit of internal locking, you simply call `Deposit(int)` and `Withdraw(int)`. If you want to use external locking, you lock the object by constructing a `strict_lock<BankAccount>` and then you call `Deposit(int, strict_lock<BankAccount>&)` and `Withdraw(int, strict_lock<BankAccount>&)`. For example, here's the `ATMWithdrawal` function implemented correctly:
Now, if you want the benefit of internal locking, you simply call Deposit(int) and Withdraw(int). If you want to use external locking, you lock the object by constructing a `strict_lock<BankAccount>` and then you call `Deposit(int, strict_lock<BankAccount>&)` and `Withdraw(int, strict_lock<BankAccount>&)`. For example, here's the `ATMWithdrawal` function implemented correctly:
void ATMWithdrawal(BankAccount& acct, int sum) {
strict_lock<BankAccount> guard(acct);
@@ -453,7 +453,7 @@ We achieved two important goals. First, the declaration of `checkingAcct_` and `
[section Allowing other strict locks]
Now imagine that the AccountManager function needs to take a `unique_lock` in order to reduce the critical regions. And at some time it needs to access to the `checkingAcct_`. As `unique_lock` is not a strict lock the following code doesn't compile:
Now imagine that the AccountManager function needs to take a `unique_lock` in order to reduce the critical regions. And at some time it needs to access to the `checkingAcct_`. As `unique_lock` is not a strict lock the following code doesn't compiles:
void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
unique_lock<AccountManager> guard(*this, defer_lock);
@@ -465,10 +465,10 @@ Now imagine that the AccountManager function needs to take a `unique_lock` in or
do_something_else();
}
We need a way to transfer the ownership from the `unique_lock` to a `strict_lock` during the time we are working with `savingsAcct_` and then restore the ownership on `unique_lock`.
We need a way to transfer the ownership from the `unique_lock` to a `strict_lock` the time we are working with `savingsAcct_` and then restore the ownership on `unique_lock`.
void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
unique_lock<AccountManager> guard1(*this, defer_lock);
unique_lock<AccountManager> guard(*this, defer_lock);
if (some_condition()) {
guard1.lock();
}
@@ -480,9 +480,9 @@ We need a way to transfer the ownership from the `unique_lock` to a `strict_lock
guard1.unlock();
}
In order to make this code compilable we need to store either a Lockable or a `unique_lock<Lockable>` reference depending on the constructor. We also need to store which kind of reference we have stored, and in the destructor call either to the Lockable `unlock` or restore the ownership.
In order to make this code compilable we need to store either a Lockable or a `unique_lock<Lockable>` reference depending on the constructor. Store which kind of reference we have stored,and in the destructor call either to the Lockable `unlock` or restore the ownership.
This seems too complicated to me. Another possibility is to define a nested strict lock class. The drawback is that instead of having only one strict lock we have two and we need either to duplicate every function taking a `strict_lock` or make these function templates. The problem with template functions is that we don't profit anymore of the C++ type system. We must add some static metafunction that checks that the Locker parameter is a strict lock. The problem is that we can not really check this or can we?. The `is_strict_lock` metafunction must be specialized by the strict lock developer. We need to believe it "sur parole". The advantage is that now we can manage with more than two strict locks without changing our code. This is really nice.
This seams too complicated to me. Another possibility is to define a nested strict lock class. The drawback is that instead of having only one strict lock we have two and we need either to duplicate every function taking a `strict_lock` or make these function templates functions. The problem with template functions is that we don't profit anymore of the C++ type system. We must add some static metafunction that check that the Locker parameter is a strict lock. The problem is that we can not really check this or can we?. The `is_strict_lock` metafunction must be specialized by the strict lock developer. We need to belive it "sur parole". The advantage is that now we can manage with more than two strict locks without changing our code. Ths is really nice.
Now we need to state that both classes are `strict_lock`s.
@@ -496,9 +496,9 @@ Now we need to state that both classes are `strict_lock`s.
struct is_strict_lock<nested_strict_lock<Locker> > : mpl::true_ {}
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.
Well let me show how 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 he will restore the ownership. Note also that the Locker needs to have already a reference to the mutex otherwise an exception is thrown and the use of the `lock_traits`.
template <typename Locker >
class nested_strict_lock

File diff suppressed because it is too large Load Diff

View File

@@ -293,7 +293,7 @@ that is to allow multiple concurrent get operations.
[heading Multiple get]
The second `get()` call in the following example is undefined.
The second `get()` call in the following example future
void bad_second_use( type arg ) {
@@ -308,7 +308,7 @@ The second `get()` call in the following example is undefined.
use3( ftr.get() ); // second use is undefined
}
Using a `shared_future` solves the issue
Using a `shared_mutex` solves the issue
void good_second_use( type arg ) {
@@ -341,7 +341,7 @@ Here `share()` could be used to simplify the code
use3( ftr.get() ); // second use is defined
}
[heading Writing on get()]
[heading Writting on get()]
The user can either read or write the future avariable.
@@ -369,17 +369,17 @@ and a `shared_future` that can be shared between several threads, but there were
[endsect]
[section:make_ready_future Making immediate futures easier]
[section:make_future Making immediate futures easier]
Some functions may know the value at the point of construction. In these cases the value is immediately available,
but needs to be returned as a future or shared_future. By using make_ready_future a future
but needs to be returned as a future or shared_future. By using make_future (make_shared_future) a future (shared_future)
can be created which holds a pre-computed result in its shared state.
Without these features it is non-trivial to create a future directly from a value.
First a promise must be created, then the promise is set, and lastly the future is retrieved from the promise.
This can now be done with one operation.
[heading make_ready_future]
[heading make_future / make_shared_future]
This function creates a future for a given value. If no value is given then a future<void> is returned.
This function is primarily useful in cases where sometimes, the return value is immediately available, but sometimes
@@ -389,14 +389,16 @@ the function must return an eventual value represented as a future.
boost::future<int> compute(int x)
{
if (x == 0) return boost::make_ready_future(0);
if (x < 0) return boost::make_ready_future<int>(std::logic_error("Error"));
if (x == 0) return boost::make_future(0);
if (x < 0) return boost::make_future(-1);
boost::future<int> f1 = boost::async([]() { return x+1; });
return f1;
}
There are two variations of this function. The first takes a value of any type, and returns a future of that type.
The input value is passed to the shared state of the returned future. The second version takes no input and returns a future<void>.
The input value is passed to the shared state of the returned future. The second version takes no input and returns a future<void>.
make_shared_future has the same functionality as make_future, except has a return type of shared_future.
[endsect]
@@ -404,16 +406,16 @@ The input value is passed to the shared state of the returned future. The second
In asynchronous programming, it is very common for one asynchronous operation, on completion, to invoke a second
operation and pass data to it. The current C++ standard does not allow one to register a continuation to a future.
With `.then`, instead of waiting for the result, a continuation is "attached" to the asynchronous operation, which is
invoked when the result is ready. Continuations registered using the `.then` function will help to avoid blocking waits
With .then, instead of waiting for the result, a continuation is "attached" to the asynchronous operation, which is
invoked when the result is ready. Continuations registered using the .then function will help to avoid blocking waits
or wasting threads on polling, greatly improving the responsiveness and scalability of an application.
`future.then()` provides the ability to sequentially compose two futures by declaring one to be the continuation of another.
With `.then()` the antecedent future is ready (has a value or exception stored in the shared state) before the continuation
future.then provides the ability to sequentially compose two futures by declaring one to be the continuation of another.
With .then the antecedent future is ready (has a value or exception stored in the shared state) before the continuation
starts as instructed by the lambda function.
In the example below the `future<string>` `f2` is registered to be a continuation of `future<int>` `f1` using the `.then()` member
function. This operation takes a lambda function which describes how `f2` should proceed after `f1` is ready.
In the example below the future<int> f2 is registered to be a continuation of future<int> f1 using the .then member
function. This operation takes a lambda function which describes how f2 should proceed after f1 is ready.
#include <boost/thread/future.hpp>
@@ -426,7 +428,7 @@ function. This operation takes a lambda function which describes how `f2` should
One key feature of this function is the ability to chain multiple asynchronous operations. In asynchronous programming,
it's common to define a sequence of operations, in which each continuation executes only when the previous one completes.
In some cases, the antecedent future produces a value that the continuation accepts as input. By using `future.then()`,
In some cases, the antecedent future produces a value that the continuation accepts as input. By using future.then,
creating a chain of continuations becomes straightforward and intuitive:
myFuture.then(...).then(...).then(...).
@@ -439,20 +441,21 @@ Some points to note are:
Input Parameters:
* Lambda function: One option which can be considered is to take two functions, one for
success and one for error handling. However this option has not been retained for the moment.
The lambda function takes a future as its input which carries the exception
* Lambda function2: One option which was considered was to follow JavaScript's approach and take two functions, one for
success and one for error handling. However this option is not viable in C++ as there is no single base type for
exceptions as there is in JavaScript. The lambda function takes a future as its input which carries the exception
through. This makes propagating exceptions straightforward. This approach also simplifies the chaining of continuations.
* Scheduler: Providing an overload to `.then`, to take a scheduler reference places great flexibility over the execution
* Scheduler: Providing an overload to .then, to take a scheduler reference places great flexibility over the execution
of the future in the programmer's hand. As described above, often taking a launch policy is not sufficient for powerful
asynchronous operations. The lifetime of the scheduler must outlive the continuation.
* Launch policy: if the additional flexibility that the scheduler provides is not required.
Return values: The decision to return a future was based primarily on the ability to chain multiple continuations using
`.then()`. This benefit of composability gives the programmer incredible control and flexibility over their code. Returning
a `future` object rather than a `shared_future` is also a much cheaper operation thereby improving performance. A
`shared_future` object is not necessary to take advantage of the chaining feature. It is also easy to go from a `future`
to a `shared_future` when needed using future::share().
.then. This benefit of composability gives the programmer incredible control and flexibility over their code. Returning
a future object rather than a shared_future is also a much cheaper operation thereby improving performance. A
shared_future object is not necessary to take advantage of the chaining feature. It is also easy to go from a future
to a shared_future when needed using future::share().
[endsect]

View File

@@ -1,5 +1,5 @@
[/
/ Copyright (c) 2008,2014 Vicente J. Botet Escriba
/ Copyright (c) 2008 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)
@@ -14,7 +14,7 @@ Consider, for example, modeling a bank account class that supports simultaneous
From here a component is a model of the `Callable` concept.
I C++11 (Boost) concurrent execution of a component is obtained by means of the `std::thread`(`boost::thread`):
On C++11 (Boost) concurrent execution of a component is obtained by means of the `std::thread`(`boost::thread`):
boost::thread thread1(S);
@@ -53,12 +53,12 @@ The following example includes a bank account of a person (Joe) and two componen
return 0;
}
From time to time, the `bankAgent` will deposit $500 in `JoesAccount`. `Joe` will similarly withdraw $100 from his account. These sentences describe that the `bankAgent` and `Joe` are executed concurrently.
From time to time, the `bankAgent` will deposit $500 in `JoesAccount`. Joe will similarly withdraw $100 from his account. These sentences describe that the bankAgent and Joe are executed concurrently.
[endsect]
[section Internal locking]
The above example works well as long as the components `bankAgent` and `Joe` doesn't access `JoesAccount` at the same time. There is, however, no guarantee that this will not happen. We may use a mutex to guarantee exclusive access to each bank.
The above example works well as long as the bankAgent and Joe doesn't access JoesAccount at the same time. There is, however, no guarantee that this will not happen. We may use a mutex to guarantee exclusive access to each bank.
class BankAccount {
boost::mutex mtx_;
@@ -82,11 +82,11 @@ The above example works well as long as the components `bankAgent` and `Joe` doe
}
};
Execution of the `Deposit` and `Withdraw` operations will no longer be able to make simultaneous access to balance.
Execution of the Deposit and Withdraw operations will no longer be able to make simultaneous access to balance.
A mutex is a simple and basic mechanism for obtaining synchronization. In the above example it is relatively easy to be convinced that the synchronization works correctly (in the absence of exception). In a system with several concurrent objects and several shared objects, it may be difficult to describe synchronization by means of mutexes. Programs that make heavy use of mutexes may be difficult to read and write. Instead, we shall introduce a number of generic classes for handling more complicated forms of synchronization and communication.
Mutex is a simple and basic mechanism for obtaining synchronization. In the above example it is relatively easy to be convinced that the synchronization works correctly (in the absence of exception). In a system with several concurrent objects and several shared objects, it may be difficult to describe synchronization by means of mutexes. Programs that make heavy use of mutexes may be difficult to read and write. Instead, we shall introduce a number of generic classes for handling more complicated forms of synchronization and communication.
With the RAII idiom we can simplify a lot this using the scoped locks. In the code below, guard's constructor locks the passed-in object `mtx_`, and guard's destructor unlocks `mtx_`.
With the RAII idiom we can simplify a lot this using the scoped locks. In the code below, guard's constructor locks the passed-in object this, and guard's destructor unlocks this.
class BankAccount {
boost::mutex mtx_; // explicit mutex declaration
@@ -135,10 +135,10 @@ In an attempt to solve this problem, let's lock the account from the outside dur
acct.Withdraw(2);
}
Notice that the code above doesn't compile, the `mtx_` field is private.
Notice that the code above doesn't compiles, the `mtx_` field is private.
We have two possibilities:
* make `mtx_` public which seems odd
* make `mtx_` public which seams odd
* make the `BankAccount` lockable by adding the lock/unlock functions
We can add these functions explicitly

View File

@@ -7,19 +7,13 @@
[section:latches Latches -- EXPERIMENTAL]
[////////////////////]
[section Introdcution]
Latches are a thread co-ordination mechanism that allow one or more threads to block until one or more threads have reached a point.
[/
An individual latch is a reusable object; once the operation has been completed, the threads can re-use the same barrier. It is thus useful for managing repeated tasks handled by multiple threads.
Latches are a thread co-ordination mechanism that allow one or more threads to block until one or more threads have reached a point. An individual latch is a reusable object; once the operation has been completed, the threads can re-use the same barrier. It is thus useful for managing repeated tasks handled by multiple threads.
A completion latch is like a latch that allows to associate a completion function which will be called once the internal counter reaches the value 0 and all the consumer threads have taken care of the notification.
]
[endsect]
[////////////////]
[section Examples]
Sample use cases for the latch include:
@@ -44,6 +38,7 @@ An example of the first use case would be as follows:
An example of the second use case is shown below. We need to load data and then process it using a number of threads. Loading the data is I/O bound, whereas starting threads and creating data structures is CPU bound. By running these in parallel, throughput can be increased.
void DoWork() {
latch start_latch(1);
vector<thread*> workers;
@@ -62,7 +57,6 @@ An example of the second use case is shown below. We need to load data and then
start_latch.count_down();
}
[/
The completion latches can be used to co-ordinate also a set of threads carrying out a repeated task. The number of threads can be adjusted dynamically to respond to changing requirements.
In the example below, a number of threads are performing a multi-stage task. Some tasks may require fewer steps than others, meaning that some threads may finish before others. We reduce the number of threads waiting on the latch when this happens.
@@ -102,10 +96,8 @@ In the example below, a number of threads are performing a multi-stage task. Som
GetNextStage(tasks);
}
}
]
[endsect]
[///////////////////////////]
[section:latch Class `latch`]
#include <boost/thread/latch.hpp>
@@ -127,20 +119,16 @@ In the example below, a number of threads are performing a multi-stage task. Som
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time);
void count_down();
void count_down_and_wait();
void reset(std::size_t count);
};
[/
void reset(std::size_t count);
]
A latch maintains an internal counter that is initialized when the latch is created. One or more threads may block waiting until the counter is decremented to 0.
Instances of __latch__ are not copyable or movable.
[///////////////////]
[section Constructor `latch(std::size_t)`]
[section Constructor]
latch(std::size_t count);
@@ -148,15 +136,14 @@ Instances of __latch__ are not copyable or movable.
[[Effects:] [Construct a latch with is initial value for the internal counter.]]
[[Note:] [The counter could be zero.]]
[[Note:] [The counter could be zero and reset later.]]
[[Throws:] [Nothing.]]
]
[endsect]
[//////////////////]
[section Destructor `~latch()`]
[section Destructor]
~latch();
@@ -171,8 +158,7 @@ Instances of __latch__ are not copyable or movable.
]
[endsect]
[/////////////////////////////////////]
[section:wait Member Function `wait()`]
[section:wait Member function `wait()`]
void wait();
@@ -192,8 +178,8 @@ are unblocked. ]]
]
[endsect]
[/////////////////////////////////////////////]
[section:try_wait Member Function `try_wait()`]
[section:try_wait Member function `try_wait()`]
bool try_wait();
@@ -208,8 +194,8 @@ are unblocked. ]]
]
[endsect]
[//////////////////////////////////////////////]
[section:wait_for Member Function `wait_for() `]
[section:wait_for Member function `wait_for() `]
template <class Rep, class Period>
cv_status wait_for(const chrono::duration<Rep, Period>& rel_time);
@@ -230,8 +216,7 @@ are unblocked. ]]
]
[endsect]
[/////////////////////////////////////////////////]
[section:wait_until Member Function `wait_until()`]
[section:wait_until Member function `wait_until()`]
template <class lock_type, class Clock, class Duration>
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time);
@@ -252,8 +237,7 @@ are unblocked. ]]
]
[endsect]
[/////////////////////////////////////////////////]
[section:count_down Member Function `count_down()`]
[section:count_down Member function `count_down()`]
void count_down();
@@ -272,8 +256,7 @@ are unblocked. ]]
]
[endsect]
[///////////////////////////////////////////////////////////////////]
[section:count_down_and_wait Member Function `count_down_and_wait()`]
[section:count_down_and_wait Member function `count_down_and_wait()`]
void count_down_and_wait();
@@ -292,9 +275,8 @@ are unblocked. ]]
]
[endsect]
[///////////////////////////////////////]
[
[section:reset Member Function `reset()`]
[section:reset Member function `reset()`]
reset( size_t );
@@ -311,11 +293,9 @@ are unblocked. ]]
]
[endsect]
]
[endsect] [/ latch]
[/
[//////////////////////////////////////////////////]
[section:completion_latch Class `completion_latch `]
#include <boost/thread/completion_latch.hpp>
@@ -353,7 +333,6 @@ Instances of completion_latch are not copyable or movable.
Only the additional functions are documented.
[/////////////////////]
[section:c Constructor]
completion_latch(std::size_t count);
@@ -369,7 +348,6 @@ Only the additional functions are documented.
]
[endsect]
[///////////////////////////////////////////////]
[section:cf Constructor with completion function]
template <typename F>
@@ -390,8 +368,7 @@ Only the additional functions are documented.
]
[endsect]
[///////////////////////////////////]
[section:then Member Function `then`]
[section:then Member function `then`]
template <typename F>
completion_function then(F&& funct);
@@ -414,6 +391,6 @@ Only the additional functions are documented.
[endsect]
[endsect] [/ completion_latch]
]
[endsect] [/ Latches]

View File

@@ -298,6 +298,8 @@ reached. If the specified time has already passed, behaves as __try_lock_ref__.]
[warning
DEPRECATED since 4.00. The following expressions were required on version 2, but are now deprecated.
Available only up to Boost 1.58.
Use instead __try_lock_for, __try_lock_until.
]
@@ -458,6 +460,8 @@ ownership of `m`.]]
[warning
DEPRECATED since 3.00. The following expressions were required on version 2, but are now deprecated.
Available only up to Boost 1.56.
Use instead __try_lock_shared_for, __try_lock_shared_until.
]
@@ -1115,44 +1119,6 @@ object passed to the constructor.]]
]
[endsect]
[endsect]
[section:with_lock_guard With Lock Guard]
// #include <boost/thread/with_lock_guard.hpp>
namespace boost
{
template <class Lockable, class Function, class... Args>
auto with_lock_guard(Lockable& m, Function&& func, Args&&... args) -> decltype(func(boost::forward<Args>(args)...));
}
[section:with_lock_guard Non Member Function `with_lock_guard`]
template <class Lockable, class Function, class... Args>
auto with_lock_guard(
Lockable& m,
Function&& func,
Args&&... args
) -> decltype(func(boost::forward<Args>(args)...));
[variablelist
[[Precondition:] [`m` must be in unlocked state]]
[[Effects:] [call `func` in scope locked by `m`]]
[[Returns:] [Result of `func(args...)` call]]
[[Throws:] [Any exception thrown by the call to `m.lock` and `func(args...)`]]
[[Postcondition:] [`m` is in unlocked state]]
[[Limitations:] [Without c++11 variadic templates support number of arguments is limited to `4`]]
[[] [Without rvalue references support calling class method with `boost::bind` must be const]]
[[] [For correct work with lambda macro `BOOST_RESULT_OF_USE_DECLTYPE` may be needed to define]]
]
[endsect]
[endsect]
@@ -1307,7 +1273,7 @@ The following classes are models of `StrictLock`:
explicit operator bool() const noexcept;
bool owns_lock() const noexcept;
mutex_type* mutex() const noexcept;
Lockable* mutex() const noexcept;
#if defined BOOST_THREAD_USE_DATE_TIME || defined BOOST_THREAD_DONT_USE_CHRONO
unique_lock(Lockable& m_,system_time const& target_time);
@@ -1569,7 +1535,7 @@ object associated with `*this`.]]
[endsect]
[section:mutex `Lockable* mutex() const noexcept`]
[section:mutex `Lockable* mutex() const`]
[variablelist
@@ -1941,7 +1907,7 @@ state (including the destructor) must be called by the same thread that acquired
[endsect]
[section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock` -- EXTENSION]
[section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock`]
// #include <boost/thread/locks.hpp>
// #include <boost/thread/lock_types.hpp>
@@ -1964,8 +1930,6 @@ state (including the destructor) must be called by the same thread that acquired
explicit operator bool() const;
bool owns_lock() const;
mutex_type* mutex() const;
};
__upgrade_to_unique_lock__ allows for a temporary upgrade of an __upgrade_lock__ to exclusive ownership. When constructed with a
@@ -1975,7 +1939,7 @@ __lockable_concept_type__ is downgraded back to ['upgrade ownership].
[endsect]
[section:scoped_try_lock Mutex-specific class `scoped_try_lock` -- DEPRECATED]
[section:scoped_try_lock Mutex-specific class `scoped_try_lock`]
class MutexType::scoped_try_lock
{

View File

@@ -34,10 +34,9 @@ Scoped Threads are wrappers around a thread that allows the user to state what t
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.
boost::strict_scoped_thread<> t1((boost::thread(f)));
//t1.detach(); // compile fails
boost::scoped_thread<> t2((boost::thread(f)));
t2.detach();
boost::strict_scoped_thread<> t1((boost::thread(F)));
boost::strict_scoped_thread<> t2((boost::thread(F)));
t2.interrupt();
[endsect]
@@ -191,7 +190,7 @@ This wrapper can be used to join the thread before destroying it seems a natural
explicit scoped_thread(thread&& th) noexcept;
template <typename F&&, typename ...Args>
explicit scoped_thread(F&&, Args&&...);
explicit strict_scoped_thread(F&&, Args&&...);
~scoped_thread();
@@ -217,7 +216,6 @@ This wrapper can be used to join the thread before destroying it seems a natural
void detach();
static unsigned hardware_concurrency() noexcept;
static unsigned physical_concurrency() noexcept;
typedef thread::native_handle_type native_handle_type;
native_handle_type native_handle();
@@ -325,7 +323,7 @@ any) to `*this`.
[section:call_constructor Move Constructor from a Callable]
template <typename F&&, typename ...Args>
explicit scoped_thread(F&&, Args&&...);
explicit strict_scoped_thread(F&&, Args&&...);
[variablelist
@@ -460,20 +458,6 @@ any) to `*this`.
[endsect]
[section:physical_concurrency Static member function `physical_concurrency()`]
unsigned physical_concurrency() noexecpt;
[variablelist
[[Effects:] [Equivalent to return `thread::physical_concurrency()`.]]
]
[endsect]
[section:nativehandle Member function `native_handle()`]
typedef thread::native_handle_type native_handle_type;

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,6 @@
[endsect] [/tutorial]
[/////////////////////]
[section:ref Reference]
#include <boost/thread/externally_locked_stream.hpp>
@@ -49,7 +48,7 @@
operator>>(externally_locked_stream<Stream, RecursiveMutex>& mtx, T& arg);
}
[/////////////////////////////////////////]
[section:stream_guard Class `stream_guard`]
#include <boost/thread/externally_locked_stream.hpp>
@@ -79,7 +78,6 @@
`stream_guard` is a model of __StrictLock.
[//////////////////////////////////////////////////]
[section:constructor `stream_guard(mutex_type & m)`]
[variablelist
@@ -91,7 +89,7 @@
]
[endsect]
[////////////////////////////////////////////////////////////////////////////]
[section:constructor_adopt `stream_guard(mutex_type & m,boost::adopt_lock_t)`]
[variablelist
@@ -107,7 +105,8 @@ obtained by a call to [lock_ref_link `m.lock()`].]]
]
[endsect]
[//////////////////////////////////////////////////////////]
[section:move_constructor `stream_guard(stream_guard && m)`]
@@ -120,7 +119,8 @@ obtained by a call to [lock_ref_link `m.lock()`].]]
]
[endsect]
[////////////////////////////////////]
[section:destructor `~stream_guard()`]
[variablelist
@@ -134,8 +134,8 @@ object passed to the constructor.]]
[endsect]
[endsect]
[//////////////////////////////////////////////////////////////////]
[section:externally_locked_stream Class `externally_locked_stream `]
#include <boost/thread/externally_locked_stream.hpp>
@@ -152,6 +152,7 @@ object passed to the constructor.]]
// Modifiers
stream_guard<Stream, RecursiveMutex> hold();
Stream& bypass() const;
};
}
@@ -161,7 +162,6 @@ provides full access to that object through the `get` member functions, provided
pass a reference to a strict lock object.
[////////////////////////////////////////////////////////////////////////]
[section:constructor `externally_locked_stream(Stream&, RecursiveMutex&)`]
[variablelist
@@ -172,7 +172,6 @@ pass a reference to a strict lock object.
[endsect]
[/////////////////////]
[section:hold `hold()`]
[variablelist
@@ -183,8 +182,6 @@ pass a reference to a strict lock object.
[endsect]
[endsect]

View File

@@ -20,44 +20,24 @@ In addition to the C++11 standard locks, Boost.Thread provides other locks and s
[section:with Executing Around a Function]
In particular, the library provides a way to lock around the execution of a function.
In particular, the library provides some lock factories.
template <class Lockable, class Function, class... Args>
auto with_lock_guard(
Lockable& m,
Function&& func,
Args&&... args
) -> decltype(func(boost::forward<Args>(args)...)) {
boost::lock_guard<Lockable> lock(m);
return func(boost::forward<Args>(args)...);
template <class Lockable, class Function>
auto with_lock_guard(Lockable& m, Function f) -> decltype(fn())
{
auto&& _ = boost::make_lock_guard(f);
f();
}
that can be used with regular functions:
int func(int, int&);
//...
boost::mutex m;
int a;
int result = boost::with_lock_guard(m, func, 1, boost::ref(a));
that can be used as
with boost::bind:
int i = with_lock_guard(mtx, {}() -> bool
{
// access the protected state
return true;
});
int result = boost::with_lock_guard(
m, boost::bind(func, 2, boost::ref(a))
);
or with lambda expression:
int a;
int result = boost::with_lock_guard(
m,
[&a](int x) {
// this scope is protected by mutex m
a = 3;
return x + 4;
},
5
);
[endsect] [/ With]

View File

@@ -6,7 +6,7 @@
/]
[section:synchronized_valuesxxx Synchronized Values - EXPERIMENTAL]
[section:synchronized_valuesxxx Synchronized values - EXPERIMENTAL]
[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 :(]

View File

@@ -8,10 +8,10 @@
[library Thread
[quickbook 1.5]
[version 4.4.0]
[version 4.1.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
[copyright 2011-14 Vicente J. Botet Escriba]
[copyright 2011-13 Vicente J. Botet Escriba]
[purpose C++ Library for launching threads and synchronizing data between them]
[category text]
[license
@@ -239,9 +239,9 @@
[include condition_variables.qbk]
[include once.qbk]
[include barrier.qbk]
[include latch.qbk]
[include async_executors.qbk]
[/include latch.qbk]
[include futures.qbk]
[/include async_executors.qbk]
[endsect]
@@ -249,7 +249,7 @@
[section:sds Synchronized Data Structures]
[include synchronized_value.qbk]
[include sync_queues_ref.qbk]
[/include sync_queues_ref.qbk]
[/include sync_streams.qbk]
[endsect]

View File

@@ -26,13 +26,7 @@
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
namespace no_interruption_point // EXTENSION
{
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
}
template<typename Callable>
void at_thread_exit(Callable func); // EXTENSION
@@ -476,7 +470,6 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
void detach();
static unsigned hardware_concurrency() noexcept;
static unsigned physical_concurrency() noexcept;
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
@@ -539,14 +532,24 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
thread& operator=(thread&& other) noexcept;
[warning
DEPRECATED since 3.0.0: BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE behavior.
Available only up to Boost 1.56.
Join the thread before moving.
]
[variablelist
[[Effects:] [Transfers ownership of the thread managed by `other` (if
any) to `*this`.
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable call __detach__, DEPRECATED
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If there was a thread previously associated with `*this` then that thread is detached, DEPRECATED
- if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to `std::terminate()`.
- if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to std::terminate.
]]
[[Postconditions:] [`other->get_id()==thread::id()` and `get_id()` returns the value of `other.get_id()` prior to the assignment.]]
@@ -565,7 +568,7 @@ any) to `*this`.
[variablelist
[[Requires:] [`Callable` must be Copyable and `func()` must be a valid expression.]]
[[Requires:] [`Callable` must by Copyable and `func()` must be a valid expression.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -592,7 +595,7 @@ not of type __thread_interrupted__, then `std::terminate()` will be called. Any
[variablelist
[[Preconditions:] [`Callable` must be copyable.]]
[[Preconditions:] [`Callable` must by copyable.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -620,7 +623,7 @@ If the attributes declare the native thread as detached, the boost::thread will
[variablelist
[[Preconditions:] [`Callable` must be Movable.]]
[[Preconditions:] [`Callable` must by Movable.]]
[[Effects:] [`func` is moved into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -647,7 +650,7 @@ not of type __thread_interrupted__, then `std::terminate()` will be called. Any
[variablelist
[[Preconditions:] [`Callable` must be copyable.]]
[[Preconditions:] [`Callable` must by copyable.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -676,7 +679,7 @@ If the attributes declare the native thread as detached, the boost::thread will
[variablelist
[[Preconditions:] [`F` and each `A`n must be copyable or movable.]]
[[Preconditions:] [`F` and each `A`n must by copyable or movable.]]
[[Effects:] [As if [link
thread.thread_management.thread.callable_constructor
@@ -703,17 +706,24 @@ are copied into internal storage for access by the new thread.]]]
~thread();
[warning
DEPRECATED since 3.0.0: BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE behavior.
Available only up to Boost 1.56.
Join the thread before destroying or use a scoped thread.
]
[variablelist
[[Effects:] [
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls __detach__, DEPRECATED
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If `*this` has an associated thread of execution, calls __detach__, DEPRECATED
- if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to `std::terminate`. Destroys `*this`.]]
- BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to std::terminate. Destroys `*this`.]]
[[Throws:] [Nothing.]]
[[Note:] [The reason to moving to std::terminate is that either implicitly detaching or joining a `joinable()` thread in its destructor could result in difficult to debug correctness (for `detach`) or performance (for `join`) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable. Join the thread before destroying or use an scoped thread.]]
[[Note:] [Either implicitly detaching or joining a `joinable()` thread in its destructor could result in difficult to debug correctness (for `detach`) or performance (for `join`) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable.]]
]
@@ -758,7 +768,7 @@ corresponding successful `join()` return. ]]
[*resource_deadlock_would_occur]: if deadlock is detected or `this->get_id() == boost::this_thread::get_id()`.
[*invalid_argument]: if the thread is not joinable and `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined.
[*invalid_argument]: if the thread is not joinable and `BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED` is defined.
[/
@@ -784,6 +794,8 @@ corresponding successful `join()` return. ]]
[warning
DEPRECATED since 3.00.
Available only up to Boost 1.56.
Use instead __try_join_for, __try_join_until.
]
@@ -807,7 +819,7 @@ unchanged.]]
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
[/
@@ -847,7 +859,7 @@ unchanged.]]
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
[/
@@ -887,7 +899,7 @@ unchanged.]]
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
[/
@@ -923,7 +935,7 @@ unchanged.]]
[*no_such_process]: if the thread is not valid.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
]]
@@ -979,21 +991,6 @@ or 0 if this information is not available.]]
[endsect]
[section:physical_concurrency Static member function `physical_concurrency()`]
unsigned physical_concurrency() noexecpt;
[variablelist
[[Returns:] [The number of physical cores available on the current system. In contrast to `hardware_concurrency()` it does not return
the number of virtual cores, but it counts only physical cores.]]
[[Throws:] [Nothing]]
]
[endsect]
[section:nativehandle Member function `native_handle()`]
typedef platform-specific-type native_handle_type;
@@ -1017,6 +1014,8 @@ implementation. If no such instance exists, `native_handle()` and `native_handle
[warning
DEPRECATED since 4.0.0.
Available only up to Boost 1.58.
Use `a.__get_id()==b.__get_id()` instead`.
]
@@ -1037,6 +1036,8 @@ Use `a.__get_id()==b.__get_id()` instead`.
[warning
DEPRECATED since 4.0.0.
Available only up to Boost 1.58.
Use `a.__get_id()!=b.__get_id()` instead`.
]
@@ -1055,6 +1056,8 @@ Use `a.__get_id()!=b.__get_id()` instead`.
[warning
DEPRECATED since 3.0.0.
Available only up to Boost 1.56.
Use `this_thread::__sleep_for()` or `this_thread::__sleep_until()`.
]
@@ -1078,6 +1081,8 @@ Use `this_thread::__sleep_for()` or `this_thread::__sleep_until()`.
[warning
DEPRECATED since 3.0.0.
Available only up to Boost 1.56.
Use `this_thread::__yield()`.
]
@@ -1469,6 +1474,8 @@ thread attributes implementation. If no such instance exists, `native_handle()`
[warning
DEPRECATED since 3.0.0.
Available only up to Boost 1.56.
Use `__sleep_for()` and `__sleep_until()` instead.
]
@@ -1495,11 +1502,6 @@ specified by `rel_time` has elapsed or the time point specified by
{
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
namespace no_interruption_point
{
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
}
}
[variablelist
@@ -1511,7 +1513,6 @@ specified by `rel_time` has elapsed or the time point specified by
do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted. ]]
[[Notes:] [`sleep_until()` is one of the predefined __interruption_points__.]]
[[Notes:] [`no_interruption_point::sleep_until()` is NOT one of the __interruption_points__.]]
]
@@ -1525,11 +1526,6 @@ do not throw exceptions. __thread_interrupted__ if the current thread of executi
{
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
namespace no_interruption_point
{
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
}
}
[variablelist
@@ -1540,7 +1536,6 @@ by `rel_time` has elapsed.]]
[[Throws:] [Nothing if operations of chrono::duration<Rep, Period> do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted.]]
[[Notes:] [`sleep_for()` is one of the predefined __interruption_points__.]]
[[Notes:] [`no_interruption_point:: sleep_for()` is NOT one of the __interruption_points__.]]
]

View File

@@ -16,7 +16,7 @@ class bounded_buffer : private boost::noncopyable
public:
typedef boost::unique_lock<boost::mutex> lock;
bounded_buffer(int n) : boost::noncopyable(), begin(0), end(0), buffered(0), circular_buf(n) { }
bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }
void send (int m) {
lock lk(monitor);

View File

@@ -1,150 +0,0 @@
// Copyright (C) 2012-2013 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/caller_context.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executors/loop_executor.hpp>
#include <boost/thread/executors/serial_executor.hpp>
#include <boost/thread/executors/inline_executor.hpp>
#include <boost/thread/executors/thread_executor.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/thread/executors/executor_adaptor.hpp>
#include <boost/thread/executor.hpp>
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <string>
#include <iostream>
void p1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
//boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
}
void p2()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
//boost::this_thread::sleep_for(boost::chrono::seconds(10));
}
int f1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
return 1;
}
int f2(int i)
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(2));
return i + 1;
}
void submit_some(boost::executor& tp)
{
for (int i = 0; i < 3; ++i) {
tp.submit(&p2);
}
for (int i = 0; i < 3; ++i) {
tp.submit(&p1);
}
}
void at_th_entry(boost::basic_thread_pool& )
{
}
int test_executor_adaptor()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
{
boost::executor_adaptor < boost::basic_thread_pool > ea(4);
submit_some( ea);
{
boost::future<int> t1 = boost::async(ea, &f1);
boost::future<int> t2 = boost::async(ea, &f1);
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
submit_some(ea);
{
boost::basic_thread_pool ea3(1);
boost::future<int> t1 = boost::async(ea3, &f1);
boost::future<int> t2 = boost::async(ea3, &f1);
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
submit_some(ea);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::loop_executor > ea2;
submit_some( ea2);
ea2.underlying_executor().run_queued_closures();
}
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::basic_thread_pool > ea1(4);
boost::executor_adaptor < boost::serial_executor > ea2(ea1);
submit_some(ea2);
}
#endif
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::inline_executor > ea1;
submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::executor_adaptor < boost::thread_executor > ea1;
submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea(4, at_th_entry);
boost::future<int> t1 = boost::async(ea, &f1);
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
}
}
catch (std::exception& ex)
{
std::cout << "ERROR= " << ex.what() << "" << std::endl;
return 1;
}
catch (...)
{
std::cout << " ERROR= exception thrown" << std::endl;
return 2;
}
}
// std::cout << BOOST_CONTEXTOF << std::endl;
return 0;
}
int main()
{
return test_executor_adaptor();
}

View File

@@ -1,103 +0,0 @@
// Copyright (C) 2012-2013 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_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/detail/log.hpp>
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <exception>
#include <string>
#include <iostream>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
int p1_ex()
{
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
throw std::logic_error("kk");
}
int p1()
{
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
return 1;;
}
int main()
{
const int number_of_tests = 100;
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
{
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();
BOOST_ASSERT(f2.get()==1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "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;
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;
boost::future<int> f2 = f1.fallback_to(-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f2.wait();
BOOST_ASSERT(f2.get()==-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "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;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
return 0;
}
#else
int main()
{
return 0;
}
#endif

View File

@@ -3,14 +3,8 @@
// 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_USES_LOG
#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/detail/log.hpp>
@@ -25,16 +19,15 @@ int p1()
return 123;
}
int p2(boost::future<int> f)
int p2(boost::future<int>& f)
{
BOOST_THREAD_LOG << "P2<" << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG << "<P2" << BOOST_THREAD_END_LOG;
try
{
return 2 * f.get();
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
@@ -44,81 +37,26 @@ int p2(boost::future<int> f)
BOOST_ASSERT(false);
}
BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG;
return 0;
}
int p2s(boost::shared_future<int> f)
{
BOOST_THREAD_LOG << "<P2S" << BOOST_THREAD_END_LOG;
try
{
return 2 * f.get();
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
catch (...)
{
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
BOOST_THREAD_LOG << "P2S>" << BOOST_THREAD_END_LOG;
return 0;
}
int main()
{
const int number_of_tests = 100;
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
try
{
for (int i=0; i< number_of_tests; i++)
try
{
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.then(&p2);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
(void)f2.get();
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = f1.then(&p2);
(void)f2.get();
}
catch (std::exception& ex)
{
for (int i=0; i< number_of_tests; i++)
try
{
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::shared_future<int> f1 = boost::async(&p1).share();
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f2 = f1.then(&p2s);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
(void)f2.get();
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
return 0;

View File

@@ -1,70 +0,0 @@
// Copyright (C) 2012-2013 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_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/detail/log.hpp>
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <string>
#include <iostream>
#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
int p1()
{
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
return 123;
}
boost::future<int> p2()
{
BOOST_THREAD_LOG << "<P2" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG;
return boost::move(f1);
}
int main()
{
const int number_of_tests = 100;
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
for (int i=0; i< number_of_tests; i++)
try
{
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
boost::future<int> inner_future = outer_future.unwrap();
int ii = inner_future.get();
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "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;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
return 0;
}
#else
int main()
{
return 0;
}
#endif

View File

@@ -1,323 +0,0 @@
// Copyright (C) 2012-2013 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_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/future.hpp>
#include <boost/thread/csbl/vector.hpp>
#include <boost/assert.hpp>
#include <boost/thread/detail/log.hpp>
#include <string>
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
int p1()
{
BOOST_THREAD_LOG
<< "P1" << BOOST_THREAD_END_LOG;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
return 123;
}
int p1b()
{
BOOST_THREAD_LOG
<< "P1b" << BOOST_THREAD_END_LOG;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
return 321;
}
int p2(boost::future<int> f)
{
BOOST_THREAD_LOG
<< " P2 " << BOOST_THREAD_END_LOG;
try
{
return 2 * f.get();
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
BOOST_THREAD_LOG
<< "P2>" << BOOST_THREAD_END_LOG;
}
int p2s(boost::shared_future<int> f)
{
BOOST_THREAD_LOG
<< "<P2" << BOOST_THREAD_END_LOG;
try
{
return 2 * f.get();
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
BOOST_ASSERT(false);
}
BOOST_THREAD_LOG
<< "P2>" << BOOST_THREAD_END_LOG;
}
int main()
{
BOOST_THREAD_LOG
<< "<MAIN" << BOOST_THREAD_END_LOG;
{
try
{
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::tuple<> > all0 = boost::when_all();
BOOST_THREAD_LOG
<< BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#endif
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::make_ready_future(1);
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
//(void) all.wait();
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<std::string> f2 = boost::make_ready_future(std::string("nnnnnnn"));;
boost::future<boost::csbl::tuple<boost::future<int>, boost::future<std::string> > > all = boost::when_all(boost::move(f1), boost::move(f2));
//(void) all.wait();
boost::csbl::tuple<boost::future<int>, boost::future<std::string> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > v;
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1b));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
}
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
{
try
{
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::tuple<> > all0 = boost::when_any();
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
boost::csbl::tuple<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#endif
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::make_ready_future(1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<std::string> f1 = boost::make_ready_future(std::string("aaaa"));
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<std::string>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<std::string>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f2 = boost::make_ready_future(1);
boost::future<int> f1 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
boost::future<int> f2 = boost::async(boost::launch::deferred, &p1b);
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
}
#endif
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > v;
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
v.push_back(boost::async(boost::launch::async, &p1b));
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::csbl::vector<boost::future<int> > res = all.get();
BOOST_THREAD_LOG
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
BOOST_THREAD_LOG
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
}
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
BOOST_THREAD_LOG
<< "MAIN>" << BOOST_THREAD_END_LOG;
return 0;
}
#else
#include <boost/thread/csbl/vector.hpp>
using namespace boost;
void f( boost::csbl::vector<future<int> > &//vec
, BOOST_THREAD_RV_REF(future<int>) //f
) {
}
int main()
{
boost::csbl::vector<future<int> > vec;
f(vec, make_ready_future(0));
return 0;
}
#endif

View File

@@ -1,153 +0,0 @@
// Copyright (C) 2014 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/thread/caller_context.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executors/loop_executor.hpp>
#include <boost/thread/executors/serial_executor.hpp>
#include <boost/thread/executors/inline_executor.hpp>
#include <boost/thread/executors/thread_executor.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/thread/executors/executor_adaptor.hpp>
#include <boost/thread/executor.hpp>
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <string>
#include <iostream>
void p1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
//boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
}
void p2()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
//boost::this_thread::sleep_for(boost::chrono::seconds(10));
}
int f1()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(1));
return 1;
}
int f2(int i)
{
// std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(2));
return i + 1;
}
void submit_some(boost::generic_executor_ref tp)
{
for (int i = 0; i < 3; ++i) {
tp.submit(&p2);
}
for (int i = 0; i < 3; ++i) {
tp.submit(&p1);
}
}
void at_th_entry(boost::basic_thread_pool& )
{
}
int test_generic_executor_ref()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
{
boost::basic_thread_pool ea(4);
submit_some( ea);
{
boost::future<int> t1 = boost::async(ea, &f1);
boost::future<int> t2 = boost::async(ea, &f1);
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
submit_some(ea);
{
boost::basic_thread_pool ea3(1);
boost::future<int> t1 = boost::async(ea3, &f1);
boost::future<int> t2 = boost::async(ea3, &f1);
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
}
submit_some(ea);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::loop_executor ea2;
submit_some( ea2);
ea2.run_queued_closures();
}
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea1(4);
boost::serial_executor ea2(ea1);
submit_some(ea2);
}
#endif
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::inline_executor ea1;
submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
//boost::thread_executor ea1;
//submit_some(ea1);
}
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea(4, at_th_entry);
boost::future<int> t1 = boost::async(ea, &f1);
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
}
}
catch (std::exception& ex)
{
std::cout << "ERROR= " << ex.what() << "" << std::endl;
return 1;
}
catch (...)
{
std::cout << " ERROR= exception thrown" << std::endl;
return 2;
}
}
// std::cout << BOOST_CONTEXTOF << std::endl;
return 0;
}
int main()
{
return test_generic_executor_ref();
}

View File

@@ -8,27 +8,22 @@
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/detail/log.hpp>
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <string>
#include <iostream>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
&& ! defined BOOST_NO_CXX11_LAMBDAS && ! (defined BOOST_MSVC && _MSC_VER < 1700)
&& ! defined BOOST_NO_CXX11_LAMBDAS
int main()
{
const int number_of_tests = 100;
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
for (int i=0; i< number_of_tests; i++)
try
{
{
@@ -38,20 +33,18 @@ int main()
}
{
boost::future<int> f1 = boost::async(boost::launch::async, []() {return 123;});
boost::future<int> f2 = f1.then([](boost::future<int> f) {return 2*f.get(); });
boost::future<int> f2 = f1.then([](boost::future<int>& f) {return 2*f.get(); });
int result = f2.get();
BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG;
}
}
catch (std::exception& ex)
{
std::cout << "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;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}

View File

@@ -3,127 +3,59 @@
// 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
#include <boost/thread/future.hpp>
#include <iostream>
namespace boost
{
template <typename T>
exception_ptr make_exception_ptr(T v)
{
return copy_exception(v);
}
}
int p1() { return 5; }
int& p1r() { static int i=0; return i; }
void p() { }
#if defined BOOST_THREAD_USES_MOVE
boost::future<void> void_compute()
{
return BOOST_THREAD_MAKE_RV_REF(boost::make_ready_future());
return BOOST_THREAD_MAKE_RV_REF(boost::make_future());
}
#endif
boost::future<int> compute(int x)
{
if (x == 0) return boost::make_ready_future(0);
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
if (x < 0) return boost::make_exceptional_future<int>(std::logic_error("Error"));
#else
if (x < 0) return boost::make_exceptional(std::logic_error("Error"));
#endif
if (x == 0) return boost::make_future(0);
if (x < 0) return boost::make_future(-1);
//boost::future<int> f1 = boost::async([]() { return x+1; });
boost::future<int> f1 = boost::async(p1);
boost::future<int> f1 = boost::async(boost::launch::async, p1);
return boost::move(f1);
}
boost::future<int&> compute_ref(int x)
{
static int i = 0;
//if (x == 0) return boost::make_ready_future<int&>(i); //This must not compile as the type is deduced as boost::future<int>
if (x == 0) return boost::make_ready_no_decay_future<int&>(i);
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
if (x < 0) return boost::make_exceptional_future<int&>(std::logic_error("Error"));
#else
if (x < 0) return boost::make_exceptional(std::logic_error("Error"));
#endif
boost::future<int&> f1 = boost::async(p1r);
return boost::move(f1);
}
boost::shared_future<int> shared_compute(int x)
{
if (x == 0) return boost::make_ready_future(0).share();
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
if (x < 0) return boost::make_exceptional_future<int>(std::logic_error("Error")).share();
#else
if (x < 0) return boost::make_exceptional(std::logic_error("Error"));
#endif
if (x == 0) return boost::make_shared_future(0);
if (x < 0) return boost::make_shared_future(-1);
//boost::future<int> f1 = boost::async([]() { return x+1; });
boost::shared_future<int> f1 = boost::async(&p1).share();
return f1;
boost::shared_future<int> f1 = boost::async(p1).share();
return boost::move(f1);
}
int main()
{
const int number_of_tests = 100;
for (int i=0; i< number_of_tests; i++)
try
{
// {
// std::cout << __FILE__ << " "<<__LINE__ << std::endl;
// boost::future<int> f = boost::async(boost::launch::async, p1);
// std::cout << i << " "<<f.get() << std::endl;
// }
#if defined BOOST_THREAD_USES_MOVE
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::future<void> f = void_compute();
f.get();
}
#endif
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::future<int> f = compute(2);
std::cout << f.get() << std::endl;
}
{
boost::future<int> f = compute(0);
std::cout << f.get() << std::endl;
}
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::future<int&> f = compute_ref(0);
boost::shared_future<int> f = shared_compute(2);
std::cout << f.get() << std::endl;
}
// {
// std::cout << __FILE__ << " "<< __LINE__ << std::endl;
// boost::future<int> f = compute(2);
// std::cout << f.get() << std::endl;
// }
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
boost::shared_future<int> f = shared_compute(0);
std::cout << f.get() << std::endl;
}
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
return 1;
}
catch (...)
{
std::cout << "ERRORRRRR "<<"ERRORRRRR exception thrown" << std::endl;
return 2;
}
return 0;
}

View File

@@ -44,8 +44,8 @@ int main()
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
scoped_thread<> t1(boost::thread(use_cerr, boost::ref(mcerr)));
scoped_thread<> t2(boost::thread(use_cout, boost::ref(mcout)));
scoped_thread<> t1(thread(use_cerr, boost::ref(mcerr)));
scoped_thread<> t2(thread(use_cout, boost::ref(mcout)));
this_thread::sleep_for(chrono::seconds(2));
std::string nm;
{

View File

@@ -1,61 +0,0 @@
// (C) Copyright 2012 Howard Hinnant
// (C) Copyright 2012 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// adapted from the example given by Howard Hinnant in
#define BOOST_THREAD_VERSION 4
#include <iostream>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/ostream_buffer.hpp>
void use_cerr()
{
using namespace boost;
chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(5);
int i = 0;
while (chrono::steady_clock::now() < tf)
{
ostream_buffer<std::ostream> mcerr(std::cerr);
mcerr.stream() << "logging data to cerr " << i++ << "\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
void use_cout()
{
using namespace boost;
chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(5);
int i = 0;
while (chrono::steady_clock::now() < tf)
{
ostream_buffer<std::ostream> mcout(std::cout);
mcout.stream() << "logging data to cout " << i++ << "\n";
this_thread::sleep_for(chrono::milliseconds(500));
}
}
int main()
{
using namespace boost;
scoped_thread<> t1(&use_cerr);
scoped_thread<> t2(&use_cout);
this_thread::sleep_for(chrono::seconds(2));
std::string nm = "he, he\n";
{
ostream_buffer<std::ostream> mcout(std::cout);
mcout.stream() << "Enter name: \n";
}
t1.join();
t2.join();
{
ostream_buffer<std::ostream> mcout(std::cout);
mcout.stream() << nm;
}
return 0;
}

View File

@@ -1,102 +0,0 @@
// 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>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/future.hpp>
#include <numeric>
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
template<typename Iterator,typename T>
struct accumulate_block
{
//typedef T result_type;
T operator()(Iterator first,Iterator last)
{
return std::accumulate(first,last,T());
}
};
template<typename Iterator,typename T>
T parallel_accumulate(Iterator first,Iterator last,T init)
{
unsigned long const length=std::distance(first,last);
if(!length)
return init;
unsigned long const block_size=25;
unsigned long const num_blocks=(length+block_size-1)/block_size;
boost::csbl::vector<boost::future<T> > futures(num_blocks-1);
boost::basic_thread_pool pool;
Iterator block_start=first;
for(unsigned long i=0;i<(num_blocks-1);++i)
{
Iterator block_end=block_start;
std::advance(block_end,block_size);
futures[i]=boost::async(pool, accumulate_block<Iterator,T>(), block_start, block_end);
block_start=block_end;
}
T last_result=accumulate_block<Iterator,T>()(block_start,last);
T result=init;
for(unsigned long i=0;i<(num_blocks-1);++i)
{
result+=futures[i].get();
}
result += last_result;
return result;
}
int main()
{
try
{
const int s = 1001;
std::vector<int> vec;
vec.reserve(s);
for (int i=0; i<s;++i)
vec.push_back(1);
int r = parallel_accumulate(vec.begin(), vec.end(),0);
std::cout << r << 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;
}
return 0;
}
#else
///#warning "This compiler doesn't supports variadics"
int main()
{
return 0;
}
#endif

View File

@@ -1,110 +0,0 @@
// Copyright (C) 2012-2013 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>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/future.hpp>
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
#include <numeric>
#include <algorithm>
#include <functional>
#include <iostream>
#include <list>
template<typename T>
struct sorter
{
boost::basic_thread_pool pool;
typedef std::list<T> return_type;
std::list<T> do_sort(std::list<T> chunk_data)
{
if(chunk_data.empty())
{
return chunk_data;
}
std::list<T> result;
result.splice(result.begin(),chunk_data, chunk_data.begin());
T const& partition_val=*result.begin();
typename std::list<T>::iterator divide_point=
std::partition(chunk_data.begin(), chunk_data.end(), [&](T const& val){return val<partition_val;});
std::list<T> new_lower_chunk;
new_lower_chunk.splice(new_lower_chunk.end(), chunk_data, chunk_data.begin(), divide_point);
boost::future<std::list<T> > new_lower = boost::async(pool, &sorter::do_sort, this, std::move(new_lower_chunk));
//boost::future<std::list<T> > new_lower = boost::async<return_type>(pool, &sorter::do_sort, this, std::move(new_lower_chunk));
std::list<T> new_higher(do_sort(chunk_data));
result.splice(result.end(),new_higher);
while(!new_lower.is_ready())
{
pool.schedule_one_or_yield();
}
result.splice(result.begin(),new_lower.get());
return result;
}
};
template<typename T>
std::list<T> parallel_quick_sort(std::list<T>& input)
{
if(input.empty())
{
return input;
}
sorter<T> s;
return s.do_sort(input);
}
int main()
{
try
{
const int s = 101;
std::list<int> lst;
for (int i=0; i<s;++i)
lst.push_back(100-i);
std::list<int> r = parallel_quick_sort(lst);
for (std::list<int>::const_iterator it=r.begin(); it != r.end(); ++it)
std::cout << *it << 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;
}
return 0;
}
#else
//#warning "This compiler doesn't supports variadics and move semantics"
int main()
{
return 0;
}
#endif

View File

@@ -143,7 +143,7 @@ namespace
{
typedef SharedData<Types> S;
auto best_producer_time = std::numeric_limits<Stopwatch::rep>::max BOOST_PREVENT_MACRO_SUBSTITUTION ();
auto best_producer_time = std::numeric_limits<Stopwatch::rep>::max();
std::vector<std::thread> consumers
{ consumer_count };
@@ -165,7 +165,7 @@ namespace
for (unsigned i = 0; i < consumer_count; ++i)
consumers[i].join();
best_producer_time = std::min BOOST_PREVENT_MACRO_SUBSTITUTION (best_producer_time, shared_data.producer_time);
best_producer_time = std::min(best_producer_time, shared_data.producer_time);
}

View File

@@ -42,7 +42,7 @@ void unique()
int main()
{
boost::chrono::high_resolution_clock::duration best_time(std::numeric_limits<boost::chrono::high_resolution_clock::duration::rep>::max BOOST_PREVENT_MACRO_SUBSTITUTION ());
boost::chrono::high_resolution_clock::duration best_time(std::numeric_limits<boost::chrono::high_resolution_clock::duration::rep>::max());
for (int i =100; i>0; --i) {
boost::chrono::high_resolution_clock clock;
boost::chrono::high_resolution_clock::time_point s1 = clock.now();
@@ -61,7 +61,7 @@ int main()
// t13.join();
boost::chrono::high_resolution_clock::time_point f1 = clock.now();
//std::cout << " Time spent:" << (f1 - s1) << std::endl;
best_time = std::min BOOST_PREVENT_MACRO_SUBSTITUTION (best_time, f1 - s1);
best_time = std::min(best_time, f1 - s1);
}
std::cout << "Best Time spent:" << best_time << std::endl;

View File

@@ -6,33 +6,22 @@
// adapted from the example given by Howard Hinnant in
#include <boost/config.hpp>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <iostream>
#include <boost/thread/scoped_thread.hpp>
#ifdef XXXX
#include <boost/thread/externally_locked_stream.hpp>
typedef boost::externally_locked_stream<std::ostream> the_ostream;
#else
typedef std::ostream the_ostream;
typedef std::istream the_istream;
#endif
#include <boost/thread/sync_queue.hpp>
void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
void producer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
sbq.push_back(i);
//sbq << i;
mos << "push_back(" << i << ") "<< sbq.size()<<"\n";
//sbq.push(i);
sbq << i;
mos << "push(" << i << ") "<< sbq.size()<<"\n";
this_thread::sleep_for(chrono::milliseconds(200));
}
}
@@ -46,19 +35,16 @@ void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
}
}
void consumer(
the_ostream &mos,
boost::sync_queue<int> & sbq)
void consumer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
sbq.pull_front(r);
//sbq >> r;
//sbq.pull(r);
sbq >> r;
mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
@@ -71,36 +57,17 @@ void consumer(
mos << "exception !!!\n";
}
}
void consumer2(the_ostream &mos, boost::sync_queue<int> & sbq)
void consumer2(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
bool closed=false;
for(int i=0; ;++i)
{
int r;
queue_op_status st = sbq.try_pull_front(r);
if (queue_op_status::closed == st) break;
if (queue_op_status::success == st) {
mos << i << " pull(" << r << ")\n";
}
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
mos << "exception !!!\n";
}
}
void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
queue_op_status res = sbq.wait_pull_front(r);
if (res==queue_op_status::closed) break;
mos << i << " wait_pull_front(" << r << ")\n";
sbq.pull(r, closed);
if (closed) break;
mos << i << " pull(" << r << ")\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
@@ -109,30 +76,43 @@ void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
mos << "exception !!!\n";
}
}
//void consumer3(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
//{
// using namespace boost;
// bool closed=false;
// try {
// for(int i=0; ;++i)
// {
// int r;
// queue_op_status res = sbq.wait_and_pull(r);
// if (res==queue_op_status::closed) break;
// mos << i << " wait_and_pull(" << r << ")\n";
// this_thread::sleep_for(chrono::milliseconds(250));
// }
// }
// catch(...)
// {
// mos << "exception !!!\n";
// }
//}
int main()
{
using namespace boost;
#ifdef XXXX
recursive_mutex terminal_mutex;
externally_locked_stream<std::ostream> mcerr(std::cerr, terminal_mutex);
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
#else
the_ostream &mcerr = std::cout;
the_ostream &mcout = std::cerr;
//the_istream &mcin = std::cin;
#endif
sync_queue<int> sbq;
{
mcout << "begin of main" << std::endl;
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq)));
scoped_thread<> t11(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(thread(consumer, boost::ref(mcout), boost::ref(sbq)));
this_thread::sleep_for(chrono::seconds(1));

View File

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

View File

@@ -6,92 +6,77 @@
// adapted from the example given by Howard Hinnant in
#include <boost/config.hpp>
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
//#define XXXX
#include <iostream>
#include <boost/thread/scoped_thread.hpp>
#ifdef XXXX
#include <boost/thread/externally_locked_stream.hpp>
typedef boost::externally_locked_stream<std::ostream> the_ostream;
#else
typedef std::ostream the_ostream;
typedef std::istream the_istream;
#endif
#include <boost/thread/sync_bounded_queue.hpp>
void producer(the_ostream &/*mos*/, boost::sync_bounded_queue<int> & sbq)
void producer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
sbq.push_back(i);
//sbq << i;
//mos << "push_back(" << i << ") "<< sbq.size()<<"\n";
//sbq.push(i);
sbq << i;
mos << "push(" << i << ") "<< sbq.size()<<"\n";
this_thread::sleep_for(chrono::milliseconds(200));
}
}
catch(sync_queue_is_closed&)
{
//mos << "closed !!!\n";
mos << "closed !!!\n";
}
catch(...)
{
//mos << "exception !!!\n";
mos << "exception !!!\n";
}
}
void consumer(the_ostream &/*mos*/, boost::sync_bounded_queue<int> & sbq)
void consumer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
{
using namespace boost;
try {
for(int i=0; ;++i)
{
int r;
sbq.pull_front(r);
//sbq >> r;
//mos << i << " pull_front(" << r << ") "<< sbq.size()<<"\n";
//sbq.pull(r);
sbq >> r;
mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(sync_queue_is_closed&)
{
//mos << "closed !!!\n";
mos << "closed !!!\n";
}
catch(...)
{
//mos << "exception !!!\n";
mos << "exception !!!\n";
}
}
void consumer2(the_ostream &/*mos*/, boost::sync_bounded_queue<int> & sbq)
void consumer2(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
{
using namespace boost;
try {
bool closed=false;
for(int i=0; ;++i)
{
int r;
queue_op_status st = sbq.try_pull_front(r);
if (queue_op_status::closed == st) break;
if (queue_op_status::success == st) {
//mos << i << " pull(" << r << ")\n";
}
sbq.pull(r, closed);
if (closed) break;
mos << i << " pull(" << r << ")\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
catch(...)
{
//mos << "exception !!!\n";
mos << "exception !!!\n";
}
}
//void consumer3(the_ostream &mos, boost::sync_bounded_queue<int> & sbq)
//void consumer3(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
//{
// using namespace boost;
// bool closed=false;
@@ -101,38 +86,33 @@ void consumer2(the_ostream &/*mos*/, boost::sync_bounded_queue<int> & sbq)
// int r;
// queue_op_status res = sbq.wait_and_pull(r);
// if (res==queue_op_status::closed) break;
// //mos << i << " wait_and_pull(" << r << ")\n";
// mos << i << " wait_and_pull(" << r << ")\n";
// this_thread::sleep_for(chrono::milliseconds(250));
// }
// }
// catch(...)
// {
// //mos << "exception !!!\n";
// mos << "exception !!!\n";
// }
//}
int main()
{
using namespace boost;
#ifdef XXXX
recursive_mutex terminal_mutex;
externally_locked_stream<std::ostream> mcerr(std::cerr, terminal_mutex);
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
#else
the_ostream &mcerr = std::cout;
the_ostream &mcout = std::cerr;
//the_istream &mcin = std::cin;
#endif
sync_bounded_queue<int> sbq(10);
{
mcout << "begin of main" << std::endl;
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq)));
scoped_thread<> t11(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(thread(consumer, boost::ref(mcout), boost::ref(sbq)));
this_thread::sleep_for(chrono::seconds(1));

View File

@@ -13,9 +13,6 @@ void do_something(int& i)
{
++i;
}
void f(int, int)
{
}
struct func
{
@@ -84,10 +81,7 @@ int main()
do_something_in_current_thread();
}
{
boost::scoped_thread<> g( &f, 1, 2 );
do_something_in_current_thread();
}
return 0;
}

View File

@@ -4,9 +4,6 @@
// 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)
#undef BOOST_THREAD_VERSION
#define BOOST_THREAD_VERSION 2
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread_only.hpp>

View File

@@ -1,73 +0,0 @@
// Copyright (C) 2012-2013 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>
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/detail/log.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/assert.hpp>
#include <string>
void p1()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " P1" << BOOST_THREAD_END_LOG;
}
void p2()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " P2" << BOOST_THREAD_END_LOG;
}
void submit_some(boost::basic_thread_pool& tp) {
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
}
int main()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
{
try
{
boost::basic_thread_pool tp;
submit_some(tp);
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << "MAIN>" << BOOST_THREAD_END_LOG;
return 0;
}

View File

@@ -1,75 +0,0 @@
// Copyright (C) 2013 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>
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#include <boost/thread/detail/log.hpp>
#include <boost/thread/executors/loop_executor.hpp>
#include <boost/assert.hpp>
#include <boost/thread/thread_only.hpp>
#include <string>
void p1()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " P1" << BOOST_THREAD_END_LOG;
}
void p2()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " P2" << BOOST_THREAD_END_LOG;
}
void submit_some(boost::loop_executor& tp) {
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
}
int main()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
{
try
{
boost::loop_executor tp;
submit_some(tp);
tp.run_queued_closures();
submit_some(tp);
tp.run_queued_closures();
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << "MAIN>" << BOOST_THREAD_END_LOG;
return 0;
}

View File

@@ -1,53 +0,0 @@
// (C) Copyright 2013 Ruslan Baratov
// 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)
// See www.boost.org/libs/thread for documentation.
#define BOOST_THREAD_VERSION 4
#include <iostream> // std::cout
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/with_lock_guard.hpp>
boost::mutex m; // protection for 'x' and 'std::cout'
int x;
#if defined(BOOST_NO_CXX11_LAMBDAS) || (defined BOOST_MSVC && _MSC_VER < 1700)
void print_x() {
++x;
std::cout << "x = " << x << std::endl;
}
void job() {
for (int i = 0; i < 10; ++i) {
boost::with_lock_guard(m, print_x);
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
}
#else
void job() {
for (int i = 0; i < 10; ++i) {
boost::with_lock_guard(
m,
[]() {
++x;
std::cout << "x = " << x << std::endl;
}
);
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
}
#endif
int main() {
#if defined(BOOST_NO_CXX11_LAMBDAS) || (defined BOOST_MSVC && _MSC_VER < 1700)
std::cout << "(no lambdas)" << std::endl;
#endif
boost::scoped_thread<> thread_1((boost::thread(job)));
boost::scoped_thread<> thread_2((boost::thread(job)));
boost::scoped_thread<> thread_3((boost::thread(job)));
return 0;
}

View File

@@ -1,7 +1,6 @@
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
// Copyright (C) 2007-8 Anthony Williams
// (C) Copyright 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -18,236 +17,51 @@
#include <boost/thread/condition_variable.hpp>
#include <string>
#include <stdexcept>
#include <boost/thread/detail/nullary_function.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace thread_detail
{
typedef detail::nullary_function<void()> void_completion_function;
typedef detail::nullary_function<size_t()> size_completion_function;
struct default_barrier_reseter
class barrier
{
unsigned int size_;
default_barrier_reseter(unsigned int size) :
size_(size)
{
}
BOOST_THREAD_MOVABLE(default_barrier_reseter)
//BOOST_THREAD_COPYABLE_AND_MOVABLE(default_barrier_reseter)
public:
BOOST_THREAD_NO_COPYABLE( barrier )
default_barrier_reseter(default_barrier_reseter const& other) BOOST_NOEXCEPT :
size_(other.size_)
{
}
default_barrier_reseter(BOOST_THREAD_RV_REF(default_barrier_reseter) other) BOOST_NOEXCEPT :
size_(BOOST_THREAD_RV(other).size_)
{
}
barrier(unsigned int count)
: m_threshold(count), m_count(count), m_generation(0)
{
if (count == 0)
boost::throw_exception(thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
}
unsigned int operator()()
{
return size_;
}
bool wait()
{
boost::unique_lock<boost::mutex> lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = m_threshold;
m_cond.notify_all();
return true;
}
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
private:
mutex m_mutex;
condition_variable m_cond;
unsigned int m_threshold;
unsigned int m_count;
unsigned int m_generation;
};
struct void_functor_barrier_reseter
{
unsigned int size_;
void_completion_function fct_;
template <typename F>
void_functor_barrier_reseter(unsigned int size, BOOST_THREAD_RV_REF(F) funct)
: size_(size), fct_(boost::move(funct))
{}
template <typename F>
void_functor_barrier_reseter(unsigned int size, F& funct)
: size_(size), fct_(funct)
{}
BOOST_THREAD_MOVABLE(void_functor_barrier_reseter)
//BOOST_THREAD_COPYABLE_AND_MOVABLE(void_functor_barrier_reseter)
void_functor_barrier_reseter(void_functor_barrier_reseter const& other) BOOST_NOEXCEPT :
size_(other.size_), fct_(other.fct_)
{
}
void_functor_barrier_reseter(BOOST_THREAD_RV_REF(void_functor_barrier_reseter) other) BOOST_NOEXCEPT :
size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
//size_(BOOST_THREAD_RV(other).size_), fct_(boost::move(BOOST_THREAD_RV(other).fct_))
{
}
unsigned int operator()()
{
fct_();
return size_;
}
};
struct void_fct_ptr_barrier_reseter
{
unsigned int size_;
void(*fct_)();
void_fct_ptr_barrier_reseter(unsigned int size, void(*funct)()) :
size_(size), fct_(funct)
{
}
BOOST_THREAD_MOVABLE(void_fct_ptr_barrier_reseter)
//BOOST_THREAD_COPYABLE_AND_MOVABLE(void_fct_ptr_barrier_reseter)
void_fct_ptr_barrier_reseter(void_fct_ptr_barrier_reseter const& other) BOOST_NOEXCEPT :
size_(other.size_), fct_(other.fct_)
{
}
void_fct_ptr_barrier_reseter(BOOST_THREAD_RV_REF(void_fct_ptr_barrier_reseter) other) BOOST_NOEXCEPT :
size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
{
}
unsigned int operator()()
{
fct_();
return size_;
}
};
}
//BOOST_THREAD_DCL_MOVABLE(thread_detail::default_barrier_reseter)
//BOOST_THREAD_DCL_MOVABLE(thread_detail::void_functor_barrier_reseter)
//BOOST_THREAD_DCL_MOVABLE(thread_detail::void_fct_ptr_barrier_reseter)
class barrier
{
static inline unsigned int check_counter(unsigned int count)
{
if (count == 0) boost::throw_exception(
thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
return count;
}
struct dummy
{
};
public:
BOOST_THREAD_NO_COPYABLE( barrier)
explicit barrier(unsigned int count) :
m_count(check_counter(count)), m_generation(0), fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count)))
{
}
template <typename F>
barrier(
unsigned int count,
BOOST_THREAD_RV_REF(F) funct,
typename enable_if<
typename is_void<typename result_of<F>::type>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
m_generation(0),
fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count,
boost::move(funct)))
)
{
}
template <typename F>
barrier(
unsigned int count,
F &funct,
typename enable_if<
typename is_void<typename result_of<F>::type>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
m_generation(0),
fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count,
funct))
)
{
}
template <typename F>
barrier(
unsigned int count,
BOOST_THREAD_RV_REF(F) funct,
typename enable_if<
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
m_generation(0),
fct_(boost::move(funct))
{
}
template <typename F>
barrier(
unsigned int count,
F& funct,
typename enable_if<
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
>::type=0
)
: m_count(check_counter(count)),
m_generation(0),
fct_(funct)
{
}
barrier(unsigned int count, void(*funct)()) :
m_count(check_counter(count)), m_generation(0),
fct_(funct
? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_fct_ptr_barrier_reseter(count, funct))))
: BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))))
)
{
}
barrier(unsigned int count, unsigned int(*funct)()) :
m_count(check_counter(count)), m_generation(0),
fct_(funct
? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(funct))
: BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))))
)
{
}
bool wait()
{
boost::unique_lock < boost::mutex > lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = static_cast<unsigned int>(fct_());
BOOST_ASSERT(m_count != 0);
m_cond.notify_all();
return true;
}
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
void count_down_and_wait()
{
wait();
}
private:
mutex m_mutex;
condition_variable m_cond;
unsigned int m_count;
unsigned int m_generation;
thread_detail::size_completion_function fct_;
};
} // namespace boost
} // namespace boost
#include <boost/config/abi_suffix.hpp>

View File

@@ -1,56 +0,0 @@
// (C) Copyright 2013 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_CALL_CONTEXT_HPP
#define BOOST_THREAD_CALL_CONTEXT_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/thread.hpp>
#endif
#include <boost/current_function.hpp>
#include <iomanip>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
struct caller_context_t
{
const char * filename;
unsigned lineno;
const char * func;
caller_context_t(const char * filename, unsigned lineno, const char * func) :
filename(filename), lineno(lineno), func(func)
{
}
};
#define BOOST_CONTEXTOF boost::caller_context_t(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION)
template <typename OStream>
OStream& operator<<(OStream& os, caller_context_t const& ctx)
{
#if defined BOOST_THREAD_USES_LOG_THREAD_ID
{
io::ios_flags_saver ifs( os );
os << std::left << std::setw(14) << boost::this_thread::get_id() << " ";
}
#endif
{
io::ios_flags_saver ifs(os);
os << ctx.filename << "["
<< std::setw(4) << std::right << std::dec<< ctx.lineno << "] ";
os << ctx.func << " " ;
}
return os;
}
}
#include <boost/config/abi_suffix.hpp>
#endif // header

View File

@@ -16,8 +16,12 @@
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <boost/assert.hpp>
//#include <boost/thread/detail/nullary_function.hpp>
#include <boost/thread/csbl/functional.hpp>
#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
#include <boost/function.hpp>
#else
#include <functional>
#endif
//#include <boost/thread/latch.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -33,8 +37,11 @@ namespace boost
{
public:
/// the implementation defined completion function type
//typedef detail::nullary_function<void()> completion_function;
typedef csbl::function<void()> completion_function;
#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
typedef function<void()> completion_function;
#else
typedef std::function<void()> completion_function;
#endif
/// noop completion function factory
static completion_function noop()
{

View File

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

View File

@@ -1,209 +0,0 @@
#ifndef BOOST_THREAD_QUEUE_ADAPTOR_HPP
#define BOOST_THREAD_QUEUE_ADAPTOR_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/concurrent_queues/queue_base.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <typename Queue>
class queue_adaptor_copyable_only :
public boost::queue_base<typename Queue::value_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
queue_adaptor_copyable_only() {}
// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }
// Modifiers
void close() { queue.close(); }
void push_back(const value_type& x) { queue.push_back(x); }
void pull_front(value_type& x) { queue.pull_front(x); };
value_type pull_front() { return queue.pull_front(); }
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
};
template <typename Queue>
class queue_adaptor_movable_only :
public boost::queue_base<typename Queue::value_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
queue_adaptor_movable_only() {}
// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }
// Modifiers
void close() { queue.close(); }
void pull_front(value_type& x) { queue.pull_front(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull_front() { return queue.pull_front(); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
};
template <typename Queue>
class queue_adaptor_copyable_and_movable :
public boost::queue_base<typename Queue::value_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
queue_adaptor_copyable_and_movable() {}
// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }
// Modifiers
void close() { queue.close(); }
void push_back(const value_type& x) { queue.push_back(x); }
void pull_front(value_type& x) { queue.pull_front(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull_front() { return queue.pull_front(); }
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
};
template <class Q, class T,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // __GNUC__
#elif defined _MSC_VER
#if _MSC_VER < 1700
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // _MSC_VER
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif
#else
bool Copyable = is_copy_constructible<T>::value,
bool Movable = has_move_emulation_enabled<T>::value
#endif
>
struct queue_adaptor;
template <class Q, class T>
struct queue_adaptor<Q, T, true, true> {
typedef queue_adaptor_copyable_and_movable<Q> type;
};
template <class Q, class T>
struct queue_adaptor<Q, T, true, false> {
typedef queue_adaptor_copyable_only<Q> type;
};
template <class Q, class T>
struct queue_adaptor<Q, T, false, true> {
typedef queue_adaptor_movable_only<Q> type;
};
}
template <typename Queue>
class queue_adaptor :
public detail::queue_adaptor<Queue, typename Queue::value_type>::type
{
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
virtual ~queue_adaptor() {};
};
}
using concurrent::queue_adaptor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,202 +0,0 @@
#ifndef BOOST_THREAD_QUEUE_BASE_HPP
#define BOOST_THREAD_QUEUE_BASE_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/type_traits/is_copy_constructible.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <typename ValueType>
class queue_base_copyable_only
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_copyable_only() {};
// Observers
virtual bool empty() const = 0;
virtual bool full() const = 0;
virtual size_type size() const = 0;
virtual bool closed() const = 0;
// Modifiers
virtual void close() = 0;
virtual void push_back(const value_type& x) = 0;
virtual void pull_front(value_type&) = 0;
virtual value_type pull_front() = 0;
virtual queue_op_status try_push_back(const value_type& x) = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
};
template <typename ValueType>
class queue_base_movable_only
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_movable_only() {};
// Observers
virtual bool empty() const = 0;
virtual bool full() const = 0;
virtual size_type size() const = 0;
virtual bool closed() const = 0;
// Modifiers
virtual void close() = 0;
virtual void pull_front(value_type&) = 0;
// enable_if is_nothrow_movable<value_type>
virtual value_type pull_front() = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
};
template <typename ValueType>
class queue_base_copyable_and_movable
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_copyable_and_movable() {};
// Observers
virtual bool empty() const = 0;
virtual bool full() const = 0;
virtual size_type size() const = 0;
virtual bool closed() const = 0;
// Modifiers
virtual void close() = 0;
virtual void push_back(const value_type& x) = 0;
virtual void pull_front(value_type&) = 0;
// enable_if is_nothrow_copy_movable<value_type>
virtual value_type pull_front() = 0;
virtual queue_op_status try_push_back(const value_type& x) = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
};
template <class T,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // __GNUC__
#elif defined _MSC_VER
#if _MSC_VER < 1700
bool Copyable = is_copy_constructible<T>::value,
bool Movable = true
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif // _MSC_VER
#else
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
#endif
#else
bool Copyable = is_copy_constructible<T>::value,
bool Movable = has_move_emulation_enabled<T>::value
#endif
>
struct queue_base;
template <class T>
struct queue_base<T, true, true> {
typedef queue_base_copyable_and_movable<T> type;
};
template <class T>
struct queue_base<T, true, false> {
typedef queue_base_copyable_only<T> type;
};
template <class T>
struct queue_base<T, false, true> {
typedef queue_base_movable_only<T> type;
};
}
template <typename ValueType>
class queue_base :
public detail::queue_base<ValueType>::type
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base() {};
};
}
using concurrent::queue_base;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,46 +0,0 @@
#ifndef BOOST_THREAD_QUEUE_OP_STATUS_HPP
#define BOOST_THREAD_QUEUE_OP_STATUS_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
BOOST_SCOPED_ENUM_DECLARE_BEGIN(queue_op_status)
{ success = 0, empty, full, closed, busy, timeout, not_ready }
BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)
struct sync_queue_is_closed : std::exception
{
};
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
struct no_block_tag{};
BOOST_CONSTEXPR_OR_CONST no_block_tag no_block = {};
#endif
using concurrent::queue_op_status;
using concurrent::sync_queue_is_closed;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,165 +0,0 @@
#ifndef BOOST_THREAD_QUEUE_VIEWS_HPP
#define BOOST_THREAD_QUEUE_VIEWS_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/concurrent_queues/queue_base.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
template <typename Queue>
class queue_back_view
{
Queue* queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_back_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
// Observers
bool empty() const { return queue->empty(); }
bool full() const { return queue->full(); }
size_type size() const { return queue->size(); }
bool closed() const { return queue->closed(); }
// Modifiers
void close() { queue->close(); }
void push(const value_type& x) { queue->push_back(x); }
void pull(value_type& x) { queue->pull_back(x); }
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue->pull_back(); }
queue_op_status try_push(const value_type& x) { return queue->try_push_back(x); }
queue_op_status try_pull(value_type& x) { return queue->try_pull_back(x); }
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_back(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_back(x); }
queue_op_status wait_push(const value_type& x) { return queue->wait_push_back(x); }
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_back(x); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_back(boost::move(x)); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_back(boost::move(x)); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_back(boost::move(x)); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_back(boost::move(x)); }
};
template <typename Queue>
class queue_front_view
{
Queue* queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_front_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
// Observers
bool empty() const { return queue->empty(); }
bool full() const { return queue->full(); }
size_type size() const { return queue->size(); }
bool closed() const { return queue->closed(); }
// Modifiers
void close() { queue->close(); }
void push(const value_type& x) { queue->push_front(x); }
void pull(value_type& x) { queue->pull_front(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue->pull_front(); }
queue_op_status try_push(const value_type& x) { return queue->try_push_front(x); }
queue_op_status try_pull(value_type& x) { return queue->try_pull_front(x); }
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_front(x); }
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_front(x); }
queue_op_status wait_push(const value_type& x) { return queue->wait_push_front(x); }
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_front(x); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_front(forward<value_type>(x)); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_front(forward<value_type>(x)); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_front(forward<value_type>(x)); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_front(forward<value_type>(x)); }
};
#if ! defined BOOST_NO_CXX11_TEMPLATE_ALIASES
template <class T>
using queue_back = queue_back_view<queue_base<T> > ;
template <class T>
using queue_front = queue_front_view<queue_base<T> > ;
#else
template <class T>
struct queue_back : queue_back_view<queue_base<T> >
{
typedef queue_back_view<queue_base<T> > base_type;
queue_back(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
};
template <class T>
struct queue_front : queue_front_view<queue_base<T> >
{
typedef queue_front_view<queue_base<T> > base_type;
queue_front(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
};
#endif
// template <class Queue>
// queue_back_view<Queue> back(Queue & q) { return queue_back_view<Queue>(q); }
// template <class Queue>
// queue_front_view<Queue> front(Queue & q) { return queue_front_view<Queue>(q); }
//#if 0
// template <class T>
// queue_back<T> back(queue_base<T> & q) { return queue_back<T>(q); }
// template <class T>
// queue_front<T> front(queue_base<T> & q) { return queue_front<T>(q); }
//#else
// template <class T>
// typename queue_back<T>::type back(queue_base<T> & q) { return typename queue_back<T>::type(q); }
// template <class T>
// typename queue_front<T>::type front(queue_base<T> & q) { return typename queue_front<T>::type(q); }
//#endif
}
using concurrent::queue_back_view;
using concurrent::queue_front_view;
using concurrent::queue_back;
using concurrent::queue_front;
//using concurrent::back;
//using concurrent::front;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

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

View File

@@ -1,362 +0,0 @@
// Copyright (C) 2014 Ian Forbed
// Copyright (C) 2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_THREAD_SYNC_PRIORITY_QUEUE
#define BOOST_THREAD_SYNC_PRIORITY_QUEUE
#include <boost/thread/detail/config.hpp>
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/csbl/vector.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/atomic.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <exception>
#include <queue>
#include <utility>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail {
template <
class Type,
class Container = csbl::vector<Type>,
class Compare = std::less<Type>
>
class priority_queue
{
private:
std::vector<Type> _elements;
Compare _compare;
public:
explicit priority_queue(const Compare& compare = Compare())
: _elements(), _compare(compare)
{ }
std::size_t size() const
{
return _elements.size();
}
bool empty() const
{
return _elements.empty();
}
void push(Type const& element)
{
_elements.push_back(element);
std::push_heap(_elements.begin(), _elements.end(), _compare);
}
void push(BOOST_RV_REF(Type) element)
{
_elements.push_back(boost::move(element));
std::push_heap(_elements.begin(), _elements.end(), _compare);
}
Type pull()
{
std::pop_heap(_elements.begin(), _elements.end(), _compare);
Type result = boost::move(_elements.back());
_elements.pop_back();
return boost::move(result);
}
Type const& top()
{
return _elements.back();
}
};
}
namespace concurrent
{
template <class ValueType,
class Container = csbl::vector<ValueType>,
class Compare = std::less<typename Container::value_type> >
class sync_priority_queue
: public detail::sync_queue_base<ValueType, boost::detail::priority_queue<ValueType,Container,Compare> >
{
typedef detail::sync_queue_base<ValueType, boost::detail::priority_queue<ValueType,Container,Compare> > super;
public:
typedef ValueType value_type;
//typedef typename super::value_type value_type; // fixme
typedef typename super::underlying_queue_type underlying_queue_type;
typedef typename super::size_type size_type;
typedef typename super::op_status op_status;
typedef chrono::steady_clock clock;
protected:
public:
sync_priority_queue() {}
~sync_priority_queue()
{
if(!super::closed())
{
super::close();
}
}
void push(const ValueType& elem);
void push(BOOST_THREAD_RV_REF(ValueType) elem);
queue_op_status try_push(const ValueType& elem);
queue_op_status try_push(BOOST_THREAD_RV_REF(ValueType) elem);
ValueType pull();
void pull(ValueType&);
queue_op_status pull_until(const clock::time_point&, ValueType&);
queue_op_status pull_for(const clock::duration&, ValueType&);
queue_op_status try_pull(ValueType& elem);
queue_op_status wait_pull(ValueType& elem);
queue_op_status nonblocking_pull(ValueType&);
private:
void push(unique_lock<mutex>&, const ValueType& elem);
void push(lock_guard<mutex>&, const ValueType& elem);
void push(unique_lock<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem);
void push(lock_guard<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem);
queue_op_status try_push(unique_lock<mutex>&, const ValueType& elem);
queue_op_status try_push(unique_lock<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem);
ValueType pull(unique_lock<mutex>&);
ValueType pull(lock_guard<mutex>&);
void pull(unique_lock<mutex>&, ValueType&);
void pull(lock_guard<mutex>&, ValueType&);
queue_op_status try_pull(lock_guard<mutex>& lk, ValueType& elem);
queue_op_status try_pull(unique_lock<mutex>& lk, ValueType& elem);
queue_op_status wait_pull(unique_lock<mutex>& lk, ValueType& elem);
queue_op_status nonblocking_pull(unique_lock<mutex>& lk, ValueType&);
sync_priority_queue(const sync_priority_queue&);
sync_priority_queue& operator= (const sync_priority_queue&);
sync_priority_queue(BOOST_THREAD_RV_REF(sync_priority_queue));
sync_priority_queue& operator= (BOOST_THREAD_RV_REF(sync_priority_queue));
}; //end class
//////////////////////
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(unique_lock<mutex>& lk, const T& elem)
{
super::throw_if_closed(lk);
super::data_.push(elem);
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, const T& elem)
{
super::throw_if_closed(lk);
super::data_.push(elem);
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(const T& elem)
{
lock_guard<mutex> lk(super::mtx_);
push(lk, elem);
}
//////////////////////
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(unique_lock<mutex>& lk, BOOST_THREAD_RV_REF(T) elem)
{
super::throw_if_closed(lk);
super::data_.push(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, BOOST_THREAD_RV_REF(T) elem)
{
super::throw_if_closed(lk);
super::data_.push(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(BOOST_THREAD_RV_REF(T) elem)
{
lock_guard<mutex> lk(super::mtx_);
push(lk, boost::move(elem));
}
//////////////////////
template <class T, class Container,class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::try_push(const T& elem)
{
lock_guard<mutex> lk(super::mtx_);
if (super::closed(lk)) return queue_op_status::closed;
push(lk, elem);
return queue_op_status::success;
}
//////////////////////
template <class T, class Container,class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::try_push(BOOST_THREAD_RV_REF(T) elem)
{
lock_guard<mutex> lk(super::mtx_);
if (super::closed(lk)) return queue_op_status::closed;
push(lk, boost::move(elem));
return queue_op_status::success;
}
//////////////////////
template <class T,class Container, class Cmp>
T sync_priority_queue<T,Container,Cmp>::pull(unique_lock<mutex>&)
{
return super::data_.pull();
}
template <class T,class Container, class Cmp>
T sync_priority_queue<T,Container,Cmp>::pull(lock_guard<mutex>&)
{
return super::data_.pull();
}
template <class T,class Container, class Cmp>
T sync_priority_queue<T,Container,Cmp>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull(lk);
}
//////////////////////
template <class T,class Container, class Cmp>
void sync_priority_queue<T,Container,Cmp>::pull(unique_lock<mutex>&, T& elem)
{
elem = super::data_.pull();
}
template <class T,class Container, class Cmp>
void sync_priority_queue<T,Container,Cmp>::pull(lock_guard<mutex>&, T& elem)
{
elem = super::data_.pull();
}
template <class T,class Container, class Cmp>
void sync_priority_queue<T,Container,Cmp>::pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
pull(lk, elem);
}
//////////////////////
template <class T, class Cont,class Cmp>
queue_op_status
sync_priority_queue<T,Cont,Cmp>::pull_until(const clock::time_point& tp, T& elem)
{
unique_lock<mutex> lk(super::mtx_);
if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp))
return queue_op_status::timeout;
pull(lk, elem);
return queue_op_status::success;
}
//////////////////////
template <class T, class Cont,class Cmp>
queue_op_status
sync_priority_queue<T,Cont,Cmp>::pull_for(const clock::duration& dura, T& elem)
{
return pull_until(clock::now() + dura, elem);
}
//////////////////////
template <class T, class Container,class Cmp>
queue_op_status
sync_priority_queue<T,Container,Cmp>::try_pull(unique_lock<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull(lk, elem);
return queue_op_status::success;
}
template <class T, class Container,class Cmp>
queue_op_status
sync_priority_queue<T,Container,Cmp>::try_pull(lock_guard<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull(lk, elem);
return queue_op_status::success;
}
template <class T, class Container,class Cmp>
queue_op_status
sync_priority_queue<T,Container,Cmp>::try_pull(T& elem)
{
lock_guard<mutex> lk(super::mtx_);
return try_pull(lk, elem);
}
//////////////////////
template <class T,class Container, class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::wait_pull(unique_lock<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
}
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
pull(lk, elem);
return queue_op_status::success;
}
template <class T,class Container, class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::wait_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_pull(lk, elem);
}
//////////////////////
template <class T,class Container, class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::nonblocking_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock()) return queue_op_status::busy;
return try_pull(lk, elem);
}
} //end concurrent namespace
using concurrent::sync_priority_queue;
} //end boost namespace
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,544 +0,0 @@
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_QUEUE_HPP
#define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_QUEUE_HPP
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/thread/detail/config.hpp>
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/csbl/deque.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
template <typename ValueType>
class sync_queue
: public detail::sync_queue_base<ValueType, csbl::deque<ValueType> >
{
typedef detail::sync_queue_base<ValueType, csbl::deque<ValueType> > super;
public:
typedef ValueType value_type;
//typedef typename super::value_type value_type; // fixme
typedef typename super::underlying_queue_type underlying_queue_type;
typedef typename super::size_type size_type;
typedef typename super::op_status op_status;
// Constructors/Assignment/Destructors
BOOST_THREAD_NO_COPYABLE(sync_queue)
inline sync_queue();
//template <typename Range>
//inline explicit sync_queue(Range range);
inline ~sync_queue();
// Modifiers
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void push(const value_type& x);
inline bool try_push(const value_type& x);
inline bool try_push(no_block_tag, const value_type& x);
inline void push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
#endif
inline void push_back(const value_type& x);
inline queue_op_status try_push_back(const value_type& x);
inline queue_op_status nonblocking_push_back(const value_type& x);
inline queue_op_status wait_push_back(const value_type& x);
inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
// Observers/Modifiers
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void pull(value_type&);
inline void pull(ValueType& elem, bool & closed);
// enable_if is_nothrow_copy_movable<value_type>
inline value_type pull();
inline shared_ptr<ValueType> ptr_pull();
#endif
inline void pull_front(value_type&);
// enable_if is_nothrow_copy_movable<value_type>
inline value_type pull_front();
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline bool try_pull(value_type&);
inline bool try_pull(no_block_tag,value_type&);
inline shared_ptr<ValueType> try_pull();
#endif
inline queue_op_status try_pull_front(value_type&);
inline queue_op_status nonblocking_pull_front(value_type&);
inline queue_op_status wait_pull_front(ValueType& elem);
private:
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
#endif
inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void pull(value_type& elem, unique_lock<mutex>& )
{
elem = boost::move(super::data_.front());
super::data_.pop_front();
}
inline value_type pull(unique_lock<mutex>& )
{
value_type e = boost::move(super::data_.front());
super::data_.pop_front();
return boost::move(e);
}
inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& )
{
shared_ptr<value_type> res = make_shared<value_type>(boost::move(super::data_.front()));
super::data_.pop_front();
return res;
}
#endif
inline void pull_front(value_type& elem, unique_lock<mutex>& )
{
elem = boost::move(super::data_.front());
super::data_.pop_front();
}
inline value_type pull_front(unique_lock<mutex>& )
{
value_type e = boost::move(super::data_.front());
super::data_.pop_front();
return boost::move(e);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
inline void push(const value_type& elem, unique_lock<mutex>& lk)
{
super::data_.push_back(elem);
super::notify_not_empty_if_needed(lk);
}
inline void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
{
super::data_.push_back(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
#endif
inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
{
super::data_.push_back(elem);
super::notify_not_empty_if_needed(lk);
}
inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
{
super::data_.push_back(boost::move(elem));
super::notify_not_empty_if_needed(lk);
}
};
template <typename ValueType>
sync_queue<ValueType>::sync_queue() :
super()
{
}
// template <typename ValueType>
// template <typename Range>
// explicit sync_queue<ValueType>::sync_queue(Range range) :
// data_(), closed_(false)
// {
// try
// {
// typedef typename Range::iterator iterator_t;
// iterator_t first = boost::begin(range);
// iterator_t end = boost::end(range);
// for (iterator_t cur = first; cur != end; ++cur)
// {
// data_.push(boost::move(*cur));;
// }
// notify_not_empty_if_needed(lk);
// }
// catch (...)
// {
// delete[] data_;
// }
// }
template <typename ValueType>
sync_queue<ValueType>::~sync_queue()
{
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
super::throw_if_closed(lk);
return false;
}
pull(elem, lk);
return true;
}
template <typename ValueType>
shared_ptr<ValueType> sync_queue<ValueType>::try_pull(unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
super::throw_if_closed(lk);
return shared_ptr<ValueType>();
}
return ptr_pull(lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
pull_front(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
}
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
pull_front(elem, lk);
return queue_op_status::success;
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_pull(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_pull(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_pull_front(elem, lk);
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_pull_front(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_pull(no_block_tag,ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return false;
}
return try_pull(elem, lk);
}
template <typename ValueType>
boost::shared_ptr<ValueType> sync_queue<ValueType>::try_pull()
{
unique_lock<mutex> lk(super::mtx_);
return try_pull(lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::nonblocking_pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_pull_front(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_queue<ValueType>::pull(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
pull(elem, lk);
}
template <typename ValueType>
void sync_queue<ValueType>::pull(ValueType& elem, bool & has_been_closed)
{
unique_lock<mutex> lk(super::mtx_);
has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) {return;}
pull(elem, lk);
}
// enable if ValueType is nothrow movable
template <typename ValueType>
ValueType sync_queue<ValueType>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull(lk);
}
template <typename ValueType>
boost::shared_ptr<ValueType> sync_queue<ValueType>::ptr_pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return ptr_pull(lk);
}
#endif
template <typename ValueType>
void sync_queue<ValueType>::pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
pull_front(elem, lk);
}
// enable if ValueType is nothrow movable
template <typename ValueType>
ValueType sync_queue<ValueType>::pull_front()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull_front(lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
{
super::throw_if_closed(lk);
push(elem, lk);
return true;
}
template <typename ValueType>
bool sync_queue<ValueType>::try_push(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push_back(elem, lk);
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(elem, lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_push_back(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(no_block_tag, const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock()) return false;
return try_push(elem, lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::nonblocking_push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock()) return queue_op_status::busy;
return try_push_back(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_queue<ValueType>::push(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push(elem, lk);
}
#endif
template <typename ValueType>
void sync_queue<ValueType>::push_back(const ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push_back(elem, lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
super::throw_if_closed(lk);
push(boost::move(elem), lk);
return true;
}
template <typename ValueType>
bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(boost::move(elem), lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
return try_push_back(boost::move(elem), lk);
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
if (super::closed(lk)) return queue_op_status::closed;
push_back(boost::move(elem), lk);
return queue_op_status::success;
}
template <typename ValueType>
queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_push_back(boost::move(elem), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
bool sync_queue<ValueType>::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return false;
}
return try_push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
queue_op_status sync_queue<ValueType>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (!lk.owns_lock())
{
return queue_op_status::busy;
}
return try_push_back(boost::move(elem), lk);
}
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
template <typename ValueType>
void sync_queue<ValueType>::push(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push(boost::move(elem), lk);
}
#endif
template <typename ValueType>
void sync_queue<ValueType>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
{
unique_lock<mutex> lk(super::mtx_);
super::throw_if_closed(lk);
push_back(boost::move(elem), lk);
}
template <typename ValueType>
sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
{
sbq.push_back(boost::move(elem));
return sbq;
}
template <typename ValueType>
sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, ValueType const&elem)
{
sbq.push_back(elem);
return sbq;
}
template <typename ValueType>
sync_queue<ValueType>& operator>>(sync_queue<ValueType>& sbq, ValueType &elem)
{
sbq.pull_front(elem);
return sbq;
}
}
using concurrent::sync_queue;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,431 +0,0 @@
// Copyright (C) 2014 Ian Forbed
// Copyright (C) 2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_THREAD_SYNC_TIMED_QUEUE_HPP
#define BOOST_THREAD_SYNC_TIMED_QUEUE_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/concurrent_queues/sync_priority_queue.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/chrono_io.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace concurrent
{
namespace detail
{
template <class T>
struct scheduled_type
{
typedef typename chrono::steady_clock clock;
typedef chrono::steady_clock::time_point time_point;
T data;
time_point time;
BOOST_THREAD_COPYABLE_AND_MOVABLE(scheduled_type)
scheduled_type(T const& pdata, time_point tp) : data(pdata), time(tp) {}
scheduled_type(BOOST_THREAD_RV_REF(T) pdata, time_point tp) : data(boost::move(pdata)), time(tp) {}
scheduled_type(scheduled_type const& other) : data(other.data), time(other.time) {}
scheduled_type& operator=(BOOST_THREAD_COPY_ASSIGN_REF(scheduled_type) other) {
data = other.data;
time = other.time;
return *this;
}
scheduled_type(BOOST_THREAD_RV_REF(scheduled_type) other) : data(boost::move(other.data)), time(other.time) {}
scheduled_type& operator=(BOOST_THREAD_RV_REF(scheduled_type) other) {
data = boost::move(other.data);
time = other.time;
return *this;
}
bool time_not_reached() const
{
return time > clock::now();
}
bool operator <(const scheduled_type<T> other) const
{
return this->time > other.time;
}
}; //end struct
} //end detail namespace
template <class T>
class sync_timed_queue
: private sync_priority_queue<detail::scheduled_type<T> >
{
typedef detail::scheduled_type<T> stype;
typedef sync_priority_queue<stype> super;
public:
//typedef typename stype::clock clock; // fixme
typedef typename chrono::steady_clock clock;
typedef typename clock::duration duration;
typedef typename clock::time_point time_point;
typedef T value_type;
//typedef typename super::value_type value_type; // fixme
typedef typename super::underlying_queue_type underlying_queue_type;
typedef typename super::size_type size_type;
typedef typename super::op_status op_status;
sync_timed_queue() : super() {};
~sync_timed_queue() {}
using super::size;
using super::empty;
using super::full;
using super::close;
using super::closed;
T pull();
void pull(T& elem);
queue_op_status pull_until(const clock::time_point& tp, T& elem);
queue_op_status pull_for(const clock::duration& dura, T& elem);
queue_op_status try_pull(T& elem);
queue_op_status wait_pull(T& elem);
queue_op_status nonblocking_pull(T& elem);
void push(const T& elem, const time_point& tp);
void push(const T& elem, const duration& dura);
queue_op_status try_push(const T& elem, const time_point& tp);
queue_op_status try_push(const T& elem, const duration& dura);
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, const time_point& tp);
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, const duration& dura);
private:
T pull(unique_lock<mutex>&);
T pull(lock_guard<mutex>&);
void pull(unique_lock<mutex>&, T& elem);
void pull(lock_guard<mutex>&, T& elem);
queue_op_status try_pull(unique_lock<mutex>&, T& elem);
queue_op_status try_pull(lock_guard<mutex>&, T& elem);
queue_op_status wait_pull(unique_lock<mutex>& lk, T& elem);
//queue_op_status nonblocking_pull(unique_lock<mutex>& lk, T& elem);
bool wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>&);
T pull_when_time_reached(unique_lock<mutex>&);
queue_op_status pull_when_time_reached_until(unique_lock<mutex>&, const clock::time_point& tp, T& elem);
bool time_not_reached(unique_lock<mutex>&);
bool time_not_reached(lock_guard<mutex>&);
bool empty_or_time_not_reached(unique_lock<mutex>&);
bool empty_or_time_not_reached(lock_guard<mutex>&);
sync_timed_queue(const sync_timed_queue&);
sync_timed_queue& operator=(const sync_timed_queue&);
sync_timed_queue(BOOST_THREAD_RV_REF(sync_timed_queue));
sync_timed_queue& operator=(BOOST_THREAD_RV_REF(sync_timed_queue));
}; //end class
template <class T>
void sync_timed_queue<T>::push(const T& elem, const time_point& tp)
{
super::push(stype(elem,tp));
}
template <class T>
void sync_timed_queue<T>::push(const T& elem, const duration& dura)
{
push(elem, clock::now() + dura);
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(const T& elem, const time_point& tp)
{
return super::try_push(stype(elem,tp));
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(const T& elem, const duration& dura)
{
return try_push(elem,clock::now() + dura);
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(BOOST_THREAD_RV_REF(T) elem, const time_point& tp)
{
return super::try_push(stype(boost::move(elem), tp));
}
template <class T>
queue_op_status sync_timed_queue<T>::try_push(BOOST_THREAD_RV_REF(T) elem, const duration& dura)
{
return try_push(boost::move(elem), clock::now() + dura);
}
///////////////////////////
template <class T>
bool sync_timed_queue<T>::time_not_reached(unique_lock<mutex>&)
{
return super::data_.top().time_not_reached();
}
template <class T>
bool sync_timed_queue<T>::time_not_reached(lock_guard<mutex>&)
{
return super::data_.top().time_not_reached();
}
///////////////////////////
template <class T>
bool sync_timed_queue<T>::wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>& lk)
{
for (;;)
{
if (super::closed(lk)) return true;
while (! super::empty(lk)) {
if (! time_not_reached(lk)) return false;
super::not_empty_.wait_until(lk, super::data_.top().time);
if (super::closed(lk)) return true;
}
if (super::closed(lk)) return true;
super::not_empty_.wait(lk);
}
return false;
}
///////////////////////////
template <class T>
T sync_timed_queue<T>::pull_when_time_reached(unique_lock<mutex>& lk)
{
while (time_not_reached(lk))
{
super::throw_if_closed(lk);
super::not_empty_.wait_until(lk,super::data_.top().time);
super::wait_until_not_empty(lk);
}
return pull(lk);
}
template <class T>
queue_op_status
sync_timed_queue<T>::pull_when_time_reached_until(unique_lock<mutex>& lk, const clock::time_point& tp, T& elem)
{
clock::time_point tpmin = (tp < super::data_.top().time) ? tp : super::data_.top().time;
while (time_not_reached(lk))
{
super::throw_if_closed(lk);
if (queue_op_status::timeout == super::not_empty_.wait_until(lk, tpmin)) {
if (time_not_reached(lk)) return queue_op_status::not_ready;
return queue_op_status::timeout;
}
}
pull(lk, elem);
return queue_op_status::success;
}
///////////////////////////
template <class T>
bool sync_timed_queue<T>::empty_or_time_not_reached(unique_lock<mutex>& lk)
{
if ( super::empty(lk) ) return true;
if ( time_not_reached(lk) ) return true;
return false;
}
template <class T>
bool sync_timed_queue<T>::empty_or_time_not_reached(lock_guard<mutex>& lk)
{
if ( super::empty(lk) ) return true;
if ( time_not_reached(lk) ) return true;
return false;
}
///////////////////////////
template <class T>
T sync_timed_queue<T>::pull(unique_lock<mutex>&)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
return boost::move(super::data_.pull().data);
#else
return super::data_.pull().data;
#endif
}
template <class T>
T sync_timed_queue<T>::pull(lock_guard<mutex>&)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
return boost::move(super::data_.pull().data);
#else
return super::data_.pull().data;
#endif
}
template <class T>
T sync_timed_queue<T>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull_when_time_reached(lk);
}
///////////////////////////
template <class T>
void sync_timed_queue<T>::pull(unique_lock<mutex>&, T& elem)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
elem = boost::move(super::data_.pull().data);
#else
elem = super::data_.pull().data;
#endif
}
template <class T>
void sync_timed_queue<T>::pull(lock_guard<mutex>&, T& elem)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
elem = boost::move(super::data_.pull().data);
#else
elem = super::data_.pull().data;
#endif
}
template <class T>
void sync_timed_queue<T>::pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
elem = pull_when_time_reached(lk);
}
//////////////////////
template <class T>
queue_op_status
sync_timed_queue<T>::pull_until(const clock::time_point& tp, T& elem)
{
unique_lock<mutex> lk(super::mtx_);
if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp))
return queue_op_status::timeout;
return pull_when_time_reached_until(lk, tp, elem);
}
//////////////////////
template <class T>
queue_op_status
sync_timed_queue<T>::pull_for(const clock::duration& dura, T& elem)
{
return pull_until(clock::now() + dura, elem);
}
///////////////////////////
template <class T>
queue_op_status sync_timed_queue<T>::try_pull(unique_lock<mutex>& lk, T& elem)
{
if ( super::empty(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
if ( time_not_reached(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::not_ready;
}
pull(lk, elem);
return queue_op_status::success;
}
template <class T>
queue_op_status sync_timed_queue<T>::try_pull(lock_guard<mutex>& lk, T& elem)
{
if ( super::empty(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
}
if ( time_not_reached(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::not_ready;
}
pull(lk, elem);
return queue_op_status::success;
}
template <class T>
queue_op_status sync_timed_queue<T>::try_pull(T& elem)
{
lock_guard<mutex> lk(super::mtx_);
return try_pull(lk, elem);
}
///////////////////////////
template <class T>
queue_op_status sync_timed_queue<T>::wait_pull(unique_lock<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
}
bool has_been_closed = wait_until_not_empty_time_reached_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
pull(lk, elem);
return queue_op_status::success;
}
template <class T>
queue_op_status sync_timed_queue<T>::wait_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_pull(lk, elem);
}
// ///////////////////////////
// template <class T>
// queue_op_status sync_timed_queue<T>::wait_pull(unique_lock<mutex> &lk, T& elem)
// {
// if (super::empty(lk))
// {
// if (super::closed(lk)) return queue_op_status::closed;
// }
// bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
// if (has_been_closed) return queue_op_status::closed;
// pull(lk, elem);
// return queue_op_status::success;
// }
// template <class T>
// queue_op_status sync_timed_queue<T>::wait_pull(T& elem)
// {
// unique_lock<mutex> lk(super::mtx_);
// return wait_pull(lk, elem);
// }
///////////////////////////
template <class T>
queue_op_status sync_timed_queue<T>::nonblocking_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (! lk.owns_lock()) return queue_op_status::busy;
return try_pull(lk, elem);
}
} //end concurrent namespace
using concurrent::sync_timed_queue;
} //end boost namespace
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,45 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_DEQUE_HPP
#define BOOST_CSBL_DEQUE_HPP
#include <boost/config.hpp>
// MSVC has some trouble instantiating a non_copyable type
//C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(606) : error C2248: 'non_copyable::non_copyable' : cannot access private member declared in class 'non_copyable'
// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(24) : see declaration of 'non_copyable::non_copyable'
// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(23) : see declaration of 'non_copyable'
// C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
// with
// [
// _Ty=non_copyable
// ]
#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_HDR_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
#ifndef BOOST_THREAD_USES_BOOST_DEQUE
#define BOOST_THREAD_USES_BOOST_DEQUE
#endif
#include <boost/container/deque.hpp>
#else
#include <deque>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_DEQUE
using ::boost::container::deque;
#else
using ::std::deque;
#endif
}
}
#endif // header

View File

@@ -1,49 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_FUNCTIONAL_HPP
#define BOOST_CSBL_FUNCTIONAL_HPP
#include <boost/config.hpp>
#include <functional>
#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL || defined BOOST_NO_CXX11_HDR_FUNCTIONAL || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_THREAD_USES_BOOST_FUNCTIONAL
#define BOOST_THREAD_USES_BOOST_FUNCTIONAL
#endif
#include <boost/function.hpp>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL
using ::boost::function;
#else
// D.8.1, base (deprecated):
// 20.9.3, reference_wrapper:
// 20.9.4, arithmetic operations:
// 20.9.5, comparisons:
// 20.9.6, logical operations:
// 20.9.7, bitwise operations:
// 20.9.8, negators:
// 20.9.9, bind:
// D.9, binders (deprecated):
// D.8.2.1, adaptors (deprecated):
// D.8.2.2, adaptors (deprecated):
// 20.9.10, member function adaptors:
// 20.9.11 polymorphic function wrappers:
using ::std::function;
// 20.9.12, hash function primary template:
#endif
}
}
#endif // header

View File

@@ -1,35 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_LIST_HPP
#define BOOST_CSBL_LIST_HPP
#include <boost/config.hpp>
#if defined BOOST_THREAD_USES_BOOST_LIST || defined BOOST_NO_CXX11_HDR_LIST || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_THREAD_USES_BOOST_LIST
#define BOOST_THREAD_USES_BOOST_LIST
#endif
#include <boost/container/list.hpp>
#else
#include <list>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_LIST
using ::boost::container::list;
#else
using ::std::list;
#endif
}
}
#endif // header

View File

@@ -1,61 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_HPP
#define BOOST_CSBL_MEMORY_HPP
// 20.7.2 Header <memory> synopsis
// 20.7.3, pointer traits
#include <boost/thread/csbl/memory/pointer_traits.hpp>
// 20.7.4, pointer safety
// 20.7.5, pointer alignment function
// 20.7.6, allocator argument tag
#include <boost/thread/csbl/memory/allocator_arg.hpp>
// 20.7.8, allocator traits
#include <boost/thread/csbl/memory/allocator_traits.hpp>
// 20.7.7, uses_allocator
#include <boost/thread/csbl/memory/scoped_allocator.hpp>
// 20.7.9, the default allocator:
namespace boost
{
namespace csbl
{
using ::std::allocator;
}
}
// 20.7.10, raw storage iterator:
// 20.7.11, temporary buffers:
// 20.7.12, specialized algorithms:
// 20.8.1 class template unique_ptr:
// default_delete
#include <boost/thread/csbl/memory/default_delete.hpp>
#include <boost/thread/csbl/memory/unique_ptr.hpp>
// 20.8.2.1, class bad_weak_ptr:
// 20.8.2.2, class template shared_ptr:
// 20.8.2.2.6, shared_ptr creation
// 20.8.2.2.7, shared_ptr comparisons:
// 20.8.2.2.8, shared_ptr specialized algorithms:
// 20.8.2.2.9, shared_ptr casts:
// 20.8.2.2.10, shared_ptr get_deleter:
// 20.8.2.2.11, shared_ptr I/O:
// 20.8.2.3, class template weak_ptr:
// 20.8.2.3.6, weak_ptr specialized algorithms:
// 20.8.2.3.7, class template owner_less:
// 20.8.2.4, class template enable_shared_from_this:
// 20.8.2.5, shared_ptr atomic access:
// 20.8.2.6 hash support
#endif // header

View File

@@ -1,41 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP
#define BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP
#include <boost/thread/csbl/memory/config.hpp>
// 20.7.6, allocator argument tag
#if defined BOOST_NO_CXX11_ALLOCATOR
#include <boost/container/scoped_allocator.hpp>
namespace boost
{
namespace csbl
{
using ::boost::container::allocator_arg_t;
using ::boost::container::allocator_arg;
}
}
#else
namespace boost
{
namespace csbl
{
using ::std::allocator_arg_t;
using ::std::allocator_arg;
}
}
#endif // BOOST_NO_CXX11_ALLOCATOR
namespace boost
{
using ::boost::csbl::allocator_arg_t;
using ::boost::csbl::allocator_arg;
}
#endif // header

View File

@@ -1,35 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_ALLOCATOR_TRAITS_HPP
#define BOOST_CSBL_MEMORY_ALLOCATOR_TRAITS_HPP
#include <boost/thread/csbl/memory/config.hpp>
// 20.7.8, allocator traits
#if defined BOOST_NO_CXX11_ALLOCATOR
#include <boost/container/allocator_traits.hpp>
namespace boost
{
namespace csbl
{
using ::boost::container::allocator_traits;
}
}
#else
namespace boost
{
namespace csbl
{
using ::std::allocator_traits;
}
}
#endif // BOOST_NO_CXX11_POINTER_TRAITS
#endif // header

View File

@@ -1,16 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_CONFIG_HPP
#define BOOST_CSBL_MEMORY_CONFIG_HPP
#include <boost/config.hpp>
#include <memory>
#endif // header

View File

@@ -1,41 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_DEFAULT_DELETE_HPP
#define BOOST_CSBL_MEMORY_DEFAULT_DELETE_HPP
#include <boost/thread/csbl/memory/config.hpp>
// 20.8.1 class template unique_ptr:
// default_delete
#if defined BOOST_NO_CXX11_SMART_PTR
#include <boost/move/unique_ptr.hpp>
namespace boost
{
namespace csbl
{
using ::boost::movelib::default_delete;
}
}
#else
namespace boost
{
namespace csbl
{
using ::std::default_delete;
}
}
#endif // defined BOOST_NO_CXX11_SMART_PTR
namespace boost
{
using ::boost::csbl::default_delete;
}
#endif // header

View File

@@ -1,35 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_POINTER_TRAITS_HPP
#define BOOST_CSBL_MEMORY_POINTER_TRAITS_HPP
#include <boost/thread/csbl/memory/config.hpp>
// 20.7.3, pointer traits
#if defined BOOST_NO_CXX11_ALLOCATOR
#include <boost/intrusive/pointer_traits.hpp>
namespace boost
{
namespace csbl
{
using ::boost::intrusive::pointer_traits;
}
}
#else
namespace boost
{
namespace csbl
{
using ::std::pointer_traits;
}
}
#endif // BOOST_NO_CXX11_ALLOCATOR
#endif // header

View File

@@ -1,35 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_SCOPED_ALLOCATOR_HPP
#define BOOST_CSBL_MEMORY_SCOPED_ALLOCATOR_HPP
#include <boost/thread/csbl/memory/config.hpp>
// 20.7.7, uses_allocator
#if defined BOOST_NO_CXX11_ALLOCATOR
#include <boost/container/scoped_allocator.hpp>
namespace boost
{
namespace csbl
{
using ::boost::container::uses_allocator;
}
}
#else
namespace boost
{
namespace csbl
{
using ::std::uses_allocator;
}
}
#endif // BOOST_NO_CXX11_POINTER_TRAITS
#endif // header

View File

@@ -1,42 +0,0 @@
// Copyright (C) 2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2014/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_SHARED_PTR_HPP
#define BOOST_CSBL_MEMORY_SHARED_PTR_HPP
#include <boost/thread/csbl/memory/config.hpp>
#if defined BOOST_NO_CXX11_SMART_PTR
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
namespace boost
{
namespace csbl
{
using ::boost::shared_ptr;
using ::boost::make_shared;
}
}
#else
#include <boost/shared_ptr.hpp>
namespace boost
{
namespace csbl
{
using std::shared_ptr;
using std::make_shared;
}
}
#endif
#endif // header

View File

@@ -1,28 +0,0 @@
// Copyright (C) 2013-2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation using interprocess::unique_ptr.
// 2014/09 Vicente J. Botet Escriba
// Adaptation to movelib::unique_ptr
#ifndef BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
#define BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
#include <boost/thread/csbl/memory/config.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/move/make_unique.hpp>
namespace boost
{
namespace csbl
{
using ::boost::movelib::unique_ptr;
using ::boost::movelib::make_unique;
}
}
#endif // header

View File

@@ -1,49 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_TUPLE_HPP
#define BOOST_CSBL_TUPLE_HPP
#include <boost/config.hpp>
#if defined BOOST_THREAD_USES_BOOST_TUPLE || defined BOOST_NO_CXX11_HDR_TUPLE || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#include <boost/tuple/tuple.hpp>
#ifndef BOOST_THREAD_USES_BOOST_TUPLE
#define BOOST_THREAD_USES_BOOST_TUPLE
#endif
#else
#include <tuple>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_TUPLE
using ::boost::tuple;
using ::boost::get;
using ::boost::make_tuple;
//using ::boost::tuple_size;
#else
// 20.4.2, class template tuple:
using ::std::tuple;
using ::std::get;
using ::std::make_tuple;
using ::std::tuple_size;
// 20.4.2.4, tuple creation functions:
// 20.4.2.5, tuple helper classes:
// 20.4.2.6, element access:
// 20.4.2.7, relational operators:
// 20.4.2.8, allocator-related traits
// 20.4.2.9, specialized algorithms:
#endif
}
}
#endif // header

View File

@@ -1,35 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_VECTOR_HPP
#define BOOST_CSBL_VECTOR_HPP
#include <boost/config.hpp>
#if defined BOOST_THREAD_USES_BOOST_VECTOR || defined BOOST_NO_CXX11_HDR_VECTOR || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_THREAD_USES_BOOST_VECTOR
#define BOOST_THREAD_USES_BOOST_VECTOR
#endif
#include <boost/container/vector.hpp>
#else
#include <vector>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_VECTOR
using ::boost::container::vector;
#else
using ::std::vector;
#endif
}
}
#endif // header

View File

@@ -9,7 +9,7 @@
#ifndef BOOST_THREAD_CV_STATUS_HPP
#define BOOST_THREAD_CV_STATUS_HPP
#include <boost/core/scoped_enum.hpp>
#include <boost/detail/scoped_enum_emulation.hpp>
namespace boost
{

View File

@@ -0,0 +1,571 @@
// Copyright (C) 2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 2013/04 Vicente J. Botet Escriba
// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined.
// Make use of Boost.Move
// Make use of Boost.Tuple (movable)
// 2012/11 Vicente J. Botet Escriba
// Adapt to boost libc++ implementation
//===----------------------------------------------------------------------===//
//
// 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.
//
// The async_func code is based on the one from libcxx.
//===----------------------------------------------------------------------===//
#ifndef BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP
#define BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP
#include <boost/config.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/detail/invoke.hpp>
#include <boost/thread/detail/make_tuple_indices.hpp>
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
! defined(BOOST_NO_CXX11_HDR_TUPLE)
#include <tuple>
#else
#include <boost/tuple/tuple.hpp>
#endif
namespace boost
{
namespace detail
{
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
! defined(BOOST_NO_CXX11_HDR_TUPLE)
template <class Fp, class ... Args>
class async_func
{
std::tuple<Fp, Args...> f_;
public:
BOOST_THREAD_MOVABLE_ONLY( async_func)
//typedef typename invoke_of<_Fp, _Args...>::type Rp;
typedef typename result_of<Fp(Args...)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args)... args)
: f_(boost::move(f), boost::move(args)...)
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f) : f_(boost::move(f.f_))
{}
result_type operator()()
{
typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
return execute(Index());
}
private:
template <size_t ...Indices>
result_type
execute(tuple_indices<Indices...>)
{
return invoke(boost::move(std::get<0>(f_)), boost::move(std::get<Indices>(f_))...);
}
};
//BOOST_THREAD_DCL_MOVABLE_BEG(X) async_func<Fp> BOOST_THREAD_DCL_MOVABLE_END
#else
template <class Fp,
class T0 = tuples::null_type, class T1 = tuples::null_type, class T2 = tuples::null_type,
class T3 = tuples::null_type, class T4 = tuples::null_type, class T5 = tuples::null_type,
class T6 = tuples::null_type, class T7 = tuples::null_type, class T8 = tuples::null_type
, class T9 = tuples::null_type
>
class async_func;
template <class Fp,
class T0 , class T1 , class T2 ,
class T3 , class T4 , class T5 ,
class T6 , class T7 , class T8 >
class async_func<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
T7 v7_;
T8 v8_;
//::boost::tuple<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8> f_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7, T8)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
, BOOST_THREAD_RV_REF(T7) a7
, BOOST_THREAD_RV_REF(T8) a8
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
, v7_(boost::move(a7))
, v8_(boost::move(a8))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
, v4_(boost::move(f.a4))
, v5_(boost::move(f.a5))
, v6_(boost::move(f.a6))
, v7_(boost::move(f.a7))
, v8_(boost::move(f.a8))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
, boost::move(v7_)
, boost::move(v8_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
class async_func<Fp, T0, T1, T2, T3, T4, T5, T6, T7>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
T7 v7_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
, BOOST_THREAD_RV_REF(T7) a7
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
, v7_(boost::move(a7))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
, v4_(boost::move(f.a4))
, v5_(boost::move(f.a5))
, v6_(boost::move(f.a6))
, v7_(boost::move(f.a7))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
, boost::move(v7_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6>
class async_func<Fp, T0, T1, T2, T3, T4, T5, T6>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
, v4_(boost::move(f.a4))
, v5_(boost::move(f.a5))
, v6_(boost::move(f.a6))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5>
class async_func<Fp, T0, T1, T2, T3, T4, T5>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
, v4_(boost::move(f.a4))
, v5_(boost::move(f.a5))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4>
class async_func<Fp, T0, T1, T2, T3, T4>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3, T4)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
, v4_(boost::move(f.a4))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3>
class async_func<Fp, T0, T1, T2, T3>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2, T3)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
, v3_(boost::move(f.a3))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
);
}
};
template <class Fp, class T0, class T1, class T2>
class async_func<Fp, T0, T1, T2>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1, T2)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
, v2_(boost::move(f.a2))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
);
}
};
template <class Fp, class T0, class T1>
class async_func<Fp, T0, T1>
{
Fp fp_;
T0 v0_;
T1 v1_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0, T1)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
, v1_(boost::move(f.a1))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
);
}
};
template <class Fp, class T0>
class async_func<Fp, T0>
{
Fp fp_;
T0 v0_;
public:
BOOST_THREAD_MOVABLE_ONLY(async_func)
typedef typename result_of<Fp(T0)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_RV_REF(async_func) f)
: fp_(boost::move(f.fp))
, v0_(boost::move(f.a0))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
);
}
};
template <class Fp>
class async_func<Fp>
{
Fp fp_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(async_func)
typedef typename result_of<Fp()>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit async_func(BOOST_THREAD_FWD_REF(Fp) f)
: fp_(boost::move(f))
{}
BOOST_SYMBOL_VISIBLE
async_func(BOOST_THREAD_FWD_REF(async_func) f)
: fp_(boost::move(f.fp_))
{}
result_type operator()()
{
return fp_();
}
};
#endif
}
}
#endif // header

View File

@@ -15,7 +15,8 @@
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
// ATTRIBUTE_MAY_ALIAS
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) > 302 \
&& !defined(__INTEL_COMPILER)
// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
// regard to violation of the strict aliasing rules.
@@ -239,7 +240,7 @@
! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
! defined(BOOST_NO_CXX11_DECLTYPE) && \
! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
! defined(BOOST_NO_CXX11_AUTO) && \
! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
! defined(BOOST_NO_CXX11_HDR_TUPLE)
@@ -247,22 +248,6 @@
#endif
#endif
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY \
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_WHEN_ALL_WHEN_ANY
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
! defined(BOOST_NO_CXX11_HDR_TUPLE)
#define BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
#endif
#endif
// ! defined(BOOST_NO_SFINAE_EXPR) &&
// ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) &&
// ! defined(BOOST_NO_CXX11_AUTO) &&
// ! defined(BOOST_NO_CXX11_DECLTYPE) &&
// ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) &&
// MAKE_READY_AT_THREAD_EXIT
#if ! defined BOOST_THREAD_PROVIDES_MAKE_READY_AT_THREAD_EXIT \
@@ -279,11 +264,6 @@
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#endif
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP \
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_UNWRAP
#define BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
#endif
// FUTURE_INVALID_AFTER_GET
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET \
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET
@@ -353,12 +333,6 @@
#endif
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_THREAD_USES_MOVE
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_FUTURE_USES_OPTIONAL
#endif
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
# pragma warn -8008 // Condition always true/false
# pragma warn -8080 // Identifier declared but never used
@@ -384,9 +358,7 @@
// compatibility with the rest of Boost's auto-linking code:
#if defined(BOOST_THREAD_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
# undef BOOST_THREAD_USE_LIB
# if !defined(BOOST_THREAD_USE_DLL)
# define BOOST_THREAD_USE_DLL
# endif
# define BOOST_THREAD_USE_DLL
#endif
#if defined(BOOST_THREAD_BUILD_DLL) //Build dll

View File

@@ -75,28 +75,15 @@ namespace boost
};
struct counter_is_not_zero
{
counter_is_not_zero(counter const& count) : count_(count) {}
counter_is_not_zero(const counter& count) : count_(count) {}
bool operator()() const { return count_ != 0; }
counter const& count_;
const counter& count_;
};
struct counter_is_zero
{
counter_is_zero(counter const& count) : count_(count) {}
counter_is_zero(const counter& count) : count_(count) {}
bool operator()() const { return count_ == 0; }
counter const& count_;
};
struct is_zero
{
is_zero(std::size_t& count) : count_(count) {}
bool operator()() const { return count_ == 0; }
std::size_t& count_;
};
struct not_equal
{
not_equal(std::size_t& x, std::size_t& y) : x_(x), y_(y) {}
bool operator()() const { return x_ != y_; }
std::size_t& x_;
std::size_t& y_;
const counter& count_;
};
}
} // namespace boost

View File

@@ -15,8 +15,7 @@
* BOOST_THREAD_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or
* makes it private.
*/
#if ! defined BOOST_NO_CXX11_DELETED_FUNCTIONS && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
CLASS(CLASS const&) = delete; \

View File

@@ -1,93 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
// Make use of Boost.Move
#ifndef BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP
#define BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP
#include <boost/config.hpp>
#include <boost/thread/detail/memory.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/csbl/memory/unique_ptr.hpp>
#include <memory>
#include <functional>
namespace boost
{
namespace detail
{
class function_wrapper
{
struct impl_base
{
virtual void call()=0;
virtual ~impl_base()
{
}
};
typedef boost::csbl::unique_ptr<impl_base> impl_base_type;
impl_base_type impl;
template <typename F>
struct impl_type: impl_base
{
F f;
impl_type(F const &f_)
: f(f_)
{}
impl_type(BOOST_THREAD_RV_REF(F) f_)
: f(boost::move(f_))
{}
void call()
{
if (impl) f();
}
};
public:
BOOST_THREAD_MOVABLE_ONLY(function_wrapper)
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename F>
function_wrapper(F const& f):
impl(new impl_type<F>(f))
{}
//#endif
template<typename F>
function_wrapper(BOOST_THREAD_RV_REF(F) f):
impl(new impl_type<F>(boost::forward<F>(f)))
{}
function_wrapper(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT :
impl(other.impl)
{
other.impl = 0;
}
function_wrapper()
: impl(0)
{
}
~function_wrapper()
{
}
function_wrapper& operator=(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT
{
impl=other.impl;
other.impl=0;
return *this;
}
void operator()()
{ impl->call();}
};
}
}
#endif // header

View File

@@ -28,11 +28,7 @@
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_member_function_pointer.hpp>
#include <boost/type_traits/remove_reference.hpp>
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
#include <functional>
@@ -44,10 +40,11 @@ namespace boost
{
#if ! defined(BOOST_NO_SFINAE_EXPR) && \
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
! defined(BOOST_NO_SFINAE_EXPR) && \
! defined(BOOST_NO_CXX11_DECLTYPE) && \
! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
! defined(BOOST_NO_CXX11_AUTO)
#define BOOST_THREAD_PROVIDES_INVOKE
@@ -61,13 +58,6 @@ namespace boost
{
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
}
template <class R, class Fp, class A0, class ...Args>
inline auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...))
{
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
}
template <class Fp, class A0, class ...Args>
inline auto
@@ -76,13 +66,6 @@ namespace boost
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
}
template <class R, class Fp, class A0, class ...Args>
inline auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...))
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
}
// bullets 3 and 4
@@ -102,38 +85,14 @@ namespace boost
return (*boost::forward<A0>(a0)).*f;
}
template <class R, class Fp, class A0>
inline auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype(boost::forward<A0>(a0).*f)
{
return boost::forward<A0>(a0).*f;
}
template <class R, class Fp, class A0>
inline auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype((*boost::forward<A0>(a0)).*f)
{
return (*boost::forward<A0>(a0)).*f;
}
// bullet 5
template <class R, class Fp, class ...Args>
inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
-> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...))
{
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
}
template <class Fp, class ...Args>
inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
-> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...))
{
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
}
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
// bullets 1 and 2
@@ -146,45 +105,21 @@ namespace boost
{
return (boost::forward<A0>(a0).*f)();
}
template <class R, class Fp, class A0>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype((boost::forward<A0>(a0).*f)())
{
return (boost::forward<A0>(a0).*f)();
}
template <class Fp, class A0, class A1>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)))
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(a1)))
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
}
template <class R, class Fp, class A0, class A1>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)))
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(a1));
}
template <class Fp, class A0, class A1, class A2>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2)))
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class R, class Fp, class A0, class A1, class A2>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2));
}
template <class Fp, class A0>
@@ -195,45 +130,21 @@ namespace boost
{
return ((*boost::forward<A0>(a0)).*f)();
}
template <class R, class Fp, class A0>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype(((*boost::forward<A0>(a0)).*f)())
{
return ((*boost::forward<A0>(a0)).*f)();
}
template <class Fp, class A0, class A1>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)))
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1)))
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1));
}
template <class R, class Fp, class A0, class A1>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)))
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
}
template <class Fp, class A0, class A1, class A2>
template <class Fp, class A0, class A1>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2)))
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class R, class Fp, class A0, class A1, class A2>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
{
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2));
}
// bullets 3 and 4
@@ -246,14 +157,6 @@ namespace boost
{
return boost::forward<A0>(a0).*f;
}
template <class R, class Fp, class A0>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype(boost::forward<A0>(a0).*f)
{
return boost::forward<A0>(a0).*f;
}
template <class Fp, class A0>
inline
@@ -263,14 +166,6 @@ namespace boost
{
return (*boost::forward<A0>(a0)).*f;
}
template <class R, class Fp, class A0>
inline
auto
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
-> decltype((*boost::forward<A0>(a0)).*f)
{
return (*boost::forward<A0>(a0)).*f;
}
// bullet 5
@@ -283,7 +178,7 @@ namespace boost
}
template <class Fp, class A1>
inline
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) a1)
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1)))
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1));
@@ -302,36 +197,6 @@ namespace boost
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class R, class Fp>
inline
auto invoke(BOOST_THREAD_RV_REF(Fp) f)
-> decltype(boost::forward<Fp>(f)())
{
return boost::forward<Fp>(f)();
}
template <class R, class Fp, class A1>
inline
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1)))
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1));
}
template <class R, class Fp, class A1, class A2>
inline
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class R, class Fp, class A1, class A2, class A3>
inline
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)))
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
#elif ! defined(BOOST_NO_SFINAE_EXPR) && \
@@ -530,28 +395,22 @@ namespace boost
// bullet 5
// f(t1, t2, ..., tN) in all other cases.
template <class Ret, class Fp, class ...Args>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
{
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
}
template <class Ret, class Fp, class ...Args>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
{
return f(boost::forward<Args>(args)...);
}
template <class Ret, class Fp, class ...Args>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<Args>(args)...);
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
}
template <class Ret, class ...Args>
inline Ret
invoke(Ret(*f)(Args... ), BOOST_THREAD_RV_REF(Args) ...args)
{
return f(boost::forward<Args>(args)...);
}
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
// bullet 1
@@ -565,34 +424,9 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(), A0& a0)
invoke(Ret (A::*f)(), BOOST_THREAD_RV_REF(A0) a0)
{
return (a0.*f)();
}
template <class Ret, class A, class A0>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(), A0* a0)
{
return ((*a0).*f)();
}
template <class Ret, class A, class A0, class A1>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1),
A0& a0, BOOST_THREAD_RV_REF(A1) a1
)
{
return (a0.*f)(boost::forward<A1>(a1));
return (boost::forward<A0>(a0).*f)();
}
template <class Ret, class A, class A0, class A1>
inline
@@ -601,33 +435,21 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1), A0& a0, A1 a1)
invoke(Ret (A::*f)(A1), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
}
template <class Ret, class A, class A0, class A1>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1), A0 a0, A1 a1)
{
return (a0.*f)(a1);
}
template <class Ret, class A, class A0, class A1>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1), A0* a0, BOOST_THREAD_RV_REF(A1) a1
)
{
return (*(a0).*f)(boost::forward<A1>(a1));
}
template <class Ret, class A, class A0, class A1>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1), A0* a0, A1 a1)
{
return (*a0.*f)(a1);
}
template <class Ret, class A, class A0, class A1, class A2>
inline
typename enable_if_c
@@ -636,10 +458,10 @@ namespace boost
Ret
>::type
invoke(Ret (A::*f)(A1, A2),
A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
)
{
return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class A, class A0, class A1, class A2>
inline
@@ -648,9 +470,9 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1, A2), A0* a0, A1 a1, A2 a2)
invoke(Ret (A::*f)(A1, A2), A0 a0, A1 a1, A2 a2)
{
return ((*a0).*f)(a1, a2);
return (a0.*f)(a1, a2);
}
template <class Ret, class A, class A0, class A1, class A2, class A3>
inline
@@ -660,9 +482,9 @@ namespace boost
Ret
>::type
invoke(Ret (A::*f)(A1, A2, A3),
A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class Ret, class A, class A0, class A1, class A2, class A3>
inline
@@ -671,9 +493,9 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1, A2, A3), A0* a0, A1 a1, A2 a2, A3 a3)
invoke(Ret (A::*f)(A1, A2, A3), A0 a0, A1 a1, A2 a2, A3 a3)
{
return ((*a0).*f)(a1, a2, a3);
return (a0.*f)(a1, a2, a3);
}
///
@@ -684,20 +506,9 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)() const, A0 const& a0)
invoke(Ret (A::*f)() const, BOOST_THREAD_RV_REF(A0) a0)
{
return (a0.*f)();
}
template <class Ret, class A, class A0>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)() const, A0 const* a0)
{
return ((*a0).*f)();
return (boost::forward<A0>(a0).*f)();
}
template <class Ret, class A, class A0, class A1>
inline
@@ -706,9 +517,9 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1) const, A0 const& a0, BOOST_THREAD_RV_REF(A1) a1)
invoke(Ret (A::*f)(A1) const, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
{
return (a0.*f)(boost::forward<A1>(a1));
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
}
template <class Ret, class A, class A0, class A1>
inline
@@ -717,19 +528,7 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1) const, A0 const* a0, BOOST_THREAD_RV_REF(A1) a1)
{
return ((*a0).*f)(boost::forward<A1>(a1));
}
template <class Ret, class A, class A0, class A1>
inline
typename enable_if_c
<
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1) const, A0 const& a0, A1 a1)
invoke(Ret (A::*f)(A1) const, A0 a0, A1 a1)
{
return (a0.*f)(a1);
}
@@ -741,7 +540,7 @@ namespace boost
Ret
>::type
invoke(Ret (A::*f)(A1, A2) const,
A0 const& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
)
{
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)
@@ -754,7 +553,7 @@ namespace boost
is_base_of<A, typename remove_reference<A0>::type>::value,
Ret
>::type
invoke(Ret (A::*f)(A1, A2) const, A0 const& a0, A1 a1, A2 a2)
invoke(Ret (A::*f)(A1, A2) const, A0 a0, A1 a1, A2 a2)
{
return (a0.*f)(a1, a2);
}
@@ -1360,241 +1159,189 @@ namespace boost
// f(t1, t2, ..., tN) in all other cases.
template <class Ret, class Fp>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f)
inline
typename enable_if_c
<
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f)
{
return boost::forward<Fp>(f)();
}
template <class Ret, class Fp>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f)
{
return f();
}
template <class Ret, class Fp>
template <class Ret, class Fp, class A1>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f));
}
template <class Ret, class Fp, class A1>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1));
}
template <class Ret, class Fp, class A1>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
{
return f(boost::forward<A1>(a1));
}
template <class Ret, class Fp, class A1>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
invoke(BOOST_THREAD_RV_REF(Fp) f, A1 a1)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1));
return boost::forward<Fp>(f)(a1);
}
template <class Ret, class Fp, class A1, class A2>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
inline
typename enable_if_c
<
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class Fp, class A1, class A2>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class Fp, class A1, class A2>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
invoke(BOOST_THREAD_RV_REF(Fp) f, A1 a1, A2 a2)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2));
return boost::forward<Fp>(f)(a1, a2);
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
inline
typename enable_if_c
<
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class Ret, class Fp, class A1>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
{
return boost::forward<Fp>(f)(a1);
}
template <class Ret, class Fp, class A1>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
{
return f(a1);
}
template <class Ret, class Fp, class A1>
inline
typename disable_if_c
<
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1);
}
template <class Ret, class Fp, class A1, class A2>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
{
return boost::forward<Fp>(f)(a1, a2);
}
template <class Ret, class Fp, class A1, class A2>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
{
return f(a1, a2);
}
template <class Ret, class Fp, class A1, class A2>
inline
typename disable_if_c
<
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2);
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
invoke(BOOST_THREAD_RV_REF(Fp) f, A1 a1, A2 a2, A3 a3)
{
return boost::forward<Fp>(f)(a1, a2, a3);
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
{
return f(a1, a2, a3);
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline
typename disable_if_c
<
is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
{
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2, a3);
}
///
template <class Ret, class Fp>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp &f)
invoke(Fp const &f)
{
return f();
}
template <class Ret, class Fp, class A1>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1)
invoke(Fp const &f, BOOST_THREAD_RV_REF(A1) a1)
{
return f(boost::forward<A1>(a1));
}
template <class Ret, class Fp, class A1>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp &f, A1 a1)
invoke(Fp const &f, A1 a1)
{
return f(a1);
}
template <class Ret, class Fp, class A1, class A2>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
invoke(Fp const &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class Fp, class A1, class A2>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp &f, A1 a1, A2 a2)
invoke(Fp const &f, A1 a1, A2 a2)
{
return f(a1, a2);
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
invoke(Fp const &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
template <class Ret, class Fp, class A1, class A2, class A3>
inline
typename disable_if_c
typename enable_if_c
<
is_member_function_pointer<Fp>::value,
! is_member_function_pointer<Fp>::value,
Ret
>::type
invoke(Fp &f, A1 a1, A2 a2, A3 a3)
invoke(Fp const &f, A1 a1, A2 a2, A3 a3)
{
return f(a1, a2, a3);
}
///
template <class Ret>
inline Ret
invoke(Ret(*f)())
{
return f();
}
template <class Ret, class A1>
inline Ret
invoke(Ret(*f)(A1), BOOST_THREAD_RV_REF(A1) a1)
{
return f(boost::forward<A1>(a1));
}
template <class Ret, class A1, class A2>
inline Ret
invoke(Ret(*f)(A1, A2),
BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
}
template <class Ret, class A1, class A2, class A3>
inline Ret
invoke(Ret(*f)(A1, A2, A3),
BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
{
return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
}
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif // all

View File

@@ -1,754 +0,0 @@
// Copyright (C) 2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// 2013/04 Vicente J. Botet Escriba
// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined.
// Make use of Boost.Move
// Make use of Boost.Tuple (movable)
// 2012/11 Vicente J. Botet Escriba
// Adapt to boost libc++ implementation
//===----------------------------------------------------------------------===//
//
// 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.
//
// The invoker code is based on the one from libcxx.
//===----------------------------------------------------------------------===//
#ifndef BOOST_THREAD_DETAIL_INVOKER_HPP
#define BOOST_THREAD_DETAIL_INVOKER_HPP
#include <boost/config.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/detail/invoke.hpp>
#include <boost/thread/detail/make_tuple_indices.hpp>
#include <boost/thread/csbl/tuple.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/thread/detail/variadic_header.hpp>
namespace boost
{
namespace detail
{
#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
template <class Fp, class ... Args>
class invoker
{
//typedef typename decay<Fp>::type Fpd;
//typedef tuple<typename decay<Args>::type...> Argsd;
//csbl::tuple<Fpd, Argsd...> f_;
csbl::tuple<Fp, Args...> f_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker)
//typedef typename invoke_of<_Fp, _Args...>::type Rp;
typedef typename result_of<Fp(Args...)>::type result_type;
template <class F, class ... As>
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args)
: f_(boost::forward<F>(f), boost::forward<As>(args)...)
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f) : f_(boost::move(BOOST_THREAD_RV(f).f_))
{}
BOOST_SYMBOL_VISIBLE
invoker( const invoker& f) : f_(f.f_)
{}
BOOST_SYMBOL_VISIBLE
invoker& operator=(BOOST_THREAD_RV_REF(invoker) f)
{
f_ = boost::move(BOOST_THREAD_RV(f).f_);
}
BOOST_SYMBOL_VISIBLE
invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f)
{
f_ = f.f_;
}
result_type operator()()
{
typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
return execute(Index());
}
private:
template <size_t ...Indices>
result_type
execute(tuple_indices<Indices...>)
{
return invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
}
};
template <class R, class Fp, class ... Args>
class invoker_ret
{
//typedef typename decay<Fp>::type Fpd;
//typedef tuple<typename decay<Args>::type...> Argsd;
//csbl::tuple<Fpd, Argsd...> f_;
csbl::tuple<Fp, Args...> f_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker_ret)
typedef R result_type;
template <class F, class ... As>
BOOST_SYMBOL_VISIBLE
explicit invoker_ret(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args)
: f_(boost::forward<F>(f), boost::forward<As>(args)...)
{}
BOOST_SYMBOL_VISIBLE
invoker_ret(BOOST_THREAD_RV_REF(invoker_ret) f) : f_(boost::move(BOOST_THREAD_RV(f).f_))
{}
result_type operator()()
{
typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
return execute(Index());
}
private:
template <size_t ...Indices>
result_type
execute(tuple_indices<Indices...>)
{
return invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
}
};
//BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END
#else
#if ! defined BOOST_MSVC
#define BOOST_THREAD_RV_REF_ARG_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(Arg##n)
#define BOOST_THREAD_RV_REF_A_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(A##n)
#define BOOST_THREAD_RV_REF_ARG(z, n, unused) , BOOST_THREAD_RV_REF(Arg##n) arg##n
#define BOOST_THREAD_FWD_REF_A(z, n, unused) , BOOST_THREAD_FWD_REF(A##n) arg##n
#define BOOST_THREAD_FWD_REF_ARG(z, n, unused) , BOOST_THREAD_FWD_REF(Arg##n) arg##n
#define BOOST_THREAD_FWD_PARAM(z, n, unused) , boost::forward<Arg##n>(arg##n)
#define BOOST_THREAD_FWD_PARAM_A(z, n, unused) , boost::forward<A##n>(arg##n)
#define BOOST_THREAD_DCL(z, n, unused) Arg##n v##n;
#define BOOST_THREAD_MOVE_PARAM(z, n, unused) , v##n(boost::move(arg##n))
#define BOOST_THREAD_FORWARD_PARAM_A(z, n, unused) , v##n(boost::forward<A##n>(arg##n))
#define BOOST_THREAD_MOVE_RHS_PARAM(z, n, unused) , v##n(boost::move(x.v##n))
#define BOOST_THREAD_MOVE_DCL(z, n, unused) , boost::move(v##n)
#define BOOST_THREAD_MOVE_DCL_T(z, n, unused) BOOST_PP_COMMA_IF(n) boost::move(v##n)
#define BOOST_THREAD_ARG_DEF(z, n, unused) , class Arg##n = tuples::null_type
template <class Fp, class Arg = tuples::null_type
BOOST_PP_REPEAT(BOOST_THREAD_MAX_ARGS, BOOST_THREAD_ARG_DEF, ~)
>
class invoker;
#define BOOST_THREAD_ASYNC_FUNCT(z, n, unused) \
template <class Fp BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class Arg) > \
class invoker<Fp BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Arg)> \
{ \
Fp fp_; \
BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
public: \
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
\
template <class F BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
BOOST_SYMBOL_VISIBLE \
explicit invoker(BOOST_THREAD_FWD_REF(F) f \
BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \
) \
: fp_(boost::forward<F>(f)) \
BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \
{} \
\
BOOST_SYMBOL_VISIBLE \
invoker(BOOST_THREAD_RV_REF(invoker) x) \
: fp_(boost::move(x.fp_)) \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
{} \
\
result_type operator()() { \
return invoke(boost::move(fp_) \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \
); \
} \
}; \
\
template <class R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class Arg) > \
class invoker<R(*)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_ARG_T, ~)) BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Arg)> \
{ \
typedef R(*Fp)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_ARG_T, ~)); \
Fp fp_; \
BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
public: \
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
\
template <class R2 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
BOOST_SYMBOL_VISIBLE \
explicit invoker(R2(*f)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_A_T, ~)) \
BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \
) \
: fp_(f) \
BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \
{} \
\
BOOST_SYMBOL_VISIBLE \
invoker(BOOST_THREAD_RV_REF(invoker) x) \
: fp_(x.fp_) \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
{} \
\
result_type operator()() { \
return fp_( \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL_T, ~) \
); \
} \
};
BOOST_PP_REPEAT(BOOST_THREAD_MAX_ARGS, BOOST_THREAD_ASYNC_FUNCT, ~)
#undef BOOST_THREAD_RV_REF_ARG_T
#undef BOOST_THREAD_RV_REF_ARG
#undef BOOST_THREAD_FWD_REF_ARG
#undef BOOST_THREAD_FWD_REF_A
#undef BOOST_THREAD_FWD_PARAM
#undef BOOST_THREAD_FWD_PARAM_A
#undef BOOST_THREAD_DCL
#undef BOOST_THREAD_MOVE_PARAM
#undef BOOST_THREAD_MOVE_RHS_PARAM
#undef BOOST_THREAD_MOVE_DCL
#undef BOOST_THREAD_ARG_DEF
#undef BOOST_THREAD_ASYNC_FUNCT
#else
template <class Fp,
class T0 = tuples::null_type, class T1 = tuples::null_type, class T2 = tuples::null_type,
class T3 = tuples::null_type, class T4 = tuples::null_type, class T5 = tuples::null_type,
class T6 = tuples::null_type, class T7 = tuples::null_type, class T8 = tuples::null_type
, class T9 = tuples::null_type
>
class invoker;
template <class Fp,
class T0 , class T1 , class T2 ,
class T3 , class T4 , class T5 ,
class T6 , class T7 , class T8 >
class invoker<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
T7 v7_;
T8 v8_;
//::boost::tuple<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8> f_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7, T8)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
, BOOST_THREAD_RV_REF(T7) a7
, BOOST_THREAD_RV_REF(T8) a8
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
, v7_(boost::move(a7))
, v8_(boost::move(a8))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
, v6_(boost::move(BOOST_THREAD_RV(f).v6_))
, v7_(boost::move(BOOST_THREAD_RV(f).v7_))
, v8_(boost::move(BOOST_THREAD_RV(f).v8_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
, boost::move(v7_)
, boost::move(v8_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
class invoker<Fp, T0, T1, T2, T3, T4, T5, T6, T7>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
T7 v7_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
, BOOST_THREAD_RV_REF(T7) a7
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
, v7_(boost::move(a7))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
, v6_(boost::move(BOOST_THREAD_RV(f).v6_))
, v7_(boost::move(BOOST_THREAD_RV(f).v7_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
, boost::move(v7_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6>
class invoker<Fp, T0, T1, T2, T3, T4, T5, T6>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
T6 v6_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
, BOOST_THREAD_RV_REF(T6) a6
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
, v6_(boost::move(a6))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
, v6_(boost::move(BOOST_THREAD_RV(f).v6_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
, boost::move(v6_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5>
class invoker<Fp, T0, T1, T2, T3, T4, T5>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
T5 v5_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
, BOOST_THREAD_RV_REF(T5) a5
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
, v5_(boost::move(a5))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
, boost::move(v5_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3, class T4>
class invoker<Fp, T0, T1, T2, T3, T4>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
T4 v4_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3, T4)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
, BOOST_THREAD_RV_REF(T4) a4
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
, v4_(boost::move(a4))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
, boost::move(v4_)
);
}
};
template <class Fp, class T0, class T1, class T2, class T3>
class invoker<Fp, T0, T1, T2, T3>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
T3 v3_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2, T3)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
, BOOST_THREAD_RV_REF(T3) a3
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
, v3_(boost::move(a3))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
, boost::move(v3_)
);
}
};
template <class Fp, class T0, class T1, class T2>
class invoker<Fp, T0, T1, T2>
{
Fp fp_;
T0 v0_;
T1 v1_;
T2 v2_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1, T2)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
, BOOST_THREAD_RV_REF(T2) a2
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
, v2_(boost::move(a2))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
, boost::move(v2_)
);
}
};
template <class Fp, class T0, class T1>
class invoker<Fp, T0, T1>
{
Fp fp_;
T0 v0_;
T1 v1_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0, T1)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
, BOOST_THREAD_RV_REF(T1) a1
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
, v1_(boost::move(a1))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
, boost::move(v1_)
);
}
};
template <class Fp, class T0>
class invoker<Fp, T0>
{
Fp fp_;
T0 v0_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp(T0)>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
, BOOST_THREAD_RV_REF(T0) a0
)
: fp_(boost::move(f))
, v0_(boost::move(a0))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
{}
result_type operator()()
{
return invoke(boost::move(fp_)
, boost::move(v0_)
);
}
};
template <class Fp>
class invoker<Fp>
{
Fp fp_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp()>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f)
: fp_(boost::move(f))
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(boost::move(f.fp_))
{}
result_type operator()()
{
return fp_();
}
};
template <class R>
class invoker<R(*)()>
{
typedef R(*Fp)();
Fp fp_;
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
typedef typename result_of<Fp()>::type result_type;
BOOST_SYMBOL_VISIBLE
explicit invoker(Fp f)
: fp_(f)
{}
BOOST_SYMBOL_VISIBLE
invoker(BOOST_THREAD_RV_REF(invoker) f)
: fp_(f.fp_)
{}
result_type operator()()
{
return fp_();
}
};
#endif
#endif
}
}
#include <boost/thread/detail/variadic_footer.hpp>
#endif // header

View File

@@ -1,9 +1,8 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011-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)
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//

View File

@@ -1,9 +1,8 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011-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)
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
@@ -13,11 +12,14 @@
#define BOOST_THREAD_DETAIL_MEMORY_HPP
#include <boost/config.hpp>
#include <boost/thread/csbl/memory/pointer_traits.hpp>
#include <boost/thread/csbl/memory/allocator_arg.hpp>
#include <boost/thread/csbl/memory/allocator_traits.hpp>
#include <boost/thread/csbl/memory/scoped_allocator.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
namespace boost
{
@@ -26,7 +28,7 @@ namespace boost
template <class _Alloc>
class allocator_destructor
{
typedef csbl::allocator_traits<_Alloc> alloc_traits;
typedef container::allocator_traits<_Alloc> alloc_traits;
public:
typedef typename alloc_traits::pointer pointer;
typedef typename alloc_traits::size_type size_type;
@@ -44,5 +46,111 @@ namespace boost
}
};
} //namespace thread_detail
}
typedef container::allocator_arg_t allocator_arg_t;
BOOST_CONSTEXPR_OR_CONST allocator_arg_t allocator_arg = {};
template <class T, class Alloc>
struct uses_allocator: public container::uses_allocator<T, Alloc>
{
};
template <class Ptr>
struct pointer_traits
{
typedef Ptr pointer;
// typedef <details> element_type;
// typedef <details> difference_type;
// template <class U> using rebind = <details>;
//
// static pointer pointer_to(<details>);
};
template <class T>
struct pointer_traits<T*>
{
typedef T* pointer;
typedef T element_type;
typedef ptrdiff_t difference_type;
// template <class U> using rebind = U*;
//
// static pointer pointer_to(<details>) noexcept;
};
namespace thread_detail {
template <class _Ptr1, class _Ptr2,
bool = is_same<typename remove_cv<typename pointer_traits<_Ptr1>::element_type>::type,
typename remove_cv<typename pointer_traits<_Ptr2>::element_type>::type
>::value
>
struct same_or_less_cv_qualified_imp
: is_convertible<_Ptr1, _Ptr2> {};
template <class _Ptr1, class _Ptr2>
struct same_or_less_cv_qualified_imp<_Ptr1, _Ptr2, false>
: false_type {};
template <class _Ptr1, class _Ptr2, bool = is_scalar<_Ptr1>::value &&
!is_pointer<_Ptr1>::value>
struct same_or_less_cv_qualified
: same_or_less_cv_qualified_imp<_Ptr1, _Ptr2> {};
template <class _Ptr1, class _Ptr2>
struct same_or_less_cv_qualified<_Ptr1, _Ptr2, true>
: false_type {};
}
template <class T>
struct BOOST_SYMBOL_VISIBLE default_delete
{
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() = default;
#else
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {}
#endif
template <class U>
BOOST_SYMBOL_VISIBLE
default_delete(const default_delete<U>&,
typename enable_if<is_convertible<U*, T*> >::type* = 0) BOOST_NOEXCEPT {}
BOOST_SYMBOL_VISIBLE
void operator() (T* ptr) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
delete ptr;
}
};
template <class T>
struct BOOST_SYMBOL_VISIBLE default_delete<T[]>
{
public:
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() = default;
#else
BOOST_SYMBOL_VISIBLE
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {}
#endif
template <class U>
BOOST_SYMBOL_VISIBLE
default_delete(const default_delete<U[]>&,
typename enable_if<thread_detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) BOOST_NOEXCEPT {}
template <class U>
BOOST_SYMBOL_VISIBLE
void operator() (U* ptr,
typename enable_if<thread_detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
delete [] ptr;
}
};
} // namespace boost
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP

View File

@@ -9,27 +9,18 @@
#include <boost/thread/detail/config.hpp>
#ifndef BOOST_NO_SFINAE
#include <boost/core/enable_if.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/decay.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/traits.hpp>
#include <boost/config/abi_prefix.hpp>
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#include <type_traits>
#endif
namespace boost
{
@@ -80,7 +71,6 @@ namespace boost
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
@@ -101,7 +91,6 @@ namespace boost
#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_MSVC
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
@@ -123,7 +112,6 @@ namespace boost
#else
#if defined BOOST_THREAD_USES_MOVE
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
@@ -143,7 +131,6 @@ namespace boost
#else
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) const TYPE&
#define BOOST_THREAD_RV_REF(TYPE) boost::detail::thread_move_t< TYPE >
#define BOOST_THREAD_RV_REF_BEG boost::detail::thread_move_t<
#define BOOST_THREAD_RV_REF_END >
@@ -202,8 +189,6 @@ namespace detail
#define BOOST_THREAD_MOVABLE(TYPE)
#define BOOST_THREAD_COPYABLE(TYPE)
#else
#if defined BOOST_THREAD_USES_MOVE
@@ -226,11 +211,6 @@ namespace detail
return *static_cast<const ::boost::rv<TYPE>* >(this); \
}\
#define BOOST_THREAD_COPYABLE(TYPE) \
TYPE& operator=(TYPE &t)\
{ this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}
#else
#define BOOST_THREAD_MOVABLE(TYPE) \
@@ -244,94 +224,21 @@ namespace detail
return x; \
} \
#define BOOST_THREAD_COPYABLE(TYPE)
#endif
#endif
#define BOOST_THREAD_MOVABLE_ONLY(TYPE) \
BOOST_THREAD_NO_COPYABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
typedef int boost_move_no_copy_constructor_or_assign; \
#define BOOST_THREAD_COPYABLE_AND_MOVABLE(TYPE) \
BOOST_THREAD_COPYABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
namespace boost
{
namespace thread_detail
{ namespace thread_detail
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#elif defined BOOST_THREAD_USES_MOVE
template <class T>
struct is_rv
: ::boost::move_detail::is_rv<T>
{};
#else
template <class T>
struct is_rv
: ::boost::integral_constant<bool, false>
{};
template <class T>
struct is_rv< ::boost::detail::thread_move_t<T> >
: ::boost::integral_constant<bool, true>
{};
template <class T>
struct is_rv< const ::boost::detail::thread_move_t<T> >
: ::boost::integral_constant<bool, true>
{};
#endif
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class Tp>
struct remove_reference : boost::remove_reference<Tp> {};
template <class Tp>
struct decay : boost::decay<Tp> {};
#else
template <class Tp>
struct remove_reference
{
typedef Tp type;
};
template <class Tp>
struct remove_reference<Tp&>
{
typedef Tp type;
};
template <class Tp>
struct remove_reference< rv<Tp> > {
typedef Tp type;
};
template <class Tp>
struct decay
{
private:
typedef typename boost::move_detail::remove_rvalue_reference<Tp>::type Up0;
typedef typename boost::remove_reference<Up0>::type Up;
public:
typedef typename conditional
<
is_array<Up>::value,
typename remove_extent<Up>::type*,
typename conditional
<
is_function<Up>::value,
typename add_pointer<Up>::type,
typename remove_cv<Up>::type
>::type
>::type type;
};
#endif
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class T>
typename decay<T>::type

View File

@@ -1,234 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
// Make use of Boost.Move
#ifndef BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP
#define BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP
#include <boost/config.hpp>
#include <boost/thread/detail/memory.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/csbl/memory/shared_ptr.hpp>
#include <boost/type_traits/decay.hpp>
namespace boost
{
namespace detail
{
template <typename F>
class nullary_function;
template <>
class nullary_function<void()>
{
struct impl_base
{
virtual void call()=0;
virtual ~impl_base()
{
}
};
csbl::shared_ptr<impl_base> impl;
template <typename F>
struct impl_type: impl_base
{
F f;
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
impl_type(F &f_)
: f(f_)
{}
#endif
impl_type(BOOST_THREAD_RV_REF(F) f_)
: f(boost::move(f_))
{}
void call()
{
f();
}
};
struct impl_type_ptr: impl_base
{
void (*f)();
impl_type_ptr(void (*f_)())
: f(f_)
{}
void call()
{
f();
}
};
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
explicit nullary_function(void (*f)()):
impl(new impl_type_ptr(f))
{}
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename F>
explicit nullary_function(F& f):
impl(new impl_type<F>(f))
{}
#endif
template<typename F>
nullary_function(BOOST_THREAD_RV_REF(F) f):
impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
{}
nullary_function()
: impl()
{
}
nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
impl(other.impl)
{
}
nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
#if defined BOOST_NO_CXX11_SMART_PTR
impl(BOOST_THREAD_RV(other).impl)
{
BOOST_THREAD_RV(other).impl.reset();
}
#else
impl(boost::move(other.impl))
{
}
#endif
~nullary_function()
{
}
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
{
impl=other.impl;
return *this;
}
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
{
#if defined BOOST_NO_CXX11_SMART_PTR
impl=BOOST_THREAD_RV(other).impl;
BOOST_THREAD_RV(other).impl.reset();
#else
impl = boost::move(other.impl);
#endif
return *this;
}
void operator()()
{ if (impl) impl->call();}
};
template <typename R>
class nullary_function<R()>
{
struct impl_base
{
virtual R call()=0;
virtual ~impl_base()
{
}
};
csbl::shared_ptr<impl_base> impl;
template <typename F>
struct impl_type: impl_base
{
F f;
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
impl_type(F &f_)
: f(f_)
{}
#endif
impl_type(BOOST_THREAD_RV_REF(F) f_)
: f(boost::move(f_))
{}
R call()
{
return f();
}
};
struct impl_type_ptr: impl_base
{
R (*f)();
impl_type_ptr(R (*f_)())
: f(f_)
{}
R call()
{
return f();
}
};
public:
BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
nullary_function(R (*f)()):
impl(new impl_type_ptr(f))
{}
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename F>
nullary_function(F& f):
impl(new impl_type<F>(f))
{}
#endif
template<typename F>
nullary_function(BOOST_THREAD_RV_REF(F) f):
impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
{}
nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
impl(other.impl)
{
}
nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
#if defined BOOST_NO_CXX11_SMART_PTR
impl(BOOST_THREAD_RV(other).impl)
{
BOOST_THREAD_RV(other).impl.reset();
}
#else
impl(boost::move(other.impl))
{
}
#endif
nullary_function()
: impl()
{
}
~nullary_function()
{
}
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
{
impl=other.impl;
return *this;
}
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
{
#if defined BOOST_NO_CXX11_SMART_PTR
impl=BOOST_THREAD_RV(other).impl;
BOOST_THREAD_RV(other).impl.reset();
#else
impl = boost::move(other.impl);
#endif
return *this;
}
R operator()()
{ if (impl) return impl->call(); else return R();}
};
}
//BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
}
#endif // header

View File

@@ -4,10 +4,9 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-2010 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// (C) Copyright 20011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/predef/platform.h>
#include <boost/thread/exceptions.hpp>
#ifndef BOOST_NO_IOSTREAM
@@ -25,12 +24,12 @@
#include <boost/assert.hpp>
#include <list>
#include <algorithm>
#include <boost/core/ref.hpp>
#include <boost/ref.hpp>
#include <boost/cstdint.hpp>
#include <boost/bind.hpp>
#include <stdlib.h>
#include <memory>
#include <boost/core/enable_if.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/io/ios_state.hpp>
#include <boost/type_traits/is_same.hpp>
@@ -65,9 +64,11 @@ namespace boost
{
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
thread_data(BOOST_THREAD_RV_REF(F) f_, BOOST_THREAD_RV_REF(ArgTypes)... args_):
fp(boost::forward<F>(f_), boost::forward<ArgTypes>(args_)...)
{}
#endif
template <std::size_t ...Indices>
void run2(tuple_indices<Indices...>)
{
@@ -173,7 +174,7 @@ namespace boost
private:
bool start_thread_noexcept();
bool start_thread_noexcept(const attributes& attr);
//public:
public:
void start_thread()
{
if (!start_thread_noexcept())
@@ -292,8 +293,7 @@ namespace boost
template <class F>
explicit thread(F f
, typename disable_if_c<
boost::thread_detail::is_rv<F>::value // todo ass a thread_detail::is_rv
//boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
//|| is_same<typename decay<F>::type, thread>::value
, dummy* >::type=0
):
@@ -303,8 +303,7 @@ namespace boost
}
template <class F>
thread(attributes const& attrs, F f
, typename disable_if<boost::thread_detail::is_rv<F>, dummy* >::type=0
//, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
):
thread_info(make_thread_info(f))
{
@@ -335,7 +334,7 @@ namespace boost
start_thread(attrs);
}
#endif
thread(BOOST_THREAD_RV_REF(thread) x) BOOST_NOEXCEPT
thread(BOOST_THREAD_RV_REF(thread) x)
{
thread_info=BOOST_THREAD_RV(x).thread_info;
BOOST_THREAD_RV(x).thread_info.reset();
@@ -467,20 +466,11 @@ namespace boost
inline void join();
#ifdef BOOST_THREAD_USES_CHRONO
#if defined(BOOST_THREAD_PLATFORM_WIN32)
template <class Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
{
chrono::milliseconds rel_time2= chrono::ceil<chrono::milliseconds>(rel_time);
return do_try_join_until(rel_time2.count());
}
#else
template <class Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_join_until(chrono::steady_clock::now() + rel_time);
}
#endif
template <class Clock, class Duration>
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
{
@@ -556,7 +546,6 @@ namespace boost
void detach();
static unsigned hardware_concurrency() BOOST_NOEXCEPT;
static unsigned physical_concurrency() BOOST_NOEXCEPT;
#define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
typedef detail::thread_data_base::native_handle_type native_handle_type;
@@ -760,10 +749,10 @@ namespace boost
#endif
void thread::join() {
if (this_thread::get_id() == get_id())
boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(),
thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")
thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")
);
}
@@ -774,7 +763,7 @@ namespace boost
#endif
{
if (this_thread::get_id() == get_id())
boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
bool res;
if (do_try_join_until_noexcept(timeout, res))
{
@@ -783,7 +772,7 @@ namespace boost
else
{
BOOST_THREAD_THROW_ELSE_RETURN(
(thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")),
(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")),
false
);
}
@@ -837,19 +826,6 @@ namespace boost
};
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
struct shared_state_base;
#if defined(BOOST_THREAD_PLATFORM_WIN32)
inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
{
detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
if(current_thread_data)
{
current_thread_data->make_ready_at_thread_exit(as);
}
}
#else
void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as);
#endif
}
namespace this_thread

View File

@@ -85,7 +85,7 @@ namespace boost
if(thrd)
{
BOOST_THREAD_ASSERT_PRECONDITION( ! is_thread_in(thrd) ,
thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying to add a duplicated thread")
thread_resource_error(system::errc::resource_deadlock_would_occur, "boost::thread_group: trying to add a duplicated thread")
);
boost::lock_guard<shared_mutex> guard(m);
@@ -106,7 +106,7 @@ namespace boost
void join_all()
{
BOOST_THREAD_ASSERT_PRECONDITION( ! is_this_thread_in() ,
thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying joining itself")
thread_resource_error(system::errc::resource_deadlock_would_occur, "boost::thread_group: trying joining itself")
);
boost::shared_lock<shared_mutex> guard(m);

View File

@@ -1,10 +0,0 @@
// 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)
#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif

View File

@@ -1,19 +0,0 @@
// 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)
#include <boost/config.hpp>
//#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#ifndef BOOST_THREAD_MAX_ARGS
#define BOOST_THREAD_MAX_ARGS 9
#endif
//#endif

View File

@@ -1,23 +0,0 @@
// (C) Copyright 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_DETAIL_WORK_HPP
#define BOOST_THREAD_DETAIL_WORK_HPP
#include <boost/thread/detail/nullary_function.hpp>
namespace boost
{
namespace thread_detail
{
typedef detail::nullary_function<void()> work;
}
} // namespace boost
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP

View File

@@ -1,44 +0,0 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2014 Vicente J. Botet Escriba
#ifndef BOOST_THREAD_EXCEPTIONAL_PTR_HPP
#define BOOST_THREAD_EXCEPTIONAL_PTR_HPP
#include <boost/thread/detail/move.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
struct exceptional_ptr {
exception_ptr ptr_;
exceptional_ptr() : ptr_() {}
explicit exceptional_ptr(exception_ptr ex) : ptr_(ex) {}
template <class E>
explicit exceptional_ptr(BOOST_FWD_REF(E) ex) : ptr_(boost::copy_exception(boost::forward<E>(ex))) {}
};
template <class E>
inline exceptional_ptr make_exceptional(BOOST_FWD_REF(E) ex) {
return exceptional_ptr(boost::forward<E>(ex));
}
inline exceptional_ptr make_exceptional(exception_ptr ex)
{
return exceptional_ptr(ex);
}
inline exceptional_ptr make_exceptional()
{
return exceptional_ptr();
}
} // namespace boost
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -124,7 +124,7 @@ namespace boost
typedef thread_exception base_type;
public:
thread_resource_error()
: base_type(static_cast<int>(system::errc::resource_unavailable_try_again), "boost::thread_resource_error")
: base_type(system::errc::resource_unavailable_try_again, "boost::thread_resource_error")
{}
thread_resource_error( int ev )
@@ -152,7 +152,7 @@ namespace boost
typedef thread_exception base_type;
public:
unsupported_thread_option()
: base_type(static_cast<int>(system::errc::invalid_argument), "boost::unsupported_thread_option")
: base_type(system::errc::invalid_argument, "boost::unsupported_thread_option")
{}
unsupported_thread_option( int ev )
@@ -176,7 +176,7 @@ namespace boost
typedef thread_exception base_type;
public:
invalid_thread_argument()
: base_type(static_cast<int>(system::errc::invalid_argument), "boost::invalid_thread_argument")
: base_type(system::errc::invalid_argument, "boost::invalid_thread_argument")
{}
invalid_thread_argument( int ev )
@@ -200,7 +200,7 @@ namespace boost
typedef thread_exception base_type;
public:
thread_permission_error()
: base_type(static_cast<int>(system::errc::permission_denied), "boost::thread_permission_error")
: base_type(system::errc::permission_denied, "boost::thread_permission_error")
{}
thread_permission_error( int ev )

View File

@@ -1,15 +0,0 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
#ifndef BOOST_THREAD_EXECUTOR_HPP
#define BOOST_THREAD_EXECUTOR_HPP
#include <boost/thread/executors/executor.hpp>
#include <boost/thread/executors/executor_adaptor.hpp>
#endif

View File

@@ -1,311 +0,0 @@
// Copyright (C) 2013-2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
// first implementation of a simple pool thread using a vector of threads and a sync_queue.
#ifndef BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP
#define BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/csbl/vector.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
class basic_thread_pool
{
public:
/// type-erasure to store the works to do
typedef executors::work work;
private:
/// the kind of stored threads are scoped threads to ensure that the threads are joined.
/// A move aware vector type
typedef scoped_thread<> thread_t;
typedef csbl::vector<thread_t> thread_vector;
/// the thread safe work queue
concurrent::sync_queue<work > work_queue;
/// A move aware vector
thread_vector threads;
public:
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one()
{
try
{
work task;
if (work_queue.try_pull_front(task) == queue_op_status::success)
{
task();
return true;
}
return false;
}
catch (...)
{
std::terminate();
return false;
}
}
/**
* Effects: schedule one task or yields
* Throws: whatever the current task constructor throws or the task() throws.
*/
void schedule_one_or_yield()
{
if ( ! try_executing_one())
{
this_thread::yield();
}
}
private:
/**
* The main loop of the worker threads
*/
void worker_thread()
{
try
{
for(;;)
{
work task;
queue_op_status st = work_queue.wait_pull_front(task);
if (st == queue_op_status::closed) return;
task();
}
}
catch (...)
{
std::terminate();
return;
}
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class AtThreadEntry>
void worker_thread1(AtThreadEntry& at_thread_entry)
{
at_thread_entry(*this);
worker_thread();
}
#endif
void worker_thread2(void(*at_thread_entry)(basic_thread_pool&))
{
at_thread_entry(*this);
worker_thread();
}
template <class AtThreadEntry>
void worker_thread3(BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry)
{
at_thread_entry(*this);
worker_thread();
}
static void do_nothing_at_thread_entry(basic_thread_pool&) {}
public:
/// basic_thread_pool is not copyable.
BOOST_THREAD_NO_COPYABLE(basic_thread_pool)
/**
* \b Effects: creates a thread pool that runs closures on \c thread_count threads.
*
* \b Throws: Whatever exception is thrown while initializing the needed resources.
*/
basic_thread_pool(unsigned const thread_count = thread::hardware_concurrency()+1)
{
try
{
threads.reserve(thread_count);
for (unsigned i = 0; i < thread_count; ++i)
{
#if 1
thread th (&basic_thread_pool::worker_thread, this);
threads.push_back(thread_t(boost::move(th)));
#else
threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
#endif
}
}
catch (...)
{
close();
throw;
}
}
/**
* \b Effects: creates a thread pool that runs closures on \c thread_count threads
* and executes the at_thread_entry function at the entry of each created thread. .
*
* \b Throws: Whatever exception is thrown while initializing the needed resources.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class AtThreadEntry>
basic_thread_pool( unsigned const thread_count, AtThreadEntry& at_thread_entry)
{
try
{
threads.reserve(thread_count);
for (unsigned i = 0; i < thread_count; ++i)
{
thread th (&basic_thread_pool::worker_thread1<AtThreadEntry>, this, at_thread_entry);
threads.push_back(thread_t(boost::move(th)));
//threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
}
}
catch (...)
{
close();
throw;
}
}
#endif
basic_thread_pool( unsigned const thread_count, void(*at_thread_entry)(basic_thread_pool&))
{
try
{
threads.reserve(thread_count);
for (unsigned i = 0; i < thread_count; ++i)
{
thread th (&basic_thread_pool::worker_thread2, this, at_thread_entry);
threads.push_back(thread_t(boost::move(th)));
//threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
}
}
catch (...)
{
close();
throw;
}
}
template <class AtThreadEntry>
basic_thread_pool( unsigned const thread_count, BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry)
{
try
{
threads.reserve(thread_count);
for (unsigned i = 0; i < thread_count; ++i)
{
thread th (&basic_thread_pool::worker_thread3<AtThreadEntry>, this, boost::forward<AtThreadEntry>(at_thread_entry));
threads.push_back(thread_t(boost::move(th)));
//threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
}
}
catch (...)
{
close();
throw;
}
}
/**
* \b Effects: Destroys the thread pool.
*
* \b Synchronization: The completion of all the closures happen before the completion of the \c basic_thread_pool destructor.
*/
~basic_thread_pool()
{
// signal to all the worker threads that there will be no more submissions.
close();
// joins all the threads as the threads were scoped_threads
}
/**
* \b Effects: join all the threads.
*/
void join()
{
for (unsigned i = 0; i < threads.size(); ++i)
{
threads[i].join();
}
}
/**
* \b Effects: close the \c basic_thread_pool for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close()
{
work_queue.close();
}
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed()
{
return work_queue.closed();
}
/**
* \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
*
* \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the \c basic_thread_pool will call \c std::terminate, as is the case with threads.
*
* \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work_queue.push_back(work(closure));
}
#endif
void submit(void (*closure)())
{
work_queue.push_back(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work_queue.push_back(work(boost::forward<Closure>(closure)));
}
/**
* \b Requires: This must be called from an scheduled task.
*
* \b Effects: reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
{
do {
if ( ! try_executing_one())
{
return false;
}
} while (! pred());
return true;
}
};
}
using executors::basic_thread_pool;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,93 +0,0 @@
// Copyright (C) 2014 Ian Forbed
// Copyright (C) 2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef SCHEDULED_EXECUTOR_HPP
#define SCHEDULED_EXECUTOR_HPP
#include <boost/atomic.hpp>
#include <boost/function.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/concurrent_queues/sync_timed_queue.hpp>
#include <boost/thread/executors/work.hpp>
namespace boost
{
namespace executors
{
namespace detail
{
class scheduled_executor_base
{
public:
typedef boost::function<void()> work;
//typedef executors::work work;
typedef chrono::steady_clock clock;
typedef clock::duration duration;
typedef clock::time_point time_point;
protected:
concurrent::sync_timed_queue<work> _workq;
scheduled_executor_base() {}
public:
~scheduled_executor_base()
{
if(!closed())
{
this->close();
}
}
void close()
{
_workq.close();
}
bool closed()
{
return _workq.closed();
}
void submit(work w)
{
_workq.push(w, clock::now());
}
void submit_at(work w, const time_point& tp)
{
_workq.push(w, tp);
}
void submit_after(work w, const duration& dura)
{
_workq.push(w, dura);
}
void loop()
{
try
{
for(;;)
{
work task;
queue_op_status st = _workq.wait_pull(task);
if (st == queue_op_status::closed) return;
task();
}
}
catch (...)
{
std::terminate();
return;
}
}
}; //end class
} //end detail namespace
} //end executors namespace
} //end boost namespace
#endif

View File

@@ -1,147 +0,0 @@
// Copyright (C) 2013,2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
#define BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
class executor
{
public:
/// type-erasure to store the works to do
typedef executors::work work;
/// executor is not copyable.
BOOST_THREAD_NO_COPYABLE(executor)
executor() {}
/**
* \par Effects
* Destroys the executor.
*
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
virtual ~executor() {};
/**
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
virtual void close() = 0;
/**
* \par Returns
* Whether the pool is closed for submissions.
*/
virtual bool closed() = 0;
/**
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
virtual void submit(BOOST_THREAD_RV_REF(work) closure) = 0;
// virtual void submit(work& closure) = 0;
/**
* \par Requires
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
*
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work w ((closure));
submit(boost::move(w));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
submit(boost::move(w));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work w = boost::move(closure);
submit(boost::move(w));
}
/**
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
virtual bool try_executing_one() = 0;
/**
* \par Requires
* This must be called from an scheduled task.
*
* \par Effects
* Reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
{
do {
//schedule_one_or_yield();
if ( ! try_executing_one())
{
return false;
}
} while (! pred());
return true;
}
};
}
using executors::executor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,137 +0,0 @@
// Copyright (C) 2013,2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
#define BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
/**
* Polymorphic adaptor of a model of Executor to an executor.
*/
template <typename Executor>
class executor_adaptor : public executor
{
Executor ex;
public:
/// type-erasure to store the works to do
typedef executor::work work;
/// executor is not copyable.
BOOST_THREAD_NO_COPYABLE(executor_adaptor)
/**
* executor_adaptor constructor
*/
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename ...Args>
executor_adaptor(BOOST_THREAD_RV_REF(Args) ... args) : ex(boost::forward<Args>(args)...) {}
#else
/**
* executor_adaptor constructor
*/
executor_adaptor() : ex() {}
template <typename A1>
executor_adaptor(
BOOST_THREAD_FWD_REF(A1) a1
) :
ex(
boost::forward<A1>(a1)
) {}
template <typename A1, typename A2>
executor_adaptor(
BOOST_THREAD_FWD_REF(A1) a1,
BOOST_THREAD_FWD_REF(A2) a2
) :
ex(
boost::forward<A1>(a1),
boost::forward<A2>(a2)
) {}
template <typename A1, typename A2, typename A3>
executor_adaptor(
BOOST_THREAD_FWD_REF(A1) a1,
BOOST_THREAD_FWD_REF(A2) a2,
BOOST_THREAD_FWD_REF(A3) a3
) :
ex(
boost::forward<A1>(a1),
boost::forward<A2>(a2),
boost::forward<A3>(a3)
) {}
#endif
Executor& underlying_executor() { return ex; }
/**
* \b Effects: close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close() { ex.close(); }
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed() { return ex.closed(); }
/**
* \b Effects: The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure) {
return ex.submit(boost::move(closure));
}
// void submit(work & closure) {
// return ex.submit(closure);
// }
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
submit(work(closure));
}
#endif
void submit(void (*closure)())
{
submit(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
submit(work(boost::forward<Closure>(closure)));
}
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one() { return ex.try_executing_one(); }
};
}
using executors::executor_adaptor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

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

View File

@@ -1,171 +0,0 @@
// 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)
//
// 2013/11 Vicente J. Botet Escriba
// first implementation of a simple serial scheduler.
#ifndef BOOST_THREAD_INLINE_EXECUTOR_HPP
#define BOOST_THREAD_INLINE_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
class inline_executor
{
public:
/// type-erasure to store the works to do
typedef executors::work work;
bool closed_;
mutable mutex mtx_;
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one()
{
return false;
}
public:
/// inline_executor is not copyable.
BOOST_THREAD_NO_COPYABLE(inline_executor)
/**
* \b Effects: creates a inline executor that runs closures immediately.
*
* \b Throws: Nothing.
*/
inline_executor()
: closed_(false)
{
}
/**
* \b Effects: Destroys the inline executor.
*
* \b Synchronization: The completion of all the closures happen before the completion of the \c inline_executor destructor.
*/
~inline_executor()
{
// signal to all the worker thread that there will be no more submissions.
close();
}
/**
* \b Effects: close the \c inline_executor for submissions.
* The loop will work until there is no more closures to run.
*/
void close()
{
lock_guard<mutex> lk(mtx_);
closed_ = true;
}
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed(lock_guard<mutex>& )
{
return closed_;
}
bool closed()
{
lock_guard<mutex> lk(mtx_);
return closed(lk);
}
/**
* \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
*
* \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the \c inline_executor will call \c std::terminate, as is the case with threads.
*
* \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
try
{
closure();
}
catch (...)
{
std::terminate();
return;
}
}
#endif
void submit(void (*closure)())
{
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
try
{
closure();
}
catch (...)
{
std::terminate();
return;
}
}
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
try
{
closure();
}
catch (...)
{
std::terminate();
return;
}
}
/**
* \b Requires: This must be called from an scheduled task.
*
* \b Effects: reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& )
{
return false;
}
};
}
using executors::inline_executor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,199 +0,0 @@
// Copyright (C) 2013,2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/11 Vicente J. Botet Escriba
// first implementation of a simple user scheduler.
// 2013/11 Vicente J. Botet Escriba
// rename loop_executor.
#ifndef BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
#define BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
class loop_executor
{
public:
/// type-erasure to store the works to do
typedef executors::work work;
private:
/// the thread safe work queue
concurrent::sync_queue<work > work_queue;
public:
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one()
{
work task;
try
{
if (work_queue.try_pull_front(task) == queue_op_status::success)
{
task();
return true;
}
return false;
}
catch (...)
{
std::terminate();
return false;
}
}
private:
/**
* Effects: schedule one task or yields
* Throws: whatever the current task constructor throws or the task() throws.
*/
void schedule_one_or_yield()
{
if ( ! try_executing_one())
{
this_thread::yield();
}
}
public:
/// loop_executor is not copyable.
BOOST_THREAD_NO_COPYABLE(loop_executor)
/**
* \b Effects: creates a thread pool that runs closures using one of its closure-executing methods.
*
* \b Throws: Whatever exception is thrown while initializing the needed resources.
*/
loop_executor()
{
}
/**
* \b Effects: Destroys the thread pool.
*
* \b Synchronization: The completion of all the closures happen before the completion of the \c loop_executor destructor.
*/
~loop_executor()
{
// signal to all the worker thread that there will be no more submissions.
close();
}
/**
* The main loop of the worker thread
*/
void loop()
{
while (!closed())
{
schedule_one_or_yield();
}
while (try_executing_one())
{
}
}
/**
* \b Effects: close the \c loop_executor for submissions.
* The loop will work until there is no more closures to run.
*/
void close()
{
work_queue.close();
}
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed()
{
return work_queue.closed();
}
/**
* \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
*
* \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the \c loop_executor will call \c std::terminate, as is the case with threads.
*
* \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work_queue.push_back(work(closure));
}
#endif
void submit(void (*closure)())
{
work_queue.push_back(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work_queue.push_back(work(boost::forward<Closure>(closure)));
}
/**
* \b Requires: This must be called from an scheduled task.
*
* \b Effects: reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
{
do {
if ( ! try_executing_one())
{
return false;
}
} while (! pred());
return true;
}
/**
* run queued closures
*/
void run_queued_closures()
{
sync_queue<work>::underlying_queue_type q = work_queue.underlying_queue();
while (! q.empty())
{
work& task = q.front();
task();
q.pop_front();
}
}
};
}
using executors::loop_executor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,68 +0,0 @@
// Copyright (C) 2014 Ian Forbed
// Copyright (C) 2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_THREAD_EXECUTORS_SCHEDULED_THREAD_POOL_HPP
#define BOOST_THREAD_EXECUTORS_SCHEDULED_THREAD_POOL_HPP
#include <boost/thread/executors/detail/scheduled_executor_base.hpp>
namespace boost
{
namespace executors
{
class scheduled_thread_pool : public detail::scheduled_executor_base
{
private:
thread_group _workers;
public:
scheduled_thread_pool(size_t num_threads) : super()
{
for(size_t i = 0; i < num_threads; i++)
{
_workers.create_thread(bind(&super::loop, this));
}
}
~scheduled_thread_pool()
{
this->close();
_workers.join_all();
}
private:
typedef detail::scheduled_executor_base super;
inline void loop();
}; //end class
void scheduled_thread_pool::loop()
{
try
{
for(;;)
{
super::work task;
queue_op_status st = super::_workq.wait_pull(task);
if (st == queue_op_status::closed) return;
task();
}
}
catch (...)
{
std::terminate();
return;
}
}
} //end executors namespace
using executors::scheduled_thread_pool;
} //end boost
#endif

View File

@@ -1,259 +0,0 @@
// Copyright (C) 2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_THREAD_EXECUTORS_SCHEDULER_HPP
#define BOOST_THREAD_EXECUTORS_SCHEDULER_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/executors/detail/scheduled_executor_base.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
/// Wraps the reference to an executor and a function to make a work that submit the function using the executor.
template <class Executor, class Function>
class resubmitter
{
public:
resubmitter(Executor& ex, Function funct) :
ex(ex),
funct(boost::move(funct))
{}
void operator()()
{
ex.submit(funct);
}
private:
Executor& ex;
Function funct;
};
/// resubmitter factory
template <class Executor, class Function>
resubmitter<Executor, typename decay<Function>::type>
resubmit(Executor& ex, BOOST_THREAD_FWD_REF(Function) funct) {
return resubmitter<Executor, typename decay<Function>::type >(ex, boost::move(funct));
}
/// Wraps references to a @c Scheduler and an @c Executor providing an @c Executor that
/// resubmit the function using the referenced Executor at a given @c time_point known at construction.
template <class Scheduler, class Executor>
class resubmit_at_executor
{
public:
typedef chrono::steady_clock clock;
resubmit_at_executor(Scheduler& sch, Executor& ex, clock::time_point const& tp) :
sch(sch),
ex(ex),
tp(tp),
is_closed(false)
{
}
~resubmit_at_executor()
{
close();
}
template <class Work>
void submit(BOOST_THREAD_FWD_REF(Work) w)
{
if (closed())
{
BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
sch.submit_at(resubmit(ex,boost::forward<Work>(w)), tp);
}
Executor& underlying_executor()
{
return ex;
}
Scheduler& underlying_scheduler()
{
return sch;
}
void close()
{
is_closed = true;
}
bool closed()
{
return is_closed || sch.closed() || ex.closed();
}
private:
Scheduler& sch;
Executor& ex;
clock::time_point tp;
bool is_closed;
};
/// Expression template helper storing a pair of references to an @c Scheduler and an @c Executor
/// It provides factory helper functions such as at/after that convert these a pair of @c Scheduler @c Executor
/// into an new @c Executor that submit the work using the referenced @c Executor at/after a specific time/duration
/// respectively, using the referenced @Scheduler.
template <class Scheduler, class Executor>
class scheduler_executor_wrapper
{
public:
typedef chrono::steady_clock clock;
typedef resubmit_at_executor<Scheduler, Executor> the_executor;
scheduler_executor_wrapper(Scheduler& sch, Executor& ex) :
sch(sch),
ex(ex)
{}
~scheduler_executor_wrapper()
{
}
Executor& underlying_executor()
{
return ex;
}
Scheduler& underlying_scheduler()
{
return sch;
}
template <class Duration>
the_executor after(Duration const& rel_time)
{
return at(clock::now() + rel_time );
}
the_executor at(clock::time_point const& abs_time)
{
return the_executor(sch, ex, abs_time);
}
private:
Scheduler& sch;
Executor& ex;
}; //end class
/// Wraps a reference to a @c Scheduler providing an @c Executor that
/// run the function at a given @c time_point known at construction.
template <class Scheduler>
class at_executor
{
public:
typedef chrono::steady_clock clock;
at_executor(Scheduler& sch, clock::time_point const& tp) :
sch(sch),
tp(tp),
is_closed(false)
{}
~at_executor()
{
close();
}
Scheduler& underlying_scheduler()
{
return sch;
}
void close()
{
is_closed = true;
}
bool closed()
{
return is_closed || sch.closed();
}
template <class Work>
void submit(BOOST_THREAD_FWD_REF(Work) w)
{
if (closed())
{
BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
}
sch.submit_at(boost::forward<Work>(w), tp);
}
template <class Executor>
resubmit_at_executor<Scheduler, Executor> on(Executor& ex)
{
return resubmit_at_executor<Scheduler, Executor>(sch, ex, tp);
}
private:
Scheduler& sch;
clock::time_point tp;
bool is_closed;
}; //end class
/// A @c Scheduler using a specific thread. Note that a Scheduler is not an Executor.
/// It provides factory helper functions such as at/after that convert a @c Scheduler into an @c Executor
/// that submit the work at/after a specific time/duration respectively.
class scheduler : public detail::scheduled_executor_base
{
public:
typedef chrono::steady_clock clock;
typedef clock::time_point time_point;
scheduler()
: super(),
thr(&super::loop, this) {}
~scheduler()
{
this->close();
thr.join();
}
template <class Ex>
scheduler_executor_wrapper<scheduler, Ex> on(Ex& ex)
{
return scheduler_executor_wrapper<scheduler, Ex>(*this, ex);
}
template <class Duration>
at_executor<scheduler> after(Duration const& rel_time)
{
return at(rel_time + clock::now());
}
at_executor<scheduler> at(time_point const& tp)
{
return at_executor<scheduler>(*this, tp);
}
private:
typedef detail::scheduled_executor_base super;
thread thr;
};
}
using executors::resubmitter;
using executors::resubmit;
using executors::resubmit_at_executor;
using executors::scheduler_executor_wrapper;
using executors::at_executor;
using executors::scheduler;
}
#include <boost/config/abi_suffix.hpp>
#endif

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