Coverage Report

Created: 2025-06-24 06:43

/src/icu/source/common/ucln_cmn.cpp
Line
Count
Source (jump to first uncovered line)
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
17
#include "unicode/utypes.h"
18
#include "unicode/uclean.h"
19
#include "cmemory.h"
20
#include "mutex.h"
21
#include "uassert.h"
22
#include "ucln.h"
23
#include "ucln_cmn.h"
24
#include "utracimp.h"
25
#include "umutex.h"
26
27
/**  Auto-client for UCLN_COMMON **/
28
#define UCLN_TYPE_IS_COMMON
29
#include "ucln_imp.h"
30
31
static cleanupFunc *gCommonCleanupFunctions[UCLN_COMMON_COUNT];
32
static cleanupFunc *gLibCleanupFunctions[UCLN_COMMON];
33
34
35
/************************************************
36
 The cleanup order is important in this function.
37
 Please be sure that you have read ucln.h
38
 ************************************************/
39
U_CAPI void U_EXPORT2
40
u_cleanup(void)
41
0
{
42
0
    UTRACE_ENTRY_OC(UTRACE_U_CLEANUP);
43
0
    icu::umtx_lock(NULL);     /* Force a memory barrier, so that we are sure to see   */
44
0
    icu::umtx_unlock(NULL);   /*   all state left around by any other threads.        */
45
46
0
    ucln_lib_cleanup();
47
48
0
    cmemory_cleanup();       /* undo any heap functions set by u_setMemoryFunctions(). */
49
0
    UTRACE_EXIT();           /* Must be before utrace_cleanup(), which turns off tracing. */
50
/*#if U_ENABLE_TRACING*/
51
0
    utrace_cleanup();
52
/*#endif*/
53
0
}
54
55
U_CAPI void U_EXPORT2 ucln_cleanupOne(ECleanupLibraryType libType) 
56
0
{
57
0
    if (gLibCleanupFunctions[libType])
58
0
    {
59
0
        gLibCleanupFunctions[libType]();
60
0
        gLibCleanupFunctions[libType] = NULL;
61
0
    }
62
0
}
63
64
U_CFUNC void
65
ucln_common_registerCleanup(ECleanupCommonType type,
66
                            cleanupFunc *func)
67
0
{
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.
75
    //
76
    // No other point in ICU uses std::call_once().
77
78
0
    U_ASSERT(UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT);
79
0
    if (type == UCLN_COMMON_MUTEX) {
80
0
        gCommonCleanupFunctions[type] = func;
81
0
    } else if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT)  {
82
0
        icu::Mutex m;     // See ticket 10295 for discussion.
83
0
        gCommonCleanupFunctions[type] = func;
84
0
    }
85
#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL))
86
    ucln_registerAutomaticCleanup();
87
#endif
88
0
}
89
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.
93
94
U_CAPI void U_EXPORT2
95
ucln_registerCleanup(ECleanupLibraryType type,
96
                     cleanupFunc *func)
97
0
{
98
0
    U_ASSERT(UCLN_START < type && type < UCLN_COMMON);
99
0
    if (UCLN_START < type && type < UCLN_COMMON)
100
0
    {
101
0
        gLibCleanupFunctions[type] = func;
102
0
    }
103
0
}
104
105
0
U_CFUNC UBool ucln_lib_cleanup(void) {
106
0
    int32_t libType = UCLN_START;
107
0
    int32_t commonFunc = UCLN_COMMON_START;
108
109
0
    for (libType++; libType<UCLN_COMMON; libType++) {
110
0
        ucln_cleanupOne(static_cast<ECleanupLibraryType>(libType));
111
0
    }
112
113
0
    for (commonFunc++; commonFunc<UCLN_COMMON_COUNT; commonFunc++) {
114
0
        if (gCommonCleanupFunctions[commonFunc])
115
0
        {
116
0
            gCommonCleanupFunctions[commonFunc]();
117
0
            gCommonCleanupFunctions[commonFunc] = NULL;
118
0
        }
119
0
    }
120
#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL))
121
    ucln_unRegisterAutomaticCleanup();
122
#endif
123
0
    return TRUE;
124
0
}