ICU-10301 Remove singleton classes, convert existing usage to UInitOnce

X-SVN-Rev: 34032
This commit is contained in:
Andy Heninger 2013-08-12 03:35:22 +00:00
parent 7879f2905b
commit 8e9b5e0b7e
8 changed files with 126 additions and 354 deletions

View file

@ -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

View file

@ -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<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) {
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<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) {
T *instance=(T *)singleton.getInstance(instantiator, context, errorCode);
return instance;
}
private:
TriStateSingleton &singleton;
};
U_NAMESPACE_END
#endif //_MUTEX_

View file

@ -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<Norm2AllModes> {
public:
Norm2AllModesSingleton(TriStateSingleton &s, const char *n) :
TriStateSingletonWrapper<Norm2AllModes>(s), name(n) {}
Norm2AllModes *getInstance(UErrorCode &errorCode) {
return TriStateSingletonWrapper<Norm2AllModes>::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<Normalizer2> {
public:
Norm2Singleton(SimpleSingleton &s) : SimpleSingletonWrapper<Normalizer2>(s) {}
Normalizer2 *getInstance(UErrorCode &errorCode) {
return SimpleSingletonWrapper<Normalizer2>::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)) {

View file

@ -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<Normalizer2Impl *>(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 {

View file

@ -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

View file

@ -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<UnicodeSet> {
public:
UnicodeSetSingleton(SimpleSingleton &s, const char *pattern) :
SimpleSingletonWrapper<UnicodeSet>(s), fPattern(pattern) {}
UnicodeSet *getInstance(UErrorCode &errorCode) {
return SimpleSingletonWrapper<UnicodeSet>::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 ------------------ ***

View file

@ -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

View file

@ -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