File indexing completed on 2025-01-30 10:01:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
0012 #define BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
0013
0014 #include <boost/thread/detail/config.hpp>
0015
0016 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
0017
0018 #include <boost/thread/detail/delete.hpp>
0019 #include <boost/thread/detail/move.hpp>
0020 #include <boost/thread/concurrent_queues/sync_queue.hpp>
0021 #include <boost/thread/executors/work.hpp>
0022 #include <boost/assert.hpp>
0023
0024 #include <boost/config/abi_prefix.hpp>
0025
0026 namespace boost
0027 {
0028 namespace executors
0029 {
0030
0031 class loop_executor
0032 {
0033 public:
0034
0035 typedef executors::work work;
0036 private:
0037
0038 concurrent::sync_queue<work > work_queue;
0039
0040 public:
0041
0042
0043
0044
0045
0046 bool try_executing_one()
0047 {
0048 return execute_one(false);
0049 }
0050
0051 private:
0052
0053
0054
0055
0056
0057
0058
0059
0060 bool execute_one(bool wait)
0061 {
0062 work task;
0063 try
0064 {
0065 queue_op_status status = wait ?
0066 work_queue.wait_pull(task) :
0067 work_queue.try_pull(task);
0068 if (status == queue_op_status::success)
0069 {
0070 task();
0071 return true;
0072 }
0073 BOOST_ASSERT(!wait || status == queue_op_status::closed);
0074 return false;
0075 }
0076 catch (...)
0077 {
0078 std::terminate();
0079
0080 }
0081 }
0082
0083 public:
0084
0085 BOOST_THREAD_NO_COPYABLE(loop_executor)
0086
0087
0088
0089
0090
0091
0092 loop_executor()
0093 {
0094 }
0095
0096
0097
0098
0099
0100 ~loop_executor()
0101 {
0102
0103 close();
0104 }
0105
0106
0107
0108
0109 void loop()
0110 {
0111 while (execute_one(true))
0112 {
0113 }
0114 BOOST_ASSERT(closed());
0115 while (try_executing_one())
0116 {
0117 }
0118 }
0119
0120
0121
0122
0123
0124 void close()
0125 {
0126 work_queue.close();
0127 }
0128
0129
0130
0131
0132 bool closed()
0133 {
0134 return work_queue.closed();
0135 }
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148 void submit(BOOST_THREAD_RV_REF(work) closure) {
0149 work_queue.push(boost::move(closure));
0150 }
0151
0152 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0153 template <typename Closure>
0154 void submit(Closure & closure)
0155 {
0156 submit(work(closure));
0157 }
0158 #endif
0159
0160 void submit(void (*closure)())
0161 {
0162 submit(work(closure));
0163 }
0164
0165 template <typename Closure>
0166 void submit(BOOST_THREAD_FWD_REF(Closure) closure)
0167 {
0168
0169 work w((boost::forward<Closure>(closure)));
0170 submit(boost::move(w));
0171 }
0172
0173
0174
0175
0176
0177
0178 template <typename Pred>
0179 bool reschedule_until(Pred const& pred)
0180 {
0181 do {
0182 if ( ! try_executing_one())
0183 {
0184 return false;
0185 }
0186 } while (! pred());
0187 return true;
0188 }
0189
0190
0191
0192
0193 void run_queued_closures()
0194 {
0195 sync_queue<work>::underlying_queue_type q = work_queue.underlying_queue();
0196 while (! q.empty())
0197 {
0198 work& task = q.front();
0199 task();
0200 q.pop_front();
0201 }
0202 }
0203
0204 };
0205 }
0206 using executors::loop_executor;
0207
0208 }
0209
0210 #include <boost/config/abi_suffix.hpp>
0211 #endif
0212
0213 #endif