1 
2 // vim:sw=2:ai
3 
4 /*
5  * Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
6  * See COPYRIGHT.txt for details.
7  */
8 
9 #ifndef DENA_THREAD_HPP
10 #define DENA_THREAD_HPP
11 
12 #include <stdexcept>
13 #include <pthread.h>
14 
15 #include "fatal.hpp"
16 
17 namespace dena {
18 
19 template <typename T>
20 struct thread : private noncopyable {
threaddena::thread21   template <typename Ta> thread(const Ta& arg, size_t stack_sz = 256 * 1024)
22     : obj(arg), thr(0), need_join(false), stack_size(stack_sz) { }
threaddena::thread23   template <typename Ta0, typename Ta1> thread(const Ta0& a0,
24     volatile Ta1& a1, size_t stack_sz = 256 * 1024)
25     : obj(a0, a1), thr(0), need_join(false), stack_size(stack_sz) { }
~threaddena::thread26   ~thread() {
27     join();
28   }
startdena::thread29   void start() {
30     if (!start_nothrow()) {
31       fatal_abort("thread::start");
32     }
33   }
start_nothrowdena::thread34   bool start_nothrow() {
35     if (need_join) {
36       return need_join; /* true */
37     }
38     void *const arg = this;
39     pthread_attr_t attr;
40     if (pthread_attr_init(&attr) != 0) {
41       fatal_abort("pthread_attr_init");
42     }
43     if (pthread_attr_setstacksize(&attr, stack_size) != 0) {
44       fatal_abort("pthread_attr_setstacksize");
45     }
46     const int r = pthread_create(&thr, &attr, thread_main, arg);
47     if (pthread_attr_destroy(&attr) != 0) {
48       fatal_abort("pthread_attr_destroy");
49     }
50     if (r != 0) {
51       return need_join; /* false */
52     }
53     need_join = true;
54     return need_join; /* true */
55   }
joindena::thread56   void join() {
57     if (!need_join) {
58       return;
59     }
60     int e = 0;
61     if ((e = pthread_join(thr, 0)) != 0) {
62       fatal_abort("pthread_join");
63     }
64     need_join = false;
65   }
operator *dena::thread66   T& operator *() { return obj; }
operator ->dena::thread67   T *operator ->() { return &obj; }
68  private:
thread_maindena::thread69   static void *thread_main(void *arg) {
70     thread *p = static_cast<thread *>(arg);
71     p->obj();
72     return 0;
73   }
74  private:
75   T obj;
76   pthread_t thr;
77   bool need_join;
78   size_t stack_size;
79 };
80 
81 };
82 
83 #endif
84 
85