media/libvpx/vpx_ports/vpx_once.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libvpx/vpx_ports/vpx_once.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,102 @@
     1.4 +/*
     1.5 + *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
     1.6 + *
     1.7 + *  Use of this source code is governed by a BSD-style license
     1.8 + *  that can be found in the LICENSE file in the root of the source
     1.9 + *  tree. An additional intellectual property rights grant can be found
    1.10 + *  in the file PATENTS.  All contributing project authors may
    1.11 + *  be found in the AUTHORS file in the root of the source tree.
    1.12 + */
    1.13 +#ifndef VPX_ONCE_H
    1.14 +#define VPX_ONCE_H
    1.15 +
    1.16 +#include "vpx_config.h"
    1.17 +
    1.18 +#if CONFIG_MULTITHREAD && defined(_WIN32)
    1.19 +#include <windows.h>
    1.20 +#include <stdlib.h>
    1.21 +static void once(void (*func)(void))
    1.22 +{
    1.23 +    static CRITICAL_SECTION *lock;
    1.24 +    static LONG waiters;
    1.25 +    static int done;
    1.26 +    void *lock_ptr = &lock;
    1.27 +
    1.28 +    /* If the initialization is complete, return early. This isn't just an
    1.29 +     * optimization, it prevents races on the destruction of the global
    1.30 +     * lock.
    1.31 +     */
    1.32 +    if(done)
    1.33 +        return;
    1.34 +
    1.35 +    InterlockedIncrement(&waiters);
    1.36 +
    1.37 +    /* Get a lock. We create one and try to make it the one-true-lock,
    1.38 +     * throwing it away if we lost the race.
    1.39 +     */
    1.40 +
    1.41 +    {
    1.42 +        /* Scope to protect access to new_lock */
    1.43 +        CRITICAL_SECTION *new_lock = malloc(sizeof(CRITICAL_SECTION));
    1.44 +        InitializeCriticalSection(new_lock);
    1.45 +        if (InterlockedCompareExchangePointer(lock_ptr, new_lock, NULL) != NULL)
    1.46 +        {
    1.47 +            DeleteCriticalSection(new_lock);
    1.48 +            free(new_lock);
    1.49 +        }
    1.50 +    }
    1.51 +
    1.52 +    /* At this point, we have a lock that can be synchronized on. We don't
    1.53 +     * care which thread actually performed the allocation.
    1.54 +     */
    1.55 +
    1.56 +    EnterCriticalSection(lock);
    1.57 +
    1.58 +    if (!done)
    1.59 +    {
    1.60 +        func();
    1.61 +        done = 1;
    1.62 +    }
    1.63 +
    1.64 +    LeaveCriticalSection(lock);
    1.65 +
    1.66 +    /* Last one out should free resources. The destructed objects are
    1.67 +     * protected by checking if(done) above.
    1.68 +     */
    1.69 +    if(!InterlockedDecrement(&waiters))
    1.70 +    {
    1.71 +        DeleteCriticalSection(lock);
    1.72 +        free(lock);
    1.73 +        lock = NULL;
    1.74 +    }
    1.75 +}
    1.76 +
    1.77 +
    1.78 +#elif CONFIG_MULTITHREAD && HAVE_PTHREAD_H
    1.79 +#include <pthread.h>
    1.80 +static void once(void (*func)(void))
    1.81 +{
    1.82 +    static pthread_once_t lock = PTHREAD_ONCE_INIT;
    1.83 +    pthread_once(&lock, func);
    1.84 +}
    1.85 +
    1.86 +
    1.87 +#else
    1.88 +/* No-op version that performs no synchronization. vp8_rtcd() is idempotent,
    1.89 + * so as long as your platform provides atomic loads/stores of pointers
    1.90 + * no synchronization is strictly necessary.
    1.91 + */
    1.92 +
    1.93 +static void once(void (*func)(void))
    1.94 +{
    1.95 +    static int done;
    1.96 +
    1.97 +    if(!done)
    1.98 +    {
    1.99 +        func();
   1.100 +        done = 1;
   1.101 +    }
   1.102 +}
   1.103 +#endif
   1.104 +
   1.105 +#endif

mercurial