Chris@102: // Copyright (C) 2014 Vicente J. Botet Escriba Chris@102: // Chris@102: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@102: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@102: // Chris@102: // 2014/01 Vicente J. Botet Escriba Chris@102: // first implementation of a thread_executor. Chris@102: Chris@102: #ifndef BOOST_THREAD_THREAD_EXECUTOR_HPP Chris@102: #define BOOST_THREAD_THREAD_EXECUTOR_HPP Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: #include Chris@102: Chris@102: namespace boost Chris@102: { Chris@102: namespace executors Chris@102: { Chris@102: class thread_executor Chris@102: { Chris@102: public: Chris@102: /// type-erasure to store the works to do Chris@102: typedef executors::work work; Chris@102: bool closed_; Chris@102: typedef scoped_thread<> thread_t; Chris@102: typedef csbl::vector threads_type; Chris@102: threads_type threads_; Chris@102: mutable mutex mtx_; Chris@102: Chris@102: /** Chris@102: * Effects: try to execute one task. Chris@102: * Returns: whether a task has been executed. Chris@102: * Throws: whatever the current task constructor throws or the task() throws. Chris@102: */ Chris@102: bool try_executing_one() Chris@102: { Chris@102: return false; Chris@102: } Chris@102: Chris@102: public: Chris@102: /// thread_executor is not copyable. Chris@102: BOOST_THREAD_NO_COPYABLE(thread_executor) Chris@102: Chris@102: /** Chris@102: * \b Effects: creates a inline executor that runs closures immediately. Chris@102: * Chris@102: * \b Throws: Nothing. Chris@102: */ Chris@102: thread_executor() Chris@102: : closed_(false) Chris@102: { Chris@102: } Chris@102: /** Chris@102: * \b Effects: Waits for closures (if any) to complete, then joins and destroys the threads. Chris@102: * Chris@102: * \b Synchronization: The completion of all the closures happen before the completion of the \c thread_executor destructor. Chris@102: */ Chris@102: ~thread_executor() Chris@102: { Chris@102: // signal to all the worker thread that there will be no more submissions. Chris@102: close(); Chris@102: // all the scoped threads will join before destroying Chris@102: } Chris@102: Chris@102: /** Chris@102: * \b Effects: close the \c thread_executor for submissions. Chris@102: * The loop will work until there is no more closures to run. Chris@102: */ Chris@102: void close() Chris@102: { Chris@102: lock_guard lk(mtx_); Chris@102: closed_ = true; Chris@102: } Chris@102: Chris@102: /** Chris@102: * \b Returns: whether the pool is closed for submissions. Chris@102: */ Chris@102: bool closed(lock_guard& ) Chris@102: { Chris@102: return closed_; Chris@102: } Chris@102: bool closed() Chris@102: { Chris@102: lock_guard lk(mtx_); Chris@102: return closed(lk); Chris@102: } Chris@102: Chris@102: /** Chris@102: * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. Chris@102: * Chris@102: * \b Effects: The specified \c closure will be scheduled for execution at some point in the future. Chris@102: * If invoked closure throws an exception the \c thread_executor will call \c std::terminate, as is the case with threads. Chris@102: * Chris@102: * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables. Chris@102: * Chris@102: * \b Throws: \c sync_queue_is_closed if the thread pool is closed. Chris@102: * Whatever exception that can be throw while storing the closure. Chris@102: */ Chris@102: Chris@102: #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@102: template Chris@102: void submit(Closure & closure) Chris@102: { Chris@102: lock_guard lk(mtx_); Chris@102: if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); Chris@102: threads_.reserve(threads_.size() + 1); Chris@102: thread th(closure); Chris@102: threads_.push_back(thread_t(boost::move(th))); Chris@102: } Chris@102: #endif Chris@102: void submit(void (*closure)()) Chris@102: { Chris@102: lock_guard lk(mtx_); Chris@102: if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); Chris@102: threads_.reserve(threads_.size() + 1); Chris@102: thread th(closure); Chris@102: threads_.push_back(thread_t(boost::move(th))); Chris@102: } Chris@102: Chris@102: template Chris@102: void submit(BOOST_THREAD_FWD_REF(Closure) closure) Chris@102: { Chris@102: lock_guard lk(mtx_); Chris@102: if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); Chris@102: threads_.reserve(threads_.size() + 1); Chris@102: thread th(boost::forward(closure)); Chris@102: threads_.push_back(thread_t(boost::move(th))); Chris@102: } Chris@102: Chris@102: /** Chris@102: * \b Requires: This must be called from an scheduled task. Chris@102: * Chris@102: * \b Effects: reschedule functions until pred() Chris@102: */ Chris@102: template Chris@102: bool reschedule_until(Pred const&) Chris@102: { Chris@102: return false; Chris@102: } Chris@102: Chris@102: }; Chris@102: } Chris@102: using executors::thread_executor; Chris@102: } Chris@102: Chris@102: #include Chris@102: Chris@102: #endif