Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/thread/user_scheduler.hpp @ 102:f46d142149f5
Whoops, finish that update
author | Chris Cannam |
---|---|
date | Mon, 07 Sep 2015 11:13:41 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
101:c530137014c0 | 102:f46d142149f5 |
---|---|
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_USER_SCHEDULER_HPP | |
10 #define BOOST_THREAD_USER_SCHEDULER_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 | |
18 #include <boost/config/abi_prefix.hpp> | |
19 | |
20 namespace boost | |
21 { | |
22 | |
23 class user_scheduler | |
24 { | |
25 /// type-erasure to store the works to do | |
26 typedef thread_detail::work work; | |
27 | |
28 /// the thread safe work queue | |
29 sync_queue<work > work_queue; | |
30 | |
31 public: | |
32 /** | |
33 * Effects: try to execute one task. | |
34 * Returns: whether a task has been executed. | |
35 * Throws: whatever the current task constructor throws or the task() throws. | |
36 */ | |
37 bool try_executing_one() | |
38 { | |
39 work task; | |
40 try | |
41 { | |
42 if (work_queue.try_pull(task) == queue_op_status::success) | |
43 { | |
44 task(); | |
45 return true; | |
46 } | |
47 return false; | |
48 } | |
49 catch (std::exception& ) | |
50 { | |
51 return false; | |
52 } | |
53 catch (...) | |
54 { | |
55 return false; | |
56 } | |
57 } | |
58 private: | |
59 /** | |
60 * Effects: schedule one task or yields | |
61 * Throws: whatever the current task constructor throws or the task() throws. | |
62 */ | |
63 void schedule_one_or_yield() | |
64 { | |
65 if ( ! try_executing_one()) | |
66 { | |
67 this_thread::yield(); | |
68 } | |
69 } | |
70 | |
71 | |
72 /** | |
73 * The main loop of the worker thread | |
74 */ | |
75 void worker_thread() | |
76 { | |
77 while (!closed()) | |
78 { | |
79 schedule_one_or_yield(); | |
80 } | |
81 while (try_executing_one()) | |
82 { | |
83 } | |
84 } | |
85 | |
86 public: | |
87 /// user_scheduler is not copyable. | |
88 BOOST_THREAD_NO_COPYABLE(user_scheduler) | |
89 | |
90 /** | |
91 * \b Effects: creates a thread pool that runs closures using one of its closure-executing methods. | |
92 * | |
93 * \b Throws: Whatever exception is thrown while initializing the needed resources. | |
94 */ | |
95 user_scheduler() | |
96 { | |
97 } | |
98 /** | |
99 * \b Effects: Destroys the thread pool. | |
100 * | |
101 * \b Synchronization: The completion of all the closures happen before the completion of the \c user_scheduler destructor. | |
102 */ | |
103 ~user_scheduler() | |
104 { | |
105 // signal to all the worker thread that there will be no more submissions. | |
106 close(); | |
107 } | |
108 | |
109 /** | |
110 * loop | |
111 */ | |
112 void loop() { worker_thread(); } | |
113 /** | |
114 * \b Effects: close the \c user_scheduler for submissions. | |
115 * The loop will work until there is no more closures to run. | |
116 */ | |
117 void close() | |
118 { | |
119 work_queue.close(); | |
120 } | |
121 | |
122 /** | |
123 * \b Returns: whether the pool is closed for submissions. | |
124 */ | |
125 bool closed() | |
126 { | |
127 return work_queue.closed(); | |
128 } | |
129 | |
130 /** | |
131 * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. | |
132 * | |
133 * \b Effects: The specified \c closure will be scheduled for execution at some point in the future. | |
134 * If invoked closure throws an exception the \c user_scheduler will call \c std::terminate, as is the case with threads. | |
135 * | |
136 * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables. | |
137 * | |
138 * \b Throws: \c sync_queue_is_closed if the thread pool is closed. | |
139 * Whatever exception that can be throw while storing the closure. | |
140 */ | |
141 | |
142 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
143 template <typename Closure> | |
144 void submit(Closure & closure) | |
145 { | |
146 work w ((closure)); | |
147 work_queue.push(boost::move(w)); | |
148 //work_queue.push(work(closure)); // todo check why this doesn't work | |
149 } | |
150 #endif | |
151 void submit(void (*closure)()) | |
152 { | |
153 work w ((closure)); | |
154 work_queue.push(boost::move(w)); | |
155 //work_queue.push(work(closure)); // todo check why this doesn't work | |
156 } | |
157 | |
158 template <typename Closure> | |
159 void submit(BOOST_THREAD_RV_REF(Closure) closure) | |
160 { | |
161 work w =boost::move(closure); | |
162 work_queue.push(boost::move(w)); | |
163 //work_queue.push(work(boost::move(closure))); // todo check why this doesn't work | |
164 } | |
165 | |
166 /** | |
167 * \b Requires: This must be called from an scheduled task. | |
168 * | |
169 * \b Effects: reschedule functions until pred() | |
170 */ | |
171 template <typename Pred> | |
172 bool reschedule_until(Pred const& pred) | |
173 { | |
174 do { | |
175 if ( ! try_executing_one()) | |
176 { | |
177 return false; | |
178 } | |
179 } while (! pred()); | |
180 return true; | |
181 } | |
182 /** | |
183 * run queued closures | |
184 */ | |
185 void run_queued_closures() | |
186 { | |
187 sync_queue<work>::underlying_queue_type q = work_queue.underlying_queue(); | |
188 while (q.empty()) | |
189 { | |
190 work task = q.front(); | |
191 q.pop_front(); | |
192 task(); | |
193 } | |
194 } | |
195 | |
196 }; | |
197 | |
198 } | |
199 | |
200 #include <boost/config/abi_suffix.hpp> | |
201 | |
202 #endif |