]> git.saurik.com Git - apple/icu.git/blob - icuSources/common/umutex.h
ICU-491.11.1.tar.gz
[apple/icu.git] / icuSources / common / umutex.h
1 /*
2 **********************************************************************
3 * Copyright (C) 1997-2011, 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 #if defined(_MSC_VER) && _MSC_VER >= 1500
26 # include <intrin.h>
27 #endif
28
29 #if U_PLATFORM_IS_DARWIN_BASED
30 #if defined(__STRICT_ANSI__)
31 #define UPRV_REMAP_INLINE
32 #define inline
33 #endif
34 #include <libkern/OSAtomic.h>
35 #define USE_MAC_OS_ATOMIC_INCREMENT 1
36 #if defined(UPRV_REMAP_INLINE)
37 #undef inline
38 #undef UPRV_REMAP_INLINE
39 #endif
40 #endif
41
42 /*
43 * If we do not compile with dynamic_annotations.h then define
44 * empty annotation macros.
45 * See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations
46 */
47 #ifndef ANNOTATE_HAPPENS_BEFORE
48 # define ANNOTATE_HAPPENS_BEFORE(obj)
49 # define ANNOTATE_HAPPENS_AFTER(obj)
50 # define ANNOTATE_UNPROTECTED_READ(x) (x)
51 #endif
52
53 #ifndef UMTX_FULL_BARRIER
54 # if !ICU_USE_THREADS
55 # define UMTX_FULL_BARRIER
56 # elif U_HAVE_GCC_ATOMICS
57 # define UMTX_FULL_BARRIER __sync_synchronize();
58 # elif defined(_MSC_VER) && _MSC_VER >= 1500
59 /* From MSVC intrin.h. Use _ReadWriteBarrier() only on MSVC 9 and higher. */
60 # define UMTX_FULL_BARRIER _ReadWriteBarrier();
61 # elif U_PLATFORM_IS_DARWIN_BASED
62 # define UMTX_FULL_BARRIER OSMemoryBarrier();
63 # else
64 # define UMTX_FULL_BARRIER \
65 { \
66 umtx_lock(NULL); \
67 umtx_unlock(NULL); \
68 }
69 # endif
70 #endif
71
72 #ifndef UMTX_ACQUIRE_BARRIER
73 # define UMTX_ACQUIRE_BARRIER UMTX_FULL_BARRIER
74 #endif
75
76 #ifndef UMTX_RELEASE_BARRIER
77 # define UMTX_RELEASE_BARRIER UMTX_FULL_BARRIER
78 #endif
79
80 /**
81 * \def UMTX_CHECK
82 * Encapsulates a safe check of an expression
83 * for use with double-checked lazy inititialization.
84 * Either memory barriers or mutexes are required, to prevent both the hardware
85 * and the compiler from reordering operations across the check.
86 * The expression must involve only a _single_ variable, typically
87 * a possibly null pointer or a boolean that indicates whether some service
88 * is initialized or not.
89 * The setting of the variable involved in the test must be the last step of
90 * the initialization process.
91 *
92 * @internal
93 */
94 #define UMTX_CHECK(pMutex, expression, result) \
95 { \
96 (result)=(expression); \
97 UMTX_ACQUIRE_BARRIER; \
98 }
99 /*
100 * TODO: Replace all uses of UMTX_CHECK and surrounding code
101 * with SimpleSingleton or TriStateSingleton, and remove UMTX_CHECK.
102 */
103
104 /*
105 * Code within ICU that accesses shared static or global data should
106 * instantiate a Mutex object while doing so. The unnamed global mutex
107 * is used throughout ICU, so keep locking short and sweet.
108 *
109 * For example:
110 *
111 * void Function(int arg1, int arg2)
112 * {
113 * static Object* foo; // Shared read-write object
114 * umtx_lock(NULL); // Lock the ICU global mutex
115 * foo->Method();
116 * umtx_unlock(NULL);
117 * }
118 *
119 * an alternative C++ mutex API is defined in the file common/mutex.h
120 */
121
122 /* Lock a mutex.
123 * @param mutex The given mutex to be locked. Pass NULL to specify
124 * the global ICU mutex. Recursive locks are an error
125 * and may cause a deadlock on some platforms.
126 */
127 U_CAPI void U_EXPORT2 umtx_lock ( UMTX* mutex );
128
129 /* Unlock a mutex. Pass in NULL if you want the single global
130 mutex.
131 * @param mutex The given mutex to be unlocked. Pass NULL to specify
132 * the global ICU mutex.
133 */
134 U_CAPI void U_EXPORT2 umtx_unlock ( UMTX* mutex );
135
136 /* Initialize a mutex. Use it this way:
137 umtx_init( &aMutex );
138 * ICU Mutexes do not need explicit initialization before use. Use of this
139 * function is not necessary.
140 * Initialization of an already initialized mutex has no effect, and is safe to do.
141 * Initialization of mutexes is thread safe. Two threads can concurrently
142 * initialize the same mutex without causing problems.
143 * @param mutex The given mutex to be initialized
144 */
145 U_CAPI void U_EXPORT2 umtx_init ( UMTX* mutex );
146
147 /* Destroy a mutex. This will free the resources of a mutex.
148 * Use it this way:
149 * umtx_destroy( &aMutex );
150 * Destroying an already destroyed mutex has no effect, and causes no problems.
151 * This function is not thread safe. Two threads must not attempt to concurrently
152 * destroy the same mutex.
153 * @param mutex The given mutex to be destroyed.
154 */
155 U_CAPI void U_EXPORT2 umtx_destroy( UMTX *mutex );
156
157 /*
158 * Atomic Increment and Decrement of an int32_t value.
159 *
160 * Return Values:
161 * If the result of the operation is zero, the return zero.
162 * If the result of the operation is not zero, the sign of returned value
163 * is the same as the sign of the result, but the returned value itself may
164 * be different from the result of the operation.
165 */
166 U_CAPI int32_t U_EXPORT2 umtx_atomic_inc(int32_t *);
167 U_CAPI int32_t U_EXPORT2 umtx_atomic_dec(int32_t *);
168
169 #endif /*_CMUTEX*/
170 /*eof*/