OLD | NEW |
1 // Copyright 2011 Google Inc. All Rights Reserved. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Use of this source code is governed by a BSD-style license | 3 // Use of this source code is governed by a BSD-style license |
4 // that can be found in the COPYING file in the root of the source | 4 // that can be found in the COPYING file in the root of the source |
5 // tree. An additional intellectual property rights grant can be found | 5 // tree. An additional intellectual property rights grant can be found |
6 // in the file PATENTS. All contributing project authors may | 6 // in the file PATENTS. All contributing project authors may |
7 // be found in the AUTHORS file in the root of the source tree. | 7 // be found in the AUTHORS file in the root of the source tree. |
8 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
9 // | 9 // |
10 // Multi-threaded worker | 10 // Multi-threaded worker |
11 // | 11 // |
12 // Author: Skal (pascal.massimino@gmail.com) | 12 // Author: Skal (pascal.massimino@gmail.com) |
13 | 13 |
14 #include <assert.h> | 14 #include <assert.h> |
15 #include <string.h> // for memset() | 15 #include <string.h> // for memset() |
16 #include "./thread.h" | 16 #include "./thread.h" |
17 #include "./utils.h" | 17 #include "./utils.h" |
18 | 18 |
19 #ifdef WEBP_USE_THREAD | 19 #ifdef WEBP_USE_THREAD |
20 | 20 |
21 #if defined(_WIN32) | 21 #if defined(_WIN32) |
22 | 22 |
23 #include <windows.h> | 23 #include <windows.h> |
24 typedef HANDLE pthread_t; | 24 typedef HANDLE pthread_t; |
25 typedef CRITICAL_SECTION pthread_mutex_t; | 25 typedef CRITICAL_SECTION pthread_mutex_t; |
| 26 |
| 27 #if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater |
| 28 #define USE_WINDOWS_CONDITION_VARIABLE |
| 29 typedef CONDITION_VARIABLE pthread_cond_t; |
| 30 #else |
26 typedef struct { | 31 typedef struct { |
27 HANDLE waiting_sem_; | 32 HANDLE waiting_sem_; |
28 HANDLE received_sem_; | 33 HANDLE received_sem_; |
29 HANDLE signal_event_; | 34 HANDLE signal_event_; |
30 } pthread_cond_t; | 35 } pthread_cond_t; |
| 36 #endif // _WIN32_WINNT >= 0x600 |
| 37 |
| 38 #ifndef WINAPI_FAMILY_PARTITION |
| 39 #define WINAPI_PARTITION_DESKTOP 1 |
| 40 #define WINAPI_FAMILY_PARTITION(x) x |
| 41 #endif |
| 42 |
| 43 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) |
| 44 #define USE_CREATE_THREAD |
| 45 #endif |
31 | 46 |
32 #else // !_WIN32 | 47 #else // !_WIN32 |
33 | 48 |
34 #include <pthread.h> | 49 #include <pthread.h> |
35 | 50 |
36 #endif // _WIN32 | 51 #endif // _WIN32 |
37 | 52 |
38 struct WebPWorkerImpl { | 53 struct WebPWorkerImpl { |
39 pthread_mutex_t mutex_; | 54 pthread_mutex_t mutex_; |
40 pthread_cond_t condition_; | 55 pthread_cond_t condition_; |
41 pthread_t thread_; | 56 pthread_t thread_; |
42 }; | 57 }; |
43 | 58 |
44 #if defined(_WIN32) | 59 #if defined(_WIN32) |
45 | 60 |
46 //------------------------------------------------------------------------------ | 61 //------------------------------------------------------------------------------ |
47 // simplistic pthread emulation layer | 62 // simplistic pthread emulation layer |
48 | 63 |
49 #include <process.h> | 64 #include <process.h> |
50 | 65 |
51 // _beginthreadex requires __stdcall | 66 // _beginthreadex requires __stdcall |
52 #define THREADFN unsigned int __stdcall | 67 #define THREADFN unsigned int __stdcall |
53 #define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val) | 68 #define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val) |
54 | 69 |
| 70 #if _WIN32_WINNT >= 0x0501 // Windows XP or greater |
| 71 #define WaitForSingleObject(obj, timeout) \ |
| 72 WaitForSingleObjectEx(obj, timeout, FALSE /*bAlertable*/) |
| 73 #endif |
| 74 |
55 static int pthread_create(pthread_t* const thread, const void* attr, | 75 static int pthread_create(pthread_t* const thread, const void* attr, |
56 unsigned int (__stdcall *start)(void*), void* arg) { | 76 unsigned int (__stdcall *start)(void*), void* arg) { |
57 (void)attr; | 77 (void)attr; |
| 78 #ifdef USE_CREATE_THREAD |
| 79 *thread = CreateThread(NULL, /* lpThreadAttributes */ |
| 80 0, /* dwStackSize */ |
| 81 start, |
| 82 arg, |
| 83 0, /* dwStackSize */ |
| 84 NULL); /* lpThreadId */ |
| 85 #else |
58 *thread = (pthread_t)_beginthreadex(NULL, /* void *security */ | 86 *thread = (pthread_t)_beginthreadex(NULL, /* void *security */ |
59 0, /* unsigned stack_size */ | 87 0, /* unsigned stack_size */ |
60 start, | 88 start, |
61 arg, | 89 arg, |
62 0, /* unsigned initflag */ | 90 0, /* unsigned initflag */ |
63 NULL); /* unsigned *thrdaddr */ | 91 NULL); /* unsigned *thrdaddr */ |
| 92 #endif |
64 if (*thread == NULL) return 1; | 93 if (*thread == NULL) return 1; |
65 SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL); | 94 SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL); |
66 return 0; | 95 return 0; |
67 } | 96 } |
68 | 97 |
69 static int pthread_join(pthread_t thread, void** value_ptr) { | 98 static int pthread_join(pthread_t thread, void** value_ptr) { |
70 (void)value_ptr; | 99 (void)value_ptr; |
71 return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 || | 100 return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 || |
72 CloseHandle(thread) == 0); | 101 CloseHandle(thread) == 0); |
73 } | 102 } |
74 | 103 |
75 // Mutex | 104 // Mutex |
76 static int pthread_mutex_init(pthread_mutex_t* const mutex, void* mutexattr) { | 105 static int pthread_mutex_init(pthread_mutex_t* const mutex, void* mutexattr) { |
77 (void)mutexattr; | 106 (void)mutexattr; |
| 107 #if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater |
| 108 InitializeCriticalSectionEx(mutex, 0 /*dwSpinCount*/, 0 /*Flags*/); |
| 109 #else |
78 InitializeCriticalSection(mutex); | 110 InitializeCriticalSection(mutex); |
| 111 #endif |
79 return 0; | 112 return 0; |
80 } | 113 } |
81 | 114 |
82 static int pthread_mutex_lock(pthread_mutex_t* const mutex) { | 115 static int pthread_mutex_lock(pthread_mutex_t* const mutex) { |
83 EnterCriticalSection(mutex); | 116 EnterCriticalSection(mutex); |
84 return 0; | 117 return 0; |
85 } | 118 } |
86 | 119 |
87 static int pthread_mutex_unlock(pthread_mutex_t* const mutex) { | 120 static int pthread_mutex_unlock(pthread_mutex_t* const mutex) { |
88 LeaveCriticalSection(mutex); | 121 LeaveCriticalSection(mutex); |
89 return 0; | 122 return 0; |
90 } | 123 } |
91 | 124 |
92 static int pthread_mutex_destroy(pthread_mutex_t* const mutex) { | 125 static int pthread_mutex_destroy(pthread_mutex_t* const mutex) { |
93 DeleteCriticalSection(mutex); | 126 DeleteCriticalSection(mutex); |
94 return 0; | 127 return 0; |
95 } | 128 } |
96 | 129 |
97 // Condition | 130 // Condition |
98 static int pthread_cond_destroy(pthread_cond_t* const condition) { | 131 static int pthread_cond_destroy(pthread_cond_t* const condition) { |
99 int ok = 1; | 132 int ok = 1; |
| 133 #ifdef USE_WINDOWS_CONDITION_VARIABLE |
| 134 (void)condition; |
| 135 #else |
100 ok &= (CloseHandle(condition->waiting_sem_) != 0); | 136 ok &= (CloseHandle(condition->waiting_sem_) != 0); |
101 ok &= (CloseHandle(condition->received_sem_) != 0); | 137 ok &= (CloseHandle(condition->received_sem_) != 0); |
102 ok &= (CloseHandle(condition->signal_event_) != 0); | 138 ok &= (CloseHandle(condition->signal_event_) != 0); |
| 139 #endif |
103 return !ok; | 140 return !ok; |
104 } | 141 } |
105 | 142 |
106 static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) { | 143 static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) { |
107 (void)cond_attr; | 144 (void)cond_attr; |
| 145 #ifdef USE_WINDOWS_CONDITION_VARIABLE |
| 146 InitializeConditionVariable(condition); |
| 147 #else |
108 condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL); | 148 condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL); |
109 condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL); | 149 condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL); |
110 condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL); | 150 condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL); |
111 if (condition->waiting_sem_ == NULL || | 151 if (condition->waiting_sem_ == NULL || |
112 condition->received_sem_ == NULL || | 152 condition->received_sem_ == NULL || |
113 condition->signal_event_ == NULL) { | 153 condition->signal_event_ == NULL) { |
114 pthread_cond_destroy(condition); | 154 pthread_cond_destroy(condition); |
115 return 1; | 155 return 1; |
116 } | 156 } |
| 157 #endif |
117 return 0; | 158 return 0; |
118 } | 159 } |
119 | 160 |
120 static int pthread_cond_signal(pthread_cond_t* const condition) { | 161 static int pthread_cond_signal(pthread_cond_t* const condition) { |
121 int ok = 1; | 162 int ok = 1; |
| 163 #ifdef USE_WINDOWS_CONDITION_VARIABLE |
| 164 WakeConditionVariable(condition); |
| 165 #else |
122 if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) { | 166 if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) { |
123 // a thread is waiting in pthread_cond_wait: allow it to be notified | 167 // a thread is waiting in pthread_cond_wait: allow it to be notified |
124 ok = SetEvent(condition->signal_event_); | 168 ok = SetEvent(condition->signal_event_); |
125 // wait until the event is consumed so the signaler cannot consume | 169 // wait until the event is consumed so the signaler cannot consume |
126 // the event via its own pthread_cond_wait. | 170 // the event via its own pthread_cond_wait. |
127 ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) != | 171 ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) != |
128 WAIT_OBJECT_0); | 172 WAIT_OBJECT_0); |
129 } | 173 } |
| 174 #endif |
130 return !ok; | 175 return !ok; |
131 } | 176 } |
132 | 177 |
133 static int pthread_cond_wait(pthread_cond_t* const condition, | 178 static int pthread_cond_wait(pthread_cond_t* const condition, |
134 pthread_mutex_t* const mutex) { | 179 pthread_mutex_t* const mutex) { |
135 int ok; | 180 int ok; |
| 181 #ifdef USE_WINDOWS_CONDITION_VARIABLE |
| 182 ok = SleepConditionVariableCS(condition, mutex, INFINITE); |
| 183 #else |
136 // note that there is a consumer available so the signal isn't dropped in | 184 // note that there is a consumer available so the signal isn't dropped in |
137 // pthread_cond_signal | 185 // pthread_cond_signal |
138 if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL)) | 186 if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL)) |
139 return 1; | 187 return 1; |
140 // now unlock the mutex so pthread_cond_signal may be issued | 188 // now unlock the mutex so pthread_cond_signal may be issued |
141 pthread_mutex_unlock(mutex); | 189 pthread_mutex_unlock(mutex); |
142 ok = (WaitForSingleObject(condition->signal_event_, INFINITE) == | 190 ok = (WaitForSingleObject(condition->signal_event_, INFINITE) == |
143 WAIT_OBJECT_0); | 191 WAIT_OBJECT_0); |
144 ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL); | 192 ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL); |
145 pthread_mutex_lock(mutex); | 193 pthread_mutex_lock(mutex); |
| 194 #endif |
146 return !ok; | 195 return !ok; |
147 } | 196 } |
148 | 197 |
149 #else // !_WIN32 | 198 #else // !_WIN32 |
150 # define THREADFN void* | 199 # define THREADFN void* |
151 # define THREAD_RETURN(val) val | 200 # define THREAD_RETURN(val) val |
152 #endif // _WIN32 | 201 #endif // _WIN32 |
153 | 202 |
154 //------------------------------------------------------------------------------ | 203 //------------------------------------------------------------------------------ |
155 | 204 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 } | 349 } |
301 g_worker_interface = *winterface; | 350 g_worker_interface = *winterface; |
302 return 1; | 351 return 1; |
303 } | 352 } |
304 | 353 |
305 const WebPWorkerInterface* WebPGetWorkerInterface(void) { | 354 const WebPWorkerInterface* WebPGetWorkerInterface(void) { |
306 return &g_worker_interface; | 355 return &g_worker_interface; |
307 } | 356 } |
308 | 357 |
309 //------------------------------------------------------------------------------ | 358 //------------------------------------------------------------------------------ |
OLD | NEW |