(file) Return to once.h CVS log (file) (dir) Up to [OMI] / omi / pal

File: [OMI] / omi / pal / once.h (download)
Revision: 1.1, Mon Apr 20 17:19:55 2015 UTC (9 years ago) by krisbash
Branch: MAIN
CVS Tags: OMI_1_0_8_2, OMI_1_0_8_1, HEAD
OMI 1.0.8-1

#ifndef _pal_once_h
#define _pal_once_h

#include "palcommon.h"
#include "atomic.h"

#ifdef _MSC_VER
#include <intrin.h>
#endif

PAL_BEGIN_EXTERNC

typedef struct _Once
{
    void* value;
}
Once;

#define ONCE_STATE_INVOKING         -2 
#define ONCE_STATE_NOTINVOKEDYET    -1

#define ONCE_INITIALIZER { (void*)ONCE_STATE_NOTINVOKEDYET }

typedef _Success_(return == 0) int (*OnceWorkerFunction)(
    _In_ void* data,
    _Outptr_result_maybenull_ void** value);

int __Once_Invoke(
    _Inout_ Once* self,
    _In_ OnceWorkerFunction func,
    _In_ void* data);

PAL_INLINE int Once_Invoke(
    _Inout_ Once* self,
    _In_ OnceWorkerFunction func,
    _In_ void* data)
{
    int result = 0;
    void* value = self->value;

/* To prevent confusing behavior, disallow compiler reordering. */
#if defined(_MSC_VER)
    _ReadBarrier();
#elif defined(__GNUC__)
    asm volatile("" ::: "memory");
#else
    /* Nothing. */
#endif

    if ((size_t)value >= (size_t)ONCE_STATE_INVOKING)
        result = __Once_Invoke(self, func, data);

    return result;
}

/* All callers to Once_Invoke (except _WithBarrier) must dereference
 * initialized data through this macro. */
#define Once_Invoke_Value(self) ((self)->value)

PAL_INLINE int Once_Invoke_WithBarrier(
    _Inout_ Once* self,
    _In_ OnceWorkerFunction func,
    _In_ void* data)
{
    int result = Once_Invoke(self, func, data);

    NonX86MemoryBarrier();
    return result;
}

PAL_END_EXTERNC

#endif /* _pal_once_h */

ViewCVS 0.9.2