ICU-2135 Doug's changes to the service registration memory handling
X-SVN-Rev: 10519
This commit is contained in:
parent
982f05ae4a
commit
ba679fb764
@ -121,14 +121,22 @@ LocaleUtility::isFallbackOf(const UnicodeString& root, const UnicodeString& chil
|
||||
child.charAt(root.length()) == UNDERSCORE_CHAR);
|
||||
}
|
||||
|
||||
UBool
|
||||
LocaleUtility::cleanup(void) {
|
||||
if (cache) {
|
||||
Mutex mutex(&lock);
|
||||
delete cache;
|
||||
cache = NULL;
|
||||
}
|
||||
umtx_destroy(&lock);
|
||||
}
|
||||
|
||||
Hashtable * LocaleUtility::cache = NULL;
|
||||
|
||||
const UChar LocaleUtility::UNDERSCORE_CHAR = 0x005f;
|
||||
|
||||
UMTX LocaleUtility::lock = 0;
|
||||
|
||||
/// !!! dlf need to destroy this lock in a cleanup function
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
*/
|
||||
@ -414,6 +422,12 @@ SimpleLocaleKeyFactory::SimpleLocaleKeyFactory(UObject* objToAdopt,
|
||||
{
|
||||
}
|
||||
|
||||
SimpleLocaleKeyFactory::~SimpleLocaleKeyFactory()
|
||||
{
|
||||
delete _obj;
|
||||
_obj = NULL;
|
||||
}
|
||||
|
||||
UObject*
|
||||
SimpleLocaleKeyFactory::create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const
|
||||
{
|
||||
@ -805,6 +819,15 @@ ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& s
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
// defined in ucln_cmn.h
|
||||
|
||||
/**
|
||||
* Release all static memory held by breakiterator.
|
||||
*/
|
||||
U_CFUNC UBool service_cleanup(void) {
|
||||
return LocaleUtility::cleanup();
|
||||
}
|
||||
|
||||
/* !UCONFIG_NO_SERVICE */
|
||||
#endif
|
||||
|
||||
|
@ -312,6 +312,11 @@ class U_COMMON_API SimpleLocaleKeyFactory : public LocaleKeyFactory {
|
||||
int32_t kind,
|
||||
int32_t coverage);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~SimpleLocaleKeyFactory();
|
||||
|
||||
/**
|
||||
* Override of superclass method. Returns the service object if kind/locale match. Service is not used.
|
||||
*/
|
||||
@ -545,6 +550,7 @@ public:
|
||||
static UnicodeString& initNameFromLocale(const Locale& locale, UnicodeString& result);
|
||||
static const Hashtable* getAvailableLocaleNames(const UnicodeString& bundleID);
|
||||
static UBool isFallbackOf(const UnicodeString& root, const UnicodeString& child);
|
||||
static UBool cleanup(void);
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
@ -638,6 +638,12 @@ private:
|
||||
UBool fActive;
|
||||
};
|
||||
|
||||
struct UVectorDeleter {
|
||||
UVector* _obj;
|
||||
UVectorDeleter() : _obj(NULL) {}
|
||||
~UVectorDeleter() { delete _obj; }
|
||||
};
|
||||
|
||||
UObject*
|
||||
ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUServiceFactory* factory, UErrorCode& status) const
|
||||
{
|
||||
@ -674,7 +680,7 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer
|
||||
}
|
||||
|
||||
UnicodeString currentDescriptor;
|
||||
UVector* cacheDescriptorList = NULL;
|
||||
UVectorDeleter cacheDescriptorList;
|
||||
UBool putInCache = FALSE;
|
||||
|
||||
int32_t startIndex = 0;
|
||||
@ -707,7 +713,7 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer
|
||||
// first test of cache failed, so we'll have to update
|
||||
// the cache if we eventually succeed-- that is, if we're
|
||||
// going to update the cache at all.
|
||||
putInCache = cacheResult;
|
||||
putInCache = TRUE;
|
||||
|
||||
int32_t n = 0;
|
||||
int32_t index = startIndex;
|
||||
@ -715,7 +721,6 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer
|
||||
ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(index++);
|
||||
UObject* service = f->create(key, this, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete cacheDescriptorList;
|
||||
delete service;
|
||||
return NULL;
|
||||
}
|
||||
@ -723,7 +728,6 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer
|
||||
result = new CacheEntry(currentDescriptor, service);
|
||||
if (result == NULL) {
|
||||
delete service;
|
||||
delete cacheDescriptorList;
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
@ -737,52 +741,45 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer
|
||||
// don't want to keep querying on an id that's going to
|
||||
// fallback to the one that succeeded, we want to hit the
|
||||
// cache the first time next goaround.
|
||||
if (cacheDescriptorList == NULL) {
|
||||
cacheDescriptorList = new UVector(uhash_deleteUnicodeString, NULL, 5, status);
|
||||
if (cacheDescriptorList._obj == NULL) {
|
||||
cacheDescriptorList._obj = new UVector(uhash_deleteUnicodeString, NULL, 5, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
UnicodeString* idToCache = new UnicodeString(currentDescriptor);
|
||||
if (idToCache == NULL || idToCache->isBogus()) {
|
||||
delete cacheDescriptorList;
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cacheDescriptorList->addElement(idToCache, status);
|
||||
cacheDescriptorList._obj->addElement(idToCache, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete cacheDescriptorList;
|
||||
return NULL;
|
||||
}
|
||||
} while (key.fallback());
|
||||
outerEnd:
|
||||
|
||||
if (result != NULL) {
|
||||
if (putInCache) {
|
||||
if (putInCache && cacheResult) {
|
||||
serviceCache->put(result->actualDescriptor, result, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete result;
|
||||
delete cacheDescriptorList;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cacheDescriptorList != NULL) {
|
||||
for (int32_t i = cacheDescriptorList->size(); --i >= 0;) {
|
||||
UnicodeString* desc = (UnicodeString*)cacheDescriptorList->elementAt(i);
|
||||
if (cacheDescriptorList._obj != NULL) {
|
||||
for (int32_t i = cacheDescriptorList._obj->size(); --i >= 0;) {
|
||||
UnicodeString* desc = (UnicodeString*)cacheDescriptorList._obj->elementAt(i);
|
||||
serviceCache->put(*desc, result, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete result;
|
||||
delete cacheDescriptorList;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->ref();
|
||||
cacheDescriptorList->removeElementAt(i);
|
||||
cacheDescriptorList._obj->removeElementAt(i);
|
||||
}
|
||||
|
||||
delete cacheDescriptorList;
|
||||
cacheDescriptorList = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -799,11 +796,16 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer
|
||||
|
||||
if (actualReturn->isBogus()) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return cloneInstance(result->service);
|
||||
UObject* service = cloneInstance(result->service);
|
||||
if (putInCache && !cacheResult) {
|
||||
delete result;
|
||||
}
|
||||
return service;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,9 @@ u_cleanup(void)
|
||||
#if !UCONFIG_NO_BREAK_ITERATION
|
||||
breakiterator_cleanup();
|
||||
#endif
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
service_cleanup();
|
||||
#endif
|
||||
#ifdef ICU_UNICODECONVERTER_USE_DEPRECATES
|
||||
UnicodeConverter_cleanup(); /* <-- deprecated code */
|
||||
#endif /* ICU_UNICODECONVERTER_USE_DEPRECATES */
|
||||
|
@ -55,4 +55,6 @@ U_CFUNC UBool putil_cleanup(void);
|
||||
|
||||
U_CFUNC UBool uset_cleanup(void);
|
||||
|
||||
U_CFUNC UBool service_cleanup(void);
|
||||
|
||||
#endif
|
||||
|
@ -157,6 +157,7 @@ UnicodeString append(UnicodeString& result, const UObject* obj)
|
||||
result.append(buffer);
|
||||
} else {
|
||||
sprintf(buffer, "%x", obj);
|
||||
result.append(buffer);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -785,6 +786,11 @@ class CalifornioLanguageFactory : public ICUResourceBundleFactory
|
||||
static const char* geek; // = californio ## "_GEEK";
|
||||
static const Hashtable* supportedIDs; // = NULL;
|
||||
|
||||
static void cleanup(void) {
|
||||
delete supportedIDs;
|
||||
supportedIDs = NULL;
|
||||
}
|
||||
|
||||
const Hashtable* getSupportedIDs(UErrorCode& status) const
|
||||
{
|
||||
if (supportedIDs == NULL) {
|
||||
@ -900,6 +906,7 @@ ICUServiceTest::testRBF()
|
||||
}
|
||||
}
|
||||
}
|
||||
CalifornioLanguageFactory::cleanup();
|
||||
}
|
||||
|
||||
class SimpleListener : public ServiceListener {
|
||||
@ -1164,13 +1171,6 @@ void ICUServiceTest::testLocale() {
|
||||
errln("could not create available locales");
|
||||
}
|
||||
}
|
||||
delete one;
|
||||
delete two;
|
||||
delete root;
|
||||
delete german;
|
||||
delete germany;
|
||||
delete japanese;
|
||||
delete japan;
|
||||
}
|
||||
|
||||
class WrapFactory : public ICUServiceFactory {
|
||||
@ -1182,6 +1182,11 @@ class WrapFactory : public ICUServiceFactory {
|
||||
return *greetingID;
|
||||
}
|
||||
|
||||
static void cleanup() {
|
||||
delete greetingID;
|
||||
greetingID = NULL;
|
||||
}
|
||||
|
||||
UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const {
|
||||
if (U_SUCCESS(status)) {
|
||||
UnicodeString temp;
|
||||
@ -1255,6 +1260,8 @@ ICUServiceTest::testWrapFactory()
|
||||
confirmEqual("wrap test: ", result, &target);
|
||||
delete result;
|
||||
}
|
||||
|
||||
WrapFactory::cleanup();
|
||||
}
|
||||
|
||||
// misc coverage tests
|
||||
|
Loading…
Reference in New Issue
Block a user