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 7 #ifndef BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP 8 #define BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP 9 10 #include <boost/thread/detail/config.hpp> 11 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE 12 13 #include <boost/thread/detail/delete.hpp> 14 #include <boost/thread/detail/move.hpp> 15 #include <boost/thread/executors/executor.hpp> 16 17 #include <boost/shared_ptr.hpp> 18 19 #include <boost/config/abi_prefix.hpp> 20 21 namespace boost 22 { 23 namespace executors 24 { 25 26 template <class Executor> 27 class executor_ref : public executor 28 { 29 Executor& ex; 30 public: 31 /// type-erasure to store the works to do 32 typedef executors::work work; 33 34 /// executor is not copyable. 35 BOOST_THREAD_NO_COPYABLE(executor_ref) executor_ref(Executor & ex_)36 executor_ref(Executor& ex_) : ex(ex_) {} 37 38 /** 39 * \par Effects 40 * Destroys the executor. 41 * 42 * \par Synchronization 43 * The completion of all the closures happen before the completion of the executor destructor. 44 */ ~executor_ref()45 ~executor_ref() {} 46 47 /** 48 * \par Effects 49 * Close the \c executor for submissions. 50 * The worker threads will work until there is no more closures to run. 51 */ close()52 void close() { ex.close(); } 53 54 /** 55 * \par Returns 56 * Whether the pool is closed for submissions. 57 */ closed()58 bool closed() { return ex.closed(); } 59 60 /** 61 * \par Effects 62 * The specified closure will be scheduled for execution at some point in the future. 63 * If invoked closure throws an exception the executor will call std::terminate, as is the case with threads. 64 * 65 * \par Synchronization 66 * Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables. 67 * 68 * \par Throws 69 * \c sync_queue_is_closed if the thread pool is closed. 70 * Whatever exception that can be throw while storing the closure. 71 */ submit(BOOST_THREAD_RV_REF (work)closure)72 void submit(BOOST_THREAD_RV_REF(work) closure) { 73 ex.submit(boost::move(closure)); 74 } 75 // void submit(work& closure) { 76 // ex.submit(closure); 77 // } 78 79 80 /** 81 * \par Effects 82 * Try to execute one task. 83 * 84 * \par Returns 85 * Whether a task has been executed. 86 * 87 * \par Throws 88 * Whatever the current task constructor throws or the task() throws. 89 */ try_executing_one()90 bool try_executing_one() { return ex.try_executing_one(); } 91 92 }; 93 94 class generic_executor_ref 95 { 96 shared_ptr<executor> ex; 97 public: 98 /// type-erasure to store the works to do 99 typedef executors::work work; 100 101 template<typename Executor> generic_executor_ref(Executor & ex_)102 generic_executor_ref(Executor& ex_) 103 //: ex(make_shared<executor_ref<Executor> >(ex_)) // todo check why this doesn't works with C++03 104 : ex( new executor_ref<Executor>(ex_) ) 105 { 106 } 107 108 //generic_executor_ref(generic_executor_ref const& other) noexcept {} 109 //generic_executor_ref& operator=(generic_executor_ref const& other) noexcept {} 110 111 112 /** 113 * \par Effects 114 * Close the \c executor for submissions. 115 * The worker threads will work until there is no more closures to run. 116 */ close()117 void close() { ex->close(); } 118 119 /** 120 * \par Returns 121 * Whether the pool is closed for submissions. 122 */ closed()123 bool closed() { return ex->closed(); } 124 125 /** 126 * \par Requires 127 * \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible. 128 * 129 * \par Effects 130 * The specified closure will be scheduled for execution at some point in the future. 131 * If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads. 132 * 133 * \par Synchronization 134 * Completion of closure on a particular thread happens before destruction of thread's thread local variables. 135 * 136 * \par Throws 137 * \c sync_queue_is_closed if the thread pool is closed. 138 * Whatever exception that can be throw while storing the closure. 139 */ 140 submit(BOOST_THREAD_RV_REF (work)closure)141 void submit(BOOST_THREAD_RV_REF(work) closure) 142 { 143 ex->submit(boost::move(closure)); 144 } 145 146 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 147 template <typename Closure> submit(Closure & closure)148 void submit(Closure & closure) 149 { 150 //work w ((closure)); 151 //submit(boost::move(w)); 152 submit(work(closure)); 153 } 154 #endif submit(void (* closure)())155 void submit(void (*closure)()) 156 { 157 work w ((closure)); 158 submit(boost::move(w)); 159 //submit(work(closure)); 160 } 161 162 template <typename Closure> submit(BOOST_THREAD_FWD_REF (Closure)closure)163 void submit(BOOST_THREAD_FWD_REF(Closure) closure) 164 { 165 work w((boost::forward<Closure>(closure))); 166 submit(boost::move(w)); 167 } 168 169 // size_t num_pending_closures() const 170 // { 171 // return ex->num_pending_closures(); 172 // } 173 174 /** 175 * \par Effects 176 * Try to execute one task. 177 * 178 * \par Returns 179 * Whether a task has been executed. 180 * 181 * \par Throws 182 * Whatever the current task constructor throws or the task() throws. 183 */ try_executing_one()184 bool try_executing_one() { return ex->try_executing_one(); } 185 186 /** 187 * \par Requires 188 * This must be called from an scheduled task. 189 * 190 * \par Effects 191 * reschedule functions until pred() 192 */ 193 template <typename Pred> reschedule_until(Pred const & pred)194 bool reschedule_until(Pred const& pred) 195 { 196 do { 197 //schedule_one_or_yield(); 198 if ( ! try_executing_one()) 199 { 200 return false; 201 } 202 } while (! pred()); 203 return true; 204 } 205 206 }; 207 } 208 using executors::executor_ref; 209 using executors::generic_executor_ref; 210 } 211 212 #include <boost/config/abi_suffix.hpp> 213 214 #endif 215 #endif 216