]> git.saurik.com Git - apple/icu.git/blame - icuSources/common/umutex.cpp
ICU-64260.0.1.tar.gz
[apple/icu.git] / icuSources / common / umutex.cpp
CommitLineData
f3c0d7a5
A
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
51004dcb
A
3/*
4******************************************************************************
5*
f3c0d7a5 6* Copyright (C) 1997-2016, International Business Machines
51004dcb
A
7* Corporation and others. All Rights Reserved.
8*
9******************************************************************************
10*
11* File umutex.cpp
12*
13* Modification History:
14*
15* Date Name Description
16* 04/02/97 aliu Creation.
17* 04/07/99 srl updated
18* 05/13/99 stephen Changed to umutex (from cmutex).
19* 11/22/99 aliu Make non-global mutex autoinitialize [j151]
20******************************************************************************
21*/
22
57a6839d
A
23#include "umutex.h"
24
51004dcb
A
25#include "unicode/utypes.h"
26#include "uassert.h"
57a6839d 27#include "cmemory.h"
51004dcb 28
3d1f044b 29U_NAMESPACE_BEGIN
57a6839d 30
51004dcb 31
57a6839d 32#if defined(U_USER_MUTEX_CPP)
3d1f044b
A
33// Support for including an alternate implementation of mutexes has been withdrawn.
34// See issue ICU-20185.
35#error U_USER_MUTEX_CPP not supported
51004dcb
A
36#endif
37
3d1f044b
A
38/*************************************************************************************************
39 *
40 * ICU Mutex wrappers.
41 *
42 *************************************************************************************************/
51004dcb 43
3d1f044b
A
44// The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer.
45static UMutex *globalMutex() {
46 static UMutex *m = STATIC_NEW(UMutex);
47 return m;
b331163b
A
48}
49
51004dcb
A
50U_CAPI void U_EXPORT2
51umtx_lock(UMutex *mutex) {
3d1f044b
A
52 if (mutex == nullptr) {
53 mutex = globalMutex();
51004dcb 54 }
3d1f044b 55 mutex->fMutex.lock();
51004dcb
A
56}
57
57a6839d 58
51004dcb
A
59U_CAPI void U_EXPORT2
60umtx_unlock(UMutex* mutex)
61{
3d1f044b
A
62 if (mutex == nullptr) {
63 mutex = globalMutex();
51004dcb 64 }
3d1f044b 65 mutex->fMutex.unlock();
51004dcb
A
66}
67
b331163b 68
3d1f044b
A
69/*************************************************************************************************
70 *
71 * UInitOnce Implementation
72 *
73 *************************************************************************************************/
b331163b 74
3d1f044b
A
75static std::mutex &initMutex() {
76 static std::mutex *m = STATIC_NEW(std::mutex);
77 return *m;
b331163b
A
78}
79
3d1f044b
A
80static std::condition_variable &initCondition() {
81 static std::condition_variable *cv = STATIC_NEW(std::condition_variable);
82 return *cv;
b331163b
A
83}
84
85
57a6839d 86// This function is called when a test of a UInitOnce::fState reveals that
3d1f044b 87// initialization has not completed, that we either need to call the init
57a6839d
A
88// function on this thread, or wait for some other thread to complete.
89//
90// The actual call to the init function is made inline by template code
3d1f044b 91// that knows the C++ types involved. This function returns true if
57a6839d
A
92// the caller needs to call the Init function.
93//
94U_COMMON_API UBool U_EXPORT2
95umtx_initImplPreInit(UInitOnce &uio) {
3d1f044b
A
96 std::unique_lock<std::mutex> lock(initMutex());
97
98 if (umtx_loadAcquire(uio.fState) == 0) {
57a6839d 99 umtx_storeRelease(uio.fState, 1);
3d1f044b 100 return true; // Caller will next call the init function.
57a6839d 101 } else {
3d1f044b 102 while (umtx_loadAcquire(uio.fState) == 1) {
57a6839d
A
103 // Another thread is currently running the initialization.
104 // Wait until it completes.
3d1f044b 105 initCondition().wait(lock);
57a6839d 106 }
57a6839d 107 U_ASSERT(uio.fState == 2);
3d1f044b 108 return false;
51004dcb 109 }
57a6839d 110}
51004dcb 111
51004dcb 112
57a6839d
A
113// This function is called by the thread that ran an initialization function,
114// just after completing the function.
115// Some threads may be waiting on the condition, requiring the broadcast wakeup.
116// Some threads may be racing to test the fState variable outside of the mutex,
117// requiring the use of store/release when changing its value.
118
119U_COMMON_API void U_EXPORT2
120umtx_initImplPostInit(UInitOnce &uio) {
3d1f044b
A
121 {
122 std::unique_lock<std::mutex> lock(initMutex());
123 umtx_storeRelease(uio.fState, 2);
124 }
125 initCondition().notify_all();
57a6839d 126}
51004dcb 127
57a6839d 128U_NAMESPACE_END
51004dcb 129
3d1f044b
A
130/*************************************************************************************************
131 *
132 * Deprecated functions for setting user mutexes.
133 *
134 *************************************************************************************************/
51004dcb 135
57a6839d
A
136U_DEPRECATED void U_EXPORT2
137u_setMutexFunctions(const void * /*context */, UMtxInitFn *, UMtxFn *,
138 UMtxFn *, UMtxFn *, UErrorCode *status) {
139 if (U_SUCCESS(*status)) {
140 *status = U_UNSUPPORTED_ERROR;
51004dcb 141 }
57a6839d 142 return;
51004dcb
A
143}
144
145
57a6839d
A
146
147U_DEPRECATED void U_EXPORT2
148u_setAtomicIncDecFunctions(const void * /*context */, UMtxAtomicFn *, UMtxAtomicFn *,
149 UErrorCode *status) {
150 if (U_SUCCESS(*status)) {
151 *status = U_UNSUPPORTED_ERROR;
152 }
153 return;
51004dcb 154}