• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[/
2  (C) Copyright 2008-9 Anthony Williams.
3  (C) Copyright 12 Vicente J. Botet Escriba.
4  Distributed under the Boost Software License, Version 1.0.
5  (See accompanying file LICENSE_1_0.txt or copy at
6  http://www.boost.org/LICENSE_1_0.txt).
7]
8
9[section:ScopedThreads Scoped Threads]
10
11[heading Synopsis]
12
13  //#include <boost/thread/scoped_thread.hpp>
14
15  struct detach;
16  struct join_if_joinable;
17  struct interrupt_and_join_if_joinable;
18  template <class CallableThread = join_if_joinable, class Thread = thread>
19  class strict_scoped_thread;
20  template <class CallableThread = join_if_joinable, class Thread = thread>
21  class scoped_thread;
22  template <class CallableThread, class Thread = thread>
23  void swap(scoped_thread<Callable, Thread>& lhs, scoped_threadCallable, Thread>& rhs) noexcept;
24
25[section:motivation Motivation]
26Based on the scoped_thread class defined in C++ Concurrency in Action Boost.Thread defines a thread wrapper class that instead of calling terminate if the thread is joinable on destruction, call a specific action given as template parameter.
27
28While the scoped_thread class defined in C++ Concurrency in Action is closer to strict_scoped_thread class that doesn't allows any change in the wrapped thread, Boost.Thread provides a class scoped_thread that provides the same non-deprecated interface as __thread.
29
30[endsect]
31
32[section:tutorial Tutorial]
33
34Scoped Threads are wrappers around a thread that allows the user to state what to do at destruction time. One of the common uses is to join the thread at destruction time so this is the default behavior. This is the single difference respect to a thread. While thread call std::terminate() on the destructor if the thread is joinable, strict_scoped_thread<> or scoped_thread<> join the thread if joinable.
35
36The difference between strict_scoped_thread and scoped_thread is that the strict_scoped_thread hides completely the owned thread and so the user can do nothing with the owned thread other than the specific action given as parameter, while scoped_thread provide the same interface as __thread and forwards all the operations.
37
38  boost::strict_scoped_thread<> t1((boost::thread(f)));
39  //t1.detach(); // compile fails
40  boost::scoped_thread<> t2((boost::thread(f)));
41  t2.detach();
42
43[endsect]
44
45[section:thread_functors Free Thread Functors]
46
47  //#include <boost/thread/scoped_thread.hpp>
48
49  struct detach;
50  struct join_if_joinable;
51  struct interrupt_and_join_if_joinable;
52
53
54[section:detach Functor `detach`]
55
56  struct detach
57  {
58    template <class Thread>
59    void operator()(Thread& t)
60    {
61      t.detach();
62    }
63  };
64[endsect]
65[section:join_if_joinable Functor `join_if_joinable`]
66
67  struct join_if_joinable
68  {
69    template <class Thread>
70    void operator()(Thread& t)
71    {
72      if (t.joinable())
73      {
74        t.join();
75      }
76    }
77  };
78
79[endsect]
80
81[section:interrupt_and_join_if_joinable Functor `interrupt_and_join_if_joinable`]
82
83  struct interrupt_and_join_if_joinable
84  {
85    template <class Thread>
86    void operator()(Thread& t)
87    {
88      t.interrupt();
89      if (t.joinable())
90      {
91        t.join();
92      }
93    }
94  };
95[endsect]
96
97[endsect]
98
99[section:strict_scoped_thread Class `strict_scoped_thread`]
100
101  // #include <boost/thread/scoped_thread.hpp>
102
103  template <class CallableThread = join_if_joinable, class Thread = ::boost::thread>
104  class strict_scoped_thread
105  {
106    thread t_; // for exposition purposes only
107  public:
108
109    strict_scoped_thread(strict_scoped_thread const&) = delete;
110    strict_scoped_thread& operator=(strict_scoped_thread const&) = delete;
111
112    explicit strict_scoped_thread(Thread&& t) noexcept;
113    template <typename F&&, typename ...Args>
114    explicit strict_scoped_thread(F&&, Args&&...);
115
116    ~strict_scoped_thread();
117
118  };
119
120
121RAII __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
122
123CallableThread: A callable `void(thread&)`.
124
125The default is a `join_if_joinable`.
126
127
128Thread destructor terminates the program if the __thread is joinable.
129This wrapper can be used to join the thread before destroying it.
130
131[heading Example]
132
133  boost::strict_scoped_thread<> t((boost::thread(F)));
134
135[section:default_constructor Constructor from a __thread]
136
137    explicit strict_scoped_thread(Thread&& t) noexcept;
138
139[variablelist
140
141[[Effects:] [move the thread to own `t_`]]
142
143[[Throws:] [Nothing]]
144
145]
146
147[endsect]
148
149
150[section:call_constructor Move Constructor from a Callable]
151
152        template <typename F&&, typename ...Args>
153        explicit strict_scoped_thread(F&&, Args&&...);
154
155[variablelist
156
157[[Effects:] [Construct an internal thread in place.]]
158
159[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
160
161[[Throws:] [Any exception the thread construction can throw.]]
162
163]
164
165[endsect]
166
167[section:destructor Destructor]
168
169    ~strict_scoped_thread();
170
171[variablelist
172
173[[Effects:] [Equivalent to `CallableThread()(t_)`.  ]]
174
175[[Throws:] [Nothing: The `CallableThread()(t_)` should not throw when joining the thread as the scoped variable is on a scope outside the thread function.]]
176
177]
178
179[endsect]
180
181[endsect]
182
183[section:scoped_thread Class `scoped_thread`]
184
185    #include <boost/thread/scoped_thread.hpp>
186
187    template <class CallableThread, class Thread = thread>
188    class scoped_thread
189    {
190      thread t_; // for exposition purposes only
191    public:
192        scoped_thread() noexcept;
193        scoped_thread(const scoped_thread&) = delete;
194        scoped_thread& operator=(const scoped_thread&) = delete;
195
196        explicit scoped_thread(thread&& th) noexcept;
197        template <typename F&&, typename ...Args>
198        explicit scoped_thread(F&&, Args&&...);
199
200        ~scoped_thread();
201
202        // move support
203        scoped_thread(scoped_thread && x) noexcept;
204        scoped_thread& operator=(scoped_thread && x) noexcept;
205
206        void swap(scoped_thread& x) noexcept;
207
208        typedef thread::id id;
209
210        id get_id() const noexcept;
211
212        bool joinable() const noexcept;
213        void join();
214    #ifdef BOOST_THREAD_USES_CHRONO
215        template <class Rep, class Period>
216        bool try_join_for(const chrono::duration<Rep, Period>& rel_time);
217        template <class Clock, class Duration>
218        bool try_join_until(const chrono::time_point<Clock, Duration>& t);
219    #endif
220
221        void detach();
222
223        static unsigned hardware_concurrency() noexcept;
224        static unsigned physical_concurrency() noexcept;
225
226        typedef thread::native_handle_type native_handle_type;
227        native_handle_type native_handle();
228
229    #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
230        void interrupt();
231        bool interruption_requested() const noexcept;
232    #endif
233
234
235    };
236
237    template <class CallableThread, class Thread = thread>
238    void swap(scoped_thread<CallableThread,Thread>& lhs,scoped_thread<CallableThread,Thread>& rhs) noexcept;
239
240
241RAII __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
242
243CallableThread: A callable void(thread&).
244The default is join_if_joinable.
245
246Thread destructor terminates the program if the thread is joinable.
247This wrapper can be used to join the thread before destroying it.
248
249Remark: `scoped_thread` is not a __thread as __thread is not designed to be derived from as a polymorphic type.
250
251Anyway `scoped_thread` can be used in most of the contexts a __thread could be used as it has the
252same non-deprecated interface with the exception of the construction.
253
254[heading Example]
255
256  boost::scoped_thread<> t((boost::thread(F)));
257  t.interrupt();
258
259
260[section:default_constructor Default Constructor]
261
262    scoped_thread() noexcept;
263
264[variablelist
265
266[[Effects:] [Constructs a scoped_thread instance that wraps to __not_a_thread__.]]
267
268[[Postconditions:] [`this->get_id()==thread::id()`]]
269
270[[Throws:] [Nothing]]
271
272]
273
274[endsect]
275
276[section:move_constructor Move Constructor]
277
278    scoped_thread(scoped_thread&& other) noexcept;
279
280[variablelist
281
282[[Effects:] [Transfers ownership of the scoped_thread managed by `other` (if any) to the newly constructed scoped_thread instance.]]
283
284[[Postconditions:] [`other.get_id()==thread::id()` and `get_id()` returns the value of `other.get_id()` prior to the construction]]
285
286[[Throws:] [Nothing]]
287
288]
289
290[endsect]
291
292[section:move_assignment Move assignment operator]
293
294    scoped_thread& operator=(scoped_thread&& other) noexcept;
295
296[variablelist
297
298[[Effects:] [Transfers ownership of the scoped_thread managed by `other` (if
299any) to `*this` after having called to `CallableThread()(t_)`.
300
301]]
302
303[[Postconditions:] [`other->get_id()==thread::id()` and `get_id()` returns the value of `other.get_id()` prior to the assignment.]]
304
305[[Throws:] [Nothing: The `CallableThread()(t_)` should not throw when joining the thread as the scoped variable is on a scope outside the thread function.]]
306
307
308]
309
310[endsect]
311
312[section:thread_constructor Move Constructor from a __thread]
313
314    scoped_thread(thread&& t);
315
316[variablelist
317
318[[Effects:] [Transfers ownership of the thread managed by `other` (if any) to the newly constructed scoped_thread instance.]]
319
320[[Postconditions:] [other.get_id()==thread::id() and get_id() returns the value of other.get_id() prior to the construction.]]
321
322[[Throws:] [Nothing]]
323
324]
325
326[endsect]
327
328[section:call_constructor Move Constructor from a Callable]
329
330        template <typename F&&, typename ...Args>
331        explicit scoped_thread(F&&, Args&&...);
332
333[variablelist
334
335[[Effects:] [Construct an internal thread in place.]]
336
337[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
338
339[[Throws:] [Any exception the thread construction can throw.]]
340
341]
342
343[endsect]
344
345
346[section:destructor Destructor]
347
348    ~scoped_thread();
349
350[variablelist
351
352[[Effects:] [Equivalent to `CallableThread()(t_)`.  ]]
353
354[[Throws:] [Nothing: The `CallableThread()(t_)` should not throw when joining the thread as the scoped variable is on a scope outside the thread function.]]
355
356]
357
358[endsect]
359
360
361[section:joinable Member function `joinable()`]
362
363    bool joinable() const noexcept;
364
365[variablelist
366
367[[Returns:] [Equivalent to return t_.joinable().]]
368
369[[Throws:] [Nothing]]
370
371]
372
373
374[endsect]
375
376[section:join Member function `join()`]
377
378    void join();
379
380[variablelist
381
382[[Effects:] [Equivalent to t_.join().]]
383
384]
385
386[endsect]
387
388[section:try_join_for Member function `try_join_for()`]
389
390        template <class Rep, class Period>
391        bool try_join_for(const chrono::duration<Rep, Period>& rel_time);
392
393[variablelist
394
395[[Effects:] [Equivalent to return `t_.try_join_for(rel_time)`.]]
396
397]
398
399[endsect]
400
401[section:try_join_until Member function `try_join_until()`]
402
403        template <class Clock, class Duration>
404        bool try_join_until(const chrono::time_point<Clock, Duration>& abs_time);
405
406[variablelist
407
408[[Effects:] [Equivalent to return `t_.try_join_until(abs_time)`.]]
409
410]
411
412[endsect]
413
414
415
416[section:detach Member function `detach()`]
417
418    void detach();
419
420[variablelist
421
422[[Effects:] [Equivalent to `t_.detach()`.]]
423
424]
425
426[endsect]
427
428
429[section:get_id Member function `get_id()`]
430
431    thread::id get_id() const noexcept;
432
433[variablelist
434
435[[Effects:] [Equivalent to return `t_.get_id()`.]]
436
437]
438
439[endsect]
440
441[section:interrupt Member function `interrupt()`]
442
443    void interrupt();
444
445[variablelist
446
447[[Effects:] [Equivalent to `t_.interrupt()`.]]
448
449]
450
451
452[endsect]
453
454[section:hardware_concurrency Static member function `hardware_concurrency()`]
455
456    unsigned hardware_concurrency() noexecpt;
457
458[variablelist
459
460[[Effects:] [Equivalent to return `thread::hardware_concurrency()`.]]
461
462]
463
464[endsect]
465
466
467[section:physical_concurrency Static member function `physical_concurrency()`]
468
469    unsigned physical_concurrency() noexecpt;
470
471[variablelist
472
473[[Effects:] [Equivalent to return `thread::physical_concurrency()`.]]
474
475]
476
477[endsect]
478
479
480[section:nativehandle Member function `native_handle()`]
481
482    typedef thread::native_handle_type native_handle_type;
483    native_handle_type native_handle();
484
485[variablelist
486
487[[Effects:] [Equivalent to return `t_.native_handle()`.]]
488
489]
490
491[endsect]
492
493[section:swap Member function `swap()`]
494
495    void swap(scoped_thread& other) noexcept;
496
497[variablelist
498
499[[Effects:] [Equivalent `t_.swap(other.t_)`.]]
500
501]
502
503[endsect]
504
505
506
507[endsect]
508[section:non_member_swap Non-member function `swap(scoped_thread&,scoped_thread&)`]
509
510    #include <boost/thread/scoped_thread.hpp>
511
512    template <class CallableThread, class Thread = thread>
513    void swap(scoped_thread<Callable, Thread>& lhs, scoped_threadCallable, Thread>& rhs) noexcept;
514
515[variablelist
516
517[[Effects:] [`lhs.swap(rhs)`.]]
518
519]
520
521[endsect]
522[endsect]
523