Add sse2/ssse3 intra predictors for 4x16
[aom.git] / aom_ports / aom_once.h
blob3cfd2fd95824f950023e486540e5f2552662cf72
1 /*
2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
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.
12 #ifndef AOM_PORTS_AOM_ONCE_H_
13 #define AOM_PORTS_AOM_ONCE_H_
15 #include "aom_config.h"
17 /* Implement a function wrapper to guarantee initialization
18 * thread-safety for library singletons.
20 * NOTE: These functions use static locks, and can only be
21 * used with one common argument per compilation unit. So
23 * file1.c:
24 * aom_once(foo);
25 * ...
26 * aom_once(foo);
28 * file2.c:
29 * aom_once(bar);
31 * will ensure foo() and bar() are each called only once, but in
33 * file1.c:
34 * aom_once(foo);
35 * aom_once(bar):
37 * bar() will never be called because the lock is used up
38 * by the call to foo().
41 #if CONFIG_MULTITHREAD && defined(_WIN32)
42 #include <windows.h>
43 #include <stdlib.h>
44 /* Declare a per-compilation-unit state variable to track the progress
45 * of calling func() only once. This must be at global scope because
46 * local initializers are not thread-safe in MSVC prior to Visual
47 * Studio 2015.
49 * As a static, once_state will be zero-initialized as program start.
51 static LONG once_state;
52 static void once(void (*func)(void)) {
53 /* Try to advance once_state from its initial value of 0 to 1.
54 * Only one thread can succeed in doing so.
56 if (InterlockedCompareExchange(&once_state, 1, 0) == 0) {
57 /* We're the winning thread, having set once_state to 1.
58 * Call our function. */
59 func();
60 /* Now advance once_state to 2, unblocking any other threads. */
61 InterlockedIncrement(&once_state);
62 return;
65 /* We weren't the winning thread, but we want to block on
66 * the state variable so we don't return before func()
67 * has finished executing elsewhere.
69 * Try to advance once_state from 2 to 2, which is only possible
70 * after the winning thead advances it from 1 to 2.
72 while (InterlockedCompareExchange(&once_state, 2, 2) != 2) {
73 /* State isn't yet 2. Try again.
75 * We are used for singleton initialization functions,
76 * which should complete quickly. Contention will likewise
77 * be rare, so it's worthwhile to use a simple but cpu-
78 * intensive busy-wait instead of successive backoff,
79 * waiting on a kernel object, or another heavier-weight scheme.
81 * We can at least yield our timeslice.
83 Sleep(0);
86 /* We've seen once_state advance to 2, so we know func()
87 * has been called. And we've left once_state as we found it,
88 * so other threads will have the same experience.
90 * It's safe to return now.
92 return;
95 #elif CONFIG_MULTITHREAD && defined(__OS2__)
96 #define INCL_DOS
97 #include <os2.h>
98 static void once(void (*func)(void)) {
99 static int done;
101 /* If the initialization is complete, return early. */
102 if (done) return;
104 /* Causes all other threads in the process to block themselves
105 * and give up their time slice.
107 DosEnterCritSec();
109 if (!done) {
110 func();
111 done = 1;
114 /* Restores normal thread dispatching for the current process. */
115 DosExitCritSec();
118 #elif CONFIG_MULTITHREAD && HAVE_PTHREAD_H
119 #include <pthread.h>
120 static void once(void (*func)(void)) {
121 static pthread_once_t lock = PTHREAD_ONCE_INIT;
122 pthread_once(&lock, func);
125 #else
126 /* No-op version that performs no synchronization. *_rtcd() is idempotent,
127 * so as long as your platform provides atomic loads/stores of pointers
128 * no synchronization is strictly necessary.
131 static void once(void (*func)(void)) {
132 static int done;
134 if (!done) {
135 func();
136 done = 1;
139 #endif
141 #endif // AOM_PORTS_AOM_ONCE_H_