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 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 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 196 U_NAMESPACE_END 197 198 #endif //_MUTEX_ 199 //eof 200