aom_once.h (2240B)
1 /* 2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved. 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 12 #ifndef AOM_AOM_PORTS_AOM_ONCE_H_ 13 #define AOM_AOM_PORTS_AOM_ONCE_H_ 14 15 #include "config/aom_config.h" 16 17 /* Implement a function wrapper to guarantee initialization 18 * thread-safety for library singletons. 19 * 20 * NOTE: This function uses static locks, and can only be 21 * used with one common argument per compilation unit. So 22 * 23 * file1.c: 24 * aom_once(foo); 25 * ... 26 * aom_once(foo); 27 * 28 * file2.c: 29 * aom_once(bar); 30 * 31 * will ensure foo() and bar() are each called only once, but in 32 * 33 * file1.c: 34 * aom_once(foo); 35 * aom_once(bar): 36 * 37 * bar() will never be called because the lock is used up 38 * by the call to foo(). 39 */ 40 41 #if CONFIG_MULTITHREAD && defined(_WIN32) 42 #undef WIN32_LEAN_AND_MEAN 43 #define WIN32_LEAN_AND_MEAN 44 #include <windows.h> 45 /* Declare a per-compilation-unit state variable to track the progress 46 * of calling func() only once. This must be at global scope because 47 * local initializers are not thread-safe in MSVC prior to Visual 48 * Studio 2015. 49 */ 50 static INIT_ONCE aom_init_once = INIT_ONCE_STATIC_INIT; 51 52 static void aom_once(void (*func)(void)) { 53 BOOL pending; 54 InitOnceBeginInitialize(&aom_init_once, 0, &pending, NULL); 55 if (!pending) { 56 // Initialization has already completed. 57 return; 58 } 59 func(); 60 InitOnceComplete(&aom_init_once, 0, NULL); 61 } 62 63 #elif CONFIG_MULTITHREAD && HAVE_PTHREAD_H 64 #include <pthread.h> 65 static void aom_once(void (*func)(void)) { 66 static pthread_once_t lock = PTHREAD_ONCE_INIT; 67 pthread_once(&lock, func); 68 } 69 70 #else 71 /* Default version that performs no synchronization. */ 72 73 static void aom_once(void (*func)(void)) { 74 static volatile int done; 75 76 if (!done) { 77 func(); 78 done = 1; 79 } 80 } 81 #endif 82 83 #endif // AOM_AOM_PORTS_AOM_ONCE_H_