diff options
-rw-r--r-- | vp8/common/rtcd.c | 91 |
1 files changed, 83 insertions, 8 deletions
diff --git a/vp8/common/rtcd.c b/vp8/common/rtcd.c index a7bb92ce4..01dad4691 100644 --- a/vp8/common/rtcd.c +++ b/vp8/common/rtcd.c @@ -11,20 +11,95 @@ #define RTCD_C #include "vpx_rtcd.h" +#if CONFIG_MULTITHREAD && defined(_WIN32) +#include <windows.h> +#include <stdlib.h> +static void once(void (*func)(void)) +{ + static CRITICAL_SECTION *lock; + static LONG waiters; + static int done; + void *lock_ptr = &lock; + + /* If the initialization is complete, return early. This isn't just an + * optimization, it prevents races on the destruction of the global + * lock. + */ + if(done) + return; + + InterlockedIncrement(&waiters); + + /* Get a lock. We create one and try to make it the one-true-lock, + * throwing it away if we lost the race. + */ + + { + /* Scope to protect access to new_lock */ + CRITICAL_SECTION *new_lock = malloc(sizeof(CRITICAL_SECTION)); + InitializeCriticalSection(new_lock); + if (InterlockedCompareExchangePointer(lock_ptr, new_lock, NULL) != NULL) + { + DeleteCriticalSection(new_lock); + free(new_lock); + } + } + + /* At this point, we have a lock that can be synchronized on. We don't + * care which thread actually performed the allocation. + */ + + EnterCriticalSection(lock); + + if (!done) + { + func(); + done = 1; + } + + LeaveCriticalSection(lock); + + /* Last one out should free resources. The destructed objects are + * protected by checking if(done) above. + */ + if(!InterlockedDecrement(&waiters)) + { + DeleteCriticalSection(lock); + free(lock); + lock = NULL; + } +} + + +#elif CONFIG_MULTITHREAD && HAVE_PTHREAD_H +#include <pthread.h> +static void once(void (*func)(void)) +{ + static pthread_once_t lock = PTHREAD_ONCE_INIT; + pthread_once(&lock, func); +} + + +#else /* No-op version that performs no synchronization. vpx_rtcd() is idempotent, * so as long as your platform provides atomic loads/stores of pointers * no synchronization is strictly necessary. */ -static void once(void (*func)(void)) { - static int done; +static void once(void (*func)(void)) +{ + static int done; - if(!done) { - func(); - done = 1; - } + if(!done) + { + func(); + done = 1; + } } +#endif + -void vpx_rtcd() { - once(setup_rtcd_internal); +void vpx_rtcd() +{ + once(setup_rtcd_internal); } |