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 */ +}