File indexing completed on 2025-01-30 10:01:11
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_THREAD_EXECUTORS_SCHEDULER_HPP
0008 #define BOOST_THREAD_EXECUTORS_SCHEDULER_HPP
0009
0010 #include <boost/thread/detail/config.hpp>
0011 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
0012 #include <boost/thread/executors/detail/scheduled_executor_base.hpp>
0013
0014 #include <boost/chrono/time_point.hpp>
0015 #include <boost/chrono/duration.hpp>
0016 #include <boost/chrono/system_clocks.hpp>
0017
0018 #include <boost/config/abi_prefix.hpp>
0019
0020 #if defined(BOOST_MSVC)
0021 # pragma warning(push)
0022 # pragma warning(disable: 4355)
0023 #endif
0024
0025 namespace boost
0026 {
0027 namespace executors
0028 {
0029
0030 template <class Executor, class Function>
0031 class resubmitter
0032 {
0033 public:
0034 resubmitter(Executor& ex, Function funct) :
0035 ex(ex),
0036 funct(boost::move(funct))
0037 {}
0038
0039 void operator()()
0040 {
0041 ex.submit(funct);
0042 }
0043
0044 private:
0045 Executor& ex;
0046 Function funct;
0047 };
0048
0049
0050 template <class Executor, class Function>
0051 resubmitter<Executor, typename decay<Function>::type>
0052 resubmit(Executor& ex, BOOST_THREAD_FWD_REF(Function) funct) {
0053 return resubmitter<Executor, typename decay<Function>::type >(ex, boost::move(funct));
0054 }
0055
0056
0057
0058 template <class Scheduler, class Executor>
0059 class resubmit_at_executor
0060 {
0061 public:
0062 typedef typename Scheduler::clock clock;
0063 typedef typename Scheduler::work work;
0064
0065 template <class Duration>
0066 resubmit_at_executor(Scheduler& sch, Executor& ex, chrono::time_point<clock, Duration> const& tp) :
0067 sch(sch),
0068 ex(ex),
0069 tp(tp),
0070 is_closed(false)
0071 {
0072 }
0073
0074 ~resubmit_at_executor()
0075 {
0076 close();
0077 }
0078
0079 template <class Work>
0080 void submit(BOOST_THREAD_FWD_REF(Work) w)
0081 {
0082 if (closed())
0083 {
0084 BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
0085 }
0086 sch.submit_at(resubmit(ex,boost::forward<Work>(w)), tp);
0087 }
0088
0089 Executor& underlying_executor()
0090 {
0091 return ex;
0092 }
0093 Scheduler& underlying_scheduler()
0094 {
0095 return sch;
0096 }
0097
0098 void close()
0099 {
0100 is_closed = true;
0101 }
0102
0103 bool closed()
0104 {
0105 return is_closed || sch.closed() || ex.closed();
0106 }
0107
0108 private:
0109 Scheduler& sch;
0110 Executor& ex;
0111 typename clock::time_point tp;
0112 bool is_closed;
0113 };
0114
0115
0116
0117
0118
0119
0120 template <class Scheduler, class Executor>
0121 class scheduler_executor_wrapper
0122 {
0123 public:
0124 typedef typename Scheduler::clock clock;
0125 typedef typename Scheduler::work work;
0126 typedef resubmit_at_executor<Scheduler, Executor> the_executor;
0127
0128 scheduler_executor_wrapper(Scheduler& sch, Executor& ex) :
0129 sch(sch),
0130 ex(ex)
0131 {}
0132
0133 ~scheduler_executor_wrapper()
0134 {
0135 }
0136
0137 Executor& underlying_executor()
0138 {
0139 return ex;
0140 }
0141 Scheduler& underlying_scheduler()
0142 {
0143 return sch;
0144 }
0145
0146 template <class Rep, class Period>
0147 the_executor after(chrono::duration<Rep,Period> const& rel_time)
0148 {
0149 return at(clock::now() + rel_time );
0150 }
0151
0152 template <class Duration>
0153 the_executor at(chrono::time_point<clock,Duration> const& abs_time)
0154 {
0155 return the_executor(sch, ex, abs_time);
0156 }
0157
0158 private:
0159 Scheduler& sch;
0160 Executor& ex;
0161 };
0162
0163
0164
0165 template <class Scheduler>
0166 class at_executor
0167 {
0168 public:
0169 typedef typename Scheduler::clock clock;
0170 typedef typename Scheduler::work work;
0171 typedef typename clock::time_point time_point;
0172
0173 template <class Duration>
0174 at_executor(Scheduler& sch, chrono::time_point<clock,Duration> const& tp) :
0175 sch(sch),
0176 tp(tp),
0177 is_closed(false)
0178 {}
0179
0180 ~at_executor()
0181 {
0182 close();
0183 }
0184
0185 Scheduler& underlying_scheduler()
0186 {
0187 return sch;
0188 }
0189
0190 void close()
0191 {
0192 is_closed = true;
0193 }
0194
0195 bool closed()
0196 {
0197 return is_closed || sch.closed();
0198 }
0199
0200 template <class Work>
0201 void submit(BOOST_THREAD_FWD_REF(Work) w)
0202 {
0203 if (closed())
0204 {
0205 BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
0206 }
0207 sch.submit_at(boost::forward<Work>(w), tp);
0208 }
0209
0210 template <class Executor>
0211 resubmit_at_executor<Scheduler, Executor> on(Executor& ex)
0212 {
0213 return resubmit_at_executor<Scheduler, Executor>(sch, ex, tp);
0214 }
0215
0216 private:
0217 Scheduler& sch;
0218 time_point tp;
0219 bool is_closed;
0220 };
0221
0222
0223
0224
0225 template <class Clock = chrono::steady_clock>
0226 class scheduler : public detail::scheduled_executor_base<Clock>
0227 {
0228 public:
0229 typedef typename detail::scheduled_executor_base<Clock>::work work;
0230
0231 typedef Clock clock;
0232
0233 scheduler()
0234 : super(),
0235 thr(&super::loop, this) {}
0236
0237 ~scheduler()
0238 {
0239 this->close();
0240 thr.interrupt();
0241 thr.join();
0242 }
0243 template <class Ex>
0244 scheduler_executor_wrapper<scheduler, Ex> on(Ex& ex)
0245 {
0246 return scheduler_executor_wrapper<scheduler, Ex>(*this, ex);
0247 }
0248
0249 template <class Rep, class Period>
0250 at_executor<scheduler> after(chrono::duration<Rep,Period> const& rel_time)
0251 {
0252 return at(rel_time + clock::now());
0253 }
0254
0255 template <class Duration>
0256 at_executor<scheduler> at(chrono::time_point<clock,Duration> const& tp)
0257 {
0258 return at_executor<scheduler>(*this, tp);
0259 }
0260
0261 private:
0262 typedef detail::scheduled_executor_base<Clock> super;
0263 thread thr;
0264 };
0265
0266
0267 }
0268 using executors::resubmitter;
0269 using executors::resubmit;
0270 using executors::resubmit_at_executor;
0271 using executors::scheduler_executor_wrapper;
0272 using executors::at_executor;
0273 using executors::scheduler;
0274 }
0275
0276 #if defined(BOOST_MSVC)
0277 # pragma warning(pop)
0278 #endif
0279
0280 #include <boost/config/abi_suffix.hpp>
0281
0282 #endif
0283 #endif