]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/intltest/tsmthred.cpp
ICU-66108.tar.gz
[apple/icu.git] / icuSources / test / intltest / tsmthred.cpp
index 768821c7ec7df21670df8d78849de1b47ba14045..98e04869d8593344bcfb9ac6ae88565d926a004f 100644 (file)
@@ -62,7 +62,6 @@ void MultithreadTest::runIndexedTest( int32_t index, UBool exec,
 
     TESTCASE_AUTO_BEGIN;
     TESTCASE_AUTO(TestThreads);
-    TESTCASE_AUTO(TestMutex);
 #if !UCONFIG_NO_FORMATTING
     TESTCASE_AUTO(TestThreadedIntl);
 #endif
@@ -72,7 +71,6 @@ void MultithreadTest::runIndexedTest( int32_t index, UBool exec,
     TESTCASE_AUTO(TestString);
     TESTCASE_AUTO(TestArabicShapingThreads);
     TESTCASE_AUTO(TestAnyTranslit);
-    TESTCASE_AUTO(TestConditionVariables);
     TESTCASE_AUTO(TestUnifiedCache);
 #if !UCONFIG_NO_TRANSLITERATION
     TESTCASE_AUTO(TestBreakTranslit);
@@ -81,7 +79,7 @@ void MultithreadTest::runIndexedTest( int32_t index, UBool exec,
     TESTCASE_AUTO(Test20104);
 #endif /* #if !UCONFIG_NO_FORMATTING */
 #endif /* #if !UCONFIG_NO_TRANSLITERATION */
-    TESTCASE_AUTO_END
+    TESTCASE_AUTO_END;
 }
 
 
@@ -160,8 +158,8 @@ void MultithreadTest::TestThreads()
 class TestArabicShapeThreads : public SimpleThread
 {
 public:
-    TestArabicShapeThreads() {};
-    virtual void run() { doTailTest(); };
+    TestArabicShapeThreads() {}
+    virtual void run() { doTailTest(); }
 private:
        void doTailTest();
 };
@@ -210,7 +208,7 @@ void TestArabicShapeThreads::doTailTest(void) {
     }
     return;
 }
-
+       
 
 void MultithreadTest::TestArabicShapingThreads()
 {
@@ -232,108 +230,6 @@ void MultithreadTest::TestArabicShapingThreads()
 }
 
 
-//-----------------------------------------------------------------------
-//
-//  TestMutex  - a simple (non-stress) test to verify that ICU mutexes
-//               and condition variables are functioning.  Does not test the use of
-//               mutexes within ICU services, but rather that the
-//               platform's mutex support is at least superficially there.
-//
-//----------------------------------------------------------------------
-static UMutex *gTestMutexA() {
-    static UMutex *m = STATIC_NEW(UMutex);
-    return m;
-}
-static std::condition_variable *gThreadsCountChanged() {
-    static std::condition_variable *cv = STATIC_NEW(std::condition_variable);
-    return cv;
-}
-
-static int     gThreadsStarted = 0;
-static int     gThreadsInMiddle = 0;
-static int     gThreadsDone = 0;
-
-static const int TESTMUTEX_THREAD_COUNT = 40;
-
-class TestMutexThread : public SimpleThread
-{
-public:
-    virtual void run() {
-        // This is the code that each of the spawned threads runs.
-        // All threads move together throught the started - middle - done sequence together,
-        // waiting for all other threads to reach each point before advancing.
-        std::unique_lock<std::mutex> lock(gTestMutexA()->fMutex);
-        gThreadsStarted += 1;
-        gThreadsCountChanged()->notify_all();
-        while (gThreadsStarted < TESTMUTEX_THREAD_COUNT) {
-            if (gThreadsInMiddle != 0) {
-                IntlTest::gTest->errln(
-                    "%s:%d gThreadsInMiddle = %d. Expected 0.", __FILE__, __LINE__, gThreadsInMiddle);
-                return;
-            }
-            gThreadsCountChanged()->wait(lock);
-        }
-
-        gThreadsInMiddle += 1;
-        gThreadsCountChanged()->notify_all();
-        while (gThreadsInMiddle < TESTMUTEX_THREAD_COUNT) {
-            if (gThreadsDone != 0) {
-                IntlTest::gTest->errln(
-                    "%s:%d gThreadsDone = %d. Expected 0.", __FILE__, __LINE__, gThreadsDone);
-                return;
-            }
-            gThreadsCountChanged()->wait(lock);
-        }
-
-        gThreadsDone += 1;
-        gThreadsCountChanged()->notify_all();
-        while (gThreadsDone < TESTMUTEX_THREAD_COUNT) {
-            gThreadsCountChanged()->wait(lock);
-        }
-    }
-};
-
-void MultithreadTest::TestMutex()
-{
-    gThreadsStarted = 0;
-    gThreadsInMiddle = 0;
-    gThreadsDone = 0;
-    int32_t i = 0;
-    TestMutexThread  threads[TESTMUTEX_THREAD_COUNT];
-    {
-        std::unique_lock<std::mutex> lock(gTestMutexA()->fMutex);
-        for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
-            if (threads[i].start() != 0) {
-                errln("%s:%d Error starting thread %d", __FILE__, __LINE__, i);
-                return;
-            }
-        }
-
-        // Because we are holding gTestMutexA, all of the threads should be blocked
-        // at the start of their run() function.
-        if (gThreadsStarted != 0) {
-            errln("%s:%d gThreadsStarted=%d. Expected 0.", __FILE__, __LINE__, gThreadsStarted);
-            return;
-        }
-
-        while (gThreadsInMiddle < TESTMUTEX_THREAD_COUNT) {
-            if (gThreadsDone != 0) {
-                errln("%s:%d gThreadsDone=%d. Expected 0.", __FILE__, __LINE__, gThreadsStarted);
-                return;
-            }
-            gThreadsCountChanged()->wait(lock);
-        }
-
-        while (gThreadsDone < TESTMUTEX_THREAD_COUNT) {
-            gThreadsCountChanged()->wait(lock);
-        }
-    }
-    for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
-        threads[i].join();
-    }
-}
-
-
 //-------------------------------------------------------------------------------------------
 //
 //   TestMultithreadedIntl.  Test ICU Formatting in a multi-threaded environment
