Home | History | Annotate | Download | only in threading
      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 
     11 namespace pp {
     12 
     13 namespace {
     14 
     15 // Use 2MB default stack size for Native Client, otherwise use system default.
     16 #if defined(__native_client__)
     17 const size_t kDefaultStackSize = 2 * 1024 * 1024;
     18 #else
     19 const size_t kDefaultStackSize = 0;
     20 #endif
     21 
     22 
     23 struct ThreadData {
     24   MessageLoop message_loop;
     25 
     26   SimpleThread::ThreadFunc func;
     27   void* user_data;
     28 };
     29 
     30 #ifdef WIN32
     31 DWORD WINAPI RunThread(void* void_data) {
     32 #else
     33 void* 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 
     49 SimpleThread::SimpleThread(const InstanceHandle& instance)
     50     : instance_(instance),
     51       message_loop_(instance),
     52       stacksize_(kDefaultStackSize),
     53       thread_(0) {
     54 }
     55 
     56 SimpleThread::SimpleThread(const InstanceHandle& instance,
     57                            size_t stacksize)
     58     : instance_(instance),
     59       message_loop_(instance),
     60       stacksize_(stacksize),
     61       thread_(0) {
     62 }
     63 
     64 SimpleThread::~SimpleThread() {
     65   Join();
     66 }
     67 
     68 bool SimpleThread::Start() {
     69   return StartWithFunction(NULL, NULL);
     70 }
     71 
     72 bool 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 
     92 bool 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