X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/729e4ab9bc6618bc3d8a898e575df7f4019e29ca..HEAD:/icuSources/common/mutex.h diff --git a/icuSources/common/mutex.h b/icuSources/common/mutex.h index ea2e3485..44b1f90b 100644 --- a/icuSources/common/mutex.h +++ b/icuSources/common/mutex.h @@ -1,7 +1,9 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /* ****************************************************************************** * -* Copyright (C) 1997-2010, International Business Machines +* Copyright (C) 1997-2013, International Business Machines * Corporation and others. All Rights Reserved. * ****************************************************************************** @@ -26,173 +28,49 @@ U_NAMESPACE_BEGIN -//---------------------------------------------------------------------------- -// Code within that accesses shared static or global data should -// should instantiate a Mutex object while doing so. You should make your own -// private mutex where possible. - -// For example: -// -// UMTX myMutex; -// -// void Function(int arg1, int arg2) -// { -// static Object* foo; // Shared read-write object -// Mutex mutex(&myMutex); // or no args for the global lock -// foo->Method(); -// // When 'mutex' goes out of scope and gets destroyed here, the lock is released -// } -// -// Note: Do NOT use the form 'Mutex mutex();' as that merely forward-declares a function -// returning a Mutex. This is a common mistake which silently slips through the -// compiler!! -// - -class U_COMMON_API Mutex : public UMemory { -public: - inline Mutex(UMTX *mutex = NULL); - inline ~Mutex(); - -private: - UMTX *fMutex; - - Mutex(const Mutex &other); // forbid copying of this class - Mutex &operator=(const Mutex &other); // forbid copying of this class -}; - -inline Mutex::Mutex(UMTX *mutex) - : fMutex(mutex) -{ - umtx_lock(fMutex); -} - -inline Mutex::~Mutex() -{ - umtx_unlock(fMutex); -} - -// common code for singletons ---------------------------------------------- *** - -/** - * Function pointer for the instantiator parameter of - * SimpleSingleton::getInstance() and TriStateSingleton::getInstance(). - * The function creates some object, optionally using the context parameter. - * The function need not check for U_FAILURE(errorCode). - */ -typedef void *InstantiatorFn(const void *context, UErrorCode &errorCode); - /** - * Singleton struct with shared instantiation/mutexing code. - * Simple: Does not remember if a previous instantiation failed. - * Best used if the instantiation can really only fail with an out-of-memory error, - * otherwise use a TriStateSingleton. - * Best used via SimpleSingletonWrapper or similar. - * Define a static SimpleSingleton instance via the STATIC_SIMPLE_SINGLETON macro. - */ -struct SimpleSingleton { - void *fInstance; + * Mutex is a helper class for convenient locking and unlocking of a UMutex. + * + * Creating a local scope Mutex will lock a UMutex, holding the lock until the Mutex + * goes out of scope. + * + * If no UMutex is specified, the ICU global mutex is implied. + * + * For example: + * + * static UMutex myMutex; + * + * void Function(int arg1, int arg2) + * { + * static Object* foo; // Shared read-write object + * Mutex mutex(&myMutex); // or no args for the global lock + * foo->Method(); + * // When 'mutex' goes out of scope and gets destroyed here, the lock is released + * } + * + * Note: Do NOT use the form 'Mutex mutex();' as that merely forward-declares a function + * returning a Mutex. This is a common mistake which silently slips through the + * compiler!! + */ - /** - * Returns the singleton instance, or NULL if it could not be created. - * Calls the instantiator with the context if the instance has not been - * created yet. In a race condition, the duplicate may not be NULL. - * The caller must delete the duplicate. - * The caller need not initialize the duplicate before the call. - */ - void *getInstance(InstantiatorFn *instantiator, const void *context, - void *&duplicate, - UErrorCode &errorCode); - /** - * Resets the fields. The caller must have deleted the singleton instance. - * Not mutexed. - * Call this from a cleanup function. - */ - void reset() { fInstance=NULL; } -}; - -#define STATIC_SIMPLE_SINGLETON(name) static SimpleSingleton name={ NULL } - -/** - * Handy wrapper for an SimpleSingleton. - * Intended for temporary use on the stack, to make the SimpleSingleton easier to deal with. - * Takes care of the duplicate deletion and type casting. - */ -template -class SimpleSingletonWrapper { +class U_COMMON_API Mutex : public UMemory { public: - SimpleSingletonWrapper(SimpleSingleton &s) : singleton(s) {} - void deleteInstance() { - delete (T *)singleton.fInstance; - singleton.reset(); + Mutex(UMutex *mutex = nullptr) : fMutex(mutex) { + umtx_lock(fMutex); } - T *getInstance(InstantiatorFn *instantiator, const void *context, - UErrorCode &errorCode) { - void *duplicate; - T *instance=(T *)singleton.getInstance(instantiator, context, duplicate, errorCode); - delete (T *)duplicate; - return instance; + ~Mutex() { + umtx_unlock(fMutex); } -private: - SimpleSingleton &singleton; -}; - -/** - * Singleton struct with shared instantiation/mutexing code. - * Tri-state: Instantiation succeeded/failed/not attempted yet. - * Best used via TriStateSingletonWrapper or similar. - * Define a static TriStateSingleton instance via the STATIC_TRI_STATE_SINGLETON macro. - */ -struct TriStateSingleton { - void *fInstance; - UErrorCode fErrorCode; - int8_t fHaveInstance; - - /** - * Returns the singleton instance, or NULL if it could not be created. - * Calls the instantiator with the context if the instance has not been - * created yet. In a race condition, the duplicate may not be NULL. - * The caller must delete the duplicate. - * The caller need not initialize the duplicate before the call. - * The singleton creation is only attempted once. If it fails, - * the singleton will then always return NULL. - */ - void *getInstance(InstantiatorFn *instantiator, const void *context, - void *&duplicate, - UErrorCode &errorCode); - /** - * Resets the fields. The caller must have deleted the singleton instance. - * Not mutexed. - * Call this from a cleanup function. - */ - void reset(); -}; -#define STATIC_TRI_STATE_SINGLETON(name) static TriStateSingleton name={ NULL, U_ZERO_ERROR, 0 } + Mutex(const Mutex &other) = delete; // forbid assigning of this class + Mutex &operator=(const Mutex &other) = delete; // forbid copying of this class + void *operator new(size_t s) = delete; // forbid heap allocation. Locals only. -/** - * Handy wrapper for an TriStateSingleton. - * Intended for temporary use on the stack, to make the TriStateSingleton easier to deal with. - * Takes care of the duplicate deletion and type casting. - */ -template -class TriStateSingletonWrapper { -public: - TriStateSingletonWrapper(TriStateSingleton &s) : singleton(s) {} - void deleteInstance() { - delete (T *)singleton.fInstance; - singleton.reset(); - } - T *getInstance(InstantiatorFn *instantiator, const void *context, - UErrorCode &errorCode) { - void *duplicate; - T *instance=(T *)singleton.getInstance(instantiator, context, duplicate, errorCode); - delete (T *)duplicate; - return instance; - } private: - TriStateSingleton &singleton; + UMutex *fMutex; }; + U_NAMESPACE_END #endif //_MUTEX_