@@ -834,7 +730,7 @@ public:
         noLines(0),
         isAtLeastUCA62(TRUE)
     {
-    };
+    }
     void setCollator(Collator *c, Line *l, int32_t nl, UBool atLeastUCA62)
     {
         coll = c;
@@ -1046,7 +942,7 @@ public:
         : SimpleThread(),
         fTraceInfo(0)
     {
-    };
+    }
 
 
     virtual void run()
@@ -1116,7 +1012,7 @@ void MultithreadTest::TestString()
 Transliterator *gSharedTranslit = NULL;
 class TxThread: public SimpleThread {
   public:
-    TxThread() {};
+    TxThread() {}
     ~TxThread();
     void run();
 };
@@ -1151,96 +1047,6 @@ void MultithreadTest::TestAnyTranslit() {
 }
 
 
-//
-// Condition Variables Test
-//   Create a swarm of threads.
-//   Using a mutex and a condition variables each thread
-//     Increments a global count of started threads.
-//     Broadcasts that it has started.
-//     Waits on the condition that all threads have started.
-//     Increments a global count of finished threads.
-//     Waits on the condition that all threads have finished.
-//     Exits.
-//
-
-class CondThread: public SimpleThread {
-  public:
-    CondThread() :fFinished(false)  {};
-    ~CondThread() {};
-    void run();
-    bool  fFinished;
-};
-
-static UMutex *gCTMutex() {
-    static UMutex *m = STATIC_NEW(UMutex);
-    return m;
-}
-static std::condition_variable *gCTConditionVar() {
-    static std::condition_variable *cv = STATIC_NEW(std::condition_variable);
-    return cv;
-}
-int gConditionTestOne = 1;   // Value one. Non-const, extern linkage to inhibit
-                             //   compiler assuming a known value.
-int gStartedThreads;
-int gFinishedThreads;
-static const int NUMTHREADS = 10;
-
-
-// Worker thread function.
-void CondThread::run() {
-    std::unique_lock<std::mutex> lock(gCTMutex()->fMutex);
-    gStartedThreads += gConditionTestOne;
-    gCTConditionVar()->notify_all();
-
-    while (gStartedThreads < NUMTHREADS) {
-        if (gFinishedThreads != 0) {
-            IntlTest::gTest->errln("File %s, Line %d: Error, gStartedThreads = %d, gFinishedThreads = %d",
-                             __FILE__, __LINE__, gStartedThreads, gFinishedThreads);
-        }
-        gCTConditionVar()->wait(lock);
-    }
-
-    gFinishedThreads += gConditionTestOne;
-    fFinished = true;
-    gCTConditionVar()->notify_all();
-
-    while (gFinishedThreads < NUMTHREADS) {
-        gCTConditionVar()->wait(lock);
-    }
-}
-
-void MultithreadTest::TestConditionVariables() {
-    gStartedThreads = 0;
-    gFinishedThreads = 0;
-    int i;
-    CondThread *threads[NUMTHREADS];
-
-    {
-        std::unique_lock<std::mutex> lock(gCTMutex()->fMutex);
-        for (i=0; i<NUMTHREADS; ++i) {
-            threads[i] = new CondThread;
-            threads[i]->start();
-        }
-
-        while (gStartedThreads < NUMTHREADS) {
-            gCTConditionVar()->wait(lock);
-        }
-
-        while (gFinishedThreads < NUMTHREADS) {
-            gCTConditionVar()->wait(lock);
-        }
-    }
-
-    for (i=0; i<NUMTHREADS; ++i) {
-        assertTrue(WHERE, threads[i]->fFinished);
-    }
-
-    for (i=0; i<NUMTHREADS; ++i) {
-        threads[i]->join();
-        delete threads[i];
-    }
-}
-
 
 //
 // Unified Cache Test
