• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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