]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/umutex.h
2 **********************************************************************
3 * Copyright (C) 1997-2012, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
9 * Modification History:
11 * Date Name Description
12 * 04/02/97 aliu Creation.
13 * 04/07/99 srl rewrite - C interface, multiple mutices
14 * 05/13/99 stephen Changed to umutex (from cmutex)
15 ******************************************************************************
21 #include "unicode/utypes.h"
22 #include "unicode/uclean.h"
25 /* For _ReadWriteBarrier(). */
26 #if defined(_MSC_VER) && _MSC_VER >= 1500
30 /* For CRITICAL_SECTION */
31 #if U_PLATFORM_HAS_WIN32_API
33 /* TODO(andy): Why doesn't windows.h compile in all files? It does in some.
34 * The intent was to include windows.h here, and have struct UMutex
35 * have an embedded CRITICAL_SECTION when building on Windows.
36 * The workaround is to put some char[] storage in UMutex instead,
37 * avoiding the need to include windows.h everwhere this header is included.
39 # define WIN32_LEAN_AND_MEAN
47 #define U_WINDOWS_CRIT_SEC_SIZE 64
50 #if U_PLATFORM_IS_DARWIN_BASED
51 #if defined(__STRICT_ANSI__)
52 #define UPRV_REMAP_INLINE
55 #include <libkern/OSAtomic.h>
56 #define USE_MAC_OS_ATOMIC_INCREMENT 1
57 #if defined(UPRV_REMAP_INLINE)
59 #undef UPRV_REMAP_INLINE
64 * If we do not compile with dynamic_annotations.h then define
65 * empty annotation macros.
66 * See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations
68 #ifndef ANNOTATE_HAPPENS_BEFORE
69 # define ANNOTATE_HAPPENS_BEFORE(obj)
70 # define ANNOTATE_HAPPENS_AFTER(obj)
71 # define ANNOTATE_UNPROTECTED_READ(x) (x)
74 #ifndef UMTX_FULL_BARRIER
75 # if U_HAVE_GCC_ATOMICS
76 # define UMTX_FULL_BARRIER __sync_synchronize();
77 # elif defined(_MSC_VER) && _MSC_VER >= 1500
78 /* From MSVC intrin.h. Use _ReadWriteBarrier() only on MSVC 9 and higher. */
79 # define UMTX_FULL_BARRIER _ReadWriteBarrier();
80 # elif U_PLATFORM_IS_DARWIN_BASED
81 # define UMTX_FULL_BARRIER OSMemoryBarrier();
83 # define UMTX_FULL_BARRIER \
91 #ifndef UMTX_ACQUIRE_BARRIER
92 # define UMTX_ACQUIRE_BARRIER UMTX_FULL_BARRIER
95 #ifndef UMTX_RELEASE_BARRIER
96 # define UMTX_RELEASE_BARRIER UMTX_FULL_BARRIER
101 * Encapsulates a safe check of an expression
102 * for use with double-checked lazy inititialization.
103 * Either memory barriers or mutexes are required, to prevent both the hardware
104 * and the compiler from reordering operations across the check.
105 * The expression must involve only a _single_ variable, typically
106 * a possibly null pointer or a boolean that indicates whether some service
107 * is initialized or not.
108 * The setting of the variable involved in the test must be the last step of
109 * the initialization process.
113 #define UMTX_CHECK(pMutex, expression, result) \
115 (result)=(expression); \
116 UMTX_ACQUIRE_BARRIER; \
119 * TODO: Replace all uses of UMTX_CHECK and surrounding code
120 * with SimpleSingleton or TriStateSingleton, and remove UMTX_CHECK.
124 * Code within ICU that accesses shared static or global data should
125 * instantiate a Mutex object while doing so. The unnamed global mutex
126 * is used throughout ICU, so keep locking short and sweet.
130 * void Function(int arg1, int arg2)
132 * static Object* foo; // Shared read-write object
133 * umtx_lock(NULL); // Lock the ICU global mutex
138 * an alternative C++ mutex API is defined in the file common/mutex.h
142 * UMutex - Mutexes for use by ICU implementation code.
143 * Must be declared as static or globals. They cannot appear as members
145 * UMutex structs must be initialized.
147 * static UMutex = U_MUTEX_INITIALIZER;
148 * The declaration of struct UMutex is platform dependent.
152 #if U_PLATFORM_HAS_WIN32_API
154 /* U_INIT_ONCE mimics the windows API INIT_ONCE, which exists on Windows Vista and newer.
155 * When ICU no longer needs to support older Windows platforms (XP) that do not have
156 * a native INIT_ONCE, switch this implementation over to wrap the native Windows APIs.
158 typedef struct U_INIT_ONCE
{
162 #define U_INIT_ONCE_STATIC_INIT {0, NULL}
164 typedef struct UMutex
{
165 U_INIT_ONCE fInitOnce
;
167 UBool fInitialized
; /* Applies to fUserMutex only. */
168 /* CRITICAL_SECTION fCS; */ /* See note above. Unresolved problems with including
169 * Windows.h, which would allow using CRITICAL_SECTION
171 char fCS
[U_WINDOWS_CRIT_SEC_SIZE
];
174 /* Initializer for a static UMUTEX. Deliberately contains no value for the
177 #define U_MUTEX_INITIALIZER {U_INIT_ONCE_STATIC_INIT, NULL, FALSE}
179 #elif U_PLATFORM_IMPLEMENTS_POSIX
183 pthread_mutex_t fMutex
;
187 #define U_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, NULL, FALSE}
190 /* Unknow platform type. */
194 #define U_MUTEX_INITIALIZER {NULL}
195 #error Unknown Platform.
199 #if (U_PLATFORM != U_PF_CYGWIN && U_PLATFORM != U_PF_MINGW) || defined(CYGWINMSVC)
200 typedef struct UMutex UMutex
;
204 * @param mutex The given mutex to be locked. Pass NULL to specify
205 * the global ICU mutex. Recursive locks are an error
206 * and may cause a deadlock on some platforms.
208 U_CAPI
void U_EXPORT2
umtx_lock(UMutex
* mutex
);
211 * @param mutex The given mutex to be unlocked. Pass NULL to specify
212 * the global ICU mutex.
214 U_CAPI
void U_EXPORT2
umtx_unlock (UMutex
* mutex
);
217 * Atomic Increment and Decrement of an int32_t value.
220 * If the result of the operation is zero, the return zero.
221 * If the result of the operation is not zero, the sign of returned value
222 * is the same as the sign of the result, but the returned value itself may
223 * be different from the result of the operation.
225 U_CAPI
int32_t U_EXPORT2
umtx_atomic_inc(int32_t *);
226 U_CAPI
int32_t U_EXPORT2
umtx_atomic_dec(int32_t *);