| 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 |