mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-10301 Remove singleton classes, convert existing usage to UInitOnce
X-SVN-Rev: 34032
This commit is contained in:
parent
7879f2905b
commit
8e9b5e0b7e
8 changed files with 126 additions and 354 deletions
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ------------------ ***
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue