OLD | NEW |
(Empty) | |
| 1 /* |
| 2 ****************************************************************************** |
| 3 * |
| 4 * Copyright (C) 1997-2010, International Business Machines |
| 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 //---------------------------------------------------------------------------- |
| 30 // Code within that accesses shared static or global data should |
| 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 // |
| 38 // void Function(int arg1, int arg2) |
| 39 // { |
| 40 // static Object* foo; // Shared read-write object |
| 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 rel
eased |
| 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 throu
gh 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 |
| 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 err
or, |
| 88 * otherwise use a TriStateSingleton. |
| 89 * Best used via SimpleSingletonWrapper or similar. |
| 90 * Define a static SimpleSingleton instance via the STATIC_SIMPLE_SINGLETON macr
o. |
| 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 t
o 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 |
| 196 U_NAMESPACE_END |
| 197 |
| 198 #endif //_MUTEX_ |
| 199 //eof |
OLD | NEW |