]> git.saurik.com Git - apple/icu.git/blob - icuSources/common/umutex.h
ICU-511.35.tar.gz
[apple/icu.git] / icuSources / common / umutex.h
1 /*
2 **********************************************************************
3 * Copyright (C) 1997-2012, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
6 *
7 * File UMUTEX.H
8 *
9 * Modification History:
10 *
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 ******************************************************************************
16 */
17
18 #ifndef UMUTEX_H
19 #define UMUTEX_H
20
21 #include "unicode/utypes.h"
22 #include "unicode/uclean.h"
23 #include "putilimp.h"
24
25 /* For _ReadWriteBarrier(). */
26 #if defined(_MSC_VER) && _MSC_VER >= 1500
27 # include <intrin.h>
28 #endif
29
30 /* For CRITICAL_SECTION */
31 #if U_PLATFORM_HAS_WIN32_API
32 #if 0
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.
38 */
39 # define WIN32_LEAN_AND_MEAN
40 # define VC_EXTRALEAN
41 # define NOUSER
42 # define NOSERVICE
43 # define NOIME
44 # define NOMCX
45 # include <windows.h>
46 #endif /* 0 */
47 #define U_WINDOWS_CRIT_SEC_SIZE 64
48 #endif /* win32 */
49
50 #if U_PLATFORM_IS_DARWIN_BASED
51 #if defined(__STRICT_ANSI__)
52 #define UPRV_REMAP_INLINE
53 #define inline
54 #endif
55 #include <libkern/OSAtomic.h>
56 #define USE_MAC_OS_ATOMIC_INCREMENT 1
57 #if defined(UPRV_REMAP_INLINE)
58 #undef inline
59 #undef UPRV_REMAP_INLINE
60 #endif
61 #endif
62
63 /*
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
67 */
68 #ifndef ANNOTATE_HAPPENS_BEFORE
69 # define ANNOTATE_HAPPENS_BEFORE(obj)
70 # define ANNOTATE_HAPPENS_AFTER(obj)
71 # define ANNOTATE_UNPROTECTED_READ(x) (x)
72 #endif
73
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();
82 # else
83 # define UMTX_FULL_BARRIER \
84 { \
85 umtx_lock(NULL); \
86 umtx_unlock(NULL); \
87 }
88 # endif
89 #endif
90
91 #ifndef UMTX_ACQUIRE_BARRIER
92 # define UMTX_ACQUIRE_BARRIER UMTX_FULL_BARRIER
93 #endif
94
95 #ifndef UMTX_RELEASE_BARRIER
96 # define UMTX_RELEASE_BARRIER UMTX_FULL_BARRIER
97 #endif
98
99 /**
100 * \def UMTX_CHECK
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.
110 *
111 * @internal
112 */
113 #define UMTX_CHECK(pMutex, expression, result) \
114 { \
115 (result)=(expression); \
116 UMTX_ACQUIRE_BARRIER; \
117 }
118 /*
119 * TODO: Replace all uses of UMTX_CHECK and surrounding code
120 * with SimpleSingleton or TriStateSingleton, and remove UMTX_CHECK.
121 */
122
123 /*
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.
127 *
128 * For example:
129 *
130 * void Function(int arg1, int arg2)
131 * {
132 * static Object* foo; // Shared read-write object
133 * umtx_lock(NULL); // Lock the ICU global mutex
134 * foo->Method();
135 * umtx_unlock(NULL);
136 * }
137 *
138 * an alternative C++ mutex API is defined in the file common/mutex.h
139 */
140
141 /*
142 * UMutex - Mutexes for use by ICU implementation code.
143 * Must be declared as static or globals. They cannot appear as members
144 * of other objects.
145 * UMutex structs must be initialized.
146 * Example:
147 * static UMutex = U_MUTEX_INITIALIZER;
148 * The declaration of struct UMutex is platform dependent.
149 */
150
151
152 #if U_PLATFORM_HAS_WIN32_API
153
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.
157 */
158 typedef struct U_INIT_ONCE {
159 long fState;
160 void *fContext;
161 } U_INIT_ONCE;
162 #define U_INIT_ONCE_STATIC_INIT {0, NULL}
163
164 typedef struct UMutex {
165 U_INIT_ONCE fInitOnce;
166 UMTX fUserMutex;
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
170 * directly here. */
171 char fCS[U_WINDOWS_CRIT_SEC_SIZE];
172 } UMutex;
173
174 /* Initializer for a static UMUTEX. Deliberately contains no value for the
175 * CRITICAL_SECTION.
176 */
177 #define U_MUTEX_INITIALIZER {U_INIT_ONCE_STATIC_INIT, NULL, FALSE}
178
179 #elif U_PLATFORM_IMPLEMENTS_POSIX
180 #include <pthread.h>
181
182 struct UMutex {
183 pthread_mutex_t fMutex;
184 UMTX fUserMutex;
185 UBool fInitialized;
186 };
187 #define U_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, NULL, FALSE}
188
189 #else
190 /* Unknow platform type. */
191 struct UMutex {
192 void *fMutex;
193 };
194 #define U_MUTEX_INITIALIZER {NULL}
195 #error Unknown Platform.
196
197 #endif
198
199 #if (U_PLATFORM != U_PF_CYGWIN && U_PLATFORM != U_PF_MINGW) || defined(CYGWINMSVC)
200 typedef struct UMutex UMutex;
201 #endif
202
203 /* Lock a mutex.
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.
207 */
208 U_CAPI void U_EXPORT2 umtx_lock(UMutex* mutex);
209
210 /* Unlock a mutex.
211 * @param mutex The given mutex to be unlocked. Pass NULL to specify
212 * the global ICU mutex.
213 */
214 U_CAPI void U_EXPORT2 umtx_unlock (UMutex* mutex);
215
216 /*
217 * Atomic Increment and Decrement of an int32_t value.
218 *
219 * Return Values:
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.
224 */
225 U_CAPI int32_t U_EXPORT2 umtx_atomic_inc(int32_t *);
226 U_CAPI int32_t U_EXPORT2 umtx_atomic_dec(int32_t *);
227
228 #endif /*_CMUTEX*/
229 /*eof*/