diff options
Diffstat (limited to 'intl/icu/source/common/ucln_cmn.cpp')
-rw-r--r-- | intl/icu/source/common/ucln_cmn.cpp | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/intl/icu/source/common/ucln_cmn.cpp b/intl/icu/source/common/ucln_cmn.cpp new file mode 100644 index 0000000000..c63bd22192 --- /dev/null +++ b/intl/icu/source/common/ucln_cmn.cpp @@ -0,0 +1,124 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +****************************************************************************** +* Copyright (C) 2001-2014, International Business Machines +* Corporation and others. All Rights Reserved. +****************************************************************************** +* file name: ucln_cmn.cpp +* encoding: UTF-8 +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2001July05 +* created by: George Rhoten +*/ + +#include "unicode/utypes.h" +#include "unicode/uclean.h" +#include "cmemory.h" +#include "mutex.h" +#include "uassert.h" +#include "ucln.h" +#include "ucln_cmn.h" +#include "utracimp.h" +#include "umutex.h" + +/** Auto-client for UCLN_COMMON **/ +#define UCLN_TYPE_IS_COMMON +#include "ucln_imp.h" + +static cleanupFunc *gCommonCleanupFunctions[UCLN_COMMON_COUNT]; +static cleanupFunc *gLibCleanupFunctions[UCLN_COMMON]; + + +/************************************************ + The cleanup order is important in this function. + Please be sure that you have read ucln.h + ************************************************/ +U_CAPI void U_EXPORT2 +u_cleanup() +{ + UTRACE_ENTRY_OC(UTRACE_U_CLEANUP); + icu::umtx_lock(nullptr); /* Force a memory barrier, so that we are sure to see */ + icu::umtx_unlock(nullptr); /* all state left around by any other threads. */ + + ucln_lib_cleanup(); + + cmemory_cleanup(); /* undo any heap functions set by u_setMemoryFunctions(). */ + UTRACE_EXIT(); /* Must be before utrace_cleanup(), which turns off tracing. */ +/*#if U_ENABLE_TRACING*/ + utrace_cleanup(); +/*#endif*/ +} + +U_CAPI void U_EXPORT2 ucln_cleanupOne(ECleanupLibraryType libType) +{ + if (gLibCleanupFunctions[libType]) + { + gLibCleanupFunctions[libType](); + gLibCleanupFunctions[libType] = nullptr; + } +} + +U_CFUNC void +ucln_common_registerCleanup(ECleanupCommonType type, + cleanupFunc *func) +{ + // Thread safety messiness: From ticket 10295, calls to registerCleanup() may occur + // concurrently. Although such cases should be storing the same value, they raise errors + // from the thread sanity checker. Doing the store within a mutex avoids those. + // BUT that can trigger a recursive entry into std::call_once() in umutex.cpp when this code, + // running from the call_once function, tries to grab the ICU global mutex, which + // re-enters the mutex init path. So, work-around by special casing UCLN_COMMON_MUTEX, not + // using the ICU global mutex for it. + // + // No other point in ICU uses std::call_once(). + + U_ASSERT(UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT); + if (type == UCLN_COMMON_MUTEX) { + gCommonCleanupFunctions[type] = func; + } else if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT) { + icu::Mutex m; // See ticket 10295 for discussion. + gCommonCleanupFunctions[type] = func; + } +#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL)) + ucln_registerAutomaticCleanup(); +#endif +} + +// Note: ucln_registerCleanup() is called with the ICU global mutex locked. +// Be aware if adding anything to the function. +// See ticket 10295 for discussion. + +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; + } +} + +U_CFUNC UBool ucln_lib_cleanup() { + int32_t libType = UCLN_START; + int32_t commonFunc = UCLN_COMMON_START; + + for (libType++; libType<UCLN_COMMON; libType++) { + ucln_cleanupOne(static_cast<ECleanupLibraryType>(libType)); + } + + for (commonFunc++; commonFunc<UCLN_COMMON_COUNT; commonFunc++) { + if (gCommonCleanupFunctions[commonFunc]) + { + gCommonCleanupFunctions[commonFunc](); + gCommonCleanupFunctions[commonFunc] = nullptr; + } + } +#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL)) + ucln_unRegisterAutomaticCleanup(); +#endif + return true; +} |