ICU-4078 Decouple the cleanup functions from u_init and u_cleanup.

X-SVN-Rev: 16403
This commit is contained in:
George Rhoten 2004-10-06 23:10:53 +00:00
parent 1188be07f8
commit e2188e6775
24 changed files with 441 additions and 401 deletions

View File

@ -58,7 +58,7 @@ DEFS += -DU_COMMON_IMPLEMENTATION
# $(LIBICUDT) is either stub data or the real DLL common data.
LIBS = $(LIBICUDT) $(DEFAULT_LIBS)
OBJECTS = putil.o uobject.o cmemory.o umutex.o \
OBJECTS = putil.o uobject.o cmemory.o umutex.o ucln_cmn.o uinit.o \
udata.o ucmndata.o udatamem.o udataswp.o umapfile.o ucol_swp.o \
uresbund.o ures_cnv.o uresdata.o resbund.o resbund_cnv.o \
ucat.o locmap.o uloc.o locid.o \
@ -70,7 +70,7 @@ unistr.o unistr_case.o unistr_cnv.o unistr_props.o \
utf_impl.o ustring.o ustr_cnv.o ustrcase.o cstring.o ustrfmt.o ustrtrns.o ustr_wcs.o uinvchar.o \
normlzr.o unorm.o unormcmp.o unorm_it.o chariter.o schriter.o uchriter.o uiter.o \
uchar.o uprops.o ucase.o propname.o ubidi.o ubidiwrt.o ubidiln.o ushape.o unames.o \
ucln_cmn.o uscript.o usc_impl.o uvector.o ustack.o uvectr32.o ucmp8.o \
uscript.o usc_impl.o uvector.o ustack.o uvectr32.o ucmp8.o \
uarrsort.o utrie.o uset.o uset_props.o uniset.o uniset_props.o ruleiter.o caniter.o unifilt.o unifunct.o usetiter.o \
brkiter.o brkdict.o ubrk.o dbbi.o dbbi_tbl.o \
rbbi.o rbbidata.o rbbinode.o rbbirb.o rbbiscan.o rbbisetb.o rbbistbl.o rbbitblb.o \

View File

