]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/thread/include/boost/thread/executors/serial_executor.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / thread / include / boost / thread / executors / serial_executor.hpp
1 // Copyright (C) 2013 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 // 2013/11 Vicente J. Botet Escriba
7 // first implementation of a simple serial scheduler.
8
9 #ifndef BOOST_THREAD_SERIAL_EXECUTOR_HPP
10 #define BOOST_THREAD_SERIAL_EXECUTOR_HPP
11
12 #include <boost/thread/detail/config.hpp>
13 #include <boost/thread/detail/delete.hpp>
14 #include <boost/thread/detail/move.hpp>
15 #include <boost/thread/concurrent_queues/sync_queue.hpp>
16 #include <boost/thread/executors/work.hpp>
17 #include <boost/thread/executors/generic_executor_ref.hpp>
18 #include <boost/thread/future.hpp>
19 #include <boost/thread/scoped_thread.hpp>
20
21 #include <boost/config/abi_prefix.hpp>
22
23 namespace boost
24 {
25 namespace executors
26 {
27 class serial_executor
28 {
29 public:
30 /// type-erasure to store the works to do
31 typedef executors::work work;
32 private:
33 typedef scoped_thread<> thread_t;
34
35 /// the thread safe work queue
36 concurrent::sync_queue<work > work_queue;
37 generic_executor_ref ex;
38 thread_t thr;
39
40 struct try_executing_one_task {
41 work& task;
42 boost::promise<void> &p;
43 try_executing_one_task(work& task, boost::promise<void> &p)
44 : task(task), p(p) {}
45 void operator()() {
46 try {
47 task();
48 p.set_value();
49 } catch (...)
50 {
51 p.set_exception(current_exception());
52 }
53 }
54 };
55 public:
56 /**
57 * \par Returns
58 * The underlying executor wrapped on a generic executor reference.
59 */
60 generic_executor_ref& underlying_executor() BOOST_NOEXCEPT { return ex; }
61
62 /**
63 * Effects: try to execute one task.
64 * Returns: whether a task has been executed.
65 * Throws: whatever the current task constructor throws or the task() throws.
66 */
67 bool try_executing_one()
68 {
69 work task;
70 try
71 {
72 if (work_queue.try_pull(task) == queue_op_status::success)
73 {
74 boost::promise<void> p;
75 try_executing_one_task tmp(task,p);
76 ex.submit(tmp);
77 p.get_future().wait();
78 return true;
79 }
80 return false;
81 }
82 catch (...)
83 {
84 std::terminate();
85 //return false;
86 }
87 }
88 private:
89 /**
90 * Effects: schedule one task or yields
91 * Throws: whatever the current task constructor throws or the task() throws.
92 */
93 void schedule_one_or_yield()
94 {
95 if ( ! try_executing_one())
96 {
97 this_thread::yield();
98 }
99 }
100
101 /**
102 * The main loop of the worker thread
103 */
104 void worker_thread()
105 {
106 while (!closed())
107 {
108 schedule_one_or_yield();
109 }
110 while (try_executing_one())
111 {
112 }
113 }
114
115 public:
116 /// serial_executor is not copyable.
117 BOOST_THREAD_NO_COPYABLE(serial_executor)
118
119 /**
120 * \b Effects: creates a thread pool that runs closures using one of its closure-executing methods.
121 *
122 * \b Throws: Whatever exception is thrown while initializing the needed resources.
123 */
124 template <class Executor>
125 serial_executor(Executor& ex)
126 : ex(ex), thr(&serial_executor::worker_thread, this)
127 {
128 }
129 /**
130 * \b Effects: Destroys the thread pool.
131 *
132 * \b Synchronization: The completion of all the closures happen before the completion of the \c serial_executor destructor.
133 */
134 ~serial_executor()
135 {
136 // signal to the worker thread that there will be no more submissions.
137 close();
138 }
139
140 /**
141 * \b Effects: close the \c serial_executor for submissions.
142 * The loop will work until there is no more closures to run.
143 */
144 void close()
145 {
146 work_queue.close();
147 }
148
149 /**
150 * \b Returns: whether the pool is closed for submissions.
151 */
152 bool closed()
153 {
154 return work_queue.closed();
155 }
156
157 /**
158 * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
159 *
160 * \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
161 * If invoked closure throws an exception the \c serial_executor will call \c std::terminate, as is the case with threads.
162 *
163 * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
164 *
165 * \b Throws: \c sync_queue_is_closed if the thread pool is closed.
166 * Whatever exception that can be throw while storing the closure.
167 */
168 void submit(BOOST_THREAD_RV_REF(work) closure)
169 {
170 work_queue.push(boost::move(closure));
171 }
172
173 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
174 template <typename Closure>
175 void submit(Closure & closure)
176 {
177 submit(work(closure));
178 }
179 #endif
180 void submit(void (*closure)())
181 {
182 submit(work(closure));
183 }
184
185 template <typename Closure>
186 void submit(BOOST_THREAD_FWD_REF(Closure) closure)
187 {
188 work w((boost::forward<Closure>(closure)));
189 submit(boost::move(w));
190 }
191
192 /**
193 * \b Requires: This must be called from an scheduled task.
194 *
195 * \b Effects: reschedule functions until pred()
196 */
197 template <typename Pred>
198 bool reschedule_until(Pred const& pred)
199 {
200 do {
201 if ( ! try_executing_one())
202 {
203 return false;
204 }
205 } while (! pred());
206 return true;
207 }
208
209 };
210 }
211 using executors::serial_executor;
212 }
213
214 #include <boost/config/abi_suffix.hpp>
215
216 #endif