154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius/*
254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius******************************************************************************
354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*
459d709d503bab6e2b61931737e662dd293b40578ccornelius*   Copyright (C) 1997-2013, International Business Machines
554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*   Corporation and others.  All Rights Reserved.
654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*
754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius******************************************************************************
854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*
954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* File umutex.cpp
1054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*
1154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* Modification History:
1254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*
1354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*   Date        Name        Description
1454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*   04/02/97    aliu        Creation.
1554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*   04/07/99    srl         updated
1654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*   05/13/99    stephen     Changed to umutex (from cmutex).
1754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*   11/22/99    aliu        Make non-global mutex autoinitialize [j151]
1854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius******************************************************************************
1954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*/
2054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
2159d709d503bab6e2b61931737e662dd293b40578ccornelius#include "umutex.h"
2259d709d503bab6e2b61931737e662dd293b40578ccornelius
2354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "unicode/utypes.h"
2454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "uassert.h"
2559d709d503bab6e2b61931737e662dd293b40578ccornelius#include "cmemory.h"
2654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "ucln_cmn.h"
2754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
2859d709d503bab6e2b61931737e662dd293b40578ccornelius
2959d709d503bab6e2b61931737e662dd293b40578ccornelius// The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer.
3059d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic UMutex   globalMutex = U_MUTEX_INITIALIZER;
3159d709d503bab6e2b61931737e662dd293b40578ccornelius
3254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius/*
3354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * ICU Mutex wrappers.  Wrap operating system mutexes, giving the rest of ICU a
3454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * platform independent set of mutex operations.  For internal ICU use only.
3554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius */
3654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
3759d709d503bab6e2b61931737e662dd293b40578ccornelius#if defined(U_USER_MUTEX_CPP)
3859d709d503bab6e2b61931737e662dd293b40578ccornelius// Build time user mutex hook: #include "U_USER_MUTEX_CPP"
3959d709d503bab6e2b61931737e662dd293b40578ccornelius#include U_MUTEX_XSTR(U_USER_MUTEX_CPP)
4054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
4159d709d503bab6e2b61931737e662dd293b40578ccornelius#elif U_PLATFORM_HAS_WIN32_API
4254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
4359d709d503bab6e2b61931737e662dd293b40578ccornelius//-------------------------------------------------------------------------------------------
4459d709d503bab6e2b61931737e662dd293b40578ccornelius//
4559d709d503bab6e2b61931737e662dd293b40578ccornelius//    Windows Specific Definitions
4659d709d503bab6e2b61931737e662dd293b40578ccornelius//
4759d709d503bab6e2b61931737e662dd293b40578ccornelius//        Note: Cygwin (and possibly others) have both WIN32 and POSIX.
4859d709d503bab6e2b61931737e662dd293b40578ccornelius//              Prefer Win32 in these cases.  (Win32 comes ahead in the #if chain)
4959d709d503bab6e2b61931737e662dd293b40578ccornelius//
5059d709d503bab6e2b61931737e662dd293b40578ccornelius//-------------------------------------------------------------------------------------------
5154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
5259d709d503bab6e2b61931737e662dd293b40578ccornelius#if defined U_NO_PLATFORM_ATOMICS
5359d709d503bab6e2b61931737e662dd293b40578ccornelius#error ICU on Win32 requires support for low level atomic operations.
5459d709d503bab6e2b61931737e662dd293b40578ccornelius// Visual Studio, gcc, clang are OK. Shouldn't get here.
5554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#endif
5654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
5754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
5859d709d503bab6e2b61931737e662dd293b40578ccornelius// This function is called when a test of a UInitOnce::fState reveals that
5959d709d503bab6e2b61931737e662dd293b40578ccornelius//   initialization has not completed, that we either need to call the
6059d709d503bab6e2b61931737e662dd293b40578ccornelius//   function on this thread, or wait for some other thread to complete.
6154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//
6259d709d503bab6e2b61931737e662dd293b40578ccornelius// The actual call to the init function is made inline by template code
6359d709d503bab6e2b61931737e662dd293b40578ccornelius//   that knows the C++ types involved. This function returns TRUE if
6459d709d503bab6e2b61931737e662dd293b40578ccornelius//   the caller needs to call the Init function.
6554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//
6654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
6759d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_BEGIN
6854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
6959d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &uio) {
7059d709d503bab6e2b61931737e662dd293b40578ccornelius    for (;;) {
7159d709d503bab6e2b61931737e662dd293b40578ccornelius        int32_t previousState = InterlockedCompareExchange(
7259d709d503bab6e2b61931737e662dd293b40578ccornelius#if (U_PLATFORM == U_PF_MINGW) || (U_PLATFORM == U_PF_CYGWIN)
7359d709d503bab6e2b61931737e662dd293b40578ccornelius           (LONG volatile *) // this is the type given in the API doc for this function.
7459d709d503bab6e2b61931737e662dd293b40578ccornelius#endif
7559d709d503bab6e2b61931737e662dd293b40578ccornelius            &uio.fState,  //  Destination
7659d709d503bab6e2b61931737e662dd293b40578ccornelius            1,            //  Exchange Value
7759d709d503bab6e2b61931737e662dd293b40578ccornelius            0);           //  Compare value
7859d709d503bab6e2b61931737e662dd293b40578ccornelius
7959d709d503bab6e2b61931737e662dd293b40578ccornelius        if (previousState == 0) {
8059d709d503bab6e2b61931737e662dd293b40578ccornelius            return true;   // Caller will next call the init function.
8159d709d503bab6e2b61931737e662dd293b40578ccornelius                           // Current state == 1.
8259d709d503bab6e2b61931737e662dd293b40578ccornelius        } else if (previousState == 2) {
8359d709d503bab6e2b61931737e662dd293b40578ccornelius            // Another thread already completed the initialization.
8459d709d503bab6e2b61931737e662dd293b40578ccornelius            //   We can simply return FALSE, indicating no
8559d709d503bab6e2b61931737e662dd293b40578ccornelius            //   further action is needed by the caller.
8659d709d503bab6e2b61931737e662dd293b40578ccornelius            return FALSE;
8759d709d503bab6e2b61931737e662dd293b40578ccornelius        } else {
8859d709d503bab6e2b61931737e662dd293b40578ccornelius            // Another thread is currently running the initialization.
8959d709d503bab6e2b61931737e662dd293b40578ccornelius            // Wait until it completes.
9059d709d503bab6e2b61931737e662dd293b40578ccornelius            do {
9159d709d503bab6e2b61931737e662dd293b40578ccornelius                Sleep(1);
9259d709d503bab6e2b61931737e662dd293b40578ccornelius                previousState = umtx_loadAcquire(uio.fState);
9359d709d503bab6e2b61931737e662dd293b40578ccornelius            } while (previousState == 1);
9454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        }
9554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
9654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
9754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
9859d709d503bab6e2b61931737e662dd293b40578ccornelius// This function is called by the thread that ran an initialization function,
9959d709d503bab6e2b61931737e662dd293b40578ccornelius// just after completing the function.
10059d709d503bab6e2b61931737e662dd293b40578ccornelius//
10159d709d503bab6e2b61931737e662dd293b40578ccornelius//   success: True:  the inialization succeeded. No further calls to the init
10259d709d503bab6e2b61931737e662dd293b40578ccornelius//                   function will be made.
10359d709d503bab6e2b61931737e662dd293b40578ccornelius//            False: the initializtion failed. The next call to umtx_initOnce()
10459d709d503bab6e2b61931737e662dd293b40578ccornelius//                   will retry the initialization.
10554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
10659d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API void U_EXPORT2 umtx_initImplPostInit(UInitOnce &uio) {
10759d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_storeRelease(uio.fState, 2);
10854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
10954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
11059d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_END
11154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
11259d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void winMutexInit(CRITICAL_SECTION *cs) {
11359d709d503bab6e2b61931737e662dd293b40578ccornelius    InitializeCriticalSection(cs);
11459d709d503bab6e2b61931737e662dd293b40578ccornelius    return;
11559d709d503bab6e2b61931737e662dd293b40578ccornelius}
11654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
11754dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI void  U_EXPORT2
11854dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusumtx_lock(UMutex *mutex) {
11954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if (mutex == NULL) {
12054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        mutex = &globalMutex;
12154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
12259d709d503bab6e2b61931737e662dd293b40578ccornelius    CRITICAL_SECTION *cs = &mutex->fCS;
12359d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(mutex->fInitOnce, winMutexInit, cs);
12459d709d503bab6e2b61931737e662dd293b40578ccornelius    EnterCriticalSection(cs);
12554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
12654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
12754dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI void  U_EXPORT2
12854dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusumtx_unlock(UMutex* mutex)
12954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius{
13054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if (mutex == NULL) {
13154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        mutex = &globalMutex;
13254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
13359d709d503bab6e2b61931737e662dd293b40578ccornelius    LeaveCriticalSection(&mutex->fCS);
13454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
13554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
13659d709d503bab6e2b61931737e662dd293b40578ccornelius#elif U_PLATFORM_IMPLEMENTS_POSIX
13759d709d503bab6e2b61931737e662dd293b40578ccornelius
13859d709d503bab6e2b61931737e662dd293b40578ccornelius//-------------------------------------------------------------------------------------------
13954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//
14059d709d503bab6e2b61931737e662dd293b40578ccornelius//  POSIX specific definitions
14154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//
14259d709d503bab6e2b61931737e662dd293b40578ccornelius//-------------------------------------------------------------------------------------------
14359d709d503bab6e2b61931737e662dd293b40578ccornelius
14459d709d503bab6e2b61931737e662dd293b40578ccornelius# include <pthread.h>
14559d709d503bab6e2b61931737e662dd293b40578ccornelius
14659d709d503bab6e2b61931737e662dd293b40578ccornelius// Each UMutex consists of a pthread_mutex_t.
14759d709d503bab6e2b61931737e662dd293b40578ccornelius// All are statically initialized and ready for use.
14859d709d503bab6e2b61931737e662dd293b40578ccornelius// There is no runtime mutex initialization code needed.
14954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
15054dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI void  U_EXPORT2
15154dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusumtx_lock(UMutex *mutex) {
15254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if (mutex == NULL) {
15354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        mutex = &globalMutex;
15454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
15559d709d503bab6e2b61931737e662dd293b40578ccornelius    int sysErr = pthread_mutex_lock(&mutex->fMutex);
15659d709d503bab6e2b61931737e662dd293b40578ccornelius    (void)sysErr;   // Suppress unused variable warnings.
15759d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(sysErr == 0);
15854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
15954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
16059d709d503bab6e2b61931737e662dd293b40578ccornelius
16154dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI void  U_EXPORT2
16254dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusumtx_unlock(UMutex* mutex)
16354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius{
16454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if (mutex == NULL) {
16554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        mutex = &globalMutex;
16654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
16759d709d503bab6e2b61931737e662dd293b40578ccornelius    int sysErr = pthread_mutex_unlock(&mutex->fMutex);
16859d709d503bab6e2b61931737e662dd293b40578ccornelius    (void)sysErr;   // Suppress unused variable warnings.
16959d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(sysErr == 0);
17054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
17154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
17259d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_BEGIN
17354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
17459d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic pthread_mutex_t initMutex = PTHREAD_MUTEX_INITIALIZER;
17559d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic pthread_cond_t initCondition = PTHREAD_COND_INITIALIZER;
17654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
17754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
17859d709d503bab6e2b61931737e662dd293b40578ccornelius// This function is called when a test of a UInitOnce::fState reveals that
17959d709d503bab6e2b61931737e662dd293b40578ccornelius//   initialization has not completed, that we either need to call the
18059d709d503bab6e2b61931737e662dd293b40578ccornelius//   function on this thread, or wait for some other thread to complete.
18159d709d503bab6e2b61931737e662dd293b40578ccornelius//
18259d709d503bab6e2b61931737e662dd293b40578ccornelius// The actual call to the init function is made inline by template code
18359d709d503bab6e2b61931737e662dd293b40578ccornelius//   that knows the C++ types involved. This function returns TRUE if
18459d709d503bab6e2b61931737e662dd293b40578ccornelius//   the caller needs to call the Init function.
18559d709d503bab6e2b61931737e662dd293b40578ccornelius//
18659d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API UBool U_EXPORT2
18759d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_initImplPreInit(UInitOnce &uio) {
18859d709d503bab6e2b61931737e662dd293b40578ccornelius    pthread_mutex_lock(&initMutex);
18959d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t state = uio.fState;
19059d709d503bab6e2b61931737e662dd293b40578ccornelius    if (state == 0) {
19159d709d503bab6e2b61931737e662dd293b40578ccornelius        umtx_storeRelease(uio.fState, 1);
19259d709d503bab6e2b61931737e662dd293b40578ccornelius        pthread_mutex_unlock(&initMutex);
19359d709d503bab6e2b61931737e662dd293b40578ccornelius        return TRUE;   // Caller will next call the init function.
19459d709d503bab6e2b61931737e662dd293b40578ccornelius    } else {
19559d709d503bab6e2b61931737e662dd293b40578ccornelius        while (uio.fState == 1) {
19659d709d503bab6e2b61931737e662dd293b40578ccornelius            // Another thread is currently running the initialization.
19759d709d503bab6e2b61931737e662dd293b40578ccornelius            // Wait until it completes.
19859d709d503bab6e2b61931737e662dd293b40578ccornelius            pthread_cond_wait(&initCondition, &initMutex);
19959d709d503bab6e2b61931737e662dd293b40578ccornelius        }
20059d709d503bab6e2b61931737e662dd293b40578ccornelius        pthread_mutex_unlock(&initMutex);
20159d709d503bab6e2b61931737e662dd293b40578ccornelius        U_ASSERT(uio.fState == 2);
20259d709d503bab6e2b61931737e662dd293b40578ccornelius        return FALSE;
20354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
20459d709d503bab6e2b61931737e662dd293b40578ccornelius}
20554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
20654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
20759d709d503bab6e2b61931737e662dd293b40578ccornelius
20859d709d503bab6e2b61931737e662dd293b40578ccornelius// This function is called by the thread that ran an initialization function,
20959d709d503bab6e2b61931737e662dd293b40578ccornelius// just after completing the function.
21059d709d503bab6e2b61931737e662dd293b40578ccornelius//   Some threads may be waiting on the condition, requiring the broadcast wakeup.
21159d709d503bab6e2b61931737e662dd293b40578ccornelius//   Some threads may be racing to test the fState variable outside of the mutex,
21259d709d503bab6e2b61931737e662dd293b40578ccornelius//   requiring the use of store/release when changing its value.
21359d709d503bab6e2b61931737e662dd293b40578ccornelius
21459d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API void U_EXPORT2
21559d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_initImplPostInit(UInitOnce &uio) {
21659d709d503bab6e2b61931737e662dd293b40578ccornelius    pthread_mutex_lock(&initMutex);
21759d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_storeRelease(uio.fState, 2);
21859d709d503bab6e2b61931737e662dd293b40578ccornelius    pthread_cond_broadcast(&initCondition);
21959d709d503bab6e2b61931737e662dd293b40578ccornelius    pthread_mutex_unlock(&initMutex);
22054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
22154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
22259d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_END
22354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
22459d709d503bab6e2b61931737e662dd293b40578ccornelius// End of POSIX specific umutex implementation.
22554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
22659d709d503bab6e2b61931737e662dd293b40578ccornelius#else  // Platform #define chain.
22754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
22859d709d503bab6e2b61931737e662dd293b40578ccornelius#error Unknown Platform
22954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
23059d709d503bab6e2b61931737e662dd293b40578ccornelius#endif  // Platform #define chain.
23154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
23254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
23359d709d503bab6e2b61931737e662dd293b40578ccornelius//-------------------------------------------------------------------------------
23459d709d503bab6e2b61931737e662dd293b40578ccornelius//
23559d709d503bab6e2b61931737e662dd293b40578ccornelius//   Atomic Operations, out-of-line versions.
23659d709d503bab6e2b61931737e662dd293b40578ccornelius//                      These are conditional, only defined if better versions
23759d709d503bab6e2b61931737e662dd293b40578ccornelius//                      were not available for the platform.
23859d709d503bab6e2b61931737e662dd293b40578ccornelius//
23959d709d503bab6e2b61931737e662dd293b40578ccornelius//                      These versions are platform neutral.
24059d709d503bab6e2b61931737e662dd293b40578ccornelius//
24159d709d503bab6e2b61931737e662dd293b40578ccornelius//--------------------------------------------------------------------------------
24254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
24359d709d503bab6e2b61931737e662dd293b40578ccornelius#if defined U_NO_PLATFORM_ATOMICS
24454dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex   gIncDecMutex = U_MUTEX_INITIALIZER;
24554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
24659d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_BEGIN
24759d709d503bab6e2b61931737e662dd293b40578ccornelius
24859d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API int32_t U_EXPORT2
24959d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_atomic_inc(u_atomic_int32_t *p)  {
25054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    int32_t retVal;
25159d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_lock(&gIncDecMutex);
25259d709d503bab6e2b61931737e662dd293b40578ccornelius    retVal = ++(*p);
25359d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_unlock(&gIncDecMutex);
25454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    return retVal;
25554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
25654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
25759d709d503bab6e2b61931737e662dd293b40578ccornelius
25859d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API int32_t U_EXPORT2
25959d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_atomic_dec(u_atomic_int32_t *p) {
26054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    int32_t retVal;
26159d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_lock(&gIncDecMutex);
26259d709d503bab6e2b61931737e662dd293b40578ccornelius    retVal = --(*p);
26359d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_unlock(&gIncDecMutex);
26454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    return retVal;
26554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
26654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
26759d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API int32_t U_EXPORT2
26859d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_loadAcquire(u_atomic_int32_t &var) {
26959d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t val = var;
27059d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_lock(&gIncDecMutex);
27159d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_unlock(&gIncDecMutex);
27259d709d503bab6e2b61931737e662dd293b40578ccornelius    return val;
27359d709d503bab6e2b61931737e662dd293b40578ccornelius}
27459d709d503bab6e2b61931737e662dd293b40578ccornelius
27559d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API void U_EXPORT2
27659d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_storeRelease(u_atomic_int32_t &var, int32_t val) {
27759d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_lock(&gIncDecMutex);
27859d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_unlock(&gIncDecMutex);
27959d709d503bab6e2b61931737e662dd293b40578ccornelius    var = val;
28059d709d503bab6e2b61931737e662dd293b40578ccornelius}
28154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
28259d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_END
28359d709d503bab6e2b61931737e662dd293b40578ccornelius#endif
28454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
28559d709d503bab6e2b61931737e662dd293b40578ccornelius//--------------------------------------------------------------------------
28659d709d503bab6e2b61931737e662dd293b40578ccornelius//
28759d709d503bab6e2b61931737e662dd293b40578ccornelius//  Deprecated functions for setting user mutexes.
28859d709d503bab6e2b61931737e662dd293b40578ccornelius//
28959d709d503bab6e2b61931737e662dd293b40578ccornelius//--------------------------------------------------------------------------
29054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
29159d709d503bab6e2b61931737e662dd293b40578ccorneliusU_DEPRECATED void U_EXPORT2
29259d709d503bab6e2b61931737e662dd293b40578ccorneliusu_setMutexFunctions(const void * /*context */, UMtxInitFn *, UMtxFn *,
29359d709d503bab6e2b61931737e662dd293b40578ccornelius                    UMtxFn *,  UMtxFn *, UErrorCode *status) {
29459d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_SUCCESS(*status)) {
29559d709d503bab6e2b61931737e662dd293b40578ccornelius        *status = U_UNSUPPORTED_ERROR;
29654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
29759d709d503bab6e2b61931737e662dd293b40578ccornelius    return;
29854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
29954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
30054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
30159d709d503bab6e2b61931737e662dd293b40578ccornelius
30259d709d503bab6e2b61931737e662dd293b40578ccorneliusU_DEPRECATED void U_EXPORT2
30359d709d503bab6e2b61931737e662dd293b40578ccorneliusu_setAtomicIncDecFunctions(const void * /*context */, UMtxAtomicFn *, UMtxAtomicFn *,
30459d709d503bab6e2b61931737e662dd293b40578ccornelius                           UErrorCode *status) {
30559d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_SUCCESS(*status)) {
30659d709d503bab6e2b61931737e662dd293b40578ccornelius        *status = U_UNSUPPORTED_ERROR;
30759d709d503bab6e2b61931737e662dd293b40578ccornelius    }
30859d709d503bab6e2b61931737e662dd293b40578ccornelius    return;
30954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
310