• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ******************************************************************************
3 *
4 *   Copyright (C) 1997-2011, 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 
Mutex(UMTX * mutex)63 inline Mutex::Mutex(UMTX *mutex)
64   : fMutex(mutex)
65 {
66   umtx_lock(fMutex);
67 }
68 
~Mutex()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      */
resetSimpleSingleton110     void reset() { fInstance=NULL; }
111 };
112 
113 #define STATIC_SIMPLE_SINGLETON(name) static SimpleSingleton name={ NULL }
114 
115 /**
116  * Handy wrapper for a 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:
SimpleSingletonWrapper(SimpleSingleton & s)123     SimpleSingletonWrapper(SimpleSingleton &s) : singleton(s) {}
deleteInstance()124     void deleteInstance() {
125         delete (T *)singleton.fInstance;
126         singleton.reset();
127     }
getInstance(InstantiatorFn * instantiator,const void * context,UErrorCode & errorCode)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 
149     /**
150      * Returns the singleton instance, or NULL if it could not be created.
151      * Calls the instantiator with the context if the instance has not been
152      * created yet. In a race condition, the duplicate may not be NULL.
153      * The caller must delete the duplicate.
154      * The caller need not initialize the duplicate before the call.
155      * The singleton creation is only attempted once. If it fails,
156      * the singleton will then always return NULL.
157      */
158     void *getInstance(InstantiatorFn *instantiator, const void *context,
159                       void *&duplicate,
160                       UErrorCode &errorCode);
161     /**
162      * Resets the fields. The caller must have deleted the singleton instance.
163      * Not mutexed.
164      * Call this from a cleanup function.
165      */
166     void reset();
167 };
168 
169 #define STATIC_TRI_STATE_SINGLETON(name) static TriStateSingleton name={ NULL, U_ZERO_ERROR }
170 
171 /**
172  * Handy wrapper for a TriStateSingleton.
173  * Intended for temporary use on the stack, to make the TriStateSingleton easier to deal with.
174  * Takes care of the duplicate deletion and type casting.
175  */
176 template<typename T>
177 class TriStateSingletonWrapper {
178 public:
TriStateSingletonWrapper(TriStateSingleton & s)179     TriStateSingletonWrapper(TriStateSingleton &s) : singleton(s) {}
deleteInstance()180     void deleteInstance() {
181         delete (T *)singleton.fInstance;
182         singleton.reset();
183     }
getInstance(InstantiatorFn * instantiator,const void * context,UErrorCode & errorCode)184     T *getInstance(InstantiatorFn *instantiator, const void *context,
185                    UErrorCode &errorCode) {
186         void *duplicate;
187         T *instance=(T *)singleton.getInstance(instantiator, context, duplicate, errorCode);
188         delete (T *)duplicate;
189         return instance;
190     }
191 private:
192     TriStateSingleton &singleton;
193 };
194 
195 U_NAMESPACE_END
196 
197 #endif //_MUTEX_
198 //eof
199