From e5381c956b73b236c5d7866b2a6b65f879e770ea Mon Sep 17 00:00:00 2001 From: Markus Scherer Date: Tue, 1 Oct 2019 16:33:53 -0700 Subject: [PATCH] ICU-20845 UMutex not trivially but constexpr constructible --- icu4c/source/common/umutex.cpp | 12 ++---------- icu4c/source/common/umutex.h | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/icu4c/source/common/umutex.cpp b/icu4c/source/common/umutex.cpp index fe50d866d4..ccbee9960a 100644 --- a/icu4c/source/common/umutex.cpp +++ b/icu4c/source/common/umutex.cpp @@ -36,15 +36,6 @@ U_NAMESPACE_BEGIN #error U_USER_MUTEX_CPP not supported #endif -// Check that UMutex is trivially constructable & destructable, which ensures that -// static instances are not running static constructors or destructors. -#if (defined(__GNUG__) && __GNUC__ < 5) || (defined(__clang__) && __clang_major__ < 5) -// skip -#else -static_assert(std::is_trivially_constructible::value, "UMutex not trivially constructable."); -static_assert(std::is_trivially_destructible::value, "UMutex not trivially destructable."); -#endif - /************************************************************************************************* * @@ -56,7 +47,8 @@ namespace { std::mutex *initMutex; std::condition_variable *initCondition; -// The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer. +// The ICU global mutex. +// Used when ICU implementation code passes nullptr for the mutex pointer. UMutex globalMutex; std::once_flag initFlag; diff --git a/icu4c/source/common/umutex.h b/icu4c/source/common/umutex.h index d154ff8433..2503aa4a29 100755 --- a/icu4c/source/common/umutex.h +++ b/icu4c/source/common/umutex.h @@ -184,6 +184,16 @@ template void umtx_initOnce(UInitOnce &uio, void (U_CALLCONV *fp)(T, UE } } +// UMutex should be constexpr-constructible, so that no initialization code +// is run during startup. +// This works on all C++ libraries except MS VS before VS2019. +#if (defined(_CPPLIB_VER) && !defined(_MSVC_STL_VERSION)) || \ + (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION < 142) + // (VS std lib older than VS2017) || (VS std lib version < VS2019) +# define UMUTEX_CONSTEXPR +#else +# define UMUTEX_CONSTEXPR constexpr +#endif /** * UMutex - ICU Mutex class. @@ -212,7 +222,7 @@ template void umtx_initOnce(UInitOnce &uio, void (U_CALLCONV *fp)(T, UE class U_COMMON_API UMutex { public: - UMutex() = default; + UMUTEX_CONSTEXPR UMutex() {} ~UMutex() = default; UMutex(const UMutex &other) = delete; @@ -230,13 +240,13 @@ public: static void cleanup(); private: - alignas(std::mutex) char fStorage[sizeof(std::mutex)]; - std::atomic fMutex; + alignas(std::mutex) char fStorage[sizeof(std::mutex)] {}; + std::atomic fMutex { nullptr }; /** All initialized UMutexes are kept in a linked list, so that they can be found, * and the underlying std::mutex destructed, by u_cleanup(). */ - UMutex *fListLink; + UMutex *fListLink { nullptr }; static UMutex *gListHead; /** Out-of-line function to lazily initialize a UMutex on first use.