TESTCASE_AUTO_BEGIN;
TESTCASE_AUTO(TestThreads);
- TESTCASE_AUTO(TestMutex);
#if !UCONFIG_NO_FORMATTING
TESTCASE_AUTO(TestThreadedIntl);
#endif
TESTCASE_AUTO(TestString);
TESTCASE_AUTO(TestArabicShapingThreads);
TESTCASE_AUTO(TestAnyTranslit);
- TESTCASE_AUTO(TestConditionVariables);
TESTCASE_AUTO(TestUnifiedCache);
#if !UCONFIG_NO_TRANSLITERATION
TESTCASE_AUTO(TestBreakTranslit);
TESTCASE_AUTO(Test20104);
#endif /* #if !UCONFIG_NO_FORMATTING */
#endif /* #if !UCONFIG_NO_TRANSLITERATION */
- TESTCASE_AUTO_END
+ TESTCASE_AUTO_END;
}
class TestArabicShapeThreads : public SimpleThread
{
public:
- TestArabicShapeThreads() {};
- virtual void run() { doTailTest(); };
+ TestArabicShapeThreads() {}
+ virtual void run() { doTailTest(); }
private:
void doTailTest();
};
}
return;
}
-
+
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
noLines(0),
isAtLeastUCA62(TRUE)
{
- };
+ }
void setCollator(Collator *c, Line *l, int32_t nl, UBool atLeastUCA62)
{
coll = c;
: SimpleThread(),
fTraceInfo(0)
{
- };
+ }
virtual void run()
Transliterator *gSharedTranslit = NULL;
class TxThread: public SimpleThread {
public:
- TxThread() {};
+ TxThread() {}
~TxThread();
void run();
};
}
-//
-// 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
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 {
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
// early, to keep subsequent threads from entering this path.
gObjectsCreated = 1;
while (gObjectsCreated < 3) {
- gCTConditionVar()->wait(lock);
+ gCTConditionVar->wait(lock);
}
}
}
// 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;
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;
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)];
delete threads[i][j];
}
}
+ delete gCTMutex;
+ delete gCTConditionVar;
}
#if !UCONFIG_NO_TRANSLITERATION
class BreakTranslitThread: public SimpleThread {
public:
- BreakTranslitThread() {};
- ~BreakTranslitThread() {};
+ BreakTranslitThread() {}
+ ~BreakTranslitThread() {}
void run();
};
class TestIncDecThread : public SimpleThread {
public:
- TestIncDecThread() { };
+ TestIncDecThread() {}
virtual void run();
};
class Test20104Thread : public SimpleThread {
public:
- Test20104Thread() { };
+ Test20104Thread() {}
virtual void run();
};