]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ****************************************************************************** | |
3 | * | |
729e4ab9 | 4 | * Copyright (C) 1997-2010, International Business Machines |
b75a7d8f A |
5 | * Corporation and others. All Rights Reserved. |
6 | * | |
7 | ****************************************************************************** | |
8 | */ | |
9 | //---------------------------------------------------------------------------- | |
10 | // File: mutex.h | |
11 | // | |
12 | // Lightweight C++ wrapper for umtx_ C mutex functions | |
13 | // | |
14 | // Author: Alan Liu 1/31/97 | |
15 | // History: | |
16 | // 06/04/97 helena Updated setImplementation as per feedback from 5/21 drop. | |
17 | // 04/07/1999 srl refocused as a thin wrapper | |
18 | // | |
19 | //---------------------------------------------------------------------------- | |
20 | #ifndef MUTEX_H | |
21 | #define MUTEX_H | |
22 | ||
23 | #include "unicode/utypes.h" | |
24 | #include "unicode/uobject.h" | |
25 | #include "umutex.h" | |
26 | ||
27 | U_NAMESPACE_BEGIN | |
28 | ||
29 | //---------------------------------------------------------------------------- | |
374ca955 | 30 | // Code within that accesses shared static or global data should |
b75a7d8f A |
31 | // should instantiate a Mutex object while doing so. You should make your own |
32 | // private mutex where possible. | |
33 | ||
34 | // For example: | |
35 | // | |
36 | // UMTX myMutex; | |
37 | // | |
b75a7d8f A |
38 | // void Function(int arg1, int arg2) |
39 | // { | |
374ca955 | 40 | // static Object* foo; // Shared read-write object |
b75a7d8f A |
41 | // Mutex mutex(&myMutex); // or no args for the global lock |
42 | // foo->Method(); | |
43 | // // When 'mutex' goes out of scope and gets destroyed here, the lock is released | |
44 | // } | |
45 | // | |
46 | // Note: Do NOT use the form 'Mutex mutex();' as that merely forward-declares a function | |
47 | // returning a Mutex. This is a common mistake which silently slips through the | |
48 | // compiler!! | |
49 | // | |
50 | ||
51 | class U_COMMON_API Mutex : public UMemory { | |
52 | public: | |
53 | inline Mutex(UMTX *mutex = NULL); | |
54 | inline ~Mutex(); | |
55 | ||
56 | private: | |
57 | UMTX *fMutex; | |
58 | ||
59 | Mutex(const Mutex &other); // forbid copying of this class | |
60 | Mutex &operator=(const Mutex &other); // forbid copying of this class | |
61 | }; | |
62 | ||
63 | inline Mutex::Mutex(UMTX *mutex) | |
64 | : fMutex(mutex) | |
65 | { | |
66 | umtx_lock(fMutex); | |
67 | } | |
68 | ||
69 | inline Mutex::~Mutex() | |
70 | { | |
71 | umtx_unlock(fMutex); | |
72 | } | |
73 | ||
729e4ab9 A |
74 | // common code for singletons ---------------------------------------------- *** |
75 | ||
76 | /** | |
77 | * Function pointer for the instantiator parameter of | |
78 | * SimpleSingleton::getInstance() and TriStateSingleton::getInstance(). | |
79 | * The function creates some object, optionally using the context parameter. | |
80 | * The function need not check for U_FAILURE(errorCode). | |
81 | */ | |
82 | typedef void *InstantiatorFn(const void *context, UErrorCode &errorCode); | |
83 | ||
84 | /** | |
85 | * Singleton struct with shared instantiation/mutexing code. | |
86 | * Simple: Does not remember if a previous instantiation failed. | |
87 | * Best used if the instantiation can really only fail with an out-of-memory error, | |
88 | * otherwise use a TriStateSingleton. | |
89 | * Best used via SimpleSingletonWrapper or similar. | |
90 | * Define a static SimpleSingleton instance via the STATIC_SIMPLE_SINGLETON macro. | |
91 | */ | |
92 | struct SimpleSingleton { | |
93 | void *fInstance; | |
94 | ||
95 | /** | |
96 | * Returns the singleton instance, or NULL if it could not be created. | |
97 | * Calls the instantiator with the context if the instance has not been | |
98 | * created yet. In a race condition, the duplicate may not be NULL. | |
99 | * The caller must delete the duplicate. | |
100 | * The caller need not initialize the duplicate before the call. | |
101 | */ | |
102 | void *getInstance(InstantiatorFn *instantiator, const void *context, | |
103 | void *&duplicate, | |
104 | UErrorCode &errorCode); | |
105 | /** | |
106 | * Resets the fields. The caller must have deleted the singleton instance. | |
107 | * Not mutexed. | |
108 | * Call this from a cleanup function. | |
109 | */ | |
110 | void reset() { fInstance=NULL; } | |
111 | }; | |
112 | ||
113 | #define STATIC_SIMPLE_SINGLETON(name) static SimpleSingleton name={ NULL } | |
114 | ||
115 | /** | |
116 | * Handy wrapper for an SimpleSingleton. | |
117 | * Intended for temporary use on the stack, to make the SimpleSingleton easier to deal with. | |
118 | * Takes care of the duplicate deletion and type casting. | |
119 | */ | |
120 | template<typename T> | |
121 | class SimpleSingletonWrapper { | |
122 | public: | |
123 | SimpleSingletonWrapper(SimpleSingleton &s) : singleton(s) {} | |
124 | void deleteInstance() { | |
125 | delete (T *)singleton.fInstance; | |
126 | singleton.reset(); | |
127 | } | |
128 | T *getInstance(InstantiatorFn *instantiator, const void *context, | |
129 | UErrorCode &errorCode) { | |
130 | void *duplicate; | |
131 | T *instance=(T *)singleton.getInstance(instantiator, context, duplicate, errorCode); | |
132 | delete (T *)duplicate; | |
133 | return instance; | |
134 | } | |
135 | private: | |
136 | SimpleSingleton &singleton; | |
137 | }; | |
138 | ||
139 | /** | |
140 | * Singleton struct with shared instantiation/mutexing code. | |
141 | * Tri-state: Instantiation succeeded/failed/not attempted yet. | |
142 | * Best used via TriStateSingletonWrapper or similar. | |
143 | * Define a static TriStateSingleton instance via the STATIC_TRI_STATE_SINGLETON macro. | |
144 | */ | |
145 | struct TriStateSingleton { | |
146 | void *fInstance; | |
147 | UErrorCode fErrorCode; | |
148 | int8_t fHaveInstance; | |
149 | ||
150 | /** | |
151 | * Returns the singleton instance, or NULL if it could not be created. | |
152 | * Calls the instantiator with the context if the instance has not been | |
153 | * created yet. In a race condition, the duplicate may not be NULL. | |
154 | * The caller must delete the duplicate. | |
155 | * The caller need not initialize the duplicate before the call. | |
156 | * The singleton creation is only attempted once. If it fails, | |
157 | * the singleton will then always return NULL. | |
158 | */ | |
159 | void *getInstance(InstantiatorFn *instantiator, const void *context, | |
160 | void *&duplicate, | |
161 | UErrorCode &errorCode); | |
162 | /** | |
163 | * Resets the fields. The caller must have deleted the singleton instance. | |
164 | * Not mutexed. | |
165 | * Call this from a cleanup function. | |
166 | */ | |
167 | void reset(); | |
168 | }; | |
169 | ||
170 | #define STATIC_TRI_STATE_SINGLETON(name) static TriStateSingleton name={ NULL, U_ZERO_ERROR, 0 } | |
171 | ||
172 | /** | |
173 | * Handy wrapper for an TriStateSingleton. | |
174 | * Intended for temporary use on the stack, to make the TriStateSingleton easier to deal with. | |
175 | * Takes care of the duplicate deletion and type casting. | |
176 | */ | |
177 | template<typename T> | |
178 | class TriStateSingletonWrapper { | |
179 | public: | |
180 | TriStateSingletonWrapper(TriStateSingleton &s) : singleton(s) {} | |
181 | void deleteInstance() { | |
182 | delete (T *)singleton.fInstance; | |
183 | singleton.reset(); | |
184 | } | |
185 | T *getInstance(InstantiatorFn *instantiator, const void *context, | |
186 | UErrorCode &errorCode) { | |
187 | void *duplicate; | |
188 | T *instance=(T *)singleton.getInstance(instantiator, context, duplicate, errorCode); | |
189 | delete (T *)duplicate; | |
190 | return instance; | |
191 | } | |
192 | private: | |
193 | TriStateSingleton &singleton; | |
194 | }; | |
195 | ||
b75a7d8f A |
196 | U_NAMESPACE_END |
197 | ||
198 | #endif //_MUTEX_ | |
199 | //eof |