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