/**
* \def U_HAVE_STD_ATOMICS
- * Defines whether to use the standard C++11 <atomic> functions
+ * Defines whether to use the C++11 std::atomic functions.
* If false, ICU will fall back to compiler or platform specific alternatives.
* Note: support for these fall back options for atomics will be removed in a future version
* of ICU, and the use of C++ 11 atomics will be required.
# define U_HAVE_CLANG_ATOMICS 0
#endif
+
+/**
+ * \def U_HAVE_STD_MUTEX
+ * Defines whether to use the C++11 std::mutex functions.
+ * If false, ICU will fall back to compiler or platform specific alternatives.
+ * std::mutex is preferred, and used by default unless this setting is overridden.
+ * Note: support for other options for mutexes will be removed in a future version
+ * of ICU, and the use of std::mutex will be required.
+ * @internal
+ */
+#ifdef U_HAVE_STD_MUTEX
+ /* Use the predefined value. */
+#else
+# define U_HAVE_STD_MUTEX 1
+#endif
+
/*===========================================================================*/
/** @{ Programs used by ICU code */
/*===========================================================================*/
// Build time user mutex hook: #include "U_USER_MUTEX_CPP"
#include U_MUTEX_XSTR(U_USER_MUTEX_CPP)
+
+#elif U_HAVE_STD_MUTEX
+
+// C++11 std::mutex based implementation of ICU mutex wrappers.
+//
+
+U_CAPI void U_EXPORT2
+umtx_lock(UMutex *mutex) {
+ if (mutex == nullptr) {
+ mutex = &globalMutex;
+ }
+ mutex->fMutex.lock();
+}
+
+
+U_CAPI void U_EXPORT2
+umtx_unlock(UMutex* mutex)
+{
+ if (mutex == nullptr) {
+ mutex = &globalMutex;
+ }
+ mutex->fMutex.unlock();
+}
+
+
+U_CAPI void U_EXPORT2
+umtx_condWait(UConditionVar *cond, UMutex *mutex) {
+ if (mutex == nullptr) {
+ mutex = &globalMutex;
+ }
+ cond->fCV.wait(mutex->fMutex);
+}
+
+
+U_CAPI void U_EXPORT2
+umtx_condBroadcast(UConditionVar *cond) {
+ cond->fCV.notify_all();
+}
+
+
+U_CAPI void U_EXPORT2
+umtx_condSignal(UConditionVar *cond) {
+ cond->fCV.notify_one();
+}
+
+
+U_NAMESPACE_BEGIN
+
+static std::mutex initMutex;
+static std::condition_variable initCondition;
+
+
+// This function is called when a test of a UInitOnce::fState reveals that
+// initialization has not completed, that we either need to call the init
+// function on this thread, or wait for some other thread to complete.
+//
+// The actual call to the init function is made inline by template code
+// that knows the C++ types involved. This function returns true if
+// the caller needs to call the Init function.
+//
+U_COMMON_API UBool U_EXPORT2
+umtx_initImplPreInit(UInitOnce &uio) {
+ std::unique_lock<std::mutex> lock(initMutex);
+
+ if (umtx_loadAcquire(uio.fState) == 0) {
+ umtx_storeRelease(uio.fState, 1);
+ return true; // Caller will next call the init function.
+ } else {
+ while (umtx_loadAcquire(uio.fState) == 1) {
+ // Another thread is currently running the initialization.
+ // Wait until it completes.
+ initCondition.wait(lock);
+ }
+ U_ASSERT(uio.fState == 2);
+ return false;
+ }
+}
+
+
+// This function is called by the thread that ran an initialization function,
+// just after completing the function.
+// Some threads may be waiting on the condition, requiring the broadcast wakeup.
+// Some threads may be racing to test the fState variable outside of the mutex,
+// requiring the use of store/release when changing its value.
+
+U_COMMON_API void U_EXPORT2
+umtx_initImplPostInit(UInitOnce &uio) {
+ {
+ std::unique_lock<std::mutex> lock(initMutex);
+ umtx_storeRelease(uio.fState, 2);
+ }
+ initCondition.notify_all();
+}
+
+U_NAMESPACE_END
+
+// End of std::mutex specific umutex implementation.
+
+
+
#elif U_PLATFORM_USES_ONLY_WIN32_API
#if defined U_NO_PLATFORM_ATOMICS
#if defined (U_USER_ATOMICS_H)
#include U_MUTEX_XSTR(U_USER_ATOMICS_H)
+// TODO: There is direct use of std::atomic<type *> from number__mapper, numberrangeformatter
+// Either add ICU abstraction, or deprecate U_USER_ATOMICS_H.
+// See Jira issu ICU-20185.
+
#elif U_HAVE_STD_ATOMICS
// C++11 atomics are available.
/*************************************************************************************************
*
* Mutex Definitions. Platform Dependent, #if platform chain follows.
- * TODO: Add a C++11 version.
- * Need to convert all mutex using files to C++ first.
*
*************************************************************************************************/
// #include "U_USER_MUTEX_H"
#include U_MUTEX_XSTR(U_USER_MUTEX_H)
+#elif U_HAVE_STD_MUTEX
+
+#include <mutex>
+#include <condition_variable>
+
+
+struct UMutex {
+ std::mutex fMutex;
+};
+
+struct UConditionVar {
+ std::condition_variable_any fCV;
+};
+
+#define U_MUTEX_INITIALIZER {}
+#define U_CONDITION_INITIALIZER {}
+
+
+
#elif U_PLATFORM_USES_ONLY_WIN32_API
/* For CRITICAL_SECTION */