• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 typedef void (PP_ThreadFunction)(void* data);
37 
38 #if defined(PPAPI_POSIX)
39 typedef pthread_t PP_Thread;
40 #elif defined(PPAPI_OS_WIN)
41 struct PP_Thread {
42   HANDLE handle;
43   PP_ThreadFunction* thread_func;
44   void* thread_arg;
45 };
46 #endif
47 
48 PP_INLINE bool PP_CreateThread(PP_Thread* thread,
49                                PP_ThreadFunction function,
50                                void* thread_arg);
51 PP_INLINE void PP_JoinThread(PP_Thread thread);
52 
53 #if defined(PPAPI_POSIX)
54 /* Because POSIX thread functions return void* and Windows thread functions do
55  * not, we make PPAPI thread functions have the least capability (no returns).
56  * This struct wraps the user data & function so that we can use the correct
57  * function type on POSIX platforms.
58  */
59 struct PP_ThreadFunctionArgWrapper {
60   void* user_data;
61   PP_ThreadFunction* user_function;
62 };
63 
PP_POSIXThreadFunctionThunk(void * posix_thread_arg)64 PP_INLINE void* PP_POSIXThreadFunctionThunk(void* posix_thread_arg) {
65   PP_ThreadFunctionArgWrapper* arg_wrapper =
66       (PP_ThreadFunctionArgWrapper*)posix_thread_arg;
67   arg_wrapper->user_function(arg_wrapper->user_data);
68   free(posix_thread_arg);
69   return NULL;
70 }
71 
PP_CreateThread(PP_Thread * thread,PP_ThreadFunction function,void * thread_arg)72 PP_INLINE bool PP_CreateThread(PP_Thread* thread,
73                                PP_ThreadFunction function,
74                                void* thread_arg) {
75   PP_ThreadFunctionArgWrapper* arg_wrapper =
76       (PP_ThreadFunctionArgWrapper*)malloc(sizeof(PP_ThreadFunctionArgWrapper));
77   arg_wrapper->user_function = function;
78   arg_wrapper->user_data = thread_arg;
79   return (pthread_create(thread,
80                          NULL,
81                          PP_POSIXThreadFunctionThunk,
82                          arg_wrapper) == 0);
83 }
84 
PP_JoinThread(PP_Thread thread)85 PP_INLINE void PP_JoinThread(PP_Thread thread) {
86   void* exit_status;
87   pthread_join(thread, &exit_status);
88 }
89 
90 #elif defined(PPAPI_OS_WIN)
91 
PP_WindowsThreadFunction(void * param)92 PP_INLINE unsigned __stdcall PP_WindowsThreadFunction(void* param) {
93   PP_Thread* thread = reinterpret_cast<PP_Thread*>(param);
94   thread->thread_func(thread->thread_arg);
95   return 0;
96 }
97 
PP_CreateThread(PP_Thread * thread,PP_ThreadFunction function,void * thread_arg)98 PP_INLINE bool PP_CreateThread(PP_Thread* thread,
99                                PP_ThreadFunction function,
100                                void* thread_arg) {
101   if (!thread)
102     return false;
103   thread->thread_func = function;
104   thread->thread_arg = thread_arg;
105   uintptr_t raw_handle = ::_beginthreadex(NULL,
106                                           0,  /* Use default stack size. */
107                                           &PP_WindowsThreadFunction,
108                                           thread,
109                                           0,
110                                           NULL);
111   thread->handle = reinterpret_cast<HANDLE>(raw_handle);
112   return (thread->handle != NULL);
113 }
114 
PP_JoinThread(PP_Thread thread)115 PP_INLINE void PP_JoinThread(PP_Thread thread) {
116   ::WaitForSingleObject(thread.handle, INFINITE);
117   ::CloseHandle(thread.handle);
118 }
119 
120 #endif
121 
122 
123 /**
124  * @}
125  */
126 
127 #endif  /* PPAPI_TESTS_PP_THREAD_H_ */
128 
129