// 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 #include #include #include #include #include namespace boost { namespace executors { template 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 ex; public: /// type-erasure to store the works to do typedef executors::work work; template generic_executor_ref(Executor& ex) //: ex(make_shared >(ex)) // todo check why this doesn't works with C++03 : ex( new executor_ref(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(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 void submit(Closure & closure) { work w ((closure)); submit(boost::move(w)); } #endif void submit(void (*closure)()) { work w ((closure)); submit(boost::move(w)); } template 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 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 #endif