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