Skip to content

Commit

Permalink
ICU-20845 UMutex not trivially but constexpr constructible
Browse files Browse the repository at this point in the history
  • Loading branch information
markusicu committed Oct 2, 2019
1 parent 7f86228 commit e5381c9
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 14 deletions.
12 changes: 2 additions & 10 deletions icu4c/source/common/umutex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<UMutex>::value, "UMutex not trivially constructable.");
static_assert(std::is_trivially_destructible<UMutex>::value, "UMutex not trivially destructable.");
#endif


/*************************************************************************************************
*
Expand All @@ -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;
Expand Down
18 changes: 14 additions & 4 deletions icu4c/source/common/umutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ template<class T> 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.
Expand Down Expand Up @@ -212,7 +222,7 @@ template<class T> 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;
Expand All @@ -230,13 +240,13 @@ class U_COMMON_API UMutex {
static void cleanup();

private:
alignas(std::mutex) char fStorage[sizeof(std::mutex)];
std::atomic<std::mutex *> fMutex;
alignas(std::mutex) char fStorage[sizeof(std::mutex)] {};
std::atomic<std::mutex *> 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.
Expand Down

0 comments on commit e5381c9

Please sign in to comment.