+ delete gCTMutex;
+ delete gCTConditionVar;
+}
+
+#if !UCONFIG_NO_TRANSLITERATION
+//
+// BreakTransliterator Threading Test
+// This is a test for bug #11603. Test verified to fail prior to fix.
+//
+
+static const Transliterator *gSharedTransliterator;
+static const UnicodeString *gTranslitInput;
+static const UnicodeString *gTranslitExpected;
+
+class BreakTranslitThread: public SimpleThread {
+ public:
+ BreakTranslitThread() {}
+ ~BreakTranslitThread() {}
+ void run();
+};
+
+void BreakTranslitThread::run() {
+ for (int i=0; i<10; i++) {
+ icu::UnicodeString s(*gTranslitInput);
+ gSharedTransliterator->transliterate(s);
+ if (*gTranslitExpected != s) {
+ IntlTest::gTest->errln("%s:%d Transliteration threading failure.", __FILE__, __LINE__);
+ break;
+ }
+ }
+}
+
+void MultithreadTest::TestBreakTranslit() {
+ UErrorCode status = U_ZERO_ERROR;
+ UnicodeString input(
+ u"\u0E42\u0E14\u0E22\u0E1E\u0E37\u0E49\u0E19\u0E10\u0E32\u0E19\u0E41\u0E25\u0E49\u0E27,");
+ // Thai script, โดยพื้นฐานแล้ว
+ gTranslitInput = &input;
+
+ gSharedTransliterator = Transliterator::createInstance(
+ UnicodeString(u"Any-Latin; Lower; NFD; [:Diacritic:]Remove; NFC; Latin-ASCII;"), UTRANS_FORWARD, status);
+ assertSuccess(WHERE, status);
+ if (!assertTrue(WHERE, gSharedTransliterator != nullptr)) {
+ return;
+ }
+
+ UnicodeString expected(*gTranslitInput);
+ gSharedTransliterator->transliterate(expected);
+ gTranslitExpected = &expected;
+
+ BreakTranslitThread threads[4];
+ for (int i=0; i<UPRV_LENGTHOF(threads); ++i) {
+ threads[i].start();
+ }
+ for (int i=0; i<UPRV_LENGTHOF(threads); ++i) {
+ threads[i].join();
+ }
+
+ delete gSharedTransliterator;
+ gTranslitInput = NULL;
+ gTranslitExpected = NULL;
+}
+
+
+class TestIncDecThread : public SimpleThread {
+public:
+ TestIncDecThread() {}
+ virtual void run();
+};
+
+static u_atomic_int32_t gIncDecCounter;
+
+void TestIncDecThread::run() {
+ umtx_atomic_inc(&gIncDecCounter);
+ for (int32_t i=0; i<5000000; ++i) {
+ umtx_atomic_inc(&gIncDecCounter);
+ umtx_atomic_dec(&gIncDecCounter);
+ }
+}
+
+void MultithreadTest::TestIncDec()
+{
+ static constexpr int NUM_THREADS = 4;
+ gIncDecCounter = 0;
+ TestIncDecThread threads[NUM_THREADS];
+ for (auto &thread:threads) {
+ thread.start();
+ }
+ for (auto &thread:threads) {
+ thread.join();
+ }
+ assertEquals(WHERE, NUM_THREADS, gIncDecCounter);
+}
+
+#if !UCONFIG_NO_FORMATTING
+static Calendar *gSharedCalendar = {};
+
+class Test20104Thread : public SimpleThread {
+public:
+ Test20104Thread() {}
+ virtual void run();
+};
+
+void Test20104Thread::run() {
+ gSharedCalendar->defaultCenturyStartYear();
+}
+
+void MultithreadTest::Test20104() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale loc("hi_IN");
+ gSharedCalendar = new IndianCalendar(loc, status);
+ assertSuccess(WHERE, status);
+
+ static constexpr int NUM_THREADS = 4;
+ Test20104Thread threads[NUM_THREADS];
+ for (auto &thread:threads) {
+ thread.start();
+ }
+ for (auto &thread:threads) {
+ thread.join();
+ }
+ delete gSharedCalendar;
+ // Note: failure is reported by Thread Sanitizer. Test itself succeeds.