1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* 2233d2500723e5594f3e7c70896ffeeef32b9c950ywan * Copyright (c) 2011 The WebM project authors. All Rights Reserved. 3233d2500723e5594f3e7c70896ffeeef32b9c950ywan * 4233d2500723e5594f3e7c70896ffeeef32b9c950ywan * Use of this source code is governed by a BSD-style license 5233d2500723e5594f3e7c70896ffeeef32b9c950ywan * that can be found in the LICENSE file in the root of the source 6233d2500723e5594f3e7c70896ffeeef32b9c950ywan * tree. An additional intellectual property rights grant can be found 7233d2500723e5594f3e7c70896ffeeef32b9c950ywan * in the file PATENTS. All contributing project authors may 8233d2500723e5594f3e7c70896ffeeef32b9c950ywan * be found in the AUTHORS file in the root of the source tree. 9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 10233d2500723e5594f3e7c70896ffeeef32b9c950ywan 11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifndef VPX_PORTS_VPX_ONCE_H_ 12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define VPX_PORTS_VPX_ONCE_H_ 13233d2500723e5594f3e7c70896ffeeef32b9c950ywan 14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_config.h" 15233d2500723e5594f3e7c70896ffeeef32b9c950ywan 16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if CONFIG_MULTITHREAD && defined(_WIN32) 17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <windows.h> 18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdlib.h> 19233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void once(void (*func)(void)) 20233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 21233d2500723e5594f3e7c70896ffeeef32b9c950ywan static CRITICAL_SECTION *lock; 22233d2500723e5594f3e7c70896ffeeef32b9c950ywan static LONG waiters; 23233d2500723e5594f3e7c70896ffeeef32b9c950ywan static int done; 24233d2500723e5594f3e7c70896ffeeef32b9c950ywan void *lock_ptr = &lock; 25233d2500723e5594f3e7c70896ffeeef32b9c950ywan 26233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* If the initialization is complete, return early. This isn't just an 27233d2500723e5594f3e7c70896ffeeef32b9c950ywan * optimization, it prevents races on the destruction of the global 28233d2500723e5594f3e7c70896ffeeef32b9c950ywan * lock. 29233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 30233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(done) 31233d2500723e5594f3e7c70896ffeeef32b9c950ywan return; 32233d2500723e5594f3e7c70896ffeeef32b9c950ywan 33233d2500723e5594f3e7c70896ffeeef32b9c950ywan InterlockedIncrement(&waiters); 34233d2500723e5594f3e7c70896ffeeef32b9c950ywan 35233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Get a lock. We create one and try to make it the one-true-lock, 36233d2500723e5594f3e7c70896ffeeef32b9c950ywan * throwing it away if we lost the race. 37233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 38233d2500723e5594f3e7c70896ffeeef32b9c950ywan 39233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 40233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Scope to protect access to new_lock */ 41233d2500723e5594f3e7c70896ffeeef32b9c950ywan CRITICAL_SECTION *new_lock = malloc(sizeof(CRITICAL_SECTION)); 42233d2500723e5594f3e7c70896ffeeef32b9c950ywan InitializeCriticalSection(new_lock); 43233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (InterlockedCompareExchangePointer(lock_ptr, new_lock, NULL) != NULL) 44233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 45233d2500723e5594f3e7c70896ffeeef32b9c950ywan DeleteCriticalSection(new_lock); 46233d2500723e5594f3e7c70896ffeeef32b9c950ywan free(new_lock); 47233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 48233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 49233d2500723e5594f3e7c70896ffeeef32b9c950ywan 50233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* At this point, we have a lock that can be synchronized on. We don't 51233d2500723e5594f3e7c70896ffeeef32b9c950ywan * care which thread actually performed the allocation. 52233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 53233d2500723e5594f3e7c70896ffeeef32b9c950ywan 54233d2500723e5594f3e7c70896ffeeef32b9c950ywan EnterCriticalSection(lock); 55233d2500723e5594f3e7c70896ffeeef32b9c950ywan 56233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!done) 57233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 58233d2500723e5594f3e7c70896ffeeef32b9c950ywan func(); 59233d2500723e5594f3e7c70896ffeeef32b9c950ywan done = 1; 60233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 61233d2500723e5594f3e7c70896ffeeef32b9c950ywan 62233d2500723e5594f3e7c70896ffeeef32b9c950ywan LeaveCriticalSection(lock); 63233d2500723e5594f3e7c70896ffeeef32b9c950ywan 64233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Last one out should free resources. The destructed objects are 65233d2500723e5594f3e7c70896ffeeef32b9c950ywan * protected by checking if(done) above. 66233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 67233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(!InterlockedDecrement(&waiters)) 68233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 69233d2500723e5594f3e7c70896ffeeef32b9c950ywan DeleteCriticalSection(lock); 70233d2500723e5594f3e7c70896ffeeef32b9c950ywan free(lock); 71233d2500723e5594f3e7c70896ffeeef32b9c950ywan lock = NULL; 72233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 73233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 74233d2500723e5594f3e7c70896ffeeef32b9c950ywan 75233d2500723e5594f3e7c70896ffeeef32b9c950ywan 76233d2500723e5594f3e7c70896ffeeef32b9c950ywan#elif CONFIG_MULTITHREAD && HAVE_PTHREAD_H 77233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <pthread.h> 78233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void once(void (*func)(void)) 79233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 80233d2500723e5594f3e7c70896ffeeef32b9c950ywan static pthread_once_t lock = PTHREAD_ONCE_INIT; 81233d2500723e5594f3e7c70896ffeeef32b9c950ywan pthread_once(&lock, func); 82233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 83233d2500723e5594f3e7c70896ffeeef32b9c950ywan 84233d2500723e5594f3e7c70896ffeeef32b9c950ywan 85233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else 86233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* No-op version that performs no synchronization. vp8_rtcd() is idempotent, 87233d2500723e5594f3e7c70896ffeeef32b9c950ywan * so as long as your platform provides atomic loads/stores of pointers 88233d2500723e5594f3e7c70896ffeeef32b9c950ywan * no synchronization is strictly necessary. 89233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 90233d2500723e5594f3e7c70896ffeeef32b9c950ywan 91233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void once(void (*func)(void)) 92233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 93233d2500723e5594f3e7c70896ffeeef32b9c950ywan static int done; 94233d2500723e5594f3e7c70896ffeeef32b9c950ywan 95233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(!done) 96233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 97233d2500723e5594f3e7c70896ffeeef32b9c950ywan func(); 98233d2500723e5594f3e7c70896ffeeef32b9c950ywan done = 1; 99233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 100233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 101233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 102233d2500723e5594f3e7c70896ffeeef32b9c950ywan 103233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif // VPX_PORTS_VPX_ONCE_H_ 104