From 8e9b5e0b7e50da4f22c75762b163ac676b70e131 Mon Sep 17 00:00:00 2001 From: Andy Heninger Date: Mon, 12 Aug 2013 03:35:22 +0000 Subject: [PATCH] ICU-10301 Remove singleton classes, convert existing usage to UInitOnce X-SVN-Rev: 34032 --- icu4c/source/common/mutex.cpp | 61 ---------- icu4c/source/common/mutex.h | 114 ------------------- icu4c/source/common/normalizer2.cpp | 142 ++++++++++++------------ icu4c/source/common/normalizer2impl.cpp | 84 ++++++-------- icu4c/source/common/normalizer2impl.h | 8 +- icu4c/source/common/uniset_props.cpp | 50 +++------ icu4c/source/common/utrie2.cpp | 6 - icu4c/source/common/utrie2.h | 15 +-- 8 files changed, 126 insertions(+), 354 deletions(-) diff --git a/icu4c/source/common/mutex.cpp b/icu4c/source/common/mutex.cpp index 1742ab57e3e..31740219f76 100644 --- a/icu4c/source/common/mutex.cpp +++ b/icu4c/source/common/mutex.cpp @@ -13,70 +13,9 @@ #include "unicode/utypes.h" #include "mutex.h" -#include "uassert.h" U_NAMESPACE_BEGIN -void *SimpleSingleton::getInstance(InstantiatorFn *instantiator, const void *context, - UErrorCode &errorCode) { - if(U_FAILURE(errorCode)) { - return NULL; - } - if (umtx_loadAcquire(fInitOnce.fState) == 2) { - return fInstance; - } - if (umtx_initImplPreInit(fInitOnce)) { - fInstance = instantiator(context, errorCode); - umtx_initImplPostInit(fInitOnce, fInstance != NULL); - } - return fInstance; -} - - -/* - * Three states: - * - * Initial state: Instance creation not attempted yet. - * fInstance=NULL && U_SUCCESS(fErrorCode) - * - * Instance creation run & succeeded: - * fInstance!=NULL && U_SUCCESS(fErrorCode) - * - * Instance creation & failed: - * fInstance=NULL && U_FAILURE(fErrorCode) - * We will not attempt again to create the instance. - * - * The instantiator function will be called only once, whether it succeeds or fails. - * The controlling state is maintained by the UInitOnce object, not by - * fInstance and fErrorCode. - * The values of fInstance and fErrorCode must only be set between pre and post init(), - * where they are in a controlled memory environment. - */ -void *TriStateSingleton::getInstance(InstantiatorFn *instantiator, const void *context, - UErrorCode &errorCode) { - if(U_FAILURE(errorCode)) { - return NULL; - } - if (umtx_loadAcquire(fInitOnce.fState) == 2) { - errorCode = fErrorCode; - return fInstance; - } - if (umtx_initImplPreInit(fInitOnce)) { - errorCode = U_ZERO_ERROR; - fInstance = instantiator(context, errorCode); - fErrorCode = errorCode; - umtx_initImplPostInit(fInitOnce, TRUE); - } - return fInstance; -} - - -void TriStateSingleton::reset() { - fInstance=NULL; - fErrorCode=U_ZERO_ERROR; - fInitOnce.reset(); -} - #if UCONFIG_NO_SERVICE /* If UCONFIG_NO_SERVICE, then there is no invocation of Mutex elsewhere in diff --git a/icu4c/source/common/mutex.h b/icu4c/source/common/mutex.h index 845a60f59a0..07dcdbbc32f 100644 --- a/icu4c/source/common/mutex.h +++ b/icu4c/source/common/mutex.h @@ -71,120 +71,6 @@ 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; - UInitOnce fInitOnce; - - /** - * 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. - */ - void *getInstance(InstantiatorFn *instantiator, const void *context, - 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; fInitOnce.reset(); } -}; - -#define SIMPLE_SINGLETON_INITIALIZER {NULL, U_INITONCE_INITIALIZER} -#define STATIC_SIMPLE_SINGLETON(name) static SimpleSingleton name = SIMPLE_SINGLETON_INITIALIZER - -/** - * 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 -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) { - T *instance=(T *)singleton.getInstance(instantiator, context, errorCode); - 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; - UInitOnce fInitOnce; - - /** - * 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. - * The singleton creation is only attempted once. If it fails, - * the singleton will then always return NULL. - */ - void *getInstance(InstantiatorFn *instantiator, const void *context, - 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, U_INITONCE_INITIALIZER } - -/** - * 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 -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) { - T *instance=(T *)singleton.getInstance(instantiator, context, errorCode); - return instance; - } -private: - TriStateSingleton &singleton; -}; - U_NAMESPACE_END #endif //_MUTEX_ diff --git a/icu4c/source/common/normalizer2.cpp b/icu4c/source/common/normalizer2.cpp index a2c27dd1426..68936c0c7c7 100644 --- a/icu4c/source/common/normalizer2.cpp +++ b/icu4c/source/common/normalizer2.cpp @@ -1,7 +1,7 @@ /* ******************************************************************************* * -* Copyright (C) 2009-2012, International Business Machines +* Copyright (C) 2009-2013, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* @@ -26,6 +26,7 @@ #include "cstring.h" #include "mutex.h" #include "normalizer2impl.h" +#include "uassert.h" #include "ucln_cmn.h" #include "uhash.h" @@ -450,46 +451,33 @@ U_CDECL_BEGIN static UBool U_CALLCONV uprv_normalizer2_cleanup(); U_CDECL_END -class Norm2AllModesSingleton : public TriStateSingletonWrapper { -public: - Norm2AllModesSingleton(TriStateSingleton &s, const char *n) : - TriStateSingletonWrapper(s), name(n) {} - Norm2AllModes *getInstance(UErrorCode &errorCode) { - return TriStateSingletonWrapper::getInstance(createInstance, name, errorCode); + +static Norm2AllModes *nfcSingleton; +static Norm2AllModes *nfkcSingleton; +static Norm2AllModes *nfkc_cfSingleton; +static Normalizer2 *noopSingleton; +static UHashtable *cache=NULL; + +static UInitOnce nfcInitOnce = U_INITONCE_INITIALIZER; +static UInitOnce nfkcInitOnce = U_INITONCE_INITIALIZER; +static UInitOnce nfkc_cfInitOnce = U_INITONCE_INITIALIZER; +static UInitOnce noopInitOnce = U_INITONCE_INITIALIZER; + +// UInitOnce singleton initialization function +static void U_CALLCONV initSingletons(const char *what, UErrorCode &errorCode) { + if (uprv_strcmp(what, "nfc") == 0) { + nfcSingleton = Norm2AllModes::createInstance(NULL, "nfc", errorCode); + } else if (uprv_strcmp(what, "nfkc") == 0) { + nfkcSingleton = Norm2AllModes::createInstance(NULL, "nfkc", errorCode); + } else if (uprv_strcmp(what, "nfkc_cf") == 0) { + nfkc_cfSingleton = Norm2AllModes::createInstance(NULL, "nfkc_cf", errorCode); + } else if (uprv_strcmp(what, "noop") == 0) { + noopSingleton = new NoopNormalizer2; + } else { + U_ASSERT(FALSE); // Unknown singleton } -private: - static void *createInstance(const void *context, UErrorCode &errorCode) { - ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanup); - return Norm2AllModes::createInstance(NULL, (const char *)context, errorCode); - } - - const char *name; -}; - -STATIC_TRI_STATE_SINGLETON(nfcSingleton); -STATIC_TRI_STATE_SINGLETON(nfkcSingleton); -STATIC_TRI_STATE_SINGLETON(nfkc_cfSingleton); - -class Norm2Singleton : public SimpleSingletonWrapper { -public: - Norm2Singleton(SimpleSingleton &s) : SimpleSingletonWrapper(s) {} - Normalizer2 *getInstance(UErrorCode &errorCode) { - return SimpleSingletonWrapper::getInstance(createInstance, NULL, errorCode); - } -private: - static void *createInstance(const void *, UErrorCode &errorCode) { - Normalizer2 *noop=new NoopNormalizer2; - if(noop==NULL) { - errorCode=U_MEMORY_ALLOCATION_ERROR; - } - ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanup); - return noop; - } -}; - -STATIC_SIMPLE_SINGLETON(noopSingleton); - -static UHashtable *cache=NULL; + ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanup); +} U_CDECL_BEGIN @@ -498,57 +486,63 @@ static void U_CALLCONV deleteNorm2AllModes(void *allModes) { } static UBool U_CALLCONV uprv_normalizer2_cleanup() { - Norm2AllModesSingleton(nfcSingleton, NULL).deleteInstance(); - Norm2AllModesSingleton(nfkcSingleton, NULL).deleteInstance(); - Norm2AllModesSingleton(nfkc_cfSingleton, NULL).deleteInstance(); - Norm2Singleton(noopSingleton).deleteInstance(); + delete nfcSingleton; + nfcSingleton = NULL; + delete nfkcSingleton; + nfkcSingleton = NULL; + delete nfkc_cfSingleton; + nfkc_cfSingleton = NULL; + delete noopSingleton; + noopSingleton = NULL; uhash_close(cache); cache=NULL; + nfcInitOnce.reset(); + nfkcInitOnce.reset(); + nfkc_cfInitOnce.reset(); + noopInitOnce.reset(); return TRUE; } U_CDECL_END const Normalizer2 *Normalizer2Factory::getNFCInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes=Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); - return allModes!=NULL ? &allModes->comp : NULL; + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); + return nfcSingleton!=NULL ? &nfcSingleton->comp : NULL; } const Normalizer2 *Normalizer2Factory::getNFDInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes=Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); - return allModes!=NULL ? &allModes->decomp : NULL; + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); + return nfcSingleton!=NULL ? &nfcSingleton->decomp : NULL; } const Normalizer2 *Normalizer2Factory::getFCDInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes=Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); - return allModes!=NULL ? &allModes->fcd : NULL; + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); + return nfcSingleton!=NULL ? &nfcSingleton->fcd : NULL; } const Normalizer2 *Normalizer2Factory::getFCCInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes=Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); - return allModes!=NULL ? &allModes->fcc : NULL; + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); + return nfcSingleton!=NULL ? &nfcSingleton->fcc : NULL; } const Normalizer2 *Normalizer2Factory::getNFKCInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfkcSingleton, "nfkc").getInstance(errorCode); - return allModes!=NULL ? &allModes->comp : NULL; + umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); + return nfkcSingleton!=NULL ? &nfkcSingleton->comp : NULL; } const Normalizer2 *Normalizer2Factory::getNFKDInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfkcSingleton, "nfkc").getInstance(errorCode); - return allModes!=NULL ? &allModes->decomp : NULL; + umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); + return nfkcSingleton!=NULL ? &nfkcSingleton->decomp : NULL; } const Normalizer2 *Normalizer2Factory::getNFKC_CFInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfkc_cfSingleton, "nfkc_cf").getInstance(errorCode); - return allModes!=NULL ? &allModes->comp : NULL; + umtx_initOnce(nfkc_cfInitOnce, &initSingletons, "nfkc_cf", errorCode); + return nfkc_cfSingleton!=NULL ? &nfkc_cfSingleton->comp : NULL; } const Normalizer2 *Normalizer2Factory::getNoopInstance(UErrorCode &errorCode) { - return Norm2Singleton(noopSingleton).getInstance(errorCode); + umtx_initOnce(noopInitOnce, &initSingletons, "noop", errorCode); + return noopSingleton; } const Normalizer2 * @@ -574,23 +568,20 @@ Normalizer2Factory::getInstance(UNormalizationMode mode, UErrorCode &errorCode) const Normalizer2Impl * Normalizer2Factory::getNFCImpl(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); - return allModes!=NULL ? &allModes->impl : NULL; + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); + return nfcSingleton!=NULL ? &nfcSingleton->impl : NULL; } const Normalizer2Impl * Normalizer2Factory::getNFKCImpl(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfkcSingleton, "nfkc").getInstance(errorCode); - return allModes!=NULL ? &allModes->impl : NULL; + umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); + return nfkcSingleton!=NULL ? &nfkcSingleton->impl : NULL; } const Normalizer2Impl * Normalizer2Factory::getNFKC_CFImpl(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfkc_cfSingleton, "nfkc_cf").getInstance(errorCode); - return allModes!=NULL ? &allModes->impl : NULL; + umtx_initOnce(nfkc_cfInitOnce, &initSingletons, "nfkc_cf", errorCode); + return nfkc_cfSingleton!=NULL ? &nfkc_cfSingleton->impl : NULL; } const Normalizer2Impl * @@ -638,11 +629,14 @@ Normalizer2::getInstance(const char *packageName, Norm2AllModes *allModes=NULL; if(packageName==NULL) { if(0==uprv_strcmp(name, "nfc")) { - allModes=Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); + allModes=nfcSingleton; } else if(0==uprv_strcmp(name, "nfkc")) { - allModes=Norm2AllModesSingleton(nfkcSingleton, "nfkc").getInstance(errorCode); + umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode); + allModes=nfkcSingleton; } else if(0==uprv_strcmp(name, "nfkc_cf")) { - allModes=Norm2AllModesSingleton(nfkc_cfSingleton, "nfkc_cf").getInstance(errorCode); + umtx_initOnce(nfkc_cfInitOnce, &initSingletons, "nfkc_cf", errorCode); + allModes=nfkc_cfSingleton; } } if(allModes==NULL && U_SUCCESS(errorCode)) { diff --git a/icu4c/source/common/normalizer2impl.cpp b/icu4c/source/common/normalizer2impl.cpp index 72221971051..9c00c1c818d 100644 --- a/icu4c/source/common/normalizer2impl.cpp +++ b/icu4c/source/common/normalizer2impl.cpp @@ -255,7 +255,7 @@ struct CanonIterData : public UMemory { Normalizer2Impl::~Normalizer2Impl() { udata_close(memory); utrie2_close(normTrie); - delete (CanonIterData *)canonIterDataSingleton.fInstance; + delete fCanonIterData; } UBool U_CALLCONV @@ -392,8 +392,7 @@ Normalizer2Impl::addCanonIterPropertyStarts(const USetAdder *sa, UErrorCode &err /* add the start code point of each same-value range of the canonical iterator data trie */ if(ensureCanonIterData(errorCode)) { // currently only used for the SEGMENT_STARTER property - utrie2_enum(((CanonIterData *)canonIterDataSingleton.fInstance)->trie, - segmentStarterMapper, enumPropertyStartsRange, sa); + utrie2_enum(fCanonIterData->trie, segmentStarterMapper, enumPropertyStartsRange, sa); } } @@ -1791,58 +1790,44 @@ void CanonIterData::addToStartSet(UChar32 origin, UChar32 decompLead, UErrorCode } } -class CanonIterDataSingleton { -public: - CanonIterDataSingleton(SimpleSingleton &s, Normalizer2Impl &ni, UErrorCode &ec) : - singleton(s), impl(ni), errorCode(ec) {} - CanonIterData *getInstance(UErrorCode &errorCode) { - CanonIterData *instance= - (CanonIterData *)singleton.getInstance(createInstance, this, errorCode); - return instance; - } - static void *createInstance(const void *context, UErrorCode &errorCode); - UBool rangeHandler(UChar32 start, UChar32 end, uint32_t value) { - if(value!=0) { - impl.makeCanonIterDataFromNorm16(start, end, (uint16_t)value, *newData, errorCode); - } - return U_SUCCESS(errorCode); - } - -private: - SimpleSingleton &singleton; - Normalizer2Impl &impl; - CanonIterData *newData; - UErrorCode &errorCode; -}; - U_CDECL_BEGIN // Call Normalizer2Impl::makeCanonIterDataFromNorm16() for a range of same-norm16 characters. +// context: the Normalizer2Impl static UBool U_CALLCONV enumCIDRangeHandler(const void *context, UChar32 start, UChar32 end, uint32_t value) { - return ((CanonIterDataSingleton *)context)->rangeHandler(start, end, value); + UErrorCode errorCode = U_ZERO_ERROR; + if (value != 0) { + Normalizer2Impl *impl = (Normalizer2Impl *)context; + impl->makeCanonIterDataFromNorm16( + start, end, (uint16_t)value, *impl->fCanonIterData, errorCode); + } + return U_SUCCESS(errorCode); +} + + + +// UInitOnce instantiation function for CanonIterData + +static void U_CALLCONV +initCanonIterData(Normalizer2Impl *impl, UErrorCode &errorCode) { + U_ASSERT(impl->fCanonIterData == NULL); + impl->fCanonIterData = new CanonIterData(errorCode); + if (impl->fCanonIterData == NULL) { + errorCode=U_MEMORY_ALLOCATION_ERROR; + } + if (U_SUCCESS(errorCode)) { + utrie2_enum(impl->getNormTrie(), NULL, enumCIDRangeHandler, impl); + utrie2_freeze(impl->fCanonIterData->trie, UTRIE2_32_VALUE_BITS, &errorCode); + } + if (U_FAILURE(errorCode)) { + delete impl->fCanonIterData; + impl->fCanonIterData = NULL; + } } U_CDECL_END -void *CanonIterDataSingleton::createInstance(const void *context, UErrorCode &errorCode) { - CanonIterDataSingleton *me=(CanonIterDataSingleton *)context; - me->newData=new CanonIterData(errorCode); - if(me->newData==NULL) { - errorCode=U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - if(U_SUCCESS(errorCode)) { - utrie2_enum(me->impl.getNormTrie(), NULL, enumCIDRangeHandler, me); - utrie2_freeze(me->newData->trie, UTRIE2_32_VALUE_BITS, &errorCode); - if(U_SUCCESS(errorCode)) { - return me->newData; - } - } - delete me->newData; - return NULL; -} - void Normalizer2Impl::makeCanonIterDataFromNorm16(UChar32 start, UChar32 end, uint16_t norm16, CanonIterData &newData, UErrorCode &errorCode) const { @@ -1919,17 +1904,16 @@ void Normalizer2Impl::makeCanonIterDataFromNorm16(UChar32 start, UChar32 end, ui UBool Normalizer2Impl::ensureCanonIterData(UErrorCode &errorCode) const { // Logically const: Synchronized instantiation. Normalizer2Impl *me=const_cast(this); - CanonIterDataSingleton(me->canonIterDataSingleton, *me, errorCode).getInstance(errorCode); + umtx_initOnce(me->fCanonIterDataInitOnce, &initCanonIterData, me, errorCode); return U_SUCCESS(errorCode); } int32_t Normalizer2Impl::getCanonValue(UChar32 c) const { - return (int32_t)utrie2_get32(((CanonIterData *)canonIterDataSingleton.fInstance)->trie, c); + return (int32_t)utrie2_get32(fCanonIterData->trie, c); } const UnicodeSet &Normalizer2Impl::getCanonStartSet(int32_t n) const { - return *(const UnicodeSet *)( - ((CanonIterData *)canonIterDataSingleton.fInstance)->canonStartSets[n]); + return *(const UnicodeSet *)fCanonIterData->canonStartSets[n]; } UBool Normalizer2Impl::isCanonSegmentStarter(UChar32 c) const { diff --git a/icu4c/source/common/normalizer2impl.h b/icu4c/source/common/normalizer2impl.h index 34d1a25e273..3b85eb040ed 100644 --- a/icu4c/source/common/normalizer2impl.h +++ b/icu4c/source/common/normalizer2impl.h @@ -215,8 +215,8 @@ private: class U_COMMON_API Normalizer2Impl : public UMemory { public: - Normalizer2Impl() : memory(NULL), normTrie(NULL) { - canonIterDataSingleton.reset(); + Normalizer2Impl() : memory(NULL), normTrie(NULL), fCanonIterData(NULL) { + fCanonIterDataInitOnce.reset(); } ~Normalizer2Impl(); @@ -586,7 +586,9 @@ private: const uint8_t *smallFCD; // [0x100] one bit per 32 BMP code points, set if any FCD!=0 uint8_t tccc180[0x180]; // tccc values for U+0000..U+017F - SimpleSingleton canonIterDataSingleton; + public: // CanonIterData is public to allow access from C callback functions. + UInitOnce fCanonIterDataInitOnce; + CanonIterData *fCanonIterData; }; // bits in canonIterData diff --git a/icu4c/source/common/uniset_props.cpp b/icu4c/source/common/uniset_props.cpp index b9151534782..42468b57989 100644 --- a/icu4c/source/common/uniset_props.cpp +++ b/icu4c/source/common/uniset_props.cpp @@ -97,35 +97,6 @@ static const char ASSIGNED[] = "Assigned"; // [:^Cn:] U_CDECL_BEGIN static UBool U_CALLCONV uset_cleanup(); -U_CDECL_END - -// Not a TriStateSingletonWrapper because we think the UnicodeSet constructor -// can only fail with an out-of-memory error -// if we have a correct pattern and the properties data is hardcoded and always available. -class UnicodeSetSingleton : public SimpleSingletonWrapper { -public: - UnicodeSetSingleton(SimpleSingleton &s, const char *pattern) : - SimpleSingletonWrapper(s), fPattern(pattern) {} - UnicodeSet *getInstance(UErrorCode &errorCode) { - return SimpleSingletonWrapper::getInstance(createInstance, fPattern, errorCode); - } -private: - static void *createInstance(const void *context, UErrorCode &errorCode) { - UnicodeString pattern((const char *)context, -1, US_INV); - UnicodeSet *set=new UnicodeSet(pattern, errorCode); - if(set==NULL) { - errorCode=U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - set->freeze(); - ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup); - return set; - } - - const char *fPattern; -}; - -U_CDECL_BEGIN struct Inclusion { UnicodeSet *fSet; @@ -133,7 +104,8 @@ struct Inclusion { }; static Inclusion gInclusions[UPROPS_SRC_COUNT]; // cached getInclusions() -STATIC_SIMPLE_SINGLETON(uni32Singleton); +static UnicodeSet *uni32Singleton; +static UInitOnce uni32InitOnce = U_INITONCE_INITIALIZER; //---------------------------------------------------------------- // Inclusions list @@ -167,7 +139,9 @@ static UBool U_CALLCONV uset_cleanup(void) { in.fInitOnce.reset(); } - UnicodeSetSingleton(uni32Singleton, NULL).deleteInstance(); + delete uni32Singleton; + uni32Singleton = NULL; + uni32InitOnce.reset(); return TRUE; } @@ -285,10 +259,22 @@ const UnicodeSet* UnicodeSet::getInclusions(int32_t src, UErrorCode &status) { // Cache some sets for other services -------------------------------------- *** +void U_CALLCONV createUni32Set(UErrorCode &errorCode) { + U_ASSERT(uni32Singleton == NULL); + uni32Singleton = new UnicodeSet(UNICODE_STRING_SIMPLE("[:age=3.2:]"), errorCode); + if(uni32Singleton==NULL) { + errorCode=U_MEMORY_ALLOCATION_ERROR; + } else { + uni32Singleton->freeze(); + } + ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup); +} + U_CFUNC UnicodeSet * uniset_getUnicode32Instance(UErrorCode &errorCode) { - return UnicodeSetSingleton(uni32Singleton, "[:age=3.2:]").getInstance(errorCode); + umtx_initOnce(uni32InitOnce, &createUni32Set, errorCode); + return uni32Singleton; } // helper functions for matching of pattern syntax pieces ------------------ *** diff --git a/icu4c/source/common/utrie2.cpp b/icu4c/source/common/utrie2.cpp index 79a67f4e5e3..86b6a774557 100644 --- a/icu4c/source/common/utrie2.cpp +++ b/icu4c/source/common/utrie2.cpp @@ -733,10 +733,4 @@ uint16_t ForwardUTrie2StringIterator::next16() { return result; } -UTrie2 *UTrie2Singleton::getInstance(InstantiatorFn *instantiator, const void *context, - UErrorCode &errorCode) { - UTrie2 *instance=(UTrie2 *)singleton.getInstance(instantiator, context, errorCode); - return instance; -} - U_NAMESPACE_END diff --git a/icu4c/source/common/utrie2.h b/icu4c/source/common/utrie2.h index 1bac06ac657..d7985fbccd3 100644 --- a/icu4c/source/common/utrie2.h +++ b/icu4c/source/common/utrie2.h @@ -1,7 +1,7 @@ /* ****************************************************************************** * -* Copyright (C) 2001-2011, International Business Machines +* Copyright (C) 2001-2013, International Business Machines * Corporation and others. All Rights Reserved. * ****************************************************************************** @@ -659,19 +659,6 @@ public: const UChar *limit; }; -class UTrie2Singleton { -public: - UTrie2Singleton(SimpleSingleton &s) : singleton(s) {} - void deleteInstance() { - utrie2_close((UTrie2 *)singleton.fInstance); - singleton.reset(); - } - UTrie2 *getInstance(InstantiatorFn *instantiator, const void *context, - UErrorCode &errorCode); -private: - SimpleSingleton &singleton; -}; - U_NAMESPACE_END #endif