]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/mutex.h
ICU-461.18.tar.gz
[apple/icu.git] / icuSources / common / mutex.h
index 26aefbf86b58aedd58cafddc5796c85e9900ac1e..ea2e3485d8da0921372687bea7e423c0fef06c37 100644 (file)
@@ -1,7 +1,7 @@
 /*
 ******************************************************************************
 *
-*   Copyright (C) 1997-2003, International Business Machines
+*   Copyright (C) 1997-2010, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 ******************************************************************************
@@ -35,14 +35,6 @@ U_NAMESPACE_BEGIN
 // 
 // 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
@@ -79,6 +71,128 @@ 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;
+
+    /**
+     * 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_