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
17namespace dena {
18
19template <typename T>
20struct thread : private noncopyable {
21 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) { }
23 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) { }
26 ~thread() {
27 join();
28 }
29 void start() {
30 if (!start_nothrow()) {
31 fatal_abort("thread::start");
32 }
33 }
34 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 }
56 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 }
66 T& operator *() { return obj; }
67 T *operator ->() { return &obj; }
68 private:
69 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