@ -26,6 +26,7 @@
#include "unicode/brkiter.h"
#include "unicode/udata.h"
#include "unicode/ures.h"
#include "ucln_cmn.h"
#include "cstring.h"
#include "mutex.h"
#include "iculserv.h"
@ -362,6 +363,26 @@ public:
// -------------------------------------
U_NAMESPACE_END
// defined in ucln_cmn.h
/**
* Release all static memory held by breakiterator.
*/
U_CDECL_BEGIN
static UBool U_CALLCONV breakiterator_cleanup(void) {
#if !UCONFIG_NO_SERVICE
if (gService) {
delete gService;
gService = NULL;
}
#endif
return TRUE;
}
U_CDECL_END
U_NAMESPACE_BEGIN
static ICULocaleService*
getService(void)
{
@ -376,6 +397,7 @@ getService(void)
if (gService == NULL) {
gService = tService;
tService = NULL;
ucln_common_registerCleanup(UCLN_COMMON_BREAKITERATOR, breakiterator_cleanup);
}
umtx_unlock(NULL);
delete tService;
@ -520,21 +542,6 @@ BreakIterator::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const {
U_NAMESPACE_END
// defined in ucln_cmn.h
/**
* Release all static memory held by breakiterator.
*/
U_CFUNC UBool breakiterator_cleanup(void) {
#if !UCONFIG_NO_SERVICE
if (gService) {
delete gService;
gService = NULL;
}
#endif
return TRUE;
}
#endif /* #if !UCONFIG_NO_BREAK_ITERATION */
//eof

View File

@ -1712,6 +1712,10 @@ SOURCE=.\umapfile.c
# End Source File
# Begin Source File
SOURCE=.\uinit.c
# End Source File
# Begin Source File
SOURCE=.\umapfile.h
# End Source File
# Begin Source File

View File

@ -962,6 +962,9 @@
<File
RelativePath=".\udataswp.h">
</File>
<File
RelativePath=".\uinit.c">
</File>
<File
RelativePath=".\umapfile.c">
<FileConfiguration

View File

@ -17,10 +17,9 @@
#include "ustrfmt.h"
#include "uhash.h"
#include "charstr.h"
#include "ucln_cmn.h"
#include "uassert.h"
U_NAMESPACE_BEGIN
// see LocaleUtility::getAvailableLocaleNames
static Hashtable * LocaleUtility_cache = NULL;
@ -32,6 +31,21 @@ static Hashtable * LocaleUtility_cache = NULL;
******************************************************************
*/
/**
* Release all static memory held by Locale Utility.
*/
U_CDECL_BEGIN
static UBool U_CALLCONV service_cleanup(void) {
if (LocaleUtility_cache) {
delete LocaleUtility_cache;
LocaleUtility_cache = NULL;
}
return TRUE;
}
U_CDECL_END
U_NAMESPACE_BEGIN
UnicodeString&
LocaleUtility::canonicalLocaleString(const UnicodeString* id, UnicodeString& result)
{
@ -194,6 +208,7 @@ LocaleUtility::getAvailableLocaleNames(const UnicodeString& bundleID)
if (h == NULL) {
LocaleUtility_cache = h = cache;
cache = NULL;
ucln_common_registerCleanup(UCLN_COMMON_SERVICE, service_cleanup);
}
umtx_unlock(NULL);
delete cache;
@ -243,15 +258,6 @@ LocaleUtility::isFallbackOf(const UnicodeString& root, const UnicodeString& chil
child.charAt(root.length()) == UNDERSCORE_CHAR);
}
UBool
LocaleUtility::cleanup(void) {
if (LocaleUtility_cache) {
delete LocaleUtility_cache;
LocaleUtility_cache = NULL;
}
return TRUE;
}
/*
******************************************************************
*/
@ -950,15 +956,6 @@ ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& s
U_NAMESPACE_END
// defined in ucln_cmn.h
/**
* Release all static memory held by Locale Utility.
*/
U_CFUNC UBool service_cleanup(void) {
return LocaleUtility::cleanup();
}
/* !UCONFIG_NO_SERVICE */
#endif

View File

@ -547,7 +547,6 @@ 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

@ -88,11 +88,8 @@ static void U_CALLCONV
deleteLocale(void *obj) {
delete (Locale *) obj;
}
U_CDECL_END
UBool
locale_cleanup(void)
static UBool U_CALLCONV locale_cleanup(void)
{
U_NAMESPACE_USE
@ -115,6 +112,7 @@ locale_cleanup(void)
return TRUE;
}
U_CDECL_END
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Locale)
@ -170,6 +168,7 @@ void locale_set_default_internal(const char *id)
umtx_lock(NULL);
if (gDefaultLocalesHashT == NULL) {
gDefaultLocalesHashT = tHashTable;
ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
umtx_unlock(NULL);
} else {
umtx_unlock(NULL);
@ -972,6 +971,7 @@ Locale::getAvailableLocales(int32_t& count)
availableLocaleListCount = count;
availableLocaleList = newLocaleList;
newLocaleList = NULL;
ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
}
umtx_unlock(NULL);
delete []newLocaleList;
@ -1175,6 +1175,7 @@ Locale::getLocaleCache(void)
if (gLocaleCache == NULL) {
gLocaleCache = tLocaleCache;
tLocaleCache = NULL;
ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
}
umtx_unlock(NULL);
if (tLocaleCache) {

View File

@ -14,6 +14,7 @@
#include "umutex.h"
#include "cmemory.h"
#include "cstring.h"
#include "ucln_cmn.h"
#include "uarrsort.h"
U_CDECL_BEGIN
@ -232,8 +233,7 @@ isPNameAcceptable(void* /*context*/,
info->formatVersion[0] == PNAME_FORMAT_VERSION;
}
UBool
pname_cleanup() {
static UBool U_CALLCONV pname_cleanup() {
if (UDATA) {
udata_close(UDATA);
UDATA = NULL;
@ -258,6 +258,7 @@ static UBool _load() {
if (UDATA == NULL) {
UDATA = data;
PNAME = (const PropertyAliases*) udata_getMemory(UDATA);
ucln_common_registerCleanup(UCLN_COMMON_PNAME, pname_cleanup);
data = NULL;
}
umtx_unlock(NULL);

View File

@ -1249,7 +1249,7 @@ static char *gDataDirectory = NULL;
static char *gCorrectedPOSIXLocale = NULL; /* Heap allocated */
#endif
UBool putil_cleanup(void)
static UBool U_CALLCONV putil_cleanup(void)
{
if (gDataDirectory) {
uprv_free(gDataDirectory);
@ -1295,6 +1295,7 @@ u_setDataDirectory(const char *directory) {
uprv_free(gDataDirectory);
}
gDataDirectory = newDataDir;
ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
umtx_unlock(NULL);
}
@ -1692,6 +1693,7 @@ The leftmost codepage (.xxx) wins.
if (gCorrectedPOSIXLocale == NULL) {
gCorrectedPOSIXLocale = correctedPOSIXLocale;
ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
correctedPOSIXLocale = NULL;
}

View File

@ -27,6 +27,7 @@
#include "cmemory.h"
#include "utrie.h"
#include "ucase.h"
#include "ucln_cmn.h"
struct UCaseProps {
UDataMemory *mem;
@ -182,6 +183,14 @@ static UCaseProps *gCsp=NULL;
static UErrorCode gErrorCode=U_ZERO_ERROR;
static int8_t gHaveData=0;
static UBool U_CALLCONV ucase_cleanup(void) {
ucase_close(gCsp);
gCsp=NULL;
gErrorCode=U_ZERO_ERROR;
gHaveData=0;
return TRUE;
}
U_CAPI UCaseProps * U_EXPORT2
ucase_getSingleton(UErrorCode *pErrorCode) {
int8_t haveData;
@ -214,6 +223,7 @@ ucase_getSingleton(UErrorCode *pErrorCode) {
gCsp=csp;
csp=NULL;
gHaveData=1;
ucln_common_registerCleanup(UCLN_COMMON_UCASE, ucase_cleanup);
}
umtx_unlock(NULL);
@ -222,14 +232,6 @@ ucase_getSingleton(UErrorCode *pErrorCode) {
}
}
U_CFUNC void
ucase_cleanup() {
ucase_close(gCsp);
gCsp=NULL;
gErrorCode=U_ZERO_ERROR;
gHaveData=0;
}
/* Unicode case mapping data swapping --------------------------------------- */
U_CAPI int32_t U_EXPORT2

View File

@ -44,9 +44,6 @@ ucase_close(UCaseProps *csp);
U_CAPI UCaseProps * U_EXPORT2
ucase_getSingleton(UErrorCode *pErrorCode);
U_CFUNC void
ucase_cleanup();
U_CAPI int32_t U_EXPORT2
ucase_swap(const UDataSwapper *ds,

View File

@ -95,8 +95,7 @@ isAcceptable(void *context,
}
}
UBool
uchar_cleanup()
static UBool U_CALLCONV uchar_cleanup(void)
{
if (propsData) {
udata_close(propsData);
@ -203,6 +202,7 @@ uprv_loadPropsData(UErrorCode *pErrorCode) {
}
havePropsData=1;
ucln_common_registerCleanup(UCLN_COMMON_UCHAR, uchar_cleanup);
umtx_unlock(NULL);
} else {
dataErrorCode=*pErrorCode;

View File

@ -25,121 +25,28 @@
#include "cmemory.h"
#include "uassert.h"
static UBool gICUInitialized = FALSE;
static UMTX gICUInitMutex = NULL;
static cleanupFunc *gCommonCleanupFunctions[UCLN_COMMON_COUNT];
static cleanupFunc *gCleanupFunctions[UCLN_COMMON] = {
NULL,
NULL,
NULL,
NULL,
NULL
};
U_CAPI void U_EXPORT2
ucln_registerCleanup(ECleanupLibraryType type,
cleanupFunc *func)
void ucln_common_registerCleanup(ECleanupCommonType type,
cleanupFunc *func)
{
U_ASSERT(UCLN_START < type && type < UCLN_COMMON);
if (UCLN_START < type && type < UCLN_COMMON)
U_ASSERT(UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT);
if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT)
{
gCleanupFunctions[type] = func;
gCommonCleanupFunctions[type] = func;
}
}
/************************************************
The cleanup order is important in this function.
Please be sure that you have read ucln.h
************************************************/
U_CAPI void U_EXPORT2
u_cleanup(void)
{
ECleanupLibraryType libType;
U_CFUNC UBool ucln_common_lib_cleanup(void) {
ECleanupCommonType commonFunc;
UTRACE_ENTRY_OC(UTRACE_U_CLEANUP);
umtx_lock(NULL); /* Force a memory barrier, so that we are sure to see */
umtx_unlock(NULL); /* all state left around by any other threads. */
for (libType = UCLN_START+1; libType<UCLN_COMMON; libType++) {
if (gCleanupFunctions[libType])
for (commonFunc = UCLN_COMMON_START+1; commonFunc<UCLN_COMMON_COUNT; commonFunc++) {
if (gCommonCleanupFunctions[commonFunc])
{
gCleanupFunctions[libType]();
gCleanupFunctions[libType] = NULL;
gCommonCleanupFunctions[commonFunc]();
gCommonCleanupFunctions[commonFunc] = NULL;
}
}
#if !UCONFIG_NO_IDNA
usprep_cleanup();
#endif
#if !UCONFIG_NO_BREAK_ITERATION
breakiterator_cleanup();
#endif
#if !UCONFIG_NO_SERVICE
service_cleanup();
#endif
ures_cleanup();
locale_cleanup();
uloc_cleanup();
#if !UCONFIG_NO_NORMALIZATION
unorm_cleanup();
#endif
uset_cleanup();
unames_cleanup();
pname_cleanup();
ucase_cleanup();
uchar_cleanup();
#if !UCONFIG_NO_CONVERSION
ucnv_cleanup();
ucnv_io_cleanup();
#endif
udata_cleanup();
putil_cleanup();
umtx_destroy(&gICUInitMutex);
umtx_cleanup();
cmemory_cleanup(); /* undo any heap functions set by u_setMemoryFunctions(). */
gICUInitialized = FALSE;
UTRACE_EXIT(); /* Must be before utrace_cleanup(), which turns off tracing. */
utrace_cleanup();
}
/*
*
* ICU Initialization Function. Force loading and/or initialization of
* any shared data that could potentially be used concurrently
* by multiple threads.
*/
U_CAPI void U_EXPORT2
u_init(UErrorCode *status) {
UTRACE_ENTRY_OC(UTRACE_U_INIT);
/* Make sure the global mutexes are initialized. */
umtx_init(NULL);
umtx_lock(&gICUInitMutex);
if (gICUInitialized || U_FAILURE(*status)) {
umtx_unlock(&gICUInitMutex);
UTRACE_EXIT_STATUS(*status);
return;
}
/* Do any required init for services that don't have open operations
* and use "only" the double-check initialization method for performance
* reasons (avoiding a mutex lock even for _checking_ whether the
* initialization had occurred).
*/
/* Char Properties */
uprv_loadPropsData(status);
#if !UCONFIG_NO_NORMALIZATION
/* Normalization */
unorm_haveData(status);
#endif
gICUInitialized = TRUE; /* TODO: don't set if U_FAILURE? */
umtx_unlock(&gICUInitMutex);
UTRACE_EXIT_STATUS(*status);
return TRUE;
}

View File

@ -1,7 +1,7 @@
/*
******************************************************************************
* *
* Copyright (C) 2001-2003, International Business Machines *
* Copyright (C) 2001-2004, International Business Machines *
* Corporation and others. All Rights Reserved. *
* *
******************************************************************************
@ -18,45 +18,43 @@
#define __UCLN_CMN_H__
#include "unicode/utypes.h"
#include "ucln.h"
/* These are the cleanup functions for various APIs. */
/* @return true if cleanup complete successfully.*/
U_CFUNC UBool unames_cleanup(void);
U_CFUNC UBool unorm_cleanup(void);
U_CFUNC UBool uchar_cleanup(void);
U_CFUNC UBool pname_cleanup(void);
U_CFUNC UBool locale_cleanup(void);
U_CFUNC UBool uloc_cleanup(void);
U_CFUNC UBool breakiterator_cleanup(void);
U_CFUNC UBool usprep_cleanup(void);
U_CFUNC UBool U_EXPORT2 ucnv_cleanup(void);
U_CFUNC UBool ucnv_io_cleanup(void);
U_CFUNC UBool ures_cleanup(void);
U_CFUNC UBool udata_cleanup(void);
U_CFUNC UBool putil_cleanup(void);
U_CFUNC UBool uset_cleanup(void);
U_CFUNC UBool service_cleanup(void);
U_CFUNC UBool cmemory_cleanup(void);
U_CFUNC UBool umtx_cleanup(void);
U_CFUNC UBool utrace_cleanup(void);
U_CFUNC UBool ucln_common_lib_cleanup(void);
/*
Please keep the order of enums declared in same order
as the functions are suppose to be called. */
typedef enum ECleanupCommonType {
UCLN_COMMON_START = -1,
UCLN_COMMON_USPREP,
UCLN_COMMON_BREAKITERATOR,
UCLN_COMMON_SERVICE,
UCLN_COMMON_URES,
UCLN_COMMON_LOCALE,
UCLN_COMMON_ULOC,
UCLN_COMMON_UNORM,
UCLN_COMMON_USET,
UCLN_COMMON_UNAMES,
UCLN_COMMON_PNAME,
UCLN_COMMON_UCASE,
UCLN_COMMON_UCHAR,
UCLN_COMMON_UCNV,
UCLN_COMMON_UCNV_IO,
UCLN_COMMON_UDATA,
UCLN_COMMON_PUTIL,
UCLN_COMMON_COUNT /* This must be last */
} ECleanupCommonType;
/* Main library cleanup registration function. */
/* See common/ucln.h for details on adding a cleanup function. */
U_CFUNC void U_EXPORT2 ucln_common_registerCleanup(ECleanupCommonType type,
cleanupFunc *func);
#endif

View File

@ -161,7 +161,7 @@ static const char DATA_TYPE[] = "cnv";
/* by open converters. */
/* Not thread safe. */
/* Not supported API. Marked U_CAPI only for use by test programs. */
U_CFUNC UBool U_EXPORT2 ucnv_cleanup(void) {
static UBool U_CALLCONV ucnv_cleanup(void) {
if (SHARED_DATA_HASHTABLE != NULL) {
ucnv_flushCache();
if (SHARED_DATA_HASHTABLE != NULL && uhash_count(SHARED_DATA_HASHTABLE) == 0) {
@ -381,6 +381,8 @@ ucnv_shareConverterData(UConverterSharedData * data)
SHARED_DATA_HASHTABLE = uhash_openSize(uhash_hashChars, uhash_compareChars,
ucnv_io_countAvailableAliases(&err),
&err);
ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
if (U_FAILURE(err))
return;
}

View File

@ -219,6 +219,37 @@ isAcceptable(void *context,
pInfo->formatVersion[0]==3);
}
static UBool U_CALLCONV ucnv_io_cleanup(void)
{
if (gAliasData) {
udata_close(gAliasData);
gAliasData = NULL;
}
ucnv_io_flushAvailableConverterCache();
gConverterListSize = 0;
gTagListSize = 0;
gAliasListSize = 0;
gUntaggedConvArraySize = 0;
gTaggedAliasArraySize = 0;
gTaggedAliasListsSize = 0;
gStringTableSize = 0;
gConverterList = NULL;
gTagList = NULL;
gAliasList = NULL;
gUntaggedConvArray = NULL;
gTaggedAliasArray = NULL;
gTaggedAliasLists = NULL;
gStringTable = NULL;
gDefaultConverterName = NULL;
gDefaultConverterNameBuffer[0] = 0;
return TRUE; /* Everything was cleaned up */
}
static UBool
haveAliasData(UErrorCode *pErrorCode) {
int haveData;
@ -292,6 +323,7 @@ haveAliasData(UErrorCode *pErrorCode) {
currOffset += reservedSize1;
gStringTable = table + currOffset;
ucln_common_registerCleanup(UCLN_COMMON_UCNV_IO, ucnv_io_cleanup);
}
umtx_unlock(NULL);
@ -316,39 +348,6 @@ isAlias(const char *alias, UErrorCode *pErrorCode) {
}
}
UBool
ucnv_io_cleanup()
{
if (gAliasData) {
udata_close(gAliasData);
gAliasData = NULL;
}
ucnv_io_flushAvailableConverterCache();
gConverterListSize = 0;
gTagListSize = 0;
gAliasListSize = 0;
gUntaggedConvArraySize = 0;
gTaggedAliasArraySize = 0;
gTaggedAliasListsSize = 0;
gStringTableSize = 0;
gConverterList = NULL;
gTagList = NULL;
gAliasList = NULL;
gUntaggedConvArray = NULL;
gTaggedAliasArray = NULL;
gTaggedAliasLists = NULL;
gStringTable = NULL;
gDefaultConverterName = NULL;
gDefaultConverterNameBuffer[0] = 0;
return TRUE; /* Everything was cleaned up */
}
static uint32_t getTagNumber(const char *tagname) {
if (gTagList) {
uint32_t tagNum;
@ -889,6 +888,7 @@ static UBool haveAvailableConverterList(UErrorCode *pErrorCode) {
if (gAvailableConverters == NULL) {
gAvailableConverters = localConverterList;
gAvailableConverterCount = localConverterCount;
/* haveData should have already registered the cleanup function */
}
else {
uprv_free((char **)localConverterList);
@ -1045,6 +1045,7 @@ ucnv_io_getDefaultConverterName() {
gDefaultConverterNameBuffer[length]=0;
gDefaultConverterName = gDefaultConverterNameBuffer;
name = gDefaultConverterName;
ucln_common_registerCleanup(UCLN_COMMON_UCNV_IO, ucnv_io_cleanup);
umtx_unlock(NULL);
/* The close may make the current name go away. */

View File

@ -78,8 +78,8 @@ static UDataMemory *gStubICUData = NULL; /* If gCommonICUData does get upda
static UHashtable *gCommonDataCache = NULL; /* Global hash table of opened ICU data files. */
UBool
udata_cleanup()
static UBool U_CALLCONV
udata_cleanup(void)
{
if (gCommonDataCache) { /* Delete the cache of user data mappings. */
uhash_close(gCommonDataCache); /* Table owns the contents, and will delete them. */
@ -128,6 +128,7 @@ setCommonICUData(UDataMemory *pData, /* The new common data. Belongs to ca
if (gCommonICUData==oldData) {
gStubICUData = gCommonICUData; /* remember the old Common Data, so it can be cleaned up. */
gCommonICUData = newCommonData;
ucln_common_registerCleanup(UCLN_COMMON_UDATA, udata_cleanup);
}
else {
if (warn==TRUE) {
@ -222,6 +223,7 @@ static UHashtable *udata_getHashTable() {
if (gCommonDataCache == NULL) {
gCommonDataCache = tHT;
tHT = NULL;
ucln_common_registerCleanup(UCLN_COMMON_UDATA, udata_cleanup);
}
umtx_unlock(NULL);
if (tHT != NULL) {

111
icu4c/source/common/uinit.c Normal file
View File

@ -0,0 +1,111 @@
/*
******************************************************************************
* *
* Copyright (C) 2001-2004, International Business Machines *
* Corporation and others. All Rights Reserved. *
* *
******************************************************************************
* file name: uinit.c
* encoding: US-ASCII
* tab size: 8 (not used)
* indentation:4
*
* created on: 2001July05
* created by: George Rhoten
*/
#include "unicode/utypes.h"
#include "unicode/uclean.h"
#include "utracimp.h"
#include "ustr_imp.h"
#include "unormimp.h"
#include "ucln_cmn.h"
#include "umutex.h"
#include "ucln.h"
#include "cmemory.h"
#include "uassert.h"
static UBool gICUInitialized = FALSE;
static UMTX gICUInitMutex = NULL;
static cleanupFunc *gLibCleanupFunctions[UCLN_COMMON];
U_CAPI void U_EXPORT2
ucln_registerCleanup(ECleanupLibraryType type,
cleanupFunc *func)
{
U_ASSERT(UCLN_START < type && type < UCLN_COMMON);
if (UCLN_START < type && type < UCLN_COMMON)
{
gLibCleanupFunctions[type] = func;
}
}
/************************************************
The cleanup order is important in this function.
Please be sure that you have read ucln.h
************************************************/
U_CAPI void U_EXPORT2
u_cleanup(void)
{
ECleanupLibraryType libType;
UTRACE_ENTRY_OC(UTRACE_U_CLEANUP);
umtx_lock(NULL); /* Force a memory barrier, so that we are sure to see */
umtx_unlock(NULL); /* all state left around by any other threads. */
for (libType = UCLN_START+1; libType<UCLN_COMMON; libType++) {
if (gLibCleanupFunctions[libType])
{
gLibCleanupFunctions[libType]();
gLibCleanupFunctions[libType] = NULL;
}
}
ucln_common_lib_cleanup();
umtx_destroy(&gICUInitMutex);
umtx_cleanup();
cmemory_cleanup(); /* undo any heap functions set by u_setMemoryFunctions(). */
gICUInitialized = FALSE;
UTRACE_EXIT(); /* Must be before utrace_cleanup(), which turns off tracing. */
utrace_cleanup();
}
/*
*
* ICU Initialization Function. Force loading and/or initialization of
* any shared data that could potentially be used concurrently
* by multiple threads.
*/
U_CAPI void U_EXPORT2
u_init(UErrorCode *status) {
UTRACE_ENTRY_OC(UTRACE_U_INIT);
/* Make sure the global mutexes are initialized. */
umtx_init(NULL);
umtx_lock(&gICUInitMutex);
if (gICUInitialized || U_FAILURE(*status)) {
umtx_unlock(&gICUInitMutex);
UTRACE_EXIT_STATUS(*status);
return;
}
/* Do any required init for services that don't have open operations
* and use "only" the double-check initialization method for performance
* reasons (avoiding a mutex lock even for _checking_ whether the
* initialization had occurred).
*/
/* Char Properties */
uprv_loadPropsData(status);
#if !UCONFIG_NO_NORMALIZATION
/* Normalization */
unorm_haveData(status);
#endif
gICUInitialized = TRUE; /* TODO: don't set if U_FAILURE? */
umtx_unlock(&gICUInitMutex);
UTRACE_EXIT_STATUS(*status);
}

View File

@ -2660,6 +2660,20 @@ uloc_getDisplayKeywordValue( const char* locale,
/* ### Get available **************************************************/
static UBool U_CALLCONV uloc_cleanup(void) {
char ** temp;
if (_installedLocales) {
temp = _installedLocales;
_installedLocales = NULL;
_installedLocalesCount = 0;
uprv_free(temp);
}
return TRUE;
}
static void _load_installedLocales()
{
UBool localesLoaded;
@ -2696,6 +2710,7 @@ static void _load_installedLocales()
_installedLocales = temp;
_installedLocalesCount = localeCount;
temp = NULL;
ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup);
}
umtx_unlock(NULL);
@ -2724,20 +2739,6 @@ uloc_countAvailable()
return _installedLocalesCount;
}
UBool uloc_cleanup(void) {
char ** temp;
if (_installedLocales) {
temp = _installedLocales;
_installedLocales = NULL;
_installedLocalesCount = 0;
uprv_free(temp);
}
return TRUE;
}
/**
* Returns a list of all language codes defined in ISO 639. This is a pointer
* to an array of pointers to arrays of char. All of these pointers are owned

View File

@ -85,8 +85,7 @@ charCatNames[U_CHAR_EXTENDED_CATEGORY_COUNT];
/* implementation ----------------------------------------------------------- */
UBool
unames_cleanup()
static UBool U_CALLCONV unames_cleanup(void)
{
if(uCharNamesData) {
udata_close(uCharNamesData);
@ -151,6 +150,7 @@ isDataLoaded(UErrorCode *pErrorCode) {
uCharNamesData=data;
data=NULL;
names=NULL;
ucln_common_registerCleanup(UCLN_COMMON_UNAMES, unames_cleanup);
}
umtx_unlock(NULL);
}

View File

@ -27,6 +27,7 @@
#include "ruleiter.h"
#include "cmemory.h"
#include "uhash.h"
#include "ucln_cmn.h"
#include "util.h"
#include "uvector.h"
#include "uprops.h"
@ -1464,6 +1465,32 @@ _set_addString(USet *set, const UChar *str, int32_t length) {
((UnicodeSet *)set)->add(UnicodeString((UBool)(length<0), str, length));
}
/**
* Cleanup function for UnicodeSet
*/
static UBool U_CALLCONV uset_cleanup(void) {
int32_t i;
for(i = UPROPS_SRC_NONE; i < UPROPS_SRC_COUNT; ++i) {
if (INCLUSIONS[i] != NULL) {
delete INCLUSIONS[i];
INCLUSIONS[i] = NULL;
}
}
if (CASE_EQUIV_HASH != NULL) {
delete CASE_EQUIV_HASH;
CASE_EQUIV_HASH = NULL;
}
if (CASE_EQUIV_CBA != NULL) {
ucmp8_close(CASE_EQUIV_CBA);
CASE_EQUIV_CBA = NULL;
}
return TRUE;
}
U_CDECL_END
const UnicodeSet* UnicodeSet::getInclusions(int32_t src, UErrorCode &status) {
@ -1503,8 +1530,9 @@ const UnicodeSet* UnicodeSet::getInclusions(int32_t src, UErrorCode &status) {
umtx_lock(NULL);
if (INCLUSIONS[src] == NULL) {
INCLUSIONS[src] = incl;
incl = NULL;
}
incl = NULL;
ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup);
}
umtx_unlock(NULL);
}
delete incl;
@ -1515,32 +1543,6 @@ const UnicodeSet* UnicodeSet::getInclusions(int32_t src, UErrorCode &status) {
return INCLUSIONS[src];
}
/**
* Cleanup function for UnicodeSet
*/
U_CFUNC UBool uset_cleanup(void) {
int32_t i;
for(i = UPROPS_SRC_NONE; i < UPROPS_SRC_COUNT; ++i) {
if (INCLUSIONS[i] != NULL) {
delete INCLUSIONS[i];
INCLUSIONS[i] = NULL;
}
}
if (CASE_EQUIV_HASH != NULL) {
delete CASE_EQUIV_HASH;
CASE_EQUIV_HASH = NULL;
}
if (CASE_EQUIV_CBA != NULL) {
ucmp8_close(CASE_EQUIV_CBA);
CASE_EQUIV_CBA = NULL;
}
return TRUE;
}
//----------------------------------------------------------------
// Case folding API
//----------------------------------------------------------------
@ -2030,6 +2032,7 @@ const CaseEquivClass* UnicodeSet::getCaseMapOf(const UnicodeString& folded) {
if (CASE_EQUIV_HASH == NULL) {
CASE_EQUIV_HASH = hash;
hash = NULL;
ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup);
}
umtx_unlock(NULL);
}
@ -2073,6 +2076,7 @@ const CaseEquivClass* UnicodeSet::getCaseMapOf(UChar folded) {
if (CASE_EQUIV_CBA == NULL) {
CASE_EQUIV_CBA = cba;
cba = NULL;
ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup);
}
umtx_unlock(NULL);
if (cba != NULL) {

View File

@ -33,6 +33,7 @@
#include "unicode/uniset.h"
#include "unicode/usetiter.h"
#include "unicode/unorm.h"
#include "ucln_cmn.h"
#include "unormimp.h"
#include "ucase.h"
#include "cmemory.h"
@ -189,7 +190,7 @@ static UnicodeSet *nxCache[_NORM_OPTIONS_SETS_MASK+1]={ NULL };
U_CDECL_BEGIN
UBool
static UBool U_CALLCONV
unorm_cleanup() {
int32_t i;
@ -348,6 +349,7 @@ loadNormData(UErrorCode &errorCode) {
(indexes[_NORM_INDEX_FCD_TRIE_SIZE]+indexes[_NORM_INDEX_AUX_TRIE_SIZE])/2;
}
haveNormData=1;
ucln_common_registerCleanup(UCLN_COMMON_UNORM, unorm_cleanup);
umtx_unlock(NULL);
/* if a different thread set it first, then close the extra data */

View File

@ -138,29 +138,6 @@ static const ResourceData *getFallbackData(const UResourceBundle* resBundle, con
}
}
/** INTERNAL: Initializes the cache for resources */
static void initCache(UErrorCode *status) {
UBool makeCache = FALSE;
umtx_lock(&resbMutex);
makeCache = (cache == NULL);
umtx_unlock(&resbMutex);
if(makeCache) {
UHashtable *newCache = uhash_open(hashEntry, compareEntries, status);
if (U_FAILURE(*status)) {
return;
}
umtx_lock(&resbMutex);
if(cache == NULL) {
cache = newCache;
newCache = NULL;
}
umtx_unlock(&resbMutex);
if(newCache != NULL) {
uhash_close(newCache);
}
}
}
/* Works just like ucnv_flushCache() */
/* TODO: figure out why fCountExisting may not go to zero. Do not make this function public yet. */
static int32_t ures_flushCache()
@ -214,7 +191,7 @@ static int32_t ures_flushCache()
return rbDeletedNum;
}
UBool ures_cleanup(void)
static UBool U_CALLCONV ures_cleanup(void)
{
if (cache != NULL) {
ures_flushCache();
@ -229,6 +206,29 @@ UBool ures_cleanup(void)
return (cache == NULL);
}
/** INTERNAL: Initializes the cache for resources */
static void initCache(UErrorCode *status) {
UBool makeCache = FALSE;
umtx_lock(&resbMutex);
makeCache = (cache == NULL);
umtx_unlock(&resbMutex);
if(makeCache) {
UHashtable *newCache = uhash_open(hashEntry, compareEntries, status);
if (U_FAILURE(*status)) {
return;
}
umtx_lock(&resbMutex);
if(cache == NULL) {
cache = newCache;
newCache = NULL;
ucln_common_registerCleanup(UCLN_COMMON_URES, ures_cleanup);
}
umtx_unlock(&resbMutex);
if(newCache != NULL) {
uhash_close(newCache);
}
}
}
/** INTERNAL: sets the name (locale) of the resource bundle to given name */

View File

@ -31,6 +31,7 @@
#include "uhash.h"
#include "cstring.h"
#include "udataswp.h"
#include "ucln_cmn.h"
#include "unormimp.h"
U_CDECL_BEGIN
@ -104,9 +105,85 @@ compareEntries(const UHashTok p1, const UHashTok p2) {
uhash_compareChars(path1, path2)));
}
static void
usprep_unload(UStringPrepProfile* data){
udata_close(data->sprepData);
}
static int32_t
usprep_internal_flushCache(UBool noRefCount){
UStringPrepProfile *profile = NULL;
UStringPrepKey *key = NULL;
int32_t pos = -1;
int32_t deletedNum = 0;
const UHashElement *e;
/*
* if shared data hasn't even been lazy evaluated yet
* return 0
*/
umtx_lock(&usprepMutex);
if (SHARED_DATA_HASHTABLE == NULL) {
umtx_unlock(&usprepMutex);
return 0;
}
/*creates an enumeration to iterate through every element in the table */
while ((e = uhash_nextElement(SHARED_DATA_HASHTABLE, &pos)) != NULL)
{
profile = (UStringPrepProfile *) e->value.pointer;
key = (UStringPrepKey *) e->key.pointer;
if ((noRefCount== FALSE && profile->refCount == 0) ||
noRefCount== TRUE) {
deletedNum++;
uhash_removeElement(SHARED_DATA_HASHTABLE, e);
/* unload the data */
usprep_unload(profile);
if(key->name != NULL) {
uprv_free(key->name);
key->name=NULL;
}
if(key->path != NULL) {
uprv_free(key->path);
key->path=NULL;
}
uprv_free(profile);
uprv_free(key);
}
}
umtx_unlock(&usprepMutex);
return deletedNum;
}
/* Works just like ucnv_flushCache()
static int32_t
usprep_flushCache(){
return usprep_internal_flushCache(FALSE);
}
*/
static UBool U_CALLCONV usprep_cleanup(void){
if (SHARED_DATA_HASHTABLE != NULL) {
usprep_internal_flushCache(TRUE);
if (SHARED_DATA_HASHTABLE != NULL && uhash_count(SHARED_DATA_HASHTABLE) == 0) {
uhash_close(SHARED_DATA_HASHTABLE);
SHARED_DATA_HASHTABLE = NULL;
}
}
umtx_destroy(&usprepMutex); /* Don't worry about destroying the mutex even */
/* if the hash table still exists. The mutex */
/* will lazily re-init itself if needed. */
return (SHARED_DATA_HASHTABLE == NULL);
}
U_CDECL_END
U_CFUNC void
static void
usprep_init() {
umtx_init(&usprepMutex);
}
@ -114,25 +191,26 @@ usprep_init() {
/** Initializes the cache for resources */
static void
initCache(UErrorCode *status) {
UBool makeCache = FALSE;
umtx_lock(&usprepMutex);
makeCache = (SHARED_DATA_HASHTABLE == NULL);
umtx_unlock(&usprepMutex);
if(makeCache) {
UHashtable *newCache = uhash_open(hashEntry, compareEntries, status);
if (U_FAILURE(*status)) {
return;
}
umtx_lock(&usprepMutex);
if(SHARED_DATA_HASHTABLE == NULL) {
SHARED_DATA_HASHTABLE = newCache;
newCache = NULL;
}
umtx_unlock(&usprepMutex);
if(newCache != NULL) {
uhash_close(newCache);
}
}
UBool makeCache = FALSE;
umtx_lock(&usprepMutex);
makeCache = (SHARED_DATA_HASHTABLE == NULL);
umtx_unlock(&usprepMutex);
if(makeCache) {
UHashtable *newCache = uhash_open(hashEntry, compareEntries, status);
if (U_FAILURE(*status)) {
return;
}
umtx_lock(&usprepMutex);
if(SHARED_DATA_HASHTABLE == NULL) {
SHARED_DATA_HASHTABLE = newCache;
ucln_common_registerCleanup(UCLN_COMMON_USPREP, usprep_cleanup);
newCache = NULL;
}
umtx_unlock(&usprepMutex);
if(newCache != NULL) {
uhash_close(newCache);
}
}
}
static UBool U_CALLCONV
@ -337,85 +415,6 @@ usprep_close(UStringPrepProfile* profile){
}
static void
usprep_unload(UStringPrepProfile* data){
udata_close(data->sprepData);
}
static int32_t
usprep_internal_flushCache(UBool noRefCount){
UStringPrepProfile *profile = NULL;
UStringPrepKey *key = NULL;
int32_t pos = -1;
int32_t deletedNum = 0;
const UHashElement *e;
/*
* if shared data hasn't even been lazy evaluated yet
* return 0
*/
umtx_lock(&usprepMutex);
if (SHARED_DATA_HASHTABLE == NULL) {
umtx_unlock(&usprepMutex);
return 0;
}
/*creates an enumeration to iterate through every element in the table */
while ((e = uhash_nextElement(SHARED_DATA_HASHTABLE, &pos)) != NULL)
{
profile = (UStringPrepProfile *) e->value.pointer;
key = (UStringPrepKey *) e->key.pointer;
if ((noRefCount== FALSE && profile->refCount == 0) ||
noRefCount== TRUE) {
deletedNum++;
uhash_removeElement(SHARED_DATA_HASHTABLE, e);
/* unload the data */
usprep_unload(profile);
if(key->name != NULL) {
uprv_free(key->name);
key->name=NULL;
}
if(key->path != NULL) {
uprv_free(key->path);
key->path=NULL;
}
uprv_free(profile);
uprv_free(key);
}
}
umtx_unlock(&usprepMutex);
return deletedNum;
}
/* Works just like ucnv_flushCache()
static int32_t
usprep_flushCache(){
return usprep_internal_flushCache(FALSE);
}
*/
U_CFUNC UBool
usprep_cleanup(void){
if (SHARED_DATA_HASHTABLE != NULL) {
usprep_internal_flushCache(TRUE);
if (SHARED_DATA_HASHTABLE != NULL && uhash_count(SHARED_DATA_HASHTABLE) == 0) {
uhash_close(SHARED_DATA_HASHTABLE);
SHARED_DATA_HASHTABLE = NULL;
}
}
umtx_destroy(&usprepMutex); /* Don't worry about destroying the mutex even */
/* if the hash table still exists. The mutex */
/* will lazily re-init itself if needed. */
return (SHARED_DATA_HASHTABLE == NULL);
}
U_CFUNC void
uprv_syntaxError(const UChar* rules,
int32_t pos,