ucln_cmn.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /*
  4. ******************************************************************************
  5. * Copyright (C) 2001-2014, International Business Machines
  6. * Corporation and others. All Rights Reserved.
  7. ******************************************************************************
  8. * file name: ucln_cmn.cpp
  9. * encoding: UTF-8
  10. * tab size: 8 (not used)
  11. * indentation:4
  12. *
  13. * created on: 2001July05
  14. * created by: George Rhoten
  15. */
  16. #include "unicode/utypes.h"
  17. #include "unicode/uclean.h"
  18. #include "cmemory.h"
  19. #include "mutex.h"
  20. #include "uassert.h"
  21. #include "ucln.h"
  22. #include "ucln_cmn.h"
  23. #include "utracimp.h"
  24. #include "umutex.h"
  25. /** Auto-client for UCLN_COMMON **/
  26. #define UCLN_TYPE_IS_COMMON
  27. #include "ucln_imp.h"
  28. static cleanupFunc *gCommonCleanupFunctions[UCLN_COMMON_COUNT];
  29. static cleanupFunc *gLibCleanupFunctions[UCLN_COMMON];
  30. /************************************************
  31. The cleanup order is important in this function.
  32. Please be sure that you have read ucln.h
  33. ************************************************/
  34. U_CAPI void U_EXPORT2
  35. u_cleanup()
  36. {
  37. UTRACE_ENTRY_OC(UTRACE_U_CLEANUP);
  38. icu::umtx_lock(nullptr); /* Force a memory barrier, so that we are sure to see */
  39. icu::umtx_unlock(nullptr); /* all state left around by any other threads. */
  40. ucln_lib_cleanup();
  41. cmemory_cleanup(); /* undo any heap functions set by u_setMemoryFunctions(). */
  42. UTRACE_EXIT(); /* Must be before utrace_cleanup(), which turns off tracing. */
  43. /*#if U_ENABLE_TRACING*/
  44. utrace_cleanup();
  45. /*#endif*/
  46. }
  47. U_CAPI void U_EXPORT2 ucln_cleanupOne(ECleanupLibraryType libType)
  48. {
  49. if (gLibCleanupFunctions[libType])
  50. {
  51. gLibCleanupFunctions[libType]();
  52. gLibCleanupFunctions[libType] = nullptr;
  53. }
  54. }
  55. U_CFUNC void
  56. ucln_common_registerCleanup(ECleanupCommonType type,
  57. cleanupFunc *func)
  58. {
  59. // Thread safety messiness: From ticket 10295, calls to registerCleanup() may occur
  60. // concurrently. Although such cases should be storing the same value, they raise errors
  61. // from the thread sanity checker. Doing the store within a mutex avoids those.
  62. // BUT that can trigger a recursive entry into std::call_once() in umutex.cpp when this code,
  63. // running from the call_once function, tries to grab the ICU global mutex, which
  64. // re-enters the mutex init path. So, work-around by special casing UCLN_COMMON_MUTEX, not
  65. // using the ICU global mutex for it.
  66. //
  67. // No other point in ICU uses std::call_once().
  68. U_ASSERT(UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT);
  69. if (type == UCLN_COMMON_MUTEX) {
  70. gCommonCleanupFunctions[type] = func;
  71. } else if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT) {
  72. icu::Mutex m; // See ticket 10295 for discussion.
  73. gCommonCleanupFunctions[type] = func;
  74. }
  75. #if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL))
  76. ucln_registerAutomaticCleanup();
  77. #endif
  78. }
  79. // Note: ucln_registerCleanup() is called with the ICU global mutex locked.
  80. // Be aware if adding anything to the function.
  81. // See ticket 10295 for discussion.
  82. U_CAPI void U_EXPORT2
  83. ucln_registerCleanup(ECleanupLibraryType type,
  84. cleanupFunc *func)
  85. {
  86. U_ASSERT(UCLN_START < type && type < UCLN_COMMON);
  87. if (UCLN_START < type && type < UCLN_COMMON)
  88. {
  89. gLibCleanupFunctions[type] = func;
  90. }
  91. }
  92. U_CFUNC UBool ucln_lib_cleanup() {
  93. int32_t libType = UCLN_START;
  94. int32_t commonFunc = UCLN_COMMON_START;
  95. for (libType++; libType<UCLN_COMMON; libType++) {
  96. ucln_cleanupOne(static_cast<ECleanupLibraryType>(libType));
  97. }
  98. for (commonFunc++; commonFunc<UCLN_COMMON_COUNT; commonFunc++) {
  99. if (gCommonCleanupFunctions[commonFunc])
  100. {
  101. gCommonCleanupFunctions[commonFunc]();
  102. gCommonCleanupFunctions[commonFunc] = nullptr;
  103. }
  104. }
  105. #if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL))
  106. ucln_unRegisterAutomaticCleanup();
  107. #endif
  108. return true;
  109. }