@@ -1275,6 +1081,9 @@ class UCTMultiThreadItem : public SharedObject {
 
 U_NAMESPACE_BEGIN
 
+static std::mutex *gCTMutex = nullptr;
+static std::condition_variable *gCTConditionVar = nullptr;
+
 template<> U_EXPORT
 const UCTMultiThreadItem *LocaleCacheKey<UCTMultiThreadItem>::createObject(
         const void *context, UErrorCode &status) const {
@@ -1292,7 +1101,7 @@ const UCTMultiThreadItem *LocaleCacheKey<UCTMultiThreadItem>::createObject(
 
     bool firstObject = false;
     {
-        std::unique_lock<std::mutex> lock(gCTMutex()->fMutex);
+        std::unique_lock<std::mutex> lock(*gCTMutex);
         firstObject = (gObjectsCreated == 0);
         if (firstObject) {
             // Force the first object creation that comes through to wait
@@ -1303,7 +1112,7 @@ const UCTMultiThreadItem *LocaleCacheKey<UCTMultiThreadItem>::createObject(
             // early, to keep subsequent threads from entering this path.
             gObjectsCreated = 1;
             while (gObjectsCreated < 3) {
-                gCTConditionVar()->wait(lock);
+                gCTConditionVar->wait(lock);
             }
         }
     }
@@ -1319,11 +1128,11 @@ const UCTMultiThreadItem *LocaleCacheKey<UCTMultiThreadItem>::createObject(
     // Log that we created an object. The first object was already counted,
     //    don't do it again.
     {
-        std::unique_lock<std::mutex> lock(gCTMutex()->fMutex);
+        std::unique_lock<std::mutex> lock(*gCTMutex);
         if (!firstObject) {
             gObjectsCreated += 1;
         }
-        gCTConditionVar()->notify_all();
+        gCTConditionVar->notify_all();
     }
 
     return result;
@@ -1336,8 +1145,8 @@ class UnifiedCacheThread: public SimpleThread {
     UnifiedCacheThread(
             const UnifiedCache *cache,
             const char *loc,
-            const char *loc2) : fCache(cache), fLoc(loc), fLoc2(loc2) {};
-    ~UnifiedCacheThread() {};
+            const char *loc2) : fCache(cache), fLoc(loc), fLoc2(loc2) {}
+    ~UnifiedCacheThread() {}
     void run();
     void exerciseByLocale(const Locale &);
     const UnifiedCache *fCache;
@@ -1386,7 +1195,9 @@ void MultithreadTest::TestUnifiedCache() {
     cache.setEvictionPolicy(2, 0, status);
     U_ASSERT(U_SUCCESS(status));
 
-    gFinishedThreads = 0;
+    gCTMutex = new std::mutex();
+    gCTConditionVar = new std::condition_variable();
+
     gObjectsCreated = 0;
 
     UnifiedCacheThread *threads[CACHE_LOAD][UPRV_LENGTHOF(gCacheLocales)];
@@ -1428,6 +1239,8 @@ void MultithreadTest::TestUnifiedCache() {
             delete threads[i][j];
         }
     }
+    delete gCTMutex;
+    delete gCTConditionVar;
 }
 
 #if !UCONFIG_NO_TRANSLITERATION
@@ -1442,8 +1255,8 @@ static const UnicodeString *gTranslitExpected;
 
 class BreakTranslitThread: public SimpleThread {
   public:
-    BreakTranslitThread() {};
-    ~BreakTranslitThread() {};
+    BreakTranslitThread() {}
+    ~BreakTranslitThread() {}
     void run();
 };
 
@@ -1492,7 +1305,7 @@ void MultithreadTest::TestBreakTranslit() {
 
 class TestIncDecThread : public SimpleThread {
 public:
-    TestIncDecThread() { };
+    TestIncDecThread() {}
     virtual void run();
 };
 
@@ -1525,7 +1338,7 @@ static Calendar  *gSharedCalendar = {};
 
 class Test20104Thread : public SimpleThread {
 public:
-    Test20104Thread() { };
+    Test20104Thread() {}
     virtual void run();
 };