1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ppapi/utility/threading/simple_thread.h"
6
7#ifdef WIN32
8#include <windows.h>
9#endif
10
11namespace pp {
12
13namespace {
14
15// Use 2MB default stack size for Native Client, otherwise use system default.
16#if defined(__native_client__)
17const size_t kDefaultStackSize = 2 * 1024 * 1024;
18#else
19const size_t kDefaultStackSize = 0;
20#endif
21
22
23struct ThreadData {
24  MessageLoop message_loop;
25
26  SimpleThread::ThreadFunc func;
27  void* user_data;
28};
29
30#ifdef WIN32
31DWORD WINAPI RunThread(void* void_data) {
32#else
33void* RunThread(void* void_data) {
34#endif
35  ThreadData* data = static_cast<ThreadData*>(void_data);
36  data->message_loop.AttachToCurrentThread();
37
38  if (data->func)
39    data->func(data->message_loop, data->user_data);
40  else
41    data->message_loop.Run();
42
43  delete data;
44  return NULL;
45}
46
47}   // namespace
48
49SimpleThread::SimpleThread(const InstanceHandle& instance)
50    : instance_(instance),
51      message_loop_(instance),
52      stacksize_(kDefaultStackSize),
53      thread_(0) {
54}
55
56SimpleThread::SimpleThread(const InstanceHandle& instance,
57                           size_t stacksize)
58    : instance_(instance),
59      message_loop_(instance),
60      stacksize_(stacksize),
61      thread_(0) {
62}
63
64SimpleThread::~SimpleThread() {
65  Join();
66}
67
68bool SimpleThread::Start() {
69  return StartWithFunction(NULL, NULL);
70}
71
72bool SimpleThread::Join() {
73  if (!thread_)
74    return false;
75
76  message_loop_.PostQuit(true);
77
78#ifdef WIN32
79  DWORD result = WaitForSingleObject(thread_, INFINITE);
80  CloseHandle(thread_);
81  thread_ = 0;
82  return result == WAIT_OBJECT_0;
83
84#else
85  void* retval;
86  int result = pthread_join(thread_, &retval);
87  thread_ = 0;
88  return result == 0;
89#endif
90}
91
92bool SimpleThread::StartWithFunction(ThreadFunc func, void* user_data) {
93  if (thread_)
94    return false;
95
96  ThreadData* data = new ThreadData;
97  data->message_loop = message_loop_;
98  data->func = func;
99  data->user_data = user_data;
100
101#ifdef WIN32
102  thread_ = CreateThread(NULL, stacksize_, &RunThread, data, 0, NULL);
103  if (!thread_) {
104#else
105  pthread_attr_t attr;
106  pthread_attr_init(&attr);
107  int setval = 0;
108  if (stacksize_ > 0)
109    setval = pthread_attr_setstacksize(&attr, stacksize_);
110  if (setval != 0 || pthread_create(&thread_, &attr, &RunThread, data) != 0) {
111#endif
112    delete data;
113    return false;
114  }
115  return true;
116}
117
118}  // namespace pp
119