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_SCHEDULER_HPP
8#define BOOST_THREAD_EXECUTORS_SCHEDULER_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#include <boost/thread/executors/detail/scheduled_executor_base.hpp>
13
14#include <boost/chrono/time_point.hpp>
15#include <boost/chrono/duration.hpp>
16#include <boost/chrono/system_clocks.hpp>
17
18#include <boost/config/abi_prefix.hpp>
19
20#if defined(BOOST_MSVC)
21# pragma warning(push)
22# pragma warning(disable: 4355) // 'this' : used in base member initializer list
23#endif
24
25namespace boost
26{
27 namespace executors
28 {
29 /// Wraps the reference to an executor and a function to make a work that submit the function using the executor.
30 template <class Executor, class Function>
31 class resubmitter
32 {
33 public:
34 resubmitter(Executor& ex, Function funct) :
35 ex(ex),
36 funct(boost::move(funct))
37 {}
38
39 void operator()()
40 {
41 ex.submit(funct);
42 }
43
44 private:
45 Executor& ex;
46 Function funct;
47 };
48
49 /// resubmitter factory
50 template <class Executor, class Function>
51 resubmitter<Executor, typename decay<Function>::type>
52 resubmit(Executor& ex, BOOST_THREAD_FWD_REF(Function) funct) {
53 return resubmitter<Executor, typename decay<Function>::type >(ex, boost::move(funct));
54 }
55
56 /// Wraps references to a @c Scheduler and an @c Executor providing an @c Executor that
57 /// resubmit the function using the referenced Executor at a given @c time_point known at construction.
58 template <class Scheduler, class Executor>
59 class resubmit_at_executor
60 {
61 public:
62 typedef typename Scheduler::clock clock;
63 typedef typename Scheduler::work work;
64
65 template <class Duration>
66 resubmit_at_executor(Scheduler& sch, Executor& ex, chrono::time_point<clock, Duration> const& tp) :
67 sch(sch),
68 ex(ex),
69 tp(tp),
70 is_closed(false)
71 {
72 }
73
74 ~resubmit_at_executor()
75 {
76 close();
77 }
78
79 template <class Work>
80 void submit(BOOST_THREAD_FWD_REF(Work) w)
81 {
82 if (closed())
83 {
84 BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
85 }
86 sch.submit_at(resubmit(ex,boost::forward<Work>(w)), tp);
87 }
88
89 Executor& underlying_executor()
90 {
91 return ex;
92 }
93 Scheduler& underlying_scheduler()
94 {
95 return sch;
96 }
97
98 void close()
99 {
100 is_closed = true;
101 }
102
103 bool closed()
104 {
105 return is_closed || sch.closed() || ex.closed();
106 }
107
108 private:
109 Scheduler& sch;
110 Executor& ex;
111 typename clock::time_point tp;
112 bool is_closed;
113 };
114
115
116 /// Expression template helper storing a pair of references to an @c Scheduler and an @c Executor
117 /// It provides factory helper functions such as at/after that convert these a pair of @c Scheduler @c Executor
118 /// into an new @c Executor that submit the work using the referenced @c Executor at/after a specific time/duration
119 /// respectively, using the referenced @Scheduler.
120 template <class Scheduler, class Executor>
121 class scheduler_executor_wrapper
122 {
123 public:
124 typedef typename Scheduler::clock clock;
125 typedef typename Scheduler::work work;
126 typedef resubmit_at_executor<Scheduler, Executor> the_executor;
127
128 scheduler_executor_wrapper(Scheduler& sch, Executor& ex) :
129 sch(sch),
130 ex(ex)
131 {}
132
133 ~scheduler_executor_wrapper()
134 {
135 }
136
137 Executor& underlying_executor()
138 {
139 return ex;
140 }
141 Scheduler& underlying_scheduler()
142 {
143 return sch;
144 }
145
146 template <class Rep, class Period>
147 the_executor after(chrono::duration<Rep,Period> const& rel_time)
148 {
149 return at(clock::now() + rel_time );
150 }
151
152 template <class Duration>
153 the_executor at(chrono::time_point<clock,Duration> const& abs_time)
154 {
155 return the_executor(sch, ex, abs_time);
156 }
157
158 private:
159 Scheduler& sch;
160 Executor& ex;
161 }; //end class
162
163 /// Wraps a reference to a @c Scheduler providing an @c Executor that
164 /// run the function at a given @c time_point known at construction.
165 template <class Scheduler>
166 class at_executor
167 {
168 public:
169 typedef typename Scheduler::clock clock;
170 typedef typename Scheduler::work work;
171 typedef typename clock::time_point time_point;
172
173 template <class Duration>
174 at_executor(Scheduler& sch, chrono::time_point<clock,Duration> const& tp) :
175 sch(sch),
176 tp(tp),
177 is_closed(false)
178 {}
179
180 ~at_executor()
181 {
182 close();
183 }
184
185 Scheduler& underlying_scheduler()
186 {
187 return sch;
188 }
189
190 void close()
191 {
192 is_closed = true;
193 }
194
195 bool closed()
196 {
197 return is_closed || sch.closed();
198 }
199
200 template <class Work>
201 void submit(BOOST_THREAD_FWD_REF(Work) w)
202 {
203 if (closed())
204 {
205 BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
206 }
207 sch.submit_at(boost::forward<Work>(w), tp);
208 }
209
210 template <class Executor>
211 resubmit_at_executor<Scheduler, Executor> on(Executor& ex)
212 {
213 return resubmit_at_executor<Scheduler, Executor>(sch, ex, tp);
214 }
215
216 private:
217 Scheduler& sch;
218 time_point tp;
219 bool is_closed;
220 }; //end class
221
222 /// A @c Scheduler using a specific thread. Note that a Scheduler is not an Executor.
223 /// It provides factory helper functions such as at/after that convert a @c Scheduler into an @c Executor
224 /// that submit the work at/after a specific time/duration respectively.
225 template <class Clock = chrono::steady_clock>
226 class scheduler : public detail::scheduled_executor_base<Clock>
227 {
228 public:
229 typedef typename detail::scheduled_executor_base<Clock>::work work;
230
231 typedef Clock clock;
232
233 scheduler()
234 : super(),
235 thr(&super::loop, this) {}
236
237 ~scheduler()
238 {
239 this->close();
240 thr.interrupt();
241 thr.join();
242 }
243 template <class Ex>
244 scheduler_executor_wrapper<scheduler, Ex> on(Ex& ex)
245 {
246 return scheduler_executor_wrapper<scheduler, Ex>(*this, ex);
247 }
248
249 template <class Rep, class Period>
250 at_executor<scheduler> after(chrono::duration<Rep,Period> const& rel_time)
251 {
252 return at(rel_time + clock::now());
253 }
254
255 template <class Duration>
256 at_executor<scheduler> at(chrono::time_point<clock,Duration> const& tp)
257 {
258 return at_executor<scheduler>(*this, tp);
259 }
260
261 private:
262 typedef detail::scheduled_executor_base<Clock> super;
263 thread thr;
264 };
265
266
267 }
268 using executors::resubmitter;
269 using executors::resubmit;
270 using executors::resubmit_at_executor;
271 using executors::scheduler_executor_wrapper;
272 using executors::at_executor;
273 using executors::scheduler;
274}
275
276#if defined(BOOST_MSVC)
277# pragma warning(pop)
278#endif
279
280#include <boost/config/abi_suffix.hpp>
281
282#endif
283#endif
284

source code of boost/libs/thread/include/boost/thread/executors/scheduler.hpp