1 /* 2 ****************************************************************************** 3 * Copyright (C) 2001-2012, International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ****************************************************************************** 6 * file name: ucln_cmn.c 7 * encoding: US-ASCII 8 * tab size: 8 (not used) 9 * indentation:4 10 * 11 * created on: 2001July05 12 * created by: George Rhoten 13 */ 14 15 #include "unicode/utypes.h" 16 #include "unicode/uclean.h" 17 #include "utracimp.h" 18 #include "ucln_cmn.h" 19 #include "umutex.h" 20 #include "ucln.h" 21 #include "cmemory.h" 22 #include "uassert.h" 23 24 /** Auto-client for UCLN_COMMON **/ 25 #define UCLN_TYPE_IS_COMMON 26 #include "ucln_imp.h" 27 28 static UBool gICUInitialized = FALSE; 29 static UMutex gICUInitMutex = U_MUTEX_INITIALIZER; 30 31 static cleanupFunc *gCommonCleanupFunctions[UCLN_COMMON_COUNT]; 32 static cleanupFunc *gLibCleanupFunctions[UCLN_COMMON]; 33 34 U_CFUNC UBool ucln_mutexedInit(initFunc *func, UErrorCode *status) { 35 UBool initialized = FALSE; 36 umtx_lock(&gICUInitMutex); 37 if (!gICUInitialized && U_SUCCESS(*status)) { 38 if (func != NULL) { 39 func(status); 40 } 41 gICUInitialized = TRUE; /* TODO: don't set if U_FAILURE? */ 42 initialized = TRUE; 43 } 44 umtx_unlock(&gICUInitMutex); 45 return initialized; 46 } 47 48 /************************************************ 49 The cleanup order is important in this function. 50 Please be sure that you have read ucln.h 51 ************************************************/ 52 U_CAPI void U_EXPORT2 53 u_cleanup(void) 54 { 55 UTRACE_ENTRY_OC(UTRACE_U_CLEANUP); 56 umtx_lock(NULL); /* Force a memory barrier, so that we are sure to see */ 57 umtx_unlock(NULL); /* all state left around by any other threads. */ 58 59 ucln_lib_cleanup(); 60 61 umtx_cleanup(); 62 cmemory_cleanup(); /* undo any heap functions set by u_setMemoryFunctions(). */ 63 gICUInitialized = FALSE; 64 UTRACE_EXIT(); /* Must be before utrace_cleanup(), which turns off tracing. */ 65 /*#if U_ENABLE_TRACING*/ 66 utrace_cleanup(); 67 /*#endif*/ 68 } 69 70 U_CAPI void U_EXPORT2 ucln_cleanupOne(ECleanupLibraryType libType) 71 { 72 if (gLibCleanupFunctions[libType]) 73 { 74 gLibCleanupFunctions[libType](); 75 gLibCleanupFunctions[libType] = NULL; 76 } 77 } 78 79 U_CFUNC void 80 ucln_common_registerCleanup(ECleanupCommonType type, 81 cleanupFunc *func) 82 { 83 U_ASSERT(UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT); 84 if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT) 85 { 86 gCommonCleanupFunctions[type] = func; 87 } 88 #if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL)) 89 ucln_registerAutomaticCleanup(); 90 #endif 91 } 92 93 U_CAPI void U_EXPORT2 94 ucln_registerCleanup(ECleanupLibraryType type, 95 cleanupFunc *func) 96 { 97 U_ASSERT(UCLN_START < type && type < UCLN_COMMON); 98 if (UCLN_START < type && type < UCLN_COMMON) 99 { 100 gLibCleanupFunctions[type] = func; 101 } 102 } 103 104 U_CFUNC UBool ucln_lib_cleanup(void) { 105 ECleanupLibraryType libType = UCLN_START; 106 ECleanupCommonType commonFunc = UCLN_COMMON_START; 107 108 for (libType++; libType<UCLN_COMMON; libType++) { 109 ucln_cleanupOne(libType); 110 } 111 112 for (commonFunc++; commonFunc<UCLN_COMMON_COUNT; commonFunc++) { 113 if (gCommonCleanupFunctions[commonFunc]) 114 { 115 gCommonCleanupFunctions[commonFunc](); 116 gCommonCleanupFunctions[commonFunc] = NULL; 117 } 118 } 119 #if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL)) 120 ucln_unRegisterAutomaticCleanup(); 121 #endif 122 return TRUE; 123 } 124