forked from boostorg/thread
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into fix/blocking_future
- Loading branch information
Showing
5 changed files
with
399 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// Copyright (C) 2015 Vicente J. Botet Escriba | ||
// | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#include <boost/config.hpp> | ||
#if ! defined BOOST_NO_CXX11_DECLTYPE | ||
#define BOOST_RESULT_OF_USE_DECLTYPE | ||
#endif | ||
|
||
#define BOOST_THREAD_VERSION 4 | ||
#define BOOST_THREAD_PROVIDES_EXECUTORS | ||
//#define BOOST_THREAD_USES_LOG | ||
#define BOOST_THREAD_USES_LOG_THREAD_ID | ||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD | ||
|
||
#include <boost/thread/caller_context.hpp> | ||
#include <boost/thread/executors/basic_thread_pool.hpp> | ||
#include <boost/thread/executors/serial_executor.hpp> | ||
#include <boost/thread/executors/executor.hpp> | ||
#include <boost/thread/executors/executor_adaptor.hpp> | ||
#include <boost/thread/executor.hpp> | ||
#include <boost/thread/future.hpp> | ||
#include <boost/assert.hpp> | ||
#include <string> | ||
#include <iostream> | ||
|
||
void p1() | ||
{ | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
boost::this_thread::sleep_for(boost::chrono::milliseconds(30)); | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
} | ||
|
||
void p2() | ||
{ | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
boost::this_thread::sleep_for(boost::chrono::milliseconds(10)); | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
} | ||
|
||
int f1() | ||
{ | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
boost::this_thread::sleep_for(boost::chrono::seconds(1)); | ||
return 1; | ||
} | ||
int f2(int i) | ||
{ | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
boost::this_thread::sleep_for(boost::chrono::seconds(2)); | ||
return i + 1; | ||
} | ||
|
||
void submit_some(boost::serial_executor& tp) | ||
{ | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
for (int i = 0; i < 3; ++i) { | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
tp.submit(&p2); | ||
} | ||
for (int i = 0; i < 3; ++i) { | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
tp.submit(&p1); | ||
} | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
|
||
} | ||
|
||
|
||
void at_th_entry(boost::basic_thread_pool& ) | ||
{ | ||
|
||
} | ||
|
||
int test_executor_adaptor() | ||
{ | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
{ | ||
try | ||
{ | ||
|
||
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
{ | ||
boost::basic_thread_pool ea1(4); | ||
boost::serial_executor ea2(ea1); | ||
submit_some(ea2); | ||
boost::this_thread::sleep_for(boost::chrono::seconds(10)); | ||
} | ||
#endif | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
} | ||
catch (std::exception& ex) | ||
{ | ||
std::cout << "ERROR= " << ex.what() << "" << std::endl; | ||
return 1; | ||
} | ||
catch (...) | ||
{ | ||
std::cout << " ERROR= exception thrown" << std::endl; | ||
return 2; | ||
} | ||
} | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
return 0; | ||
} | ||
|
||
|
||
int main() | ||
{ | ||
return test_executor_adaptor(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// Copyright (C) 2015 Vicente J. Botet Escriba | ||
// | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#include <boost/config.hpp> | ||
#if ! defined BOOST_NO_CXX11_DECLTYPE | ||
#define BOOST_RESULT_OF_USE_DECLTYPE | ||
#endif | ||
|
||
#define BOOST_THREAD_VERSION 4 | ||
#define BOOST_THREAD_PROVIDES_EXECUTORS | ||
//#define BOOST_THREAD_USES_LOG | ||
#define BOOST_THREAD_USES_LOG_THREAD_ID | ||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD | ||
|
||
#include <boost/thread/caller_context.hpp> | ||
#include <boost/thread/executors/basic_thread_pool.hpp> | ||
#include <boost/thread/executors/serial_executor_cont.hpp> | ||
#include <boost/thread/executors/executor.hpp> | ||
#include <boost/thread/executors/executor_adaptor.hpp> | ||
#include <boost/thread/executor.hpp> | ||
#include <boost/thread/future.hpp> | ||
#include <boost/assert.hpp> | ||
#include <string> | ||
#include <iostream> | ||
|
||
void p1() | ||
{ | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
boost::this_thread::sleep_for(boost::chrono::milliseconds(30)); | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
} | ||
|
||
void p2() | ||
{ | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
boost::this_thread::sleep_for(boost::chrono::milliseconds(10)); | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
} | ||
|
||
int f1() | ||
{ | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
boost::this_thread::sleep_for(boost::chrono::seconds(1)); | ||
return 1; | ||
} | ||
int f2(int i) | ||
{ | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
boost::this_thread::sleep_for(boost::chrono::seconds(2)); | ||
return i + 1; | ||
} | ||
|
||
void submit_some(boost::serial_executor_cont& tp) | ||
{ | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
for (int i = 0; i < 3; ++i) { | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
tp.submit(&p2); | ||
} | ||
for (int i = 0; i < 3; ++i) { | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
tp.submit(&p1); | ||
} | ||
std::cout << BOOST_CONTEXTOF << std::endl; | ||
|
||
} | ||
|
||
|
||
void at_th_entry(boost::basic_thread_pool& ) | ||
{ | ||
|
||
} | ||
|
||
int test_executor_adaptor() | ||
{ | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
{ | ||
try | ||
{ | ||
|
||
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
{ | ||
boost::basic_thread_pool ea1(4); | ||
boost::serial_executor_cont ea2(ea1); | ||
submit_some(ea2); | ||
boost::this_thread::sleep_for(boost::chrono::seconds(10)); | ||
} | ||
#endif | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
} | ||
catch (std::exception& ex) | ||
{ | ||
std::cout << "ERROR= " << ex.what() << "" << std::endl; | ||
return 1; | ||
} | ||
catch (...) | ||
{ | ||
std::cout << " ERROR= exception thrown" << std::endl; | ||
return 2; | ||
} | ||
} | ||
// std::cout << BOOST_CONTEXTOF << std::endl; | ||
return 0; | ||
} | ||
|
||
|
||
int main() | ||
{ | ||
return test_executor_adaptor(); | ||
} |
170 changes: 170 additions & 0 deletions
170
include/boost/thread/executors/serial_executor_cont.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
// 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/11 Vicente J. Botet Escriba | ||
// first implementation of a simple serial scheduler. | ||
|
||
#ifndef BOOST_THREAD_SERIAL_EXECUTOR_HPP | ||
#define BOOST_THREAD_SERIAL_EXECUTOR_HPP | ||
|
||
#include <boost/thread/detail/config.hpp> | ||
#include <boost/thread/detail/delete.hpp> | ||
#include <boost/thread/detail/move.hpp> | ||
#include <boost/thread/concurrent_queues/sync_queue.hpp> | ||
#include <boost/thread/executors/work.hpp> | ||
#include <boost/thread/executors/generic_executor_ref.hpp> | ||
#include <boost/thread/future.hpp> | ||
#include <boost/thread/scoped_thread.hpp> | ||
|
||
#include <boost/config/abi_prefix.hpp> | ||
|
||
namespace boost | ||
{ | ||
namespace executors | ||
{ | ||
class serial_executor_cont | ||
{ | ||
public: | ||
/// type-erasure to store the works to do | ||
typedef executors::work work; | ||
private: | ||
|
||
generic_executor_ref ex_; | ||
future<void> fut_; // protected by mtx_ | ||
bool closed_; // protected by mtx_ | ||
mutex mtx_; | ||
|
||
struct continuation { | ||
work task; | ||
template <class X> | ||
struct result { | ||
typedef void type; | ||
}; | ||
continuation(BOOST_THREAD_RV_REF(work) tsk) | ||
: task(boost::move(tsk)) {} | ||
void operator()(future<void> f) | ||
{ | ||
try { | ||
task(); | ||
} catch (...) { | ||
std::terminate(); | ||
} | ||
} | ||
}; | ||
|
||
bool closed(lock_guard<mutex>&) const | ||
{ | ||
return closed_; | ||
} | ||
public: | ||
/** | ||
* \par Returns | ||
* The underlying executor wrapped on a generic executor reference. | ||
*/ | ||
generic_executor_ref& underlying_executor() BOOST_NOEXCEPT { return ex_; } | ||
|
||
/// serial_executor_cont is not copyable. | ||
BOOST_THREAD_NO_COPYABLE(serial_executor_cont) | ||
|
||
/** | ||
* \b Effects: creates a serial executor that runs closures in fifo order using one the associated executor. | ||
* | ||
* \b Throws: Whatever exception is thrown while initializing the needed resources. | ||
* | ||
* \b Notes: | ||
* * The lifetime of the associated executor must outlive the serial executor. | ||
* * The current implementation doesn't support submission from synchronous continuation, that is, | ||
* - the executor must execute the continuation asynchronously or | ||
* - the continuation can not submit to this serial executor. | ||
*/ | ||
template <class Executor> | ||
serial_executor_cont(Executor& ex) | ||
: ex_(ex), fut_(make_ready_future()), closed_(false) | ||
{ | ||
} | ||
/** | ||
* \b Effects: Destroys the thread pool. | ||
* | ||
* \b Synchronization: The completion of all the closures happen before the completion of the \c serial_executor_cont destructor. | ||
*/ | ||
~serial_executor_cont() | ||
{ | ||
// signal to the worker thread that there will be no more submissions. | ||
close(); | ||
} | ||
|
||
/** | ||
* \b Effects: close the \c serial_executor_cont for submissions. | ||
* The loop will work until there is no more closures to run. | ||
*/ | ||
void close() | ||
{ | ||
lock_guard<mutex> lk(mtx_); | ||
closed_ = true;; | ||
} | ||
|
||
/** | ||
* \b Returns: whether the pool is closed for submissions. | ||
*/ | ||
bool closed() | ||
{ | ||
lock_guard<mutex> lk(mtx_); | ||
return closed(lk); | ||
} | ||
|
||
/** | ||
* Effects: none. | ||
* Returns: always false. | ||
* Throws: No. | ||
* Remark: A serial executor can not execute one of its pending tasks as the tasks depends on the other tasks. | ||
*/ | ||
bool try_executing_one() | ||
{ | ||
return false; | ||
} | ||
|
||
/** | ||
* \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. | ||
* | ||
* \b Effects: The specified \c closure will be scheduled for execution after the last submitted closure finish. | ||
* If the invoked closure throws an exception the \c serial_executor_cont will call \c std::terminate, as is the case with threads. | ||
* | ||
* \b Throws: \c sync_queue_is_closed if the executor is closed. | ||
* Whatever exception that can be throw while storing the closure. | ||
* | ||
*/ | ||
|
||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | ||
template <typename Closure> | ||
void submit(Closure & closure) | ||
{ | ||
lock_guard<mutex> lk(mtx_); | ||
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); | ||
fut_ = fut_.then(ex_, continuation(work(closure))); | ||
} | ||
#endif | ||
void submit(void (*closure)()) | ||
{ | ||
lock_guard<mutex> lk(mtx_); | ||
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); | ||
fut_ = fut_.then(ex_, continuation(work(closure))); | ||
} | ||
|
||
template <typename Closure> | ||
void submit(BOOST_THREAD_RV_REF(Closure) closure) | ||
{ | ||
lock_guard<mutex> lk(mtx_); | ||
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); | ||
fut_ = fut_.then(ex_, continuation(work(boost::forward<Closure>(closure)))); | ||
} | ||
|
||
}; | ||
} | ||
using executors::serial_executor_cont; | ||
} | ||
|
||
#include <boost/config/abi_suffix.hpp> | ||
|
||
#endif |
Oops, something went wrong.