Chris@16
|
1 #ifndef BOOST_THREAD_THREAD_COMMON_HPP
|
Chris@16
|
2 #define BOOST_THREAD_THREAD_COMMON_HPP
|
Chris@16
|
3 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
4 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 // (C) Copyright 2007-2010 Anthony Williams
|
Chris@101
|
7 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
Chris@16
|
8
|
Chris@16
|
9 #include <boost/thread/detail/config.hpp>
|
Chris@101
|
10 #include <boost/predef/platform.h>
|
Chris@16
|
11
|
Chris@16
|
12 #include <boost/thread/exceptions.hpp>
|
Chris@16
|
13 #ifndef BOOST_NO_IOSTREAM
|
Chris@16
|
14 #include <ostream>
|
Chris@16
|
15 #endif
|
Chris@16
|
16 #include <boost/thread/detail/move.hpp>
|
Chris@16
|
17 #include <boost/thread/mutex.hpp>
|
Chris@16
|
18 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
19 #include <boost/thread/xtime.hpp>
|
Chris@16
|
20 #endif
|
Chris@16
|
21 #include <boost/thread/detail/thread_heap_alloc.hpp>
|
Chris@16
|
22 #include <boost/thread/detail/make_tuple_indices.hpp>
|
Chris@16
|
23 #include <boost/thread/detail/invoke.hpp>
|
Chris@16
|
24 #include <boost/thread/detail/is_convertible.hpp>
|
Chris@16
|
25 #include <boost/assert.hpp>
|
Chris@16
|
26 #include <list>
|
Chris@16
|
27 #include <algorithm>
|
Chris@101
|
28 #include <boost/core/ref.hpp>
|
Chris@16
|
29 #include <boost/cstdint.hpp>
|
Chris@16
|
30 #include <boost/bind.hpp>
|
Chris@16
|
31 #include <stdlib.h>
|
Chris@16
|
32 #include <memory>
|
Chris@101
|
33 #include <boost/core/enable_if.hpp>
|
Chris@16
|
34 #include <boost/type_traits/remove_reference.hpp>
|
Chris@16
|
35 #include <boost/io/ios_state.hpp>
|
Chris@16
|
36 #include <boost/type_traits/is_same.hpp>
|
Chris@16
|
37 #include <boost/type_traits/decay.hpp>
|
Chris@16
|
38 #include <boost/functional/hash.hpp>
|
Chris@16
|
39 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
40 #include <boost/chrono/system_clocks.hpp>
|
Chris@16
|
41 #include <boost/chrono/ceil.hpp>
|
Chris@16
|
42 #endif
|
Chris@16
|
43
|
Chris@16
|
44 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
45 #include <tuple>
|
Chris@16
|
46 #endif
|
Chris@16
|
47 #include <boost/config/abi_prefix.hpp>
|
Chris@16
|
48
|
Chris@16
|
49 #ifdef BOOST_MSVC
|
Chris@16
|
50 #pragma warning(push)
|
Chris@16
|
51 #pragma warning(disable:4251)
|
Chris@16
|
52 #endif
|
Chris@16
|
53
|
Chris@16
|
54 namespace boost
|
Chris@16
|
55 {
|
Chris@16
|
56
|
Chris@16
|
57 namespace detail
|
Chris@16
|
58 {
|
Chris@16
|
59
|
Chris@16
|
60 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
61
|
Chris@16
|
62 template<typename F, class ...ArgTypes>
|
Chris@16
|
63 class thread_data:
|
Chris@16
|
64 public detail::thread_data_base
|
Chris@16
|
65 {
|
Chris@16
|
66 public:
|
Chris@16
|
67 BOOST_THREAD_NO_COPYABLE(thread_data)
|
Chris@16
|
68 thread_data(BOOST_THREAD_RV_REF(F) f_, BOOST_THREAD_RV_REF(ArgTypes)... args_):
|
Chris@16
|
69 fp(boost::forward<F>(f_), boost::forward<ArgTypes>(args_)...)
|
Chris@16
|
70 {}
|
Chris@16
|
71 template <std::size_t ...Indices>
|
Chris@16
|
72 void run2(tuple_indices<Indices...>)
|
Chris@16
|
73 {
|
Chris@16
|
74
|
Chris@16
|
75 invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...);
|
Chris@16
|
76 }
|
Chris@16
|
77 void run()
|
Chris@16
|
78 {
|
Chris@16
|
79 typedef typename make_tuple_indices<std::tuple_size<std::tuple<F, ArgTypes...> >::value, 1>::type index_type;
|
Chris@16
|
80
|
Chris@16
|
81 run2(index_type());
|
Chris@16
|
82 }
|
Chris@16
|
83
|
Chris@16
|
84 private:
|
Chris@16
|
85 std::tuple<typename decay<F>::type, typename decay<ArgTypes>::type...> fp;
|
Chris@16
|
86 };
|
Chris@16
|
87 #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
88
|
Chris@16
|
89 template<typename F>
|
Chris@16
|
90 class thread_data:
|
Chris@16
|
91 public detail::thread_data_base
|
Chris@16
|
92 {
|
Chris@16
|
93 public:
|
Chris@16
|
94 BOOST_THREAD_NO_COPYABLE(thread_data)
|
Chris@16
|
95 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
96 thread_data(BOOST_THREAD_RV_REF(F) f_):
|
Chris@16
|
97 f(boost::forward<F>(f_))
|
Chris@16
|
98 {}
|
Chris@16
|
99 // This overloading must be removed if we want the packaged_task's tests to pass.
|
Chris@16
|
100 // thread_data(F& f_):
|
Chris@16
|
101 // f(f_)
|
Chris@16
|
102 // {}
|
Chris@16
|
103 #else
|
Chris@16
|
104
|
Chris@16
|
105 thread_data(BOOST_THREAD_RV_REF(F) f_):
|
Chris@16
|
106 f(f_)
|
Chris@16
|
107 {}
|
Chris@16
|
108 thread_data(F f_):
|
Chris@16
|
109 f(f_)
|
Chris@16
|
110 {}
|
Chris@16
|
111 #endif
|
Chris@16
|
112 //thread_data() {}
|
Chris@16
|
113
|
Chris@16
|
114 void run()
|
Chris@16
|
115 {
|
Chris@16
|
116 f();
|
Chris@16
|
117 }
|
Chris@16
|
118
|
Chris@16
|
119 private:
|
Chris@16
|
120 F f;
|
Chris@16
|
121 };
|
Chris@16
|
122
|
Chris@16
|
123 template<typename F>
|
Chris@16
|
124 class thread_data<boost::reference_wrapper<F> >:
|
Chris@16
|
125 public detail::thread_data_base
|
Chris@16
|
126 {
|
Chris@16
|
127 private:
|
Chris@16
|
128 F& f;
|
Chris@16
|
129 public:
|
Chris@16
|
130 BOOST_THREAD_NO_COPYABLE(thread_data)
|
Chris@16
|
131 thread_data(boost::reference_wrapper<F> f_):
|
Chris@16
|
132 f(f_)
|
Chris@16
|
133 {}
|
Chris@16
|
134 void run()
|
Chris@16
|
135 {
|
Chris@16
|
136 f();
|
Chris@16
|
137 }
|
Chris@16
|
138 };
|
Chris@16
|
139
|
Chris@16
|
140 template<typename F>
|
Chris@16
|
141 class thread_data<const boost::reference_wrapper<F> >:
|
Chris@16
|
142 public detail::thread_data_base
|
Chris@16
|
143 {
|
Chris@16
|
144 private:
|
Chris@16
|
145 F& f;
|
Chris@16
|
146 public:
|
Chris@16
|
147 BOOST_THREAD_NO_COPYABLE(thread_data)
|
Chris@16
|
148 thread_data(const boost::reference_wrapper<F> f_):
|
Chris@16
|
149 f(f_)
|
Chris@16
|
150 {}
|
Chris@16
|
151 void run()
|
Chris@16
|
152 {
|
Chris@16
|
153 f();
|
Chris@16
|
154 }
|
Chris@16
|
155 };
|
Chris@16
|
156 #endif
|
Chris@16
|
157 }
|
Chris@16
|
158
|
Chris@16
|
159 class BOOST_THREAD_DECL thread
|
Chris@16
|
160 {
|
Chris@16
|
161 public:
|
Chris@16
|
162 typedef thread_attributes attributes;
|
Chris@16
|
163
|
Chris@16
|
164 BOOST_THREAD_MOVABLE_ONLY(thread)
|
Chris@16
|
165 private:
|
Chris@16
|
166
|
Chris@16
|
167 struct dummy;
|
Chris@16
|
168
|
Chris@16
|
169 void release_handle();
|
Chris@16
|
170
|
Chris@16
|
171 detail::thread_data_ptr thread_info;
|
Chris@16
|
172
|
Chris@16
|
173 private:
|
Chris@16
|
174 bool start_thread_noexcept();
|
Chris@16
|
175 bool start_thread_noexcept(const attributes& attr);
|
Chris@101
|
176 //public:
|
Chris@16
|
177 void start_thread()
|
Chris@16
|
178 {
|
Chris@16
|
179 if (!start_thread_noexcept())
|
Chris@16
|
180 {
|
Chris@16
|
181 boost::throw_exception(thread_resource_error());
|
Chris@16
|
182 }
|
Chris@16
|
183 }
|
Chris@16
|
184 void start_thread(const attributes& attr)
|
Chris@16
|
185 {
|
Chris@16
|
186 if (!start_thread_noexcept(attr))
|
Chris@16
|
187 {
|
Chris@16
|
188 boost::throw_exception(thread_resource_error());
|
Chris@16
|
189 }
|
Chris@16
|
190 }
|
Chris@16
|
191
|
Chris@16
|
192 explicit thread(detail::thread_data_ptr data);
|
Chris@16
|
193
|
Chris@16
|
194 detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const;
|
Chris@16
|
195
|
Chris@16
|
196 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
197 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
198 template<typename F, class ...ArgTypes>
|
Chris@16
|
199 static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_RV_REF(ArgTypes)... args)
|
Chris@16
|
200 {
|
Chris@16
|
201 return detail::thread_data_ptr(detail::heap_new<
|
Chris@16
|
202 detail::thread_data<typename boost::remove_reference<F>::type, ArgTypes...>
|
Chris@16
|
203 >(
|
Chris@16
|
204 boost::forward<F>(f), boost::forward<ArgTypes>(args)...
|
Chris@16
|
205 )
|
Chris@16
|
206 );
|
Chris@16
|
207 }
|
Chris@16
|
208 #else
|
Chris@16
|
209 template<typename F>
|
Chris@16
|
210 static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
|
Chris@16
|
211 {
|
Chris@16
|
212 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(
|
Chris@16
|
213 boost::forward<F>(f)));
|
Chris@16
|
214 }
|
Chris@16
|
215 #endif
|
Chris@16
|
216 static inline detail::thread_data_ptr make_thread_info(void (*f)())
|
Chris@16
|
217 {
|
Chris@16
|
218 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(
|
Chris@16
|
219 boost::forward<void(*)()>(f)));
|
Chris@16
|
220 }
|
Chris@16
|
221 #else
|
Chris@16
|
222 template<typename F>
|
Chris@16
|
223 static inline detail::thread_data_ptr make_thread_info(F f
|
Chris@16
|
224 , typename disable_if_c<
|
Chris@16
|
225 //boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value ||
|
Chris@16
|
226 is_same<typename decay<F>::type, thread>::value,
|
Chris@16
|
227 dummy* >::type=0
|
Chris@16
|
228 )
|
Chris@16
|
229 {
|
Chris@16
|
230 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
|
Chris@16
|
231 }
|
Chris@16
|
232 template<typename F>
|
Chris@16
|
233 static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
|
Chris@16
|
234 {
|
Chris@16
|
235 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
|
Chris@16
|
236 }
|
Chris@16
|
237
|
Chris@16
|
238 #endif
|
Chris@16
|
239 public:
|
Chris@16
|
240 #if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
|
Chris@16
|
241 #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
|
Chris@16
|
242 thread(const volatile thread&);
|
Chris@16
|
243 #endif
|
Chris@16
|
244 #endif
|
Chris@16
|
245 thread() BOOST_NOEXCEPT;
|
Chris@16
|
246 ~thread()
|
Chris@16
|
247 {
|
Chris@16
|
248
|
Chris@16
|
249 #if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
|
Chris@16
|
250 if (joinable()) {
|
Chris@16
|
251 std::terminate();
|
Chris@16
|
252 }
|
Chris@16
|
253 #else
|
Chris@16
|
254 detach();
|
Chris@16
|
255 #endif
|
Chris@16
|
256 }
|
Chris@16
|
257 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
258 template <
|
Chris@16
|
259 class F
|
Chris@16
|
260 >
|
Chris@16
|
261 explicit thread(BOOST_THREAD_RV_REF(F) f
|
Chris@16
|
262 //, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
|
Chris@16
|
263 ):
|
Chris@16
|
264 thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
|
Chris@16
|
265 {
|
Chris@16
|
266 start_thread();
|
Chris@16
|
267 }
|
Chris@16
|
268 template <
|
Chris@16
|
269 class F
|
Chris@16
|
270 >
|
Chris@16
|
271 thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f):
|
Chris@16
|
272 thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
|
Chris@16
|
273 {
|
Chris@16
|
274 start_thread(attrs);
|
Chris@16
|
275 }
|
Chris@16
|
276
|
Chris@16
|
277 #else
|
Chris@16
|
278 #ifdef BOOST_NO_SFINAE
|
Chris@16
|
279 template <class F>
|
Chris@16
|
280 explicit thread(F f):
|
Chris@16
|
281 thread_info(make_thread_info(f))
|
Chris@16
|
282 {
|
Chris@16
|
283 start_thread();
|
Chris@16
|
284 }
|
Chris@16
|
285 template <class F>
|
Chris@16
|
286 thread(attributes const& attrs, F f):
|
Chris@16
|
287 thread_info(make_thread_info(f))
|
Chris@16
|
288 {
|
Chris@16
|
289 start_thread(attrs);
|
Chris@16
|
290 }
|
Chris@16
|
291 #else
|
Chris@16
|
292 template <class F>
|
Chris@16
|
293 explicit thread(F f
|
Chris@16
|
294 , typename disable_if_c<
|
Chris@101
|
295 boost::thread_detail::is_rv<F>::value // todo ass a thread_detail::is_rv
|
Chris@101
|
296 //boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
|
Chris@16
|
297 //|| is_same<typename decay<F>::type, thread>::value
|
Chris@16
|
298 , dummy* >::type=0
|
Chris@16
|
299 ):
|
Chris@16
|
300 thread_info(make_thread_info(f))
|
Chris@16
|
301 {
|
Chris@16
|
302 start_thread();
|
Chris@16
|
303 }
|
Chris@16
|
304 template <class F>
|
Chris@16
|
305 thread(attributes const& attrs, F f
|
Chris@101
|
306 , typename disable_if<boost::thread_detail::is_rv<F>, dummy* >::type=0
|
Chris@101
|
307 //, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
|
Chris@16
|
308 ):
|
Chris@16
|
309 thread_info(make_thread_info(f))
|
Chris@16
|
310 {
|
Chris@16
|
311 start_thread(attrs);
|
Chris@16
|
312 }
|
Chris@16
|
313 #endif
|
Chris@16
|
314 template <class F>
|
Chris@16
|
315 explicit thread(BOOST_THREAD_RV_REF(F) f
|
Chris@16
|
316 , typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
|
Chris@16
|
317 ):
|
Chris@16
|
318 #ifdef BOOST_THREAD_USES_MOVE
|
Chris@16
|
319 thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward
|
Chris@16
|
320 #else
|
Chris@16
|
321 thread_info(make_thread_info(f)) // todo : Add forward
|
Chris@16
|
322 #endif
|
Chris@16
|
323 {
|
Chris@16
|
324 start_thread();
|
Chris@16
|
325 }
|
Chris@16
|
326
|
Chris@16
|
327 template <class F>
|
Chris@16
|
328 thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f):
|
Chris@16
|
329 #ifdef BOOST_THREAD_USES_MOVE
|
Chris@16
|
330 thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward
|
Chris@16
|
331 #else
|
Chris@16
|
332 thread_info(make_thread_info(f)) // todo : Add forward
|
Chris@16
|
333 #endif
|
Chris@16
|
334 {
|
Chris@16
|
335 start_thread(attrs);
|
Chris@16
|
336 }
|
Chris@16
|
337 #endif
|
Chris@101
|
338 thread(BOOST_THREAD_RV_REF(thread) x) BOOST_NOEXCEPT
|
Chris@16
|
339 {
|
Chris@16
|
340 thread_info=BOOST_THREAD_RV(x).thread_info;
|
Chris@16
|
341 BOOST_THREAD_RV(x).thread_info.reset();
|
Chris@16
|
342 }
|
Chris@16
|
343 #if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
|
Chris@16
|
344 #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
|
Chris@16
|
345 thread& operator=(thread x)
|
Chris@16
|
346 {
|
Chris@16
|
347 swap(x);
|
Chris@16
|
348 return *this;
|
Chris@16
|
349 }
|
Chris@16
|
350 #endif
|
Chris@16
|
351 #endif
|
Chris@16
|
352
|
Chris@16
|
353 thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT
|
Chris@16
|
354 {
|
Chris@16
|
355
|
Chris@16
|
356 #if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
|
Chris@16
|
357 if (joinable()) std::terminate();
|
Chris@16
|
358 #endif
|
Chris@16
|
359 thread_info=BOOST_THREAD_RV(other).thread_info;
|
Chris@16
|
360 BOOST_THREAD_RV(other).thread_info.reset();
|
Chris@16
|
361 return *this;
|
Chris@16
|
362 }
|
Chris@16
|
363
|
Chris@16
|
364 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
365 template <class F, class Arg, class ...Args>
|
Chris@16
|
366 thread(F&& f, Arg&& arg, Args&&... args) :
|
Chris@16
|
367 thread_info(make_thread_info(
|
Chris@16
|
368 thread_detail::decay_copy(boost::forward<F>(f)),
|
Chris@16
|
369 thread_detail::decay_copy(boost::forward<Arg>(arg)),
|
Chris@16
|
370 thread_detail::decay_copy(boost::forward<Args>(args))...)
|
Chris@16
|
371 )
|
Chris@16
|
372
|
Chris@16
|
373 {
|
Chris@16
|
374 start_thread();
|
Chris@16
|
375 }
|
Chris@16
|
376 template <class F, class Arg, class ...Args>
|
Chris@16
|
377 thread(attributes const& attrs, F&& f, Arg&& arg, Args&&... args) :
|
Chris@16
|
378 thread_info(make_thread_info(
|
Chris@16
|
379 thread_detail::decay_copy(boost::forward<F>(f)),
|
Chris@16
|
380 thread_detail::decay_copy(boost::forward<Arg>(arg)),
|
Chris@16
|
381 thread_detail::decay_copy(boost::forward<Args>(args))...)
|
Chris@16
|
382 )
|
Chris@16
|
383
|
Chris@16
|
384 {
|
Chris@16
|
385 start_thread(attrs);
|
Chris@16
|
386 }
|
Chris@16
|
387 #else
|
Chris@16
|
388 template <class F,class A1>
|
Chris@16
|
389 thread(F f,A1 a1,typename disable_if<boost::thread_detail::is_convertible<F&,thread_attributes >, dummy* >::type=0):
|
Chris@16
|
390 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
|
Chris@16
|
391 {
|
Chris@16
|
392 start_thread();
|
Chris@16
|
393 }
|
Chris@16
|
394 template <class F,class A1,class A2>
|
Chris@16
|
395 thread(F f,A1 a1,A2 a2):
|
Chris@16
|
396 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2)))
|
Chris@16
|
397 {
|
Chris@16
|
398 start_thread();
|
Chris@16
|
399 }
|
Chris@16
|
400
|
Chris@16
|
401 template <class F,class A1,class A2,class A3>
|
Chris@16
|
402 thread(F f,A1 a1,A2 a2,A3 a3):
|
Chris@16
|
403 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3)))
|
Chris@16
|
404 {
|
Chris@16
|
405 start_thread();
|
Chris@16
|
406 }
|
Chris@16
|
407
|
Chris@16
|
408 template <class F,class A1,class A2,class A3,class A4>
|
Chris@16
|
409 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4):
|
Chris@16
|
410 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4)))
|
Chris@16
|
411 {
|
Chris@16
|
412 start_thread();
|
Chris@16
|
413 }
|
Chris@16
|
414
|
Chris@16
|
415 template <class F,class A1,class A2,class A3,class A4,class A5>
|
Chris@16
|
416 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5):
|
Chris@16
|
417 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5)))
|
Chris@16
|
418 {
|
Chris@16
|
419 start_thread();
|
Chris@16
|
420 }
|
Chris@16
|
421
|
Chris@16
|
422 template <class F,class A1,class A2,class A3,class A4,class A5,class A6>
|
Chris@16
|
423 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6):
|
Chris@16
|
424 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6)))
|
Chris@16
|
425 {
|
Chris@16
|
426 start_thread();
|
Chris@16
|
427 }
|
Chris@16
|
428
|
Chris@16
|
429 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7>
|
Chris@16
|
430 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7):
|
Chris@16
|
431 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7)))
|
Chris@16
|
432 {
|
Chris@16
|
433 start_thread();
|
Chris@16
|
434 }
|
Chris@16
|
435
|
Chris@16
|
436 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8>
|
Chris@16
|
437 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8):
|
Chris@16
|
438 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8)))
|
Chris@16
|
439 {
|
Chris@16
|
440 start_thread();
|
Chris@16
|
441 }
|
Chris@16
|
442
|
Chris@16
|
443 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9>
|
Chris@16
|
444 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9):
|
Chris@16
|
445 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9)))
|
Chris@16
|
446 {
|
Chris@16
|
447 start_thread();
|
Chris@16
|
448 }
|
Chris@16
|
449 #endif
|
Chris@16
|
450 void swap(thread& x) BOOST_NOEXCEPT
|
Chris@16
|
451 {
|
Chris@16
|
452 thread_info.swap(x.thread_info);
|
Chris@16
|
453 }
|
Chris@16
|
454
|
Chris@16
|
455 class id;
|
Chris@16
|
456 #ifdef BOOST_THREAD_PLATFORM_PTHREAD
|
Chris@16
|
457 inline id get_id() const BOOST_NOEXCEPT;
|
Chris@16
|
458 #else
|
Chris@16
|
459 id get_id() const BOOST_NOEXCEPT;
|
Chris@16
|
460 #endif
|
Chris@16
|
461
|
Chris@16
|
462
|
Chris@16
|
463 bool joinable() const BOOST_NOEXCEPT;
|
Chris@16
|
464 private:
|
Chris@16
|
465 bool join_noexcept();
|
Chris@16
|
466 public:
|
Chris@16
|
467 inline void join();
|
Chris@16
|
468
|
Chris@16
|
469 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@101
|
470 #if defined(BOOST_THREAD_PLATFORM_WIN32)
|
Chris@101
|
471 template <class Rep, class Period>
|
Chris@101
|
472 bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
|
Chris@101
|
473 {
|
Chris@101
|
474 chrono::milliseconds rel_time2= chrono::ceil<chrono::milliseconds>(rel_time);
|
Chris@101
|
475 return do_try_join_until(rel_time2.count());
|
Chris@101
|
476 }
|
Chris@101
|
477 #else
|
Chris@16
|
478 template <class Rep, class Period>
|
Chris@16
|
479 bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
|
Chris@16
|
480 {
|
Chris@16
|
481 return try_join_until(chrono::steady_clock::now() + rel_time);
|
Chris@16
|
482 }
|
Chris@101
|
483 #endif
|
Chris@16
|
484 template <class Clock, class Duration>
|
Chris@16
|
485 bool try_join_until(const chrono::time_point<Clock, Duration>& t)
|
Chris@16
|
486 {
|
Chris@16
|
487 using namespace chrono;
|
Chris@16
|
488 system_clock::time_point s_now = system_clock::now();
|
Chris@16
|
489 bool joined= false;
|
Chris@16
|
490 do {
|
Chris@16
|
491 typename Clock::duration d = ceil<nanoseconds>(t-Clock::now());
|
Chris@16
|
492 if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached
|
Chris@16
|
493 joined = try_join_until(s_now + d);
|
Chris@16
|
494 } while (! joined);
|
Chris@16
|
495 return true;
|
Chris@16
|
496 }
|
Chris@16
|
497 template <class Duration>
|
Chris@16
|
498 bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t)
|
Chris@16
|
499 {
|
Chris@16
|
500 using namespace chrono;
|
Chris@16
|
501 typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
|
Chris@16
|
502 return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
|
Chris@16
|
503 }
|
Chris@16
|
504 #endif
|
Chris@16
|
505 #if defined(BOOST_THREAD_PLATFORM_WIN32)
|
Chris@16
|
506 private:
|
Chris@16
|
507 bool do_try_join_until_noexcept(uintmax_t milli, bool& res);
|
Chris@16
|
508 inline bool do_try_join_until(uintmax_t milli);
|
Chris@16
|
509 public:
|
Chris@16
|
510 bool timed_join(const system_time& abs_time);
|
Chris@16
|
511 //{
|
Chris@16
|
512 // return do_try_join_until(get_milliseconds_until(wait_until));
|
Chris@16
|
513 //}
|
Chris@16
|
514
|
Chris@16
|
515 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
516 bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
|
Chris@16
|
517 {
|
Chris@16
|
518 chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
|
Chris@16
|
519 return do_try_join_until(rel_time.count());
|
Chris@16
|
520 }
|
Chris@16
|
521 #endif
|
Chris@16
|
522
|
Chris@16
|
523
|
Chris@16
|
524 #else
|
Chris@16
|
525 private:
|
Chris@16
|
526 bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res);
|
Chris@16
|
527 inline bool do_try_join_until(struct timespec const &timeout);
|
Chris@16
|
528 public:
|
Chris@16
|
529 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
530 bool timed_join(const system_time& abs_time)
|
Chris@16
|
531 {
|
Chris@16
|
532 struct timespec const ts=detail::to_timespec(abs_time);
|
Chris@16
|
533 return do_try_join_until(ts);
|
Chris@16
|
534 }
|
Chris@16
|
535 #endif
|
Chris@16
|
536 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
537 bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
|
Chris@16
|
538 {
|
Chris@16
|
539 using namespace chrono;
|
Chris@16
|
540 nanoseconds d = tp.time_since_epoch();
|
Chris@16
|
541 timespec ts = boost::detail::to_timespec(d);
|
Chris@16
|
542 return do_try_join_until(ts);
|
Chris@16
|
543 }
|
Chris@16
|
544 #endif
|
Chris@16
|
545
|
Chris@16
|
546 #endif
|
Chris@16
|
547 public:
|
Chris@16
|
548
|
Chris@16
|
549 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
550 template<typename TimeDuration>
|
Chris@16
|
551 inline bool timed_join(TimeDuration const& rel_time)
|
Chris@16
|
552 {
|
Chris@16
|
553 return timed_join(get_system_time()+rel_time);
|
Chris@16
|
554 }
|
Chris@16
|
555 #endif
|
Chris@16
|
556 void detach();
|
Chris@16
|
557
|
Chris@16
|
558 static unsigned hardware_concurrency() BOOST_NOEXCEPT;
|
Chris@101
|
559 static unsigned physical_concurrency() BOOST_NOEXCEPT;
|
Chris@16
|
560
|
Chris@16
|
561 #define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
|
Chris@16
|
562 typedef detail::thread_data_base::native_handle_type native_handle_type;
|
Chris@16
|
563 native_handle_type native_handle();
|
Chris@16
|
564
|
Chris@16
|
565 #if defined BOOST_THREAD_PROVIDES_THREAD_EQ
|
Chris@16
|
566 // Use thread::id when comparisions are needed
|
Chris@16
|
567 // backwards compatibility
|
Chris@16
|
568 bool operator==(const thread& other) const;
|
Chris@16
|
569 bool operator!=(const thread& other) const;
|
Chris@16
|
570 #endif
|
Chris@16
|
571 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
572 static inline void yield() BOOST_NOEXCEPT
|
Chris@16
|
573 {
|
Chris@16
|
574 this_thread::yield();
|
Chris@16
|
575 }
|
Chris@16
|
576
|
Chris@16
|
577 static inline void sleep(const system_time& xt)
|
Chris@16
|
578 {
|
Chris@16
|
579 this_thread::sleep(xt);
|
Chris@16
|
580 }
|
Chris@16
|
581 #endif
|
Chris@16
|
582
|
Chris@16
|
583 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
584 // extensions
|
Chris@16
|
585 void interrupt();
|
Chris@16
|
586 bool interruption_requested() const BOOST_NOEXCEPT;
|
Chris@16
|
587 #endif
|
Chris@16
|
588 };
|
Chris@16
|
589
|
Chris@16
|
590 inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT
|
Chris@16
|
591 {
|
Chris@16
|
592 return lhs.swap(rhs);
|
Chris@16
|
593 }
|
Chris@16
|
594
|
Chris@16
|
595 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
596 inline thread&& move(thread& t) BOOST_NOEXCEPT
|
Chris@16
|
597 {
|
Chris@16
|
598 return static_cast<thread&&>(t);
|
Chris@16
|
599 }
|
Chris@16
|
600 #endif
|
Chris@16
|
601
|
Chris@16
|
602 BOOST_THREAD_DCL_MOVABLE(thread)
|
Chris@16
|
603
|
Chris@16
|
604 namespace this_thread
|
Chris@16
|
605 {
|
Chris@16
|
606 #ifdef BOOST_THREAD_PLATFORM_PTHREAD
|
Chris@16
|
607 inline thread::id get_id() BOOST_NOEXCEPT;
|
Chris@16
|
608 #else
|
Chris@16
|
609 thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT;
|
Chris@16
|
610 #endif
|
Chris@16
|
611
|
Chris@16
|
612 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
613 void BOOST_THREAD_DECL interruption_point();
|
Chris@16
|
614 bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
|
Chris@16
|
615 bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
|
Chris@16
|
616 #endif
|
Chris@16
|
617
|
Chris@16
|
618 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
619 inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time)
|
Chris@16
|
620 {
|
Chris@16
|
621 sleep(system_time(abs_time));
|
Chris@16
|
622 }
|
Chris@16
|
623 #endif
|
Chris@16
|
624 }
|
Chris@16
|
625
|
Chris@16
|
626 class BOOST_SYMBOL_VISIBLE thread::id
|
Chris@16
|
627 {
|
Chris@16
|
628 private:
|
Chris@16
|
629 friend inline
|
Chris@16
|
630 std::size_t
|
Chris@16
|
631 hash_value(const thread::id &v)
|
Chris@16
|
632 {
|
Chris@16
|
633 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
|
Chris@16
|
634 return hash_value(v.thread_data);
|
Chris@16
|
635 #else
|
Chris@16
|
636 return hash_value(v.thread_data.get());
|
Chris@16
|
637 #endif
|
Chris@16
|
638 }
|
Chris@16
|
639
|
Chris@16
|
640 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
|
Chris@16
|
641 #if defined(BOOST_THREAD_PLATFORM_WIN32)
|
Chris@16
|
642 typedef unsigned int data;
|
Chris@16
|
643 #else
|
Chris@16
|
644 typedef thread::native_handle_type data;
|
Chris@16
|
645 #endif
|
Chris@16
|
646 #else
|
Chris@16
|
647 typedef detail::thread_data_ptr data;
|
Chris@16
|
648 #endif
|
Chris@16
|
649 data thread_data;
|
Chris@16
|
650
|
Chris@16
|
651 id(data thread_data_):
|
Chris@16
|
652 thread_data(thread_data_)
|
Chris@16
|
653 {}
|
Chris@16
|
654 friend class thread;
|
Chris@16
|
655 friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT;
|
Chris@16
|
656 public:
|
Chris@16
|
657 id() BOOST_NOEXCEPT:
|
Chris@16
|
658 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
|
Chris@16
|
659 thread_data(0)
|
Chris@16
|
660 #else
|
Chris@16
|
661 thread_data()
|
Chris@16
|
662 #endif
|
Chris@16
|
663 {}
|
Chris@16
|
664
|
Chris@16
|
665 id(const id& other) BOOST_NOEXCEPT :
|
Chris@16
|
666 thread_data(other.thread_data)
|
Chris@16
|
667 {}
|
Chris@16
|
668
|
Chris@16
|
669 bool operator==(const id& y) const BOOST_NOEXCEPT
|
Chris@16
|
670 {
|
Chris@16
|
671 return thread_data==y.thread_data;
|
Chris@16
|
672 }
|
Chris@16
|
673
|
Chris@16
|
674 bool operator!=(const id& y) const BOOST_NOEXCEPT
|
Chris@16
|
675 {
|
Chris@16
|
676 return thread_data!=y.thread_data;
|
Chris@16
|
677 }
|
Chris@16
|
678
|
Chris@16
|
679 bool operator<(const id& y) const BOOST_NOEXCEPT
|
Chris@16
|
680 {
|
Chris@16
|
681 return thread_data<y.thread_data;
|
Chris@16
|
682 }
|
Chris@16
|
683
|
Chris@16
|
684 bool operator>(const id& y) const BOOST_NOEXCEPT
|
Chris@16
|
685 {
|
Chris@16
|
686 return y.thread_data<thread_data;
|
Chris@16
|
687 }
|
Chris@16
|
688
|
Chris@16
|
689 bool operator<=(const id& y) const BOOST_NOEXCEPT
|
Chris@16
|
690 {
|
Chris@16
|
691 return !(y.thread_data<thread_data);
|
Chris@16
|
692 }
|
Chris@16
|
693
|
Chris@16
|
694 bool operator>=(const id& y) const BOOST_NOEXCEPT
|
Chris@16
|
695 {
|
Chris@16
|
696 return !(thread_data<y.thread_data);
|
Chris@16
|
697 }
|
Chris@16
|
698
|
Chris@16
|
699 #ifndef BOOST_NO_IOSTREAM
|
Chris@16
|
700 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
Chris@16
|
701 template<class charT, class traits>
|
Chris@16
|
702 friend BOOST_SYMBOL_VISIBLE
|
Chris@16
|
703 std::basic_ostream<charT, traits>&
|
Chris@16
|
704 operator<<(std::basic_ostream<charT, traits>& os, const id& x)
|
Chris@16
|
705 {
|
Chris@16
|
706 if(x.thread_data)
|
Chris@16
|
707 {
|
Chris@16
|
708 io::ios_flags_saver ifs( os );
|
Chris@16
|
709 return os<< std::hex << x.thread_data;
|
Chris@16
|
710 }
|
Chris@16
|
711 else
|
Chris@16
|
712 {
|
Chris@16
|
713 return os<<"{Not-any-thread}";
|
Chris@16
|
714 }
|
Chris@16
|
715 }
|
Chris@16
|
716 #else
|
Chris@16
|
717 template<class charT, class traits>
|
Chris@16
|
718 BOOST_SYMBOL_VISIBLE
|
Chris@16
|
719 std::basic_ostream<charT, traits>&
|
Chris@16
|
720 print(std::basic_ostream<charT, traits>& os) const
|
Chris@16
|
721 {
|
Chris@16
|
722 if(thread_data)
|
Chris@16
|
723 {
|
Chris@16
|
724 io::ios_flags_saver ifs( os );
|
Chris@16
|
725 return os<< std::hex << thread_data;
|
Chris@16
|
726 }
|
Chris@16
|
727 else
|
Chris@16
|
728 {
|
Chris@16
|
729 return os<<"{Not-any-thread}";
|
Chris@16
|
730 }
|
Chris@16
|
731 }
|
Chris@16
|
732
|
Chris@16
|
733 #endif
|
Chris@16
|
734 #endif
|
Chris@16
|
735 };
|
Chris@16
|
736
|
Chris@16
|
737 #ifdef BOOST_THREAD_PLATFORM_PTHREAD
|
Chris@16
|
738 thread::id thread::get_id() const BOOST_NOEXCEPT
|
Chris@16
|
739 {
|
Chris@16
|
740 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
|
Chris@16
|
741 return const_cast<thread*>(this)->native_handle();
|
Chris@16
|
742 #else
|
Chris@16
|
743 detail::thread_data_ptr const local_thread_info=(get_thread_info)();
|
Chris@16
|
744 return (local_thread_info? id(local_thread_info) : id());
|
Chris@16
|
745 #endif
|
Chris@16
|
746 }
|
Chris@16
|
747
|
Chris@16
|
748 namespace this_thread
|
Chris@16
|
749 {
|
Chris@16
|
750 inline thread::id get_id() BOOST_NOEXCEPT
|
Chris@16
|
751 {
|
Chris@16
|
752 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
|
Chris@16
|
753 return pthread_self();
|
Chris@16
|
754 #else
|
Chris@16
|
755 boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
|
Chris@16
|
756 return (thread_info?thread::id(thread_info->shared_from_this()):thread::id());
|
Chris@16
|
757 #endif
|
Chris@16
|
758 }
|
Chris@16
|
759 }
|
Chris@16
|
760 #endif
|
Chris@16
|
761 void thread::join() {
|
Chris@16
|
762 if (this_thread::get_id() == get_id())
|
Chris@101
|
763 boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
|
Chris@16
|
764
|
Chris@16
|
765 BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(),
|
Chris@101
|
766 thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")
|
Chris@16
|
767 );
|
Chris@16
|
768 }
|
Chris@16
|
769
|
Chris@16
|
770 #ifdef BOOST_THREAD_PLATFORM_PTHREAD
|
Chris@16
|
771 bool thread::do_try_join_until(struct timespec const &timeout)
|
Chris@16
|
772 #else
|
Chris@16
|
773 bool thread::do_try_join_until(uintmax_t timeout)
|
Chris@16
|
774 #endif
|
Chris@16
|
775 {
|
Chris@16
|
776 if (this_thread::get_id() == get_id())
|
Chris@101
|
777 boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
|
Chris@16
|
778 bool res;
|
Chris@16
|
779 if (do_try_join_until_noexcept(timeout, res))
|
Chris@16
|
780 {
|
Chris@16
|
781 return res;
|
Chris@16
|
782 }
|
Chris@16
|
783 else
|
Chris@16
|
784 {
|
Chris@16
|
785 BOOST_THREAD_THROW_ELSE_RETURN(
|
Chris@101
|
786 (thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")),
|
Chris@16
|
787 false
|
Chris@16
|
788 );
|
Chris@16
|
789 }
|
Chris@16
|
790 }
|
Chris@16
|
791
|
Chris@16
|
792 #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
Chris@16
|
793 template<class charT, class traits>
|
Chris@16
|
794 BOOST_SYMBOL_VISIBLE
|
Chris@16
|
795 std::basic_ostream<charT, traits>&
|
Chris@16
|
796 operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x)
|
Chris@16
|
797 {
|
Chris@16
|
798 return x.print(os);
|
Chris@16
|
799 }
|
Chris@16
|
800 #endif
|
Chris@16
|
801
|
Chris@16
|
802 #if defined BOOST_THREAD_PROVIDES_THREAD_EQ
|
Chris@16
|
803 inline bool thread::operator==(const thread& other) const
|
Chris@16
|
804 {
|
Chris@16
|
805 return get_id()==other.get_id();
|
Chris@16
|
806 }
|
Chris@16
|
807
|
Chris@16
|
808 inline bool thread::operator!=(const thread& other) const
|
Chris@16
|
809 {
|
Chris@16
|
810 return get_id()!=other.get_id();
|
Chris@16
|
811 }
|
Chris@16
|
812 #endif
|
Chris@16
|
813
|
Chris@16
|
814 namespace detail
|
Chris@16
|
815 {
|
Chris@16
|
816 struct thread_exit_function_base
|
Chris@16
|
817 {
|
Chris@16
|
818 virtual ~thread_exit_function_base()
|
Chris@16
|
819 {}
|
Chris@16
|
820 virtual void operator()()=0;
|
Chris@16
|
821 };
|
Chris@16
|
822
|
Chris@16
|
823 template<typename F>
|
Chris@16
|
824 struct thread_exit_function:
|
Chris@16
|
825 thread_exit_function_base
|
Chris@16
|
826 {
|
Chris@16
|
827 F f;
|
Chris@16
|
828
|
Chris@16
|
829 thread_exit_function(F f_):
|
Chris@16
|
830 f(f_)
|
Chris@16
|
831 {}
|
Chris@16
|
832
|
Chris@16
|
833 void operator()()
|
Chris@16
|
834 {
|
Chris@16
|
835 f();
|
Chris@16
|
836 }
|
Chris@16
|
837 };
|
Chris@16
|
838
|
Chris@16
|
839 void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
|
Chris@16
|
840 struct shared_state_base;
|
Chris@16
|
841 #if defined(BOOST_THREAD_PLATFORM_WIN32)
|
Chris@16
|
842 inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
Chris@16
|
843 {
|
Chris@16
|
844 detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
|
Chris@16
|
845 if(current_thread_data)
|
Chris@16
|
846 {
|
Chris@16
|
847 current_thread_data->make_ready_at_thread_exit(as);
|
Chris@16
|
848 }
|
Chris@16
|
849 }
|
Chris@16
|
850 #else
|
Chris@16
|
851 void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as);
|
Chris@16
|
852 #endif
|
Chris@16
|
853 }
|
Chris@16
|
854
|
Chris@16
|
855 namespace this_thread
|
Chris@16
|
856 {
|
Chris@16
|
857 template<typename F>
|
Chris@16
|
858 void at_thread_exit(F f)
|
Chris@16
|
859 {
|
Chris@16
|
860 detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f);
|
Chris@16
|
861 detail::add_thread_exit_function(thread_exit_func);
|
Chris@16
|
862 }
|
Chris@16
|
863 }
|
Chris@16
|
864 }
|
Chris@16
|
865
|
Chris@16
|
866 #ifdef BOOST_MSVC
|
Chris@16
|
867 #pragma warning(pop)
|
Chris@16
|
868 #endif
|
Chris@16
|
869
|
Chris@16
|
870 #include <boost/config/abi_suffix.hpp>
|
Chris@16
|
871
|
Chris@16
|
872 #endif
|