OLD | NEW |
1 /* | 1 /* |
2 ****************************************************************************** | 2 ****************************************************************************** |
3 * | 3 * |
4 * Copyright (C) 1997-2013, International Business Machines | 4 * Copyright (C) 1997-2014, International Business Machines |
5 * Corporation and others. All Rights Reserved. | 5 * Corporation and others. All Rights Reserved. |
6 * | 6 * |
7 ****************************************************************************** | 7 ****************************************************************************** |
8 * | 8 * |
9 * File umutex.cpp | 9 * File umutex.cpp |
10 * | 10 * |
11 * Modification History: | 11 * Modification History: |
12 * | 12 * |
13 * Date Name Description | 13 * Date Name Description |
14 * 04/02/97 aliu Creation. | 14 * 04/02/97 aliu Creation. |
15 * 04/07/99 srl updated | 15 * 04/07/99 srl updated |
16 * 05/13/99 stephen Changed to umutex (from cmutex). | 16 * 05/13/99 stephen Changed to umutex (from cmutex). |
17 * 11/22/99 aliu Make non-global mutex autoinitialize [j151] | 17 * 11/22/99 aliu Make non-global mutex autoinitialize [j151] |
18 ****************************************************************************** | 18 ****************************************************************************** |
19 */ | 19 */ |
20 | 20 |
21 #include "umutex.h" | 21 #include "umutex.h" |
22 | 22 |
23 #include "unicode/utypes.h" | 23 #include "unicode/utypes.h" |
24 #include "uassert.h" | 24 #include "uassert.h" |
25 #include "cmemory.h" | 25 #include "cmemory.h" |
26 #include "ucln_cmn.h" | |
27 | 26 |
28 | 27 |
29 // The ICU global mutex. Used when ICU implementation code passes NULL for the m
utex pointer. | 28 // The ICU global mutex. Used when ICU implementation code passes NULL for the m
utex pointer. |
30 static UMutex globalMutex = U_MUTEX_INITIALIZER; | 29 static UMutex globalMutex = U_MUTEX_INITIALIZER; |
31 | 30 |
32 /* | 31 /* |
33 * ICU Mutex wrappers. Wrap operating system mutexes, giving the rest of ICU a | 32 * ICU Mutex wrappers. Wrap operating system mutexes, giving the rest of ICU a |
34 * platform independent set of mutex operations. For internal ICU use only. | 33 * platform independent set of mutex operations. For internal ICU use only. |
35 */ | 34 */ |
36 | 35 |
(...skipping 25 matching lines...) Expand all Loading... |
62 // The actual call to the init function is made inline by template code | 61 // The actual call to the init function is made inline by template code |
63 // that knows the C++ types involved. This function returns TRUE if | 62 // that knows the C++ types involved. This function returns TRUE if |
64 // the caller needs to call the Init function. | 63 // the caller needs to call the Init function. |
65 // | 64 // |
66 | 65 |
67 U_NAMESPACE_BEGIN | 66 U_NAMESPACE_BEGIN |
68 | 67 |
69 U_COMMON_API UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &uio) { | 68 U_COMMON_API UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &uio) { |
70 for (;;) { | 69 for (;;) { |
71 int32_t previousState = InterlockedCompareExchange( | 70 int32_t previousState = InterlockedCompareExchange( |
72 #if (U_PLATFORM == U_PF_MINGW) || (U_PLATFORM == U_PF_CYGWIN) | 71 #if (U_PLATFORM == U_PF_MINGW) || (U_PLATFORM == U_PF_CYGWIN) || defined(__clang
__) |
73 (LONG volatile *) // this is the type given in the API doc for this f
unction. | 72 (LONG volatile *) // this is the type given in the API doc for this f
unction. |
74 #endif | 73 #endif |
75 &uio.fState, // Destination | 74 &uio.fState, // Destination |
76 1, // Exchange Value | 75 1, // Exchange Value |
77 0); // Compare value | 76 0); // Compare value |
78 | 77 |
79 if (previousState == 0) { | 78 if (previousState == 0) { |
80 return true; // Caller will next call the init function. | 79 return true; // Caller will next call the init function. |
81 // Current state == 1. | 80 // Current state == 1. |
82 } else if (previousState == 2) { | 81 } else if (previousState == 2) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 | 125 |
127 U_CAPI void U_EXPORT2 | 126 U_CAPI void U_EXPORT2 |
128 umtx_unlock(UMutex* mutex) | 127 umtx_unlock(UMutex* mutex) |
129 { | 128 { |
130 if (mutex == NULL) { | 129 if (mutex == NULL) { |
131 mutex = &globalMutex; | 130 mutex = &globalMutex; |
132 } | 131 } |
133 LeaveCriticalSection(&mutex->fCS); | 132 LeaveCriticalSection(&mutex->fCS); |
134 } | 133 } |
135 | 134 |
| 135 |
| 136 U_CAPI void U_EXPORT2 |
| 137 umtx_condBroadcast(UConditionVar *condition) { |
| 138 // We require that the associated mutex be held by the caller, |
| 139 // so access to fWaitCount is protected and safe. No other thread can |
| 140 // call condWait() while we are here. |
| 141 if (condition->fWaitCount == 0) { |
| 142 return; |
| 143 } |
| 144 ResetEvent(condition->fExitGate); |
| 145 SetEvent(condition->fEntryGate); |
| 146 } |
| 147 |
| 148 U_CAPI void U_EXPORT2 |
| 149 umtx_condSignal(UConditionVar *condition) { |
| 150 // Function not implemented. There is no immediate requirement from ICU to h
ave it. |
| 151 // Once ICU drops support for Windows XP and Server 2003, ICU Condition Vari
ables will be |
| 152 // changed to be thin wrappers on native Windows CONDITION_VARIABLEs, and th
is function |
| 153 // becomes trivial to provide. |
| 154 U_ASSERT(FALSE); |
| 155 } |
| 156 |
| 157 U_CAPI void U_EXPORT2 |
| 158 umtx_condWait(UConditionVar *condition, UMutex *mutex) { |
| 159 if (condition->fEntryGate == NULL) { |
| 160 // Note: because the associated mutex must be locked when calling |
| 161 // wait, we know that there can not be multiple threads |
| 162 // running here with the same condition variable. |
| 163 // Meaning that lazy initialization is safe. |
| 164 U_ASSERT(condition->fExitGate == NULL); |
| 165 condition->fEntryGate = CreateEvent(NULL, // Security Attributes |
| 166 TRUE, // Manual Reset |
| 167 FALSE, // Initially reset |
| 168 NULL); // Name. |
| 169 U_ASSERT(condition->fEntryGate != NULL); |
| 170 condition->fExitGate = CreateEvent(NULL, TRUE, TRUE, NULL); |
| 171 U_ASSERT(condition->fExitGate != NULL); |
| 172 } |
| 173 |
| 174 condition->fWaitCount++; |
| 175 umtx_unlock(mutex); |
| 176 WaitForSingleObject(condition->fEntryGate, INFINITE); |
| 177 umtx_lock(mutex); |
| 178 condition->fWaitCount--; |
| 179 if (condition->fWaitCount == 0) { |
| 180 // All threads that were waiting at the entry gate have woken up |
| 181 // and moved through. Shut the entry gate and open the exit gate. |
| 182 ResetEvent(condition->fEntryGate); |
| 183 SetEvent(condition->fExitGate); |
| 184 } else { |
| 185 umtx_unlock(mutex); |
| 186 WaitForSingleObject(condition->fExitGate, INFINITE); |
| 187 umtx_lock(mutex); |
| 188 } |
| 189 } |
| 190 |
| 191 |
136 #elif U_PLATFORM_IMPLEMENTS_POSIX | 192 #elif U_PLATFORM_IMPLEMENTS_POSIX |
137 | 193 |
138 //------------------------------------------------------------------------------
------------- | 194 //------------------------------------------------------------------------------
------------- |
139 // | 195 // |
140 // POSIX specific definitions | 196 // POSIX specific definitions |
141 // | 197 // |
142 //------------------------------------------------------------------------------
------------- | 198 //------------------------------------------------------------------------------
------------- |
143 | 199 |
144 # include <pthread.h> | 200 # include <pthread.h> |
145 | 201 |
(...skipping 16 matching lines...) Expand all Loading... |
162 umtx_unlock(UMutex* mutex) | 218 umtx_unlock(UMutex* mutex) |
163 { | 219 { |
164 if (mutex == NULL) { | 220 if (mutex == NULL) { |
165 mutex = &globalMutex; | 221 mutex = &globalMutex; |
166 } | 222 } |
167 int sysErr = pthread_mutex_unlock(&mutex->fMutex); | 223 int sysErr = pthread_mutex_unlock(&mutex->fMutex); |
168 (void)sysErr; // Suppress unused variable warnings. | 224 (void)sysErr; // Suppress unused variable warnings. |
169 U_ASSERT(sysErr == 0); | 225 U_ASSERT(sysErr == 0); |
170 } | 226 } |
171 | 227 |
| 228 |
| 229 U_CAPI void U_EXPORT2 |
| 230 umtx_condWait(UConditionVar *cond, UMutex *mutex) { |
| 231 if (mutex == NULL) { |
| 232 mutex = &globalMutex; |
| 233 } |
| 234 int sysErr = pthread_cond_wait(&cond->fCondition, &mutex->fMutex); |
| 235 (void)sysErr; |
| 236 U_ASSERT(sysErr == 0); |
| 237 } |
| 238 |
| 239 U_CAPI void U_EXPORT2 |
| 240 umtx_condBroadcast(UConditionVar *cond) { |
| 241 int sysErr = pthread_cond_broadcast(&cond->fCondition); |
| 242 (void)sysErr; |
| 243 U_ASSERT(sysErr == 0); |
| 244 } |
| 245 |
| 246 U_CAPI void U_EXPORT2 |
| 247 umtx_condSignal(UConditionVar *cond) { |
| 248 int sysErr = pthread_cond_signal(&cond->fCondition); |
| 249 (void)sysErr; |
| 250 U_ASSERT(sysErr == 0); |
| 251 } |
| 252 |
| 253 |
| 254 |
172 U_NAMESPACE_BEGIN | 255 U_NAMESPACE_BEGIN |
173 | 256 |
174 static pthread_mutex_t initMutex = PTHREAD_MUTEX_INITIALIZER; | 257 static pthread_mutex_t initMutex = PTHREAD_MUTEX_INITIALIZER; |
175 static pthread_cond_t initCondition = PTHREAD_COND_INITIALIZER; | 258 static pthread_cond_t initCondition = PTHREAD_COND_INITIALIZER; |
176 | 259 |
177 | 260 |
178 // This function is called when a test of a UInitOnce::fState reveals that | 261 // This function is called when a test of a UInitOnce::fState reveals that |
179 // initialization has not completed, that we either need to call the | 262 // initialization has not completed, that we either need to call the |
180 // function on this thread, or wait for some other thread to complete. | 263 // function on this thread, or wait for some other thread to complete. |
181 // | 264 // |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 | 383 |
301 | 384 |
302 U_DEPRECATED void U_EXPORT2 | 385 U_DEPRECATED void U_EXPORT2 |
303 u_setAtomicIncDecFunctions(const void * /*context */, UMtxAtomicFn *, UMtxAtomic
Fn *, | 386 u_setAtomicIncDecFunctions(const void * /*context */, UMtxAtomicFn *, UMtxAtomic
Fn *, |
304 UErrorCode *status) { | 387 UErrorCode *status) { |
305 if (U_SUCCESS(*status)) { | 388 if (U_SUCCESS(*status)) { |
306 *status = U_UNSUPPORTED_ERROR; | 389 *status = U_UNSUPPORTED_ERROR; |
307 } | 390 } |
308 return; | 391 return; |
309 } | 392 } |
OLD | NEW |