1/* 2 * Copyright (c) 2011 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10#include "vpx_config.h" 11 12#if CONFIG_MULTITHREAD && defined(_WIN32) 13#include <windows.h> 14#include <stdlib.h> 15static void once(void (*func)(void)) 16{ 17 static CRITICAL_SECTION *lock; 18 static LONG waiters; 19 static int done; 20 void *lock_ptr = &lock; 21 22 /* If the initialization is complete, return early. This isn't just an 23 * optimization, it prevents races on the destruction of the global 24 * lock. 25 */ 26 if(done) 27 return; 28 29 InterlockedIncrement(&waiters); 30 31 /* Get a lock. We create one and try to make it the one-true-lock, 32 * throwing it away if we lost the race. 33 */ 34 35 { 36 /* Scope to protect access to new_lock */ 37 CRITICAL_SECTION *new_lock = malloc(sizeof(CRITICAL_SECTION)); 38 InitializeCriticalSection(new_lock); 39 if (InterlockedCompareExchangePointer(lock_ptr, new_lock, NULL) != NULL) 40 { 41 DeleteCriticalSection(new_lock); 42 free(new_lock); 43 } 44 } 45 46 /* At this point, we have a lock that can be synchronized on. We don't 47 * care which thread actually performed the allocation. 48 */ 49 50 EnterCriticalSection(lock); 51 52 if (!done) 53 { 54 func(); 55 done = 1; 56 } 57 58 LeaveCriticalSection(lock); 59 60 /* Last one out should free resources. The destructed objects are 61 * protected by checking if(done) above. 62 */ 63 if(!InterlockedDecrement(&waiters)) 64 { 65 DeleteCriticalSection(lock); 66 free(lock); 67 lock = NULL; 68 } 69} 70 71 72#elif CONFIG_MULTITHREAD && HAVE_PTHREAD_H 73#include <pthread.h> 74static void once(void (*func)(void)) 75{ 76 static pthread_once_t lock = PTHREAD_ONCE_INIT; 77 pthread_once(&lock, func); 78} 79 80 81#else 82/* No-op version that performs no synchronization. vp8_rtcd() is idempotent, 83 * so as long as your platform provides atomic loads/stores of pointers 84 * no synchronization is strictly necessary. 85 */ 86 87static void once(void (*func)(void)) 88{ 89 static int done; 90 91 if(!done) 92 { 93 func(); 94 done = 1; 95 } 96} 97#endif 98