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 // 2013/11 Vicente J. Botet Escriba 7 // first implementation of a simple serial scheduler. 8 9 #ifndef BOOST_THREAD_INLINE_EXECUTOR_HPP 10 #define BOOST_THREAD_INLINE_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 <exception> // std::terminate 16 #include <boost/throw_exception.hpp> 17 #include <boost/thread/detail/delete.hpp> 18 #include <boost/thread/detail/move.hpp> 19 #include <boost/thread/executors/work.hpp> 20 #include <boost/thread/mutex.hpp> 21 #include <boost/thread/lock_guard.hpp> 22 #include <boost/thread/concurrent_queues/queue_op_status.hpp> // sync_queue_is_closed 23 24 #include <boost/config/abi_prefix.hpp> 25 26 namespace boost 27 { 28 namespace executors 29 { 30 class inline_executor 31 { 32 public: 33 /// type-erasure to store the works to do 34 typedef executors::work work; 35 bool closed_; 36 mutable mutex mtx_; 37 /** 38 * Effects: try to execute one task. 39 * Returns: whether a task has been executed. 40 * Throws: whatever the current task constructor throws or the task() throws. 41 */ try_executing_one()42 bool try_executing_one() 43 { 44 return false; 45 } 46 47 public: 48 /// inline_executor is not copyable. 49 BOOST_THREAD_NO_COPYABLE(inline_executor) 50 51 /** 52 * \b Effects: creates a inline executor that runs closures immediately. 53 * 54 * \b Throws: Nothing. 55 */ inline_executor()56 inline_executor() 57 : closed_(false) 58 { 59 } 60 /** 61 * \b Effects: Destroys the inline executor. 62 * 63 * \b Synchronization: The completion of all the closures happen before the completion of the \c inline_executor destructor. 64 */ ~inline_executor()65 ~inline_executor() 66 { 67 // signal to all the worker thread that there will be no more submissions. 68 close(); 69 } 70 71 /** 72 * \b Effects: close the \c inline_executor for submissions. 73 * The loop will work until there is no more closures to run. 74 */ close()75 void close() 76 { 77 lock_guard<mutex> lk(mtx_); 78 closed_ = true; 79 } 80 81 /** 82 * \b Returns: whether the pool is closed for submissions. 83 */ closed(lock_guard<mutex> &)84 bool closed(lock_guard<mutex>& ) 85 { 86 return closed_; 87 } closed()88 bool closed() 89 { 90 lock_guard<mutex> lk(mtx_); 91 return closed(lk); 92 } 93 94 /** 95 * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. 96 * 97 * \b Effects: The specified \c closure will be scheduled for execution at some point in the future. 98 * If invoked closure throws an exception the \c inline_executor will call \c std::terminate, as is the case with threads. 99 * 100 * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables. 101 * 102 * \b Throws: \c sync_queue_is_closed if the thread pool is closed. 103 * Whatever exception that can be throw while storing the closure. 104 */ 105 106 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 107 template <typename Closure> submit(Closure & closure)108 void submit(Closure & closure) 109 { 110 { 111 lock_guard<mutex> lk(mtx_); 112 if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); 113 } 114 try 115 { 116 closure(); 117 } 118 catch (...) 119 { 120 std::terminate(); 121 return; 122 } 123 } 124 #endif submit(void (* closure)())125 void submit(void (*closure)()) 126 { 127 { 128 lock_guard<mutex> lk(mtx_); 129 if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); 130 } 131 try 132 { 133 closure(); 134 } 135 catch (...) 136 { 137 std::terminate(); 138 return; 139 } 140 } 141 142 template <typename Closure> submit(BOOST_THREAD_FWD_REF (Closure)closure)143 void submit(BOOST_THREAD_FWD_REF(Closure) closure) 144 { 145 { 146 lock_guard<mutex> lk(mtx_); 147 if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); 148 } 149 try 150 { 151 closure(); 152 } 153 catch (...) 154 { 155 std::terminate(); 156 return; 157 } 158 } 159 160 /** 161 * \b Requires: This must be called from an scheduled task. 162 * 163 * \b Effects: reschedule functions until pred() 164 */ 165 template <typename Pred> reschedule_until(Pred const &)166 bool reschedule_until(Pred const& ) 167 { 168 return false; 169 } 170 171 }; 172 } 173 using executors::inline_executor; 174 } 175 176 #include <boost/config/abi_suffix.hpp> 177 178 #endif 179 #endif 180