Home | History | Annotate | Download | only in tests
      1 /* Copyright (c) 2011 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 
      6 #ifndef PPAPI_TESTS_PP_THREAD_H_
      7 #define PPAPI_TESTS_PP_THREAD_H_
      8 
      9 #include "ppapi/c/pp_macros.h"
     10 #include "ppapi/tests/test_utils.h"
     11 
     12 #if defined(PPAPI_POSIX)
     13 #include <pthread.h>
     14 #elif defined(PPAPI_OS_WIN)
     15 #include <process.h>
     16 #include <windows.h>
     17 #else
     18 #error No thread library detected.
     19 #endif
     20 
     21 /**
     22  * @file
     23  * This file provides platform-independent wrappers around threads. This is for
     24  * use by PPAPI wrappers and tests which need to run on multiple platforms to
     25  * support both trusted platforms (Windows, Mac, Linux) and untrusted (Native
     26  * Client). Apps that use PPAPI only with Native Client should generally use the
     27  * Native Client POSIX implementation instead.
     28  *
     29  * TODO(dmichael): Move this file to ppapi/c and delete this comment, if we end
     30  * up needing platform independent threads in PPAPI C or C++. This file was
     31  * written using inline functions and PPAPI naming conventions with the intent
     32  * of making it possible to put it in to ppapi/c. Currently, however, it's only
     33  * used in ppapi/tests, so is not part of the published API.
     34  */
     35 
     36 #if defined(PPAPI_POSIX)
     37 typedef pthread_t PP_ThreadType;
     38 #elif defined(PPAPI_OS_WIN)
     39 typedef uintptr_t PP_ThreadType;
     40 #endif
     41 
     42 typedef void (PP_ThreadFunction)(void* data);
     43 
     44 PP_INLINE bool PP_CreateThread(PP_ThreadType* thread,
     45                                PP_ThreadFunction function,
     46                                void* thread_arg);
     47 PP_INLINE void PP_JoinThread(PP_ThreadType thread);
     48 
     49 #if defined(PPAPI_POSIX)
     50 /* Because POSIX thread functions return void* and Windows thread functions do
     51  * not, we make PPAPI thread functions have the least capability (no returns).
     52  * This struct wraps the user data & function so that we can use the correct
     53  * function type on POSIX platforms.
     54  */
     55 struct PP_ThreadFunctionArgWrapper {
     56   void* user_data;
     57   PP_ThreadFunction* user_function;
     58 };
     59 
     60 PP_INLINE void* PP_POSIXThreadFunctionThunk(void* posix_thread_arg) {
     61   PP_ThreadFunctionArgWrapper* arg_wrapper =
     62       (PP_ThreadFunctionArgWrapper*)posix_thread_arg;
     63   arg_wrapper->user_function(arg_wrapper->user_data);
     64   free(posix_thread_arg);
     65   return NULL;
     66 }
     67 
     68 PP_INLINE bool PP_CreateThread(PP_ThreadType* thread,
     69                                PP_ThreadFunction function,
     70                                void* thread_arg) {
     71   PP_ThreadFunctionArgWrapper* arg_wrapper =
     72       (PP_ThreadFunctionArgWrapper*)malloc(sizeof(PP_ThreadFunctionArgWrapper));
     73   arg_wrapper->user_function = function;
     74   arg_wrapper->user_data = thread_arg;
     75   return (pthread_create(thread,
     76                          NULL,
     77                          PP_POSIXThreadFunctionThunk,
     78                          arg_wrapper) == 0);
     79 }
     80 
     81 PP_INLINE void PP_JoinThread(PP_ThreadType thread) {
     82   void* exit_status;
     83   pthread_join(thread, &exit_status);
     84 }
     85 
     86 #elif defined(PPAPI_OS_WIN)
     87 typedef DWORD (PP_WindowsThreadFunction)(void* data);
     88 
     89 PP_INLINE bool PP_CreateThread(PP_ThreadType* thread,
     90                                PP_ThreadFunction function,
     91                                void* thread_arg) {
     92   if (!thread)
     93     return false;
     94   *thread = ::_beginthread(function,
     95                            0,  /* Use default stack size. */
     96                            thread_arg);
     97   return (*thread != NULL);
     98 }
     99 
    100 PP_INLINE void PP_JoinThread(PP_ThreadType thread) {
    101   ::WaitForSingleObject((HANDLE)thread, INFINITE);
    102 }
    103 
    104 #endif
    105 
    106 
    107 /**
    108  * @}
    109  */
    110 
    111 #endif  /* PPAPI_TESTS_PP_THREAD_H_ */
    112 
    113