+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
******************************************************************************
*
-* Copyright (C) 1997-2012, International Business Machines
+* Copyright (C) 1997-2013, International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
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:
-//
-// 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!!
-//
+/**
+ * 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:
+ *
+ * UMutex *myMutex() {
+ * static UMutex *m = STATIC_NEW(UMutex);
+ * return m;
+ * }
+ *
+ * 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(UMutex *mutex = NULL);
- inline ~Mutex();
-
-private:
- UMutex *fMutex;
+ Mutex(UMutex *mutex = nullptr) : fMutex(mutex) {
+ umtx_lock(fMutex);
+ };
+ ~Mutex() {
+ umtx_unlock(fMutex);
+ };
- Mutex(const Mutex &other); // forbid copying of this class
- Mutex &operator=(const Mutex &other); // forbid copying of this class
-};
-
-inline Mutex::Mutex(UMutex *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(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.
- /**
- * 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 a 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<typename T>
-class SimpleSingletonWrapper {
-public:
- SimpleSingletonWrapper(SimpleSingleton &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:
- 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;
-
- /**
- * 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();
+ UMutex *fMutex;
};
-#define STATIC_TRI_STATE_SINGLETON(name) static TriStateSingleton name={ NULL, U_ZERO_ERROR }
-
-/**
- * Handy wrapper for a 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<typename T>
-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;
-};
U_NAMESPACE_END