123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- // © 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;
- }
|