/*
******************************************************************************
*
-* Copyright (C) 1997-2003, International Business Machines
+* Copyright (C) 1997-2010, International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
//
// UMTX myMutex;
//
-// int InitializeMyMutex()
-// {
-// umtx_init( &myMutex );
-// return 0;
-// }
-//
-// static int initializeMyMutex = InitializeMyMutex();
-//
// void Function(int arg1, int arg2)
// {
// static Object* foo; // Shared read-write object
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;
+
+ /**
+ * 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<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;
+ 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 }
+
+/**
+ * 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<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
#endif //_MUTEX_