diff --git a/icu4c/source/common/Makefile.in b/icu4c/source/common/Makefile.in
index 5859e683c26..3b39c378787 100644
--- a/icu4c/source/common/Makefile.in
+++ b/icu4c/source/common/Makefile.in
@@ -60,7 +60,7 @@ CXXFLAGS += $(LIBCXXFLAGS)
ifneq ($(top_builddir),$(top_srcdir))
CPPFLAGS += -I$(top_builddir)/common
endif
-CPPFLAGS += -I$(srcdir) -I$(top_srcdir)/i18n $(LIBCPPFLAGS)
+CPPFLAGS += -I$(srcdir) -I$(top_srcdir)/i18n $(LIBCPPFLAGS) $(CPPFLAGSICUUC)
DEFS += -DU_COMMON_IMPLEMENTATION
LDFLAGS += $(LDFLAGSICUUC)
diff --git a/icu4c/source/common/common.vcproj b/icu4c/source/common/common.vcproj
index f6d15af6ba3..c0d10cb3557 100644
--- a/icu4c/source/common/common.vcproj
+++ b/icu4c/source/common/common.vcproj
@@ -2135,11 +2135,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/icu4c/source/common/ucln.h b/icu4c/source/common/ucln.h
index a4573e93bb2..6c99e6c264e 100644
--- a/icu4c/source/common/ucln.h
+++ b/icu4c/source/common/ucln.h
@@ -1,7 +1,7 @@
/*
******************************************************************************
* *
-* Copyright (C) 2001-2007, International Business Machines *
+* Copyright (C) 2001-2009, International Business Machines *
* Corporation and others. All Rights Reserved. *
* *
******************************************************************************
@@ -47,6 +47,9 @@
* Please see common/ucln_cmn.{h,c} and i18n/ucln_in.{h,c} for examples.
*/
+/**
+ * Data Type for cleanup function selector. These roughly correspond to libraries.
+ */
typedef enum ECleanupLibraryType {
UCLN_START = -1,
UCLN_CUSTOM, /* Custom is for anyone else. */
@@ -58,11 +61,27 @@ typedef enum ECleanupLibraryType {
UCLN_COMMON /* This must be the last one to cleanup. */
} ECleanupLibraryType;
+/**
+ * Data type for cleanup function pointer
+ */
U_CDECL_BEGIN
typedef UBool U_CALLCONV cleanupFunc(void);
U_CDECL_END
+/**
+ * Register a cleanup function
+ * @param type which library to register for.
+ * @param func the function pointer
+ */
U_CAPI void U_EXPORT2 ucln_registerCleanup(ECleanupLibraryType type,
cleanupFunc *func);
+/**
+ * Request cleanup for one specific library.
+ * Not thread safe.
+ * Calling this with UCLN_COMMON just calls u_cleanup();
+ * @param type which library to cleanup
+ */
+U_CAPI void U_EXPORT2 ucln_cleanupOne(ECleanupLibraryType type);
+
#endif
diff --git a/icu4c/source/common/ucln_cmn.c b/icu4c/source/common/ucln_cmn.c
index 452e628bb38..66c8fb8535a 100644
--- a/icu4c/source/common/ucln_cmn.c
+++ b/icu4c/source/common/ucln_cmn.c
@@ -1,7 +1,7 @@
/*
******************************************************************************
* *
-* Copyright (C) 2001-2006, International Business Machines *
+* Copyright (C) 2001-2009, International Business Machines *
* Corporation and others. All Rights Reserved. *
* *
******************************************************************************
@@ -25,9 +25,49 @@
#include "cmemory.h"
#include "uassert.h"
+/** Auto-client for UCLN_COMMON **/
+#define UCLN_TYPE UCLN_COMMON
+#include "ucln_imp.h"
+
static cleanupFunc *gCommonCleanupFunctions[UCLN_COMMON_COUNT];
static cleanupFunc *gLibCleanupFunctions[UCLN_COMMON];
+
+/* Enables debugging information about when a library is cleaned up. */
+#ifndef UCLN_DEBUG_CLEANUP
+#define UCLN_DEBUG_CLEANUP 0
+#endif
+
+
+#if defined(UCLN_DEBUG_CLEANUP)
+#include
+#endif
+
+static void ucln_cleanup_internal(ECleanupLibraryType libType)
+{
+ if (gLibCleanupFunctions[libType])
+ {
+ gLibCleanupFunctions[libType]();
+ gLibCleanupFunctions[libType] = NULL;
+ }
+}
+
+U_CAPI void U_EXPORT2 ucln_cleanupOne(ECleanupLibraryType libType)
+{
+ if(libType==UCLN_COMMON) {
+#if UCLN_DEBUG_CLEANUP
+ fprintf(stderr, "Cleaning up: UCLN_COMMON with u_cleanup, type %d\n", (int)libType);
+#endif
+ u_cleanup();
+ } else {
+#if UCLN_DEBUG_CLEANUP
+ fprintf(stderr, "Cleaning up: using ucln_cleanup_internal, type %d\n", (int)libType);
+#endif
+ ucln_cleanup_internal(libType);
+ }
+}
+
+
U_CFUNC void
ucln_common_registerCleanup(ECleanupCommonType type,
cleanupFunc *func)
@@ -37,6 +77,9 @@ ucln_common_registerCleanup(ECleanupCommonType type,
{
gCommonCleanupFunctions[type] = func;
}
+#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL))
+ ucln_registerAutomaticCleanup();
+#endif
}
U_CAPI void U_EXPORT2
@@ -55,11 +98,7 @@ U_CFUNC UBool ucln_lib_cleanup(void) {
ECleanupCommonType commonFunc = UCLN_COMMON_START;
for (libType++; libType
+
+/**
+ * Auto cleanup of ICU libraries
+ * There are several methods in per library cleanup of icu libraries:
+ * 1) Compiler/Platform based cleanup:
+ * a) Windows MSVC uses DllMain()
+ * b) GCC uses destructor function attribute
+ * c) Sun Studio, AIX VA, and HP-UX aCC uses a linker option to set the exit function
+ * 2) Using atexit()
+ * 3) Implementing own automatic cleanup functions
+ *
+ * For option 1, ensure that UCLN_NO_AUTO_CLEANUP is set to 0 by using --enable-auto-cleanup
+ * configure option or by setting UCLN_NO_AUTO_CLEANUP to 0 in pwin32.h (For Visual Studio
+ * solution file builds)
+ * For option 2, follow option 1 and also define UCLN_AUTO_ATEXIT
+ * For option 3, follow option 1 and also define UCLN_AUTO_LOCAL (see below for more information)
+ */
+
+#if !UCLN_NO_AUTO_CLEANUP
+
+/*
+ * The following declarations are for when UCLN_AUTO_LOCAL or UCLN_AUTO_ATEXIT
+ * are defined. They are commented out because they are static and will be defined
+ * later. The information is still here to provide some guidance for the developer
+ * who chooses to use UCLN_AUTO_LOCAL.
+ */
+/**
+ * Give the library an opportunity to register an automatic cleanup.
+ * This may be called more than once.
+ */
+/*static void ucln_registerAutomaticCleanup();*/
+/**
+ * Unregister an automatic cleanup, if possible. Called from cleanup.
+ */
+/*static void ucln_unRegisterAutomaticCleanup();*/
+
+/* ------------ automatic cleanup: registration. Choose ONE ------- */
+#if defined(UCLN_AUTO_LOCAL)
+/* To use:
+ * 1. define UCLN_AUTO_LOCAL,
+ * 2. create ucln_local_hook.c containing implementations of
+ * static void ucln_registerAutomaticCleanup()
+ * static void ucln_unRegisterAutomaticCleanup()
+ */
+#include "ucln_local_hook.c"
+
+#elif defined(UCLN_AUTO_ATEXIT)
+/*
+ * Use the ANSI C 'atexit' function. Note that this mechanism does not
+ * guarantee the order of cleanup relative to other users of ICU!
+ */
+static UBool gAutoCleanRegistered = FALSE;
+
+static void ucln_atexit_handler()
+{
+ ucln_cleanupOne(UCLN_TYPE);
+}
+
+static void ucln_registerAutomaticCleanup()
+{
+ if(!gAutoCleanRegistered) {
+ gAutoCleanRegistered = TRUE;
+ atexit(&ucln_atexit_handler);
+ }
+}
+
+static void ucln_unRegisterAutomaticCleanup () {
+}
+/* ------------end of automatic cleanup: registration. ------- */
+
+#elif defined (UCLN_FINI)
+/**
+ * If UCLN_FINI is defined, it is the (versioned, etc) name of a cleanup
+ * entrypoint. Add a stub to call ucln_cleanupOne
+ * Used on AIX, Solaris, and HP-UX
+ */
+U_CAPI void U_EXPORT2 UCLN_FINI (void);
+
+U_CAPI void U_EXPORT2 UCLN_FINI ()
+{
+ /* This function must be defined, if UCLN_FINI is defined, else link error. */
+ ucln_cleanupOne(UCLN_TYPE);
+}
+#elif defined(__GNUC__)
+/* GCC - use __attribute((destructor)) */
+static void ucln_destructor() __attribute__((destructor)) ;
+
+static void ucln_destructor()
+{
+ ucln_cleanupOne(UCLN_TYPE);
+}
+
+/* Windows: DllMain */
+#elif defined (U_WINDOWS)
+/*
+ * ICU's own DllMain.
+ */
+
+/* these are from putil.c */
+/* READ READ READ READ! Are you getting compilation errors from windows.h?
+ Any source file which includes this (ucln_imp.h) header MUST
+ be defined with language extensions ON. */
+# define WIN32_LEAN_AND_MEAN
+# define VC_EXTRALEAN
+# define NOUSER
+# define NOSERVICE
+# define NOIME
+# define NOMCX
+# include
+/*
+ * This is a stub DllMain function with icu specific process handling code.
+ */
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ BOOL status = TRUE;
+
+ switch(fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ /* ICU does not trap process attach, but must pass these through properly. */
+ /* ICU specific process attach could go here */
+ break;
+
+ case DLL_PROCESS_DETACH:
+ /* Here is the one we actually care about. */
+
+ ucln_cleanupOne(UCLN_TYPE);
+
+ break;
+
+ case DLL_THREAD_ATTACH:
+ /* ICU does not trap thread attach, but must pass these through properly. */
+ /* ICU specific thread attach could go here */
+ break;
+
+ case DLL_THREAD_DETACH:
+ /* ICU does not trap thread detach, but must pass these through properly. */
+ /* ICU specific thread detach could go here */
+ break;
+
+ }
+ return status;
+}
+#endif
+
+#endif /* UCLN_NO_AUTO_CLEANUP */
+
+#else
+#error This file can only be included once.
+#endif
diff --git a/icu4c/source/common/unicode/platform.h.in b/icu4c/source/common/unicode/platform.h.in
index 04c9b4a3051..69be984522c 100644
--- a/icu4c/source/common/unicode/platform.h.in
+++ b/icu4c/source/common/unicode/platform.h.in
@@ -27,6 +27,11 @@
/* 1 or 0 to enable or disable threads. If undefined, default is: enable threads. */
#define ICU_USE_THREADS @ICU_USE_THREADS@
+/* Determine wheter to enable auto cleanup of libraries. */
+#ifndef UCLN_NO_AUTO_CLEANUP
+#define UCLN_NO_AUTO_CLEANUP @UCLN_NO_AUTO_CLEANUP@
+#endif
+
/* Need platform.h when using CYGWINMSVC to get definitions above. Ignore everything else. */
#ifndef CYGWINMSVC
diff --git a/icu4c/source/common/unicode/pwin32.h b/icu4c/source/common/unicode/pwin32.h
index e72671b178f..b728db791e8 100644
--- a/icu4c/source/common/unicode/pwin32.h
+++ b/icu4c/source/common/unicode/pwin32.h
@@ -185,6 +185,11 @@ typedef unsigned int uint32_t;
#define ICU_USE_THREADS 1
#endif
+/** 0 or 1 to enable or disable auto cleanup of libraries. If undefined, default is: disabled. */
+#ifndef UCLN_NO_AUTO_CLEANUP
+#define UCLN_NO_AUTO_CLEANUP 1
+#endif
+
/* On strong memory model CPUs (e.g. x86 CPUs), we use a safe & quick double check mutex lock. */
/**
Microsoft can define _M_IX86, _M_AMD64 (before Visual Studio 8) or _M_X64 (starting in Visual Studio 8).
diff --git a/icu4c/source/config/mh-aix-va b/icu4c/source/config/mh-aix-va
index 453ad4323c2..a7e88d39621 100644
--- a/icu4c/source/config/mh-aix-va
+++ b/icu4c/source/config/mh-aix-va
@@ -16,6 +16,24 @@ CXXFLAGS += -qproto -qroconst
# If you readd this line, you must change the SO value
#LDFLAGS += -brtl
+ifeq ($(UCLN_NO_AUTO_CLEANUP),0)
+# set up init point.
+UCLN_FINI = ucln_fini$(TARGET_STUBNAME)_$(SO_TARGET_VERSION_MAJOR)$(ICULIBSUFFIXCNAME)
+CPPFLAGS_FINI = -DUCLN_FINI=$(UCLN_FINI)
+LDFLAGS_FINI = -binitfini::$(UCLN_FINI)
+
+CPPFLAGSICUUC += $(CPPFLAGS_FINI)
+LDFLAGSICUUC += $(LDFLAGS_FINI)
+CPPFLAGSICUIO += $(CPPFLAGS_FINI)
+LDFLAGSICUIO += $(LDFLAGS_FINI)
+CPPFLAGSICUI18N += $(CPPFLAGS_FINI)
+LDFLAGSICUI18N += $(LDFLAGS_FINI)
+CPPFLAGSCTESTFW += $(CPPFLAGS_FINI)
+LDFLAGSCTESTFW += $(LDFLAGS_FINI)
+
+# ICUUC, ICUIO, ICUI18N, CTESTFW
+endif
+
## We need to delete things prior to linking, or else we'll get
## SEVERE ERROR: output file in use .. on AIX.
## But, shell script version should NOT delete target as we don't
diff --git a/icu4c/source/config/mh-hpux-acc b/icu4c/source/config/mh-hpux-acc
index cb294391003..bf1db030e90 100644
--- a/icu4c/source/config/mh-hpux-acc
+++ b/icu4c/source/config/mh-hpux-acc
@@ -27,6 +27,24 @@ THREADSCPPFLAGS = -D_REENTRANT -D_THREAD_SAFE
CFLAGS += -Ae +Olit=all
CXXFLAGS += -Wc,-ansi_for_scope,on +W740 +W749 +W823 +W4232
+ifeq ($(UCLN_NO_AUTO_CLEANUP),0)
+# set up init point.
+UCLN_FINI = ucln_fini$(TARGET_STUBNAME)_$(SO_TARGET_VERSION_MAJOR)$(ICULIBSUFFIXCNAME)
+CPPFLAGS_FINI = -DUCLN_FINI=$(UCLN_FINI)
+LDFLAGS_FINI = -Wl,+fini,$(UCLN_FINI)
+
+CPPFLAGSICUUC += $(CPPFLAGS_FINI)
+LDFLAGSICUUC += $(LDFLAGS_FINI)
+CPPFLAGSICUIO += $(CPPFLAGS_FINI)
+LDFLAGSICUIO += $(LDFLAGS_FINI)
+CPPFLAGSICUI18N += $(CPPFLAGS_FINI)
+LDFLAGSICUI18N += $(LDFLAGS_FINI)
+CPPFLAGSCTESTFW += $(CPPFLAGS_FINI)
+LDFLAGSCTESTFW += $(LDFLAGS_FINI)
+
+# ICUUC, ICUIO, ICUI18N, CTESTFW
+endif
+
# -Bhidden_def Hides all symbols defined in the module.
#LIBCFLAGS = -Bhidden_def
#LIBCXXFLAGS = -Bhidden_def
diff --git a/icu4c/source/config/mh-solaris b/icu4c/source/config/mh-solaris
index 5c7c8d72268..2a9bbd06864 100644
--- a/icu4c/source/config/mh-solaris
+++ b/icu4c/source/config/mh-solaris
@@ -12,6 +12,24 @@ SHAREDLIBCPPFLAGS = -DPIC
GEN_DEPS.c= $(CC) -xM $(DEFS) $(CPPFLAGS)
GEN_DEPS.cc= $(CXX) -xM $(DEFS) $(CPPFLAGS)
+ifeq ($(UCLN_NO_AUTO_CLEANUP),0)
+# set up init point.
+UCLN_FINI = ucln_fini$(TARGET_STUBNAME)_$(SO_TARGET_VERSION_MAJOR)$(ICULIBSUFFIXCNAME)
+CPPFLAGS_FINI = -DUCLN_FINI=$(UCLN_FINI)
+LDFLAGS_FINI = -zfiniarray=$(UCLN_FINI)
+
+CPPFLAGSICUUC += $(CPPFLAGS_FINI)
+LDFLAGSICUUC += $(LDFLAGS_FINI)
+CPPFLAGSICUIO += $(CPPFLAGS_FINI)
+LDFLAGSICUIO += $(LDFLAGS_FINI)
+CPPFLAGSICUI18N += $(CPPFLAGS_FINI)
+LDFLAGSICUI18N += $(LDFLAGS_FINI)
+CPPFLAGSCTESTFW += $(CPPFLAGS_FINI)
+LDFLAGSCTESTFW += $(LDFLAGS_FINI)
+
+# ICUUC, ICUIO, ICUI18N, CTESTFW
+endif
+
# -mt means 'compiles and links a multithreaded program'
THREADSCFLAGS += -mt
THREADSCXXFLAGS += -mt
diff --git a/icu4c/source/configure b/icu4c/source/configure
index ba102156a32..14ee30ae4e3 100755
--- a/icu4c/source/configure
+++ b/icu4c/source/configure
@@ -701,6 +701,7 @@ LIBCXXFLAGS
LIBCFLAGS
U_USE_GCC_VISIBILITY_ATTRIBUTE
U_DEFAULT_SHOW_DRAFT
+UCLN_NO_AUTO_CLEANUP
ENABLE_RELEASE
ENABLE_DEBUG
ENABLE_STATIC
@@ -791,6 +792,7 @@ enable_shared
enable_static
enable_debug
enable_release
+enable_auto_cleanup
enable_draft
enable_renaming
enable_tracing
@@ -1448,6 +1450,7 @@ Optional Features:
--enable-static build static libraries default=no
--enable-debug build debug libraries default=no
--enable-release build release libraries default=yes
+ --enable-auto-cleanup enable auto cleanup of libraries default=no
--enable-draft enable draft APIs default=yes
--enable-renaming add a version suffix to symbols default=yes
--enable-tracing enable function and data tracing default=no
@@ -5014,6 +5017,23 @@ fi
$as_echo "$enabled" >&6; }
+# Check whether to enable auto cleanup of libraries
+{ $as_echo "$as_me:$LINENO: checking whether to enable auto cleanup of libraries" >&5
+$as_echo_n "checking whether to enable auto cleanup of libraries... " >&6; }
+enabled=no
+UCLN_NO_AUTO_CLEANUP=1
+# Check whether --enable-auto-cleanup was given.
+if test "${enable_auto_cleanup+set}" = set; then
+ enableval=$enable_auto_cleanup; case "${enableval}" in
+ yes) enabled=yes; UCLN_NO_AUTO_CLEANUP=0 ;;
+ *) ;;
+ esac
+fi
+
+{ $as_echo "$as_me:$LINENO: result: $enabled" >&5
+$as_echo "$enabled" >&6; }
+
+
# MSVC floating-point option
MSVC_RELEASE_FLAG=""
if test $enabled = yes
diff --git a/icu4c/source/configure.in b/icu4c/source/configure.in
index 63df878d5c3..ea504de13ae 100644
--- a/icu4c/source/configure.in
+++ b/icu4c/source/configure.in
@@ -192,6 +192,20 @@ AC_ARG_ENABLE(release,
AC_MSG_RESULT($enabled)
AC_SUBST(ENABLE_RELEASE)
+# Check whether to enable auto cleanup of libraries
+AC_MSG_CHECKING([whether to enable auto cleanup of libraries])
+enabled=no
+UCLN_NO_AUTO_CLEANUP=1
+AC_ARG_ENABLE(auto-cleanup,
+ [ --enable-auto-cleanup enable auto cleanup of libraries [default=no]],
+ [ case "${enableval}" in
+ yes) enabled=yes; UCLN_NO_AUTO_CLEANUP=0 ;;
+ *) ;;
+ esac],
+)
+AC_MSG_RESULT($enabled)
+AC_SUBST(UCLN_NO_AUTO_CLEANUP)
+
# MSVC floating-point option
MSVC_RELEASE_FLAG=""
if test $enabled = yes
diff --git a/icu4c/source/i18n/Makefile.in b/icu4c/source/i18n/Makefile.in
index 4848ee0d920..771b5adc653 100644
--- a/icu4c/source/i18n/Makefile.in
+++ b/icu4c/source/i18n/Makefile.in
@@ -56,7 +56,7 @@ CXXFLAGS += $(LIBCXXFLAGS)
ifneq ($(top_builddir),$(top_srcdir))
CPPFLAGS += -I$(top_builddir)/common
endif
-CPPFLAGS += -I$(srcdir) -I$(top_srcdir)/common $(LIBCPPFLAGS)
+CPPFLAGS += -I$(srcdir) -I$(top_srcdir)/common $(LIBCPPFLAGS) $(CPPFLAGSICUI18N)
DEFS += -DU_I18N_IMPLEMENTATION
LDFLAGS += $(LDFLAGSICUI18N)
LIBS = $(LIBICUUC) $(DEFAULT_LIBS)
diff --git a/icu4c/source/i18n/i18n.vcproj b/icu4c/source/i18n/i18n.vcproj
index fabfa501673..f94fe537e88 100644
--- a/icu4c/source/i18n/i18n.vcproj
+++ b/icu4c/source/i18n/i18n.vcproj
@@ -3273,6 +3273,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/icu4c/source/tools/ctestfw/ucln_ct.c b/icu4c/source/tools/ctestfw/ucln_ct.c
new file mode 100644
index 00000000000..8d4f2d04733
--- /dev/null
+++ b/icu4c/source/tools/ctestfw/ucln_ct.c
@@ -0,0 +1,15 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2007-2009, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+
+
+/** Auto-client **/
+#define UCLN_TYPE UCLN_CTESTFW
+#include "ucln_imp.h"
+
+int dummyFunction()
+{
+ /* this is here to prevent the compiler from complaining about an empty file */
+}