• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Distributed under the Boost Software License, Version 1.0. (See
2 // accompanying file LICENSE_1_0.txt or copy at
3 // http://www.boost.org/LICENSE_1_0.txt)
4 // (C) Copyright 2009-2012 Anthony Williams
5 // (C) Copyright 2012 Vicente J. Botet Escriba
6 
7 // Based on the Anthony's idea of scoped_thread in CCiA
8 
9 #ifndef BOOST_THREAD_SCOPED_THREAD_HPP
10 #define BOOST_THREAD_SCOPED_THREAD_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/thread_functors.hpp>
16 #include <boost/thread/thread_only.hpp>
17 
18 #include <boost/config/abi_prefix.hpp>
19 
20 namespace boost
21 {
22 
23   /**
24    * RAI @c thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
25    *
26    * CallableThread: A callable void(thread&) .
27    * The default is a join_if_joinable.
28    *
29    * thread std/boost::thread destructor terminates the program if the thread is not joinable.
30    * Having a wrapper that can join the thread before destroying it seems a natural need.
31    *
32    * Example:
33    *
34    *     boost::strict_scoped_thread<> t((boost::thread(F)));
35    *
36    */
37   template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
38   class strict_scoped_thread
39   {
40     Thread t_;
41     struct dummy;
42   public:
43 
44     BOOST_THREAD_NO_COPYABLE( strict_scoped_thread) /// non copyable
45 
46     /*
47      *
48      */
49 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
50     template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type>
strict_scoped_thread(BOOST_THREAD_FWD_REF (F)f,BOOST_THREAD_FWD_REF (Args)...args)51     explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
52       t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
53 #else
54     template <class F>
55     explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f,
56         typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type=0) :
57       t_(boost::forward<F>(f)) {}
58     template <class F, class A1>
59     strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) :
60       t_(boost::forward<F>(f), boost::forward<A1>(a1)) {}
61     template <class F, class A1, class A2>
62     strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) :
63       t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2)) {}
64     template <class F, class A1, class A2, class A3>
65     strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) :
66       t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)) {}
67 #endif
68 
69     /**
70      * Constructor from the thread to own.
71      *
72      * @param t: the thread to own.
73      *
74      * Effects: move the thread to own @c t.
75      */
strict_scoped_thread(BOOST_THREAD_RV_REF (Thread)t)76     explicit strict_scoped_thread(BOOST_THREAD_RV_REF(Thread) t) BOOST_NOEXCEPT :
77     t_(boost::move(t))
78     {
79     }
80 
81     /**
82      * Destructor
83      * Effects: Call the CallableThread functor before destroying the owned thread.
84      * Remark: The CallableThread should not throw when joining the thread as the scoped variable is on a scope outside the thread function.
85      */
~strict_scoped_thread()86     ~strict_scoped_thread()
87     {
88       CallableThread on_destructor;
89 
90       on_destructor(t_);
91     }
92 
93   };
94 
95   /**
96    * RAI @c thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
97    *
98    * CallableThread: A callable void(thread&) .
99    * The default is join_if_joinable.
100    *
101    * thread std::thread destructor terminates the program if the thread is not joinable.
102    * Having a wrapper that can join the thread before destroying it seems a natural need.
103    *
104    * Remark: @c scoped_thread is not a @c thread as @c thread is not designed to be derived from as a polymorphic type.
105    * Anyway @c scoped_thread can be used in most of the contexts a @c thread could be used as it has the
106    * same non-deprecated interface with the exception of the construction.
107    *
108    * Example:
109    *
110    *     boost::scoped_thread<> t((boost::thread(F)));
111    *     t.interrupt();
112    *
113    */
114   template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
115   class scoped_thread
116   {
117     Thread t_;
118     struct dummy;
119   public:
120 
121     typedef typename Thread::id id;
122     typedef typename Thread::native_handle_type native_handle_type;
123 
124     BOOST_THREAD_MOVABLE_ONLY( scoped_thread) /// Movable only
125 
126     /**
127      * Default Constructor.
128      *
129      * Effects: wraps a not-a-thread.
130      */
scoped_thread()131     scoped_thread() BOOST_NOEXCEPT:
132     t_()
133     {
134     }
135 
136     /**
137      *
138      */
139 
140 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
141     template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type>
scoped_thread(BOOST_THREAD_FWD_REF (F)f,BOOST_THREAD_FWD_REF (Args)...args)142     explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
143       t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
144 #else
145     template <class F>
scoped_thread(BOOST_THREAD_FWD_REF (F)f,typename disable_if<is_same<typename decay<F>::type,Thread>,void * >::type=0)146     explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f,
147         typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type=0) :
148       t_(boost::forward<F>(f)) {}
149     template <class F, class A1>
scoped_thread(BOOST_THREAD_FWD_REF (F)f,BOOST_THREAD_FWD_REF (A1)a1)150     scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) :
151       t_(boost::forward<F>(f), boost::forward<A1>(a1)) {}
152     template <class F, class A1, class A2>
scoped_thread(BOOST_THREAD_FWD_REF (F)f,BOOST_THREAD_FWD_REF (A1)a1,BOOST_THREAD_FWD_REF (A2)a2)153     scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) :
154       t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2)) {}
155     template <class F, class A1, class A2, class A3>
scoped_thread(BOOST_THREAD_FWD_REF (F)f,BOOST_THREAD_FWD_REF (A1)a1,BOOST_THREAD_FWD_REF (A2)a2,BOOST_THREAD_FWD_REF (A3)a3)156     scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) :
157       t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)) {}
158 
159 #endif
160     /**
161      * Constructor from the thread to own.
162      *
163      * @param t: the thread to own.
164      *
165      * Effects: move the thread to own @c t.
166      */
scoped_thread(BOOST_THREAD_RV_REF (Thread)t)167     explicit scoped_thread(BOOST_THREAD_RV_REF(Thread) t) BOOST_NOEXCEPT :
168     t_(boost::move(t))
169     {
170     }
171 
172 //    explicit operator Thread()
173 //    {
174 //      return boost::move(t_);
175 //    }
176 
177     /**
178      * Move constructor.
179      */
scoped_thread(BOOST_RV_REF (scoped_thread)x)180     scoped_thread(BOOST_RV_REF(scoped_thread) x) BOOST_NOEXCEPT :
181     t_(boost::move(BOOST_THREAD_RV(x).t_))
182     {}
183 
184     /**
185      * Destructor
186      *
187      * Effects: Call the CallableThread functor before destroying the owned thread.
188      */
~scoped_thread()189     ~scoped_thread()
190     {
191       CallableThread on_destructor;
192 
193       on_destructor(t_);
194     }
195 
196     /**
197      * Move assignment.
198      */
operator =(BOOST_RV_REF (scoped_thread)x)199     scoped_thread& operator=(BOOST_RV_REF(scoped_thread) x)
200     {
201       CallableThread on_destructor;
202 
203       on_destructor(t_);
204       t_ = boost::move(BOOST_THREAD_RV(x).t_);
205       return *this;
206     }
207 
208     /**
209      *
210      */
swap(scoped_thread & x)211     void swap(scoped_thread& x) BOOST_NOEXCEPT
212     {
213       t_.swap(x.t_);
214     }
215 
216     // forwarded thread functions
get_id() const217     inline id get_id() const BOOST_NOEXCEPT
218     {
219       return t_.get_id();
220     }
221 
detach()222     void detach()
223     {
224       t_.detach();
225     }
226 
join()227     void join()
228     {
229       t_.join();
230     }
231 
232 #ifdef BOOST_THREAD_USES_CHRONO
233     template <class Rep, class Period>
try_join_for(const chrono::duration<Rep,Period> & rel_time)234     bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
235     {
236       return t_.try_join_for(rel_time);
237     }
238 
239     template <class Clock, class Duration>
try_join_until(const chrono::time_point<Clock,Duration> & abs_time)240     bool try_join_until(const chrono::time_point<Clock, Duration>& abs_time)
241     {
242       return t_.try_join_until(abs_time);
243     }
244 #endif
245 
native_handle()246     native_handle_type native_handle()BOOST_NOEXCEPT
247     {
248       return t_.native_handle();
249     }
250 
joinable() const251     bool joinable() const BOOST_NOEXCEPT
252     {
253       return t_.joinable();
254     }
255 
256 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
interrupt()257     void interrupt()
258     {
259       t_.interrupt();
260     }
261 
interruption_requested() const262     bool interruption_requested() const BOOST_NOEXCEPT
263     {
264       return t_.interruption_requested();
265     }
266 #endif
267 
hardware_concurrency()268     static unsigned hardware_concurrency() BOOST_NOEXCEPT
269     {
270       return Thread::hardware_concurrency();
271     }
272 
273 #ifdef BOOST_THREAD_PROVIDES_PHYSICAL_CONCURRENCY
physical_concurrency()274     static unsigned physical_concurrency() BOOST_NOEXCEPT
275     {
276       return Thread::physical_concurrency();
277     }
278 #endif
279   };
280 
281   /**
282    * Effects: swaps the contents of two scoped threads.
283    */
284   template <class Destroyer, class Thread >
swap(scoped_thread<Destroyer,Thread> & lhs,scoped_thread<Destroyer,Thread> & rhs)285   void swap(scoped_thread<Destroyer, Thread>& lhs, scoped_thread<Destroyer, Thread>& rhs)
286 BOOST_NOEXCEPT {
287   return lhs.swap(rhs);
288 }
289 
290   typedef scoped_thread<> joining_thread;
291 }
292 #include <boost/config/abi_suffix.hpp>
293 
294 #endif
295