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 | // 2013/11 Vicente J. Botet Escriba |
7 | // first implementation of a simple serial scheduler. |
8 | |
9 | #ifndef BOOST_THREAD_INLINE_EXECUTOR_HPP |
10 | #define BOOST_THREAD_INLINE_EXECUTOR_HPP |
11 | |
12 | #include <boost/thread/detail/config.hpp> |
13 | #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE |
14 | |
15 | #include <exception> // std::terminate |
16 | #include <boost/throw_exception.hpp> |
17 | #include <boost/thread/detail/delete.hpp> |
18 | #include <boost/thread/detail/move.hpp> |
19 | #include <boost/thread/executors/work.hpp> |
20 | #include <boost/thread/mutex.hpp> |
21 | #include <boost/thread/lock_guard.hpp> |
22 | #include <boost/thread/concurrent_queues/queue_op_status.hpp> // sync_queue_is_closed |
23 | |
24 | #include <boost/config/abi_prefix.hpp> |
25 | |
26 | namespace boost |
27 | { |
28 | namespace executors |
29 | { |
30 | class inline_executor |
31 | { |
32 | public: |
33 | /// type-erasure to store the works to do |
34 | typedef executors::work work; |
35 | bool closed_; |
36 | mutable mutex mtx_; |
37 | /** |
38 | * Effects: try to execute one task. |
39 | * Returns: whether a task has been executed. |
40 | * Throws: whatever the current task constructor throws or the task() throws. |
41 | */ |
42 | bool try_executing_one() |
43 | { |
44 | return false; |
45 | } |
46 | |
47 | public: |
48 | /// inline_executor is not copyable. |
49 | BOOST_THREAD_NO_COPYABLE(inline_executor) |
50 | |
51 | /** |
52 | * \b Effects: creates a inline executor that runs closures immediately. |
53 | * |
54 | * \b Throws: Nothing. |
55 | */ |
56 | inline_executor() |
57 | : closed_(false) |
58 | { |
59 | } |
60 | /** |
61 | * \b Effects: Destroys the inline executor. |
62 | * |
63 | * \b Synchronization: The completion of all the closures happen before the completion of the \c inline_executor destructor. |
64 | */ |
65 | ~inline_executor() |
66 | { |
67 | // signal to all the worker thread that there will be no more submissions. |
68 | close(); |
69 | } |
70 | |
71 | /** |
72 | * \b Effects: close the \c inline_executor for submissions. |
73 | * The loop will work until there is no more closures to run. |
74 | */ |
75 | void close() |
76 | { |
77 | lock_guard<mutex> lk(mtx_); |
78 | closed_ = true; |
79 | } |
80 | |
81 | /** |
82 | * \b Returns: whether the pool is closed for submissions. |
83 | */ |
84 | bool closed(lock_guard<mutex>& ) |
85 | { |
86 | return closed_; |
87 | } |
88 | bool closed() |
89 | { |
90 | lock_guard<mutex> lk(mtx_); |
91 | return closed(lk); |
92 | } |
93 | |
94 | /** |
95 | * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. |
96 | * |
97 | * \b Effects: The specified \c closure will be scheduled for execution at some point in the future. |
98 | * If invoked closure throws an exception the \c inline_executor will call \c std::terminate, as is the case with threads. |
99 | * |
100 | * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables. |
101 | * |
102 | * \b Throws: \c sync_queue_is_closed if the thread pool is closed. |
103 | * Whatever exception that can be throw while storing the closure. |
104 | */ |
105 | |
106 | #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
107 | template <typename Closure> |
108 | void submit(Closure & closure) |
109 | { |
110 | { |
111 | lock_guard<mutex> lk(mtx_); |
112 | if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); |
113 | } |
114 | try |
115 | { |
116 | closure(); |
117 | } |
118 | catch (...) |
119 | { |
120 | std::terminate(); |
121 | return; |
122 | } |
123 | } |
124 | #endif |
125 | void submit(void (*closure)()) |
126 | { |
127 | { |
128 | lock_guard<mutex> lk(mtx_); |
129 | if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); |
130 | } |
131 | try |
132 | { |
133 | closure(); |
134 | } |
135 | catch (...) |
136 | { |
137 | std::terminate(); |
138 | return; |
139 | } |
140 | } |
141 | |
142 | template <typename Closure> |
143 | void submit(BOOST_THREAD_FWD_REF(Closure) closure) |
144 | { |
145 | { |
146 | lock_guard<mutex> lk(mtx_); |
147 | if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); |
148 | } |
149 | try |
150 | { |
151 | closure(); |
152 | } |
153 | catch (...) |
154 | { |
155 | std::terminate(); |
156 | return; |
157 | } |
158 | } |
159 | |
160 | /** |
161 | * \b Requires: This must be called from an scheduled task. |
162 | * |
163 | * \b Effects: reschedule functions until pred() |
164 | */ |
165 | template <typename Pred> |
166 | bool reschedule_until(Pred const& ) |
167 | { |
168 | return false; |
169 | } |
170 | |
171 | }; |
172 | } |
173 | using executors::inline_executor; |
174 | } |
175 | |
176 | #include <boost/config/abi_suffix.hpp> |
177 | |
178 | #endif |
179 | #endif |
180 | |