1/*
2******************************************************************************
3* Copyright (C) 2001-2013, 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 "cmutex.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
28static cleanupFunc *gCommonCleanupFunctions[UCLN_COMMON_COUNT];
29static cleanupFunc *gLibCleanupFunctions[UCLN_COMMON];
30
31
32/************************************************
33 The cleanup order is important in this function.
34 Please be sure that you have read ucln.h
35 ************************************************/
36U_CAPI void U_EXPORT2
37u_cleanup(void)
38{
39    UTRACE_ENTRY_OC(UTRACE_U_CLEANUP);
40    umtx_lock(NULL);     /* Force a memory barrier, so that we are sure to see   */
41    umtx_unlock(NULL);   /*   all state left around by any other threads.        */
42
43    ucln_lib_cleanup();
44
45    cmemory_cleanup();       /* undo any heap functions set by u_setMemoryFunctions(). */
46    UTRACE_EXIT();           /* Must be before utrace_cleanup(), which turns off tracing. */
47/*#if U_ENABLE_TRACING*/
48    utrace_cleanup();
49/*#endif*/
50}
51
52U_CAPI void U_EXPORT2 ucln_cleanupOne(ECleanupLibraryType libType)
53{
54    if (gLibCleanupFunctions[libType])
55    {
56        gLibCleanupFunctions[libType]();
57        gLibCleanupFunctions[libType] = NULL;
58    }
59}
60
61U_CFUNC void
62ucln_common_registerCleanup(ECleanupCommonType type,
63                            cleanupFunc *func)
64{
65    U_ASSERT(UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT);
66    if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT)
67    {
68        gCommonCleanupFunctions[type] = func;
69    }
70#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL))
71    ucln_registerAutomaticCleanup();
72#endif
73}
74
75U_CAPI void U_EXPORT2
76ucln_registerCleanup(ECleanupLibraryType type,
77                     cleanupFunc *func)
78{
79    U_ASSERT(UCLN_START < type && type < UCLN_COMMON);
80    if (UCLN_START < type && type < UCLN_COMMON)
81    {
82        gLibCleanupFunctions[type] = func;
83    }
84}
85
86U_CFUNC UBool ucln_lib_cleanup(void) {
87    ECleanupLibraryType libType = UCLN_START;
88    ECleanupCommonType commonFunc = UCLN_COMMON_START;
89
90    for (libType++; libType<UCLN_COMMON; libType++) {
91        ucln_cleanupOne(libType);
92    }
93
94    for (commonFunc++; commonFunc<UCLN_COMMON_COUNT; commonFunc++) {
95        if (gCommonCleanupFunctions[commonFunc])
96        {
97            gCommonCleanupFunctions[commonFunc]();
98            gCommonCleanupFunctions[commonFunc] = NULL;
99        }
100    }
101#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL))
102    ucln_unRegisterAutomaticCleanup();
103#endif
104    return TRUE;
105}
106