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