00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00029 #ifndef AVCODEC_W32PTHREADS_H
00030 #define AVCODEC_W32PTHREADS_H
00031
00032
00033
00034
00035
00036
00037
00038 #define WIN32_LEAN_AND_MEAN
00039 #include <windows.h>
00040 #include <process.h>
00041
00042 #include "libavutil/common.h"
00043 #include "libavutil/internal.h"
00044 #include "libavutil/mem.h"
00045
00046 typedef struct {
00047 void *handle;
00048 void *(*func)(void* arg);
00049 void *arg;
00050 void *ret;
00051 } pthread_t;
00052
00053
00054
00055 typedef CRITICAL_SECTION pthread_mutex_t;
00056
00057
00058
00059
00060 typedef struct {
00061 void *ptr;
00062 } pthread_cond_t;
00063
00064
00065 static void (WINAPI *cond_broadcast)(pthread_cond_t *cond);
00066 static void (WINAPI *cond_init)(pthread_cond_t *cond);
00067 static void (WINAPI *cond_signal)(pthread_cond_t *cond);
00068 static BOOL (WINAPI *cond_wait)(pthread_cond_t *cond, pthread_mutex_t *mutex,
00069 DWORD milliseconds);
00070
00071 static unsigned __stdcall attribute_align_arg win32thread_worker(void *arg)
00072 {
00073 pthread_t *h = arg;
00074 h->ret = h->func(h->arg);
00075 return 0;
00076 }
00077
00078 static int pthread_create(pthread_t *thread, const void *unused_attr,
00079 void *(*start_routine)(void*), void *arg)
00080 {
00081 thread->func = start_routine;
00082 thread->arg = arg;
00083 thread->handle = (void*)_beginthreadex(NULL, 0, win32thread_worker, thread,
00084 0, NULL);
00085 return !thread->handle;
00086 }
00087
00088 static void pthread_join(pthread_t thread, void **value_ptr)
00089 {
00090 DWORD ret = WaitForSingleObject(thread.handle, INFINITE);
00091 if (ret != WAIT_OBJECT_0)
00092 return;
00093 if (value_ptr)
00094 *value_ptr = thread.ret;
00095 CloseHandle(thread.handle);
00096 }
00097
00098 static inline int pthread_mutex_init(pthread_mutex_t *m, void* attr)
00099 {
00100 InitializeCriticalSection(m);
00101 return 0;
00102 }
00103 static inline int pthread_mutex_destroy(pthread_mutex_t *m)
00104 {
00105 DeleteCriticalSection(m);
00106 return 0;
00107 }
00108 static inline int pthread_mutex_lock(pthread_mutex_t *m)
00109 {
00110 EnterCriticalSection(m);
00111 return 0;
00112 }
00113 static inline int pthread_mutex_unlock(pthread_mutex_t *m)
00114 {
00115 LeaveCriticalSection(m);
00116 return 0;
00117 }
00118
00119
00120
00121 typedef struct {
00122 pthread_mutex_t mtx_broadcast;
00123 pthread_mutex_t mtx_waiter_count;
00124 volatile int waiter_count;
00125 HANDLE semaphore;
00126 HANDLE waiters_done;
00127 volatile int is_broadcast;
00128 } win32_cond_t;
00129
00130 static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr)
00131 {
00132 win32_cond_t *win32_cond = NULL;
00133 if (cond_init) {
00134 cond_init(cond);
00135 return;
00136 }
00137
00138
00139 win32_cond = av_mallocz(sizeof(win32_cond_t));
00140 if (!win32_cond)
00141 return;
00142 cond->ptr = win32_cond;
00143 win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
00144 if (!win32_cond->semaphore)
00145 return;
00146 win32_cond->waiters_done = CreateEvent(NULL, TRUE, FALSE, NULL);
00147 if (!win32_cond->waiters_done)
00148 return;
00149
00150 pthread_mutex_init(&win32_cond->mtx_waiter_count, NULL);
00151 pthread_mutex_init(&win32_cond->mtx_broadcast, NULL);
00152 }
00153
00154 static void pthread_cond_destroy(pthread_cond_t *cond)
00155 {
00156 win32_cond_t *win32_cond = cond->ptr;
00157
00158 if (cond_init)
00159 return;
00160
00161
00162 CloseHandle(win32_cond->semaphore);
00163 CloseHandle(win32_cond->waiters_done);
00164 pthread_mutex_destroy(&win32_cond->mtx_waiter_count);
00165 pthread_mutex_destroy(&win32_cond->mtx_broadcast);
00166 av_freep(&win32_cond);
00167 cond->ptr = NULL;
00168 }
00169
00170 static void pthread_cond_broadcast(pthread_cond_t *cond)
00171 {
00172 win32_cond_t *win32_cond = cond->ptr;
00173 int have_waiter;
00174
00175 if (cond_broadcast) {
00176 cond_broadcast(cond);
00177 return;
00178 }
00179
00180
00181 pthread_mutex_lock(&win32_cond->mtx_broadcast);
00182 pthread_mutex_lock(&win32_cond->mtx_waiter_count);
00183 have_waiter = 0;
00184
00185 if (win32_cond->waiter_count) {
00186 win32_cond->is_broadcast = 1;
00187 have_waiter = 1;
00188 }
00189
00190 if (have_waiter) {
00191 ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL);
00192 pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
00193 WaitForSingleObject(win32_cond->waiters_done, INFINITE);
00194 ResetEvent(win32_cond->waiters_done);
00195 win32_cond->is_broadcast = 0;
00196 } else
00197 pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
00198 pthread_mutex_unlock(&win32_cond->mtx_broadcast);
00199 }
00200
00201 static int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
00202 {
00203 win32_cond_t *win32_cond = cond->ptr;
00204 int last_waiter;
00205 if (cond_wait) {
00206 cond_wait(cond, mutex, INFINITE);
00207 return 0;
00208 }
00209
00210
00211 pthread_mutex_lock(&win32_cond->mtx_broadcast);
00212 pthread_mutex_lock(&win32_cond->mtx_waiter_count);
00213 win32_cond->waiter_count++;
00214 pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
00215 pthread_mutex_unlock(&win32_cond->mtx_broadcast);
00216
00217
00218 pthread_mutex_unlock(mutex);
00219 WaitForSingleObject(win32_cond->semaphore, INFINITE);
00220
00221 pthread_mutex_lock(&win32_cond->mtx_waiter_count);
00222 win32_cond->waiter_count--;
00223 last_waiter = !win32_cond->waiter_count || !win32_cond->is_broadcast;
00224 pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
00225
00226 if (last_waiter)
00227 SetEvent(win32_cond->waiters_done);
00228
00229
00230 return pthread_mutex_lock(mutex);
00231 }
00232
00233 static void pthread_cond_signal(pthread_cond_t *cond)
00234 {
00235 win32_cond_t *win32_cond = cond->ptr;
00236 int have_waiter;
00237 if (cond_signal) {
00238 cond_signal(cond);
00239 return;
00240 }
00241
00242 pthread_mutex_lock(&win32_cond->mtx_broadcast);
00243
00244
00245 pthread_mutex_lock(&win32_cond->mtx_waiter_count);
00246 have_waiter = win32_cond->waiter_count;
00247 pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
00248
00249 if (have_waiter) {
00250 ReleaseSemaphore(win32_cond->semaphore, 1, NULL);
00251 WaitForSingleObject(win32_cond->waiters_done, INFINITE);
00252 ResetEvent(win32_cond->waiters_done);
00253 }
00254
00255 pthread_mutex_unlock(&win32_cond->mtx_broadcast);
00256 }
00257
00258 static void w32thread_init(void)
00259 {
00260 HANDLE kernel_dll = GetModuleHandle(TEXT("kernel32.dll"));
00261
00262 cond_init =
00263 (void*)GetProcAddress(kernel_dll, "InitializeConditionVariable");
00264 cond_broadcast =
00265 (void*)GetProcAddress(kernel_dll, "WakeAllConditionVariable");
00266 cond_signal =
00267 (void*)GetProcAddress(kernel_dll, "WakeConditionVariable");
00268 cond_wait =
00269 (void*)GetProcAddress(kernel_dll, "SleepConditionVariableCS");
00270 }
00271
00272 #endif