ICU-2135 Doug's changes to the service registration memory handling

X-SVN-Rev: 10519
This commit is contained in:
Vladimir Weinstein 2002-12-06 00:22:10 +00:00
parent 982f05ae4a
commit ba679fb764
6 changed files with 72 additions and 29 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -55,4 +55,6 @@ U_CFUNC UBool putil_cleanup(void);
U_CFUNC UBool uset_cleanup(void);
U_CFUNC UBool service_cleanup(void);
#endif

View File

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