1 // Copyright (C) 2014 Vicente J. Botet Escriba 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 // 6 // 2014/01 Vicente J. Botet Escriba 7 // first implementation of a thread_executor. 8 9 #ifndef BOOST_THREAD_THREAD_EXECUTOR_HPP 10 #define BOOST_THREAD_THREAD_EXECUTOR_HPP 11 12 #include <boost/thread/detail/config.hpp> 13 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE 14 15 #include <boost/throw_exception.hpp> 16 #include <boost/thread/detail/delete.hpp> 17 #include <boost/thread/detail/move.hpp> 18 #include <boost/thread/executors/work.hpp> 19 #include <boost/thread/executors/executor.hpp> 20 #include <boost/thread/mutex.hpp> 21 #include <boost/thread/lock_guard.hpp> 22 #include <boost/thread/thread_only.hpp> 23 #include <boost/thread/scoped_thread.hpp> 24 #include <boost/thread/csbl/vector.hpp> 25 #include <boost/thread/concurrent_queues/queue_op_status.hpp> 26 27 #include <boost/config/abi_prefix.hpp> 28 29 namespace boost 30 { 31 namespace executors 32 { 33 class thread_executor 34 { 35 public: 36 /// type-erasure to store the works to do 37 typedef executors::work work; 38 bool closed_; 39 typedef scoped_thread<> thread_t; 40 typedef csbl::vector<thread_t> threads_type; 41 threads_type threads_; 42 mutable mutex mtx_; 43 44 /** 45 * Effects: try to execute one task. 46 * Returns: whether a task has been executed. 47 * Throws: whatever the current task constructor throws or the task() throws. 48 */ try_executing_one()49 bool try_executing_one() 50 { 51 return false; 52 } 53 54 public: 55 /// thread_executor is not copyable. 56 BOOST_THREAD_NO_COPYABLE(thread_executor) 57 58 /** 59 * \b Effects: creates a inline executor that runs closures immediately. 60 * 61 * \b Throws: Nothing. 62 */ thread_executor()63 thread_executor() 64 : closed_(false) 65 { 66 } 67 /** 68 * \b Effects: Waits for closures (if any) to complete, then joins and destroys the threads. 69 * 70 * \b Synchronization: The completion of all the closures happen before the completion of the \c thread_executor destructor. 71 */ ~thread_executor()72 ~thread_executor() 73 { 74 // signal to all the worker thread that there will be no more submissions. 75 close(); 76 // all the scoped threads will join before destroying 77 } 78 79 /** 80 * \b Effects: close the \c thread_executor for submissions. 81 * The loop will work until there is no more closures to run. 82 */ close()83 void close() 84 { 85 lock_guard<mutex> lk(mtx_); 86 closed_ = true; 87 } 88 89 /** 90 * \b Returns: whether the pool is closed for submissions. 91 */ closed(lock_guard<mutex> &)92 bool closed(lock_guard<mutex>& ) 93 { 94 return closed_; 95 } closed()96 bool closed() 97 { 98 lock_guard<mutex> lk(mtx_); 99 return closed(lk); 100 } 101 102 /** 103 * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. 104 * 105 * \b Effects: The specified \c closure will be scheduled for execution at some point in the future. 106 * If invoked closure throws an exception the \c thread_executor will call \c std::terminate, as is the case with threads. 107 * 108 * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables. 109 * 110 * \b Throws: \c sync_queue_is_closed if the thread pool is closed. 111 * Whatever exception that can be throw while storing the closure. 112 */ 113 114 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 115 template <typename Closure> submit(Closure & closure)116 void submit(Closure & closure) 117 { 118 lock_guard<mutex> lk(mtx_); 119 if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); 120 threads_.reserve(threads_.size() + 1); 121 thread th(closure); 122 threads_.push_back(thread_t(boost::move(th))); 123 } 124 #endif submit(void (* closure)())125 void submit(void (*closure)()) 126 { 127 lock_guard<mutex> lk(mtx_); 128 if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); 129 threads_.reserve(threads_.size() + 1); 130 thread th(closure); 131 threads_.push_back(thread_t(boost::move(th))); 132 } 133 134 template <typename Closure> submit(BOOST_THREAD_FWD_REF (Closure)closure)135 void submit(BOOST_THREAD_FWD_REF(Closure) closure) 136 { 137 lock_guard<mutex> lk(mtx_); 138 if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); 139 threads_.reserve(threads_.size() + 1); 140 thread th(boost::forward<Closure>(closure)); 141 threads_.push_back(thread_t(boost::move(th))); 142 } 143 144 /** 145 * \b Requires: This must be called from an scheduled task. 146 * 147 * \b Effects: reschedule functions until pred() 148 */ 149 template <typename Pred> reschedule_until(Pred const &)150 bool reschedule_until(Pred const&) 151 { 152 return false; 153 } 154 155 }; 156 } 157 using executors::thread_executor; 158 } 159 160 #include <boost/config/abi_suffix.hpp> 161 162 #endif 163 #endif 164