OLD | NEW |
1 /* Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 * Use of this source code is governed by a BSD-style license that can be |
3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
4 */ | 4 */ |
5 | 5 |
6 #ifndef PPAPI_TESTS_PP_THREAD_H_ | 6 #ifndef PPAPI_TESTS_PP_THREAD_H_ |
7 #define PPAPI_TESTS_PP_THREAD_H_ | 7 #define PPAPI_TESTS_PP_THREAD_H_ |
8 | 8 |
9 #include "ppapi/c/pp_macros.h" | 9 #include "ppapi/c/pp_macros.h" |
10 #include "ppapi/tests/test_utils.h" | 10 #include "ppapi/tests/test_utils.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 * Client). Apps that use PPAPI only with Native Client should generally use the | 26 * Client). Apps that use PPAPI only with Native Client should generally use the |
27 * Native Client POSIX implementation instead. | 27 * Native Client POSIX implementation instead. |
28 * | 28 * |
29 * TODO(dmichael): Move this file to ppapi/c and delete this comment, if we end | 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 | 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 | 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 | 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. | 33 * used in ppapi/tests, so is not part of the published API. |
34 */ | 34 */ |
35 | 35 |
| 36 typedef void (PP_ThreadFunction)(void* data); |
| 37 |
36 #if defined(PPAPI_POSIX) | 38 #if defined(PPAPI_POSIX) |
37 typedef pthread_t PP_ThreadType; | 39 typedef pthread_t PP_Thread; |
38 #elif defined(PPAPI_OS_WIN) | 40 #elif defined(PPAPI_OS_WIN) |
39 typedef uintptr_t PP_ThreadType; | 41 struct PP_Thread { |
| 42 HANDLE handle; |
| 43 PP_ThreadFunction* thread_func; |
| 44 void* thread_arg; |
| 45 }; |
40 #endif | 46 #endif |
41 | 47 |
42 typedef void (PP_ThreadFunction)(void* data); | 48 PP_INLINE bool PP_CreateThread(PP_Thread* thread, |
43 | |
44 PP_INLINE bool PP_CreateThread(PP_ThreadType* thread, | |
45 PP_ThreadFunction function, | 49 PP_ThreadFunction function, |
46 void* thread_arg); | 50 void* thread_arg); |
47 PP_INLINE void PP_JoinThread(PP_ThreadType thread); | 51 PP_INLINE void PP_JoinThread(PP_Thread thread); |
48 | 52 |
49 #if defined(PPAPI_POSIX) | 53 #if defined(PPAPI_POSIX) |
50 /* Because POSIX thread functions return void* and Windows thread functions do | 54 /* Because POSIX thread functions return void* and Windows thread functions do |
51 * not, we make PPAPI thread functions have the least capability (no returns). | 55 * 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 | 56 * This struct wraps the user data & function so that we can use the correct |
53 * function type on POSIX platforms. | 57 * function type on POSIX platforms. |
54 */ | 58 */ |
55 struct PP_ThreadFunctionArgWrapper { | 59 struct PP_ThreadFunctionArgWrapper { |
56 void* user_data; | 60 void* user_data; |
57 PP_ThreadFunction* user_function; | 61 PP_ThreadFunction* user_function; |
58 }; | 62 }; |
59 | 63 |
60 PP_INLINE void* PP_POSIXThreadFunctionThunk(void* posix_thread_arg) { | 64 PP_INLINE void* PP_POSIXThreadFunctionThunk(void* posix_thread_arg) { |
61 PP_ThreadFunctionArgWrapper* arg_wrapper = | 65 PP_ThreadFunctionArgWrapper* arg_wrapper = |
62 (PP_ThreadFunctionArgWrapper*)posix_thread_arg; | 66 (PP_ThreadFunctionArgWrapper*)posix_thread_arg; |
63 arg_wrapper->user_function(arg_wrapper->user_data); | 67 arg_wrapper->user_function(arg_wrapper->user_data); |
64 free(posix_thread_arg); | 68 free(posix_thread_arg); |
65 return NULL; | 69 return NULL; |
66 } | 70 } |
67 | 71 |
68 PP_INLINE bool PP_CreateThread(PP_ThreadType* thread, | 72 PP_INLINE bool PP_CreateThread(PP_Thread* thread, |
69 PP_ThreadFunction function, | 73 PP_ThreadFunction function, |
70 void* thread_arg) { | 74 void* thread_arg) { |
71 PP_ThreadFunctionArgWrapper* arg_wrapper = | 75 PP_ThreadFunctionArgWrapper* arg_wrapper = |
72 (PP_ThreadFunctionArgWrapper*)malloc(sizeof(PP_ThreadFunctionArgWrapper)); | 76 (PP_ThreadFunctionArgWrapper*)malloc(sizeof(PP_ThreadFunctionArgWrapper)); |
73 arg_wrapper->user_function = function; | 77 arg_wrapper->user_function = function; |
74 arg_wrapper->user_data = thread_arg; | 78 arg_wrapper->user_data = thread_arg; |
75 return (pthread_create(thread, | 79 return (pthread_create(thread, |
76 NULL, | 80 NULL, |
77 PP_POSIXThreadFunctionThunk, | 81 PP_POSIXThreadFunctionThunk, |
78 arg_wrapper) == 0); | 82 arg_wrapper) == 0); |
79 } | 83 } |
80 | 84 |
81 PP_INLINE void PP_JoinThread(PP_ThreadType thread) { | 85 PP_INLINE void PP_JoinThread(PP_Thread thread) { |
82 void* exit_status; | 86 void* exit_status; |
83 pthread_join(thread, &exit_status); | 87 pthread_join(thread, &exit_status); |
84 } | 88 } |
85 | 89 |
86 #elif defined(PPAPI_OS_WIN) | 90 #elif defined(PPAPI_OS_WIN) |
87 typedef DWORD (PP_WindowsThreadFunction)(void* data); | |
88 | 91 |
89 PP_INLINE bool PP_CreateThread(PP_ThreadType* thread, | 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 |
| 98 PP_INLINE bool PP_CreateThread(PP_Thread* thread, |
90 PP_ThreadFunction function, | 99 PP_ThreadFunction function, |
91 void* thread_arg) { | 100 void* thread_arg) { |
92 if (!thread) | 101 if (!thread) |
93 return false; | 102 return false; |
94 *thread = ::_beginthread(function, | 103 thread->thread_func = function; |
95 0, /* Use default stack size. */ | 104 thread->thread_arg = thread_arg; |
96 thread_arg); | 105 uintptr_t raw_handle = ::_beginthreadex(NULL, |
97 return (*thread != 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); |
98 } | 113 } |
99 | 114 |
100 PP_INLINE void PP_JoinThread(PP_ThreadType thread) { | 115 PP_INLINE void PP_JoinThread(PP_Thread thread) { |
101 ::WaitForSingleObject((HANDLE)thread, INFINITE); | 116 ::WaitForSingleObject(thread.handle, INFINITE); |
| 117 ::CloseHandle(thread.handle); |
102 } | 118 } |
103 | 119 |
104 #endif | 120 #endif |
105 | 121 |
106 | 122 |
107 /** | 123 /** |
108 * @} | 124 * @} |
109 */ | 125 */ |
110 | 126 |
111 #endif /* PPAPI_TESTS_PP_THREAD_H_ */ | 127 #endif /* PPAPI_TESTS_PP_THREAD_H_ */ |
112 | 128 |
OLD | NEW |