summaryrefslogtreecommitdiff
path: root/Build/source/libs/icu/icu-49.1/test/threadtest
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/icu/icu-49.1/test/threadtest')
-rw-r--r--Build/source/libs/icu/icu-49.1/test/threadtest/Makefile.in90
-rw-r--r--Build/source/libs/icu/icu-49.1/test/threadtest/converttest.cpp88
-rw-r--r--Build/source/libs/icu/icu-49.1/test/threadtest/stringtest.cpp143
-rw-r--r--Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.cpp537
-rw-r--r--Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.dsp166
-rw-r--r--Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.dsw29
-rw-r--r--Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.h45
7 files changed, 1098 insertions, 0 deletions
diff --git a/Build/source/libs/icu/icu-49.1/test/threadtest/Makefile.in b/Build/source/libs/icu/icu-49.1/test/threadtest/Makefile.in
new file mode 100644
index 00000000000..4014a7fec58
--- /dev/null
+++ b/Build/source/libs/icu/icu-49.1/test/threadtest/Makefile.in
@@ -0,0 +1,90 @@
+## Makefile.in for ICU - test/threadtest
+## Copyright (c) 2001-2011, International Business Machines Corporation and
+## others. All Rights Reserved.
+
+## Source directory information
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+top_builddir = ../..
+
+include $(top_builddir)/icudefs.mk
+
+## Platform-specific setup
+include @platform_make_fragment@
+
+## Build directory information
+subdir = test/threadtest
+
+## Extra files to remove for 'make clean'
+CLEANFILES = *~ $(DEPS)
+
+## Target information
+TARGET = threadtest
+
+DEFS = @DEFS@
+CPPFLAGS = @CPPFLAGS@ -I$(top_srcdir)/common -I$(top_srcdir)/i18n
+CFLAGS = @CFLAGS@
+CXXFLAGS = @CXXFLAGS@
+ENABLE_RPATH = @ENABLE_RPATH@
+ifeq ($(ENABLE_RPATH),YES)
+RPATHLDFLAGS = $(LD_RPATH)$(LD_RPATH_PRE)$(libdir)
+endif
+LDFLAGS = @LDFLAGS@ $(RPATHLDFLAGS)
+LIBS = $(LIBICUI18N) $(LIBICUUC) @LIBS@ @LIB_M@
+
+OBJECTS = threadtest.o stringtest.o converttest.o
+
+DEPS = $(OBJECTS:.o=.d)
+
+## List of phony targets
+.PHONY : all all-local install install-local clean clean-local \
+distclean distclean-local dist dist-local check check-local
+
+## Clear suffix list
+.SUFFIXES :
+
+## List of standard targets
+all: all-local
+install: install-local
+clean: clean-local
+distclean : distclean-local
+dist: dist-local
+check: all check-local
+
+all-local: $(TARGET)
+
+install-local:
+
+dist-local:
+
+clean-local:
+ test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES)
+ $(RMV) $(OBJECTS) $(TARGET)
+
+distclean-local: clean-local
+ $(RMV) Makefile
+
+check-local: all-local
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(TARGET) : $(OBJECTS)
+ $(LINK.cc) -o $@ $^ $(LIBS)
+ $(POST_BUILD_STEP)
+
+invoke:
+ ICU_DATA=$${ICU_DATA:-$(top_builddir)/data/} TZ=PST8PDT $(INVOKE) $(INVOCATION)
+
+ifeq (,$(MAKECMDGOALS))
+-include $(DEPS)
+else
+ifneq ($(patsubst %clean,,$(MAKECMDGOALS)),)
+ifneq ($(patsubst %install,,$(MAKECMDGOALS)),)
+-include $(DEPS)
+endif
+endif
+endif
+
diff --git a/Build/source/libs/icu/icu-49.1/test/threadtest/converttest.cpp b/Build/source/libs/icu/icu-49.1/test/threadtest/converttest.cpp
new file mode 100644
index 00000000000..8de22efa786
--- /dev/null
+++ b/Build/source/libs/icu/icu-49.1/test/threadtest/converttest.cpp
@@ -0,0 +1,88 @@
+//
+//********************************************************************
+// Copyright (C) 2002-2003, International Business Machines
+// Corporation and others. All Rights Reserved.
+//********************************************************************
+//
+// File converttest.cpp
+//
+
+#include "threadtest.h"
+#include "unicode/utypes.h"
+#include "unicode/ucnv.h"
+#include "unicode/uclean.h"
+#include "stdio.h"
+
+U_CAPI UBool U_EXPORT2 ucnv_cleanup();
+
+class ConvertThreadTest: public AbstractThreadTest {
+public:
+ ConvertThreadTest();
+ virtual ~ConvertThreadTest();
+ virtual void check();
+ virtual void runOnce();
+
+private:
+ UConverter *fCnv;
+};
+
+
+ConvertThreadTest::ConvertThreadTest() {
+ UErrorCode err = U_ZERO_ERROR;
+
+ fCnv = ucnv_open("gb18030", &err);
+ if (U_FAILURE(err)) {
+ fprintf(stderr, "ConvertTest - could not ucnv_open(\"gb18030\")\n");
+ fCnv = NULL;
+ }
+};
+
+
+ConvertThreadTest::~ConvertThreadTest() {
+ ucnv_close(fCnv);
+ fCnv = 0;
+}
+
+void ConvertThreadTest::runOnce() {
+ UErrorCode err = U_ZERO_ERROR;
+ UConverter *cnv1;
+ UConverter *cnv2;
+ char buf[U_CNV_SAFECLONE_BUFFERSIZE];
+ int32_t bufSize = U_CNV_SAFECLONE_BUFFERSIZE;
+
+ cnv1 = ucnv_open("shift_jis", &err);
+ if (U_FAILURE(err)) {
+ fprintf(stderr, "ucnv_open(\"shift_jis\") failed.\n");
+ }
+
+ cnv2 = ucnv_safeClone(fCnv, // The source converter, common to all threads.
+ buf,
+ &bufSize,
+ &err);
+ if (U_FAILURE(err)) {
+ fprintf(stderr, "ucnv_safeClone() failed.\n");
+ }
+ ucnv_close(cnv1);
+ ucnv_close(cnv2);
+ ucnv_flushCache();
+}
+
+void ConvertThreadTest::check() {
+ UErrorCode err = U_ZERO_ERROR;
+
+ if (fCnv) {ucnv_close(fCnv);}
+ //if (ucnv_cleanup () == FALSE) {
+ // fprintf(stderr, "ucnv_cleanup() failed - cache was not empty.\n");
+ //}
+ fCnv = ucnv_open("gb18030", &err);
+ if (U_FAILURE(err)) {
+ fprintf(stderr, "ConvertTest::check() - could not redo ucnv_open(\"gb18030\")\n");
+ fCnv = NULL;
+ }
+}
+
+
+AbstractThreadTest *createConvertTest() {
+ return new ConvertThreadTest();
+}
+
diff --git a/Build/source/libs/icu/icu-49.1/test/threadtest/stringtest.cpp b/Build/source/libs/icu/icu-49.1/test/threadtest/stringtest.cpp
new file mode 100644
index 00000000000..2380a3c7713
--- /dev/null
+++ b/Build/source/libs/icu/icu-49.1/test/threadtest/stringtest.cpp
@@ -0,0 +1,143 @@
+//
+//********************************************************************
+// Copyright (C) 2002, International Business Machines
+// Corporation and others. All Rights Reserved.
+//********************************************************************
+//
+// File stringtest.cpp
+//
+
+#include "threadtest.h"
+#include "unicode/unistr.h"
+#include "stdio.h"
+
+class StringThreadTest: public AbstractThreadTest {
+public:
+ StringThreadTest();
+ virtual ~StringThreadTest();
+ virtual void check();
+ virtual void runOnce();
+ void makeStringCopies(int recursionCount);
+
+private:
+ UnicodeString *fCleanStrings;
+ UnicodeString *fSourceStrings;
+};
+
+StringThreadTest::StringThreadTest() {
+ // cleanStrings and sourceStrings are separately initialized to the same values.
+ // cleanStrings are never touched after in any remotely unsafe way.
+ // sourceStrings are copied during the test, which will run their buffer's reference
+ // counts all over the place.
+ fCleanStrings = new UnicodeString[5];
+ fSourceStrings = new UnicodeString[5];
+
+ fCleanStrings[0] = "When sorrows come, they come not single spies, but in batallions.";
+ fSourceStrings[0] = "When sorrows come, they come not single spies, but in batallions.";
+ fCleanStrings[1] = "Away, you scullion! You rampallion! You fustilarion! I'll tickle your catastrophe!";
+ fSourceStrings[1] = "Away, you scullion! You rampallion! You fustilarion! I'll tickle your catastrophe!";
+ fCleanStrings[2] = "hot";
+ fSourceStrings[2] = "hot";
+ fCleanStrings[3] = "";
+ fSourceStrings[3] = "";
+ fCleanStrings[4] = "Tomorrow, and tomorrow, and tomorrow,\n"
+ "Creeps in this petty pace from day to day\n"
+ "To the last syllable of recorded time;\n"
+ "And all our yesterdays have lighted fools \n"
+ "The way to dusty death. Out, out brief candle!\n"
+ "Life's but a walking shadow, a poor player\n"
+ "That struts and frets his hour upon the stage\n"
+ "And then is heard no more. It is a tale\n"
+ "Told by and idiot, full of sound and fury,\n"
+ "Signifying nothing.\n";
+ fSourceStrings[4] = "Tomorrow, and tomorrow, and tomorrow,\n"
+ "Creeps in this petty pace from day to day\n"
+ "To the last syllable of recorded time;\n"
+ "And all our yesterdays have lighted fools \n"
+ "The way to dusty death. Out, out brief candle!\n"
+ "Life's but a walking shadow, a poor player\n"
+ "That struts and frets his hour upon the stage\n"
+ "And then is heard no more. It is a tale\n"
+ "Told by and idiot, full of sound and fury,\n"
+ "Signifying nothing.\n";
+};
+
+
+StringThreadTest::~StringThreadTest() {
+ delete [] fCleanStrings;
+ delete [] fSourceStrings;
+}
+
+
+void StringThreadTest::runOnce() {
+ makeStringCopies(25);
+}
+
+void StringThreadTest::makeStringCopies(int recursionCount) {
+ UnicodeString firstGeneration[5];
+ UnicodeString secondGeneration[5];
+ UnicodeString thirdGeneration[5];
+ UnicodeString fourthGeneration[5];
+
+ // Make four generations of copies of the source strings, in slightly variant ways.
+ //
+ int i;
+ for (i=0; i<5; i++) {
+ firstGeneration[i] = fSourceStrings[i];
+ secondGeneration[i] = firstGeneration[i];
+ thirdGeneration[i] = UnicodeString(secondGeneration[i]);
+ // fourthGeneration[i] = UnicodeString("Lay on, MacDuff, And damn'd be him that first cries, \"Hold, enough!\"");
+ fourthGeneration[i] = UnicodeString();
+ fourthGeneration[i] = thirdGeneration[i];
+ }
+
+
+ // Recurse to make even more copies of the strings/
+ //
+ if (recursionCount > 0) {
+ makeStringCopies(recursionCount-1);
+ }
+
+
+ // Verify that all four generations are equal.
+ for (i=0; i<5; i++) {
+ if (firstGeneration[i] != fSourceStrings[i] ||
+ firstGeneration[i] != secondGeneration[i] ||
+ firstGeneration[i] != thirdGeneration[i] ||
+ firstGeneration[i] != fourthGeneration[i])
+ {
+ fprintf(stderr, "Error, strings don't compare equal.\n");
+ }
+ }
+
+};
+
+
+void StringThreadTest::check() {
+ //
+ // Check that the reference counts on the buffers for all of the source strings
+ // are one. The ref counts will have run way up while the test threads
+ // make numerous copies of the strings, but at the top of the loop all
+ // of the copies should be gone.
+ //
+ int i;
+
+ for (i=0; i<5; i++) {
+ if (fSourceStrings[i].fFlags & UnicodeString::kRefCounted) {
+ const UChar *buf = fSourceStrings[i].getBuffer();
+ uint32_t refCount = fSourceStrings[i].refCount();
+ if (refCount != 1) {
+ fprintf(stderr, "\nFailure. SourceString Ref Count was %d, should be 1.\n", refCount);
+ }
+ }
+ }
+};
+
+
+//
+// Factory functoin for StringThreadTest.
+// C function lets ThreadTest create StringTests without needing StringThreadTest header.
+//
+AbstractThreadTest *createStringTest() {
+ return new StringThreadTest();
+};
diff --git a/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.cpp b/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.cpp
new file mode 100644
index 00000000000..85e53a552a4
--- /dev/null
+++ b/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.cpp
@@ -0,0 +1,537 @@
+//
+//********************************************************************
+// Copyright (C) 2002-2011, International Business Machines
+// Corporation and others. All Rights Reserved.
+//********************************************************************
+//
+// File threadtest.cpp
+//
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "unicode/utypes.h"
+#include "unicode/uclean.h"
+#include "umutex.h"
+#include "threadtest.h"
+
+AbstractThreadTest::~AbstractThreadTest() {}
+
+//------------------------------------------------------------------------------
+//
+// Factory functions for creating different test types.
+//
+//------------------------------------------------------------------------------
+extern AbstractThreadTest *createStringTest();
+extern AbstractThreadTest *createConvertTest();
+
+
+
+//------------------------------------------------------------------------------
+//
+// Windows specific code for starting threads
+//
+//------------------------------------------------------------------------------
+#if U_PLATFORM_USES_ONLY_WIN32_API
+
+#include "Windows.h"
+#include "process.h"
+
+
+
+typedef void (*ThreadFunc)(void *);
+
+class ThreadFuncs // This class isolates OS dependent threading
+{ // functions from the rest of ThreadTest program.
+public:
+ static void Sleep(int millis) {::Sleep(millis);};
+ static void startThread(ThreadFunc, void *param);
+ static unsigned long getCurrentMillis();
+ static void yield() {::Sleep(0);};
+};
+
+void ThreadFuncs::startThread(ThreadFunc func, void *param)
+{
+ unsigned long x;
+ x = _beginthread(func, 0x10000, param);
+ if (x == -1)
+ {
+ fprintf(stderr, "Error starting thread. Errno = %d\n", errno);
+ exit(-1);
+ }
+}
+
+unsigned long ThreadFuncs::getCurrentMillis()
+{
+ return (unsigned long)::GetTickCount();
+}
+
+
+
+
+// #elif defined (POSIX)
+#else
+
+//------------------------------------------------------------------------------
+//
+// UNIX specific code for starting threads
+//
+//------------------------------------------------------------------------------
+#include <pthread.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sched.h>
+#include <sys/timeb.h>
+
+
+extern "C" {
+
+
+typedef void (*ThreadFunc)(void *);
+typedef void *(*pthreadfunc)(void *);
+
+class ThreadFuncs // This class isolates OS dependent threading
+{ // functions from the rest of ThreadTest program.
+public:
+ static void Sleep(int millis);
+ static void startThread(ThreadFunc, void *param);
+ static unsigned long getCurrentMillis();
+ static void yield() {sched_yield();};
+};
+
+void ThreadFuncs::Sleep(int millis)
+{
+ int seconds = millis/1000;
+ if (seconds <= 0) seconds = 1;
+ ::sleep(seconds);
+}
+
+
+void ThreadFuncs::startThread(ThreadFunc func, void *param)
+{
+ unsigned long x;
+
+ pthread_t tId;
+ //thread_t tId;
+#if defined(_HP_UX) && defined(XML_USE_DCE)
+ x = pthread_create( &tId, pthread_attr_default, (pthreadfunc)func, param);
+#else
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ x = pthread_create( &tId, &attr, (pthreadfunc)func, param);
+#endif
+ if (x == -1)
+ {
+ fprintf(stderr, "Error starting thread. Errno = %d\n", errno);
+ exit(-1);
+ }
+}
+
+unsigned long ThreadFuncs::getCurrentMillis() {
+ timeb aTime;
+ ftime(&aTime);
+ return (unsigned long)(aTime.time*1000 + aTime.millitm);
+}
+}
+
+
+// #else
+// #error This platform is not supported
+#endif
+
+
+
+//------------------------------------------------------------------------------
+//
+// struct runInfo Holds the info extracted from the command line and data
+// that is shared by all threads.
+// There is only one of these, and it is static.
+// During the test, the threads will access this info without
+// any synchronization.
+//
+//------------------------------------------------------------------------------
+const int MAXINFILES = 25;
+struct RunInfo
+{
+ bool quiet;
+ bool verbose;
+ int numThreads;
+ int totalTime;
+ int checkTime;
+ AbstractThreadTest *fTest;
+ bool stopFlag;
+ bool exitFlag;
+ int32_t runningThreads;
+};
+
+
+//------------------------------------------------------------------------------
+//
+// struct threadInfo Holds information specific to an individual thread.
+// One of these is set up for each thread in the test.
+// The main program monitors the threads by looking
+// at the status stored in these structs.
+//
+//------------------------------------------------------------------------------
+struct ThreadInfo
+{
+ bool fHeartBeat; // Set true by the thread each time it finishes
+ // a test.
+ unsigned int fCycles; // Number of cycles completed.
+ int fThreadNum; // Identifying number for this thread.
+ ThreadInfo() {
+ fHeartBeat = false;
+ fCycles = 0;
+ fThreadNum = -1;
+ }
+};
+
+
+//
+//------------------------------------------------------------------------------
+//
+// Global Data
+//
+//------------------------------------------------------------------------------
+RunInfo gRunInfo;
+ThreadInfo *gThreadInfo;
+UMTX gStopMutex; // Lets main thread suspend test threads.
+UMTX gInfoMutex; // Synchronize access to data passed between
+ // worker threads and the main thread
+
+
+//----------------------------------------------------------------------
+//
+// parseCommandLine Read through the command line, and save all
+// of the options in the gRunInfo struct.
+//
+// Display the usage message if the command line
+// is no good.
+//
+// Probably ought to be a member function of RunInfo.
+//
+//----------------------------------------------------------------------
+
+void parseCommandLine(int argc, char **argv)
+{
+ gRunInfo.quiet = false; // Set up defaults for run.
+ gRunInfo.verbose = false;
+ gRunInfo.numThreads = 2;
+ gRunInfo.totalTime = 0;
+ gRunInfo.checkTime = 10;
+
+ try // Use exceptions for command line syntax errors.
+ {
+ int argnum = 1;
+ while (argnum < argc)
+ {
+ if (strcmp(argv[argnum], "-quiet") == 0)
+ gRunInfo.quiet = true;
+ else if (strcmp(argv[argnum], "-verbose") == 0)
+ gRunInfo.verbose = true;
+ else if (strcmp(argv[argnum], "--help") == 0 ||
+ (strcmp(argv[argnum], "?") == 0)) {throw 1; }
+
+ else if (strcmp(argv[argnum], "-threads") == 0)
+ {
+ ++argnum;
+ if (argnum >= argc)
+ throw 1;
+ gRunInfo.numThreads = atoi(argv[argnum]);
+ if (gRunInfo.numThreads < 0)
+ throw 1;
+ }
+ else if (strcmp(argv[argnum], "-time") == 0)
+ {
+ ++argnum;
+ if (argnum >= argc)
+ throw 1;
+ gRunInfo.totalTime = atoi(argv[argnum]);
+ if (gRunInfo.totalTime < 1)
+ throw 1;
+ }
+ else if (strcmp(argv[argnum], "-ctime") == 0)
+ {
+ ++argnum;
+ if (argnum >= argc)
+ throw 1;
+ gRunInfo.checkTime = atoi(argv[argnum]);
+ if (gRunInfo.checkTime < 1)
+ throw 1;
+ }
+ else if (strcmp(argv[argnum], "string") == 0)
+ {
+ gRunInfo.fTest = createStringTest();
+ }
+ else if (strcmp(argv[argnum], "convert") == 0)
+ {
+ gRunInfo.fTest = createConvertTest();
+ }
+ else
+ {
+ fprintf(stderr, "Unrecognized command line option. Scanning \"%s\"\n",
+ argv[argnum]);
+ throw 1;
+ }
+ argnum++;
+ }
+ // We've reached the end of the command line parameters.
+ // Fail if no test name was specified.
+ if (gRunInfo.fTest == NULL) {
+ fprintf(stderr, "No test specified.\n");
+ throw 1;
+ }
+
+ }
+ catch (int)
+ {
+ fprintf(stderr, "usage: threadtest [-threads nnn] [-time nnn] [-quiet] [-verbose] test-name\n"
+ " -quiet Suppress periodic status display. \n"
+ " -verbose Display extra messages. \n"
+ " -threads nnn Number of threads. Default is 2. \n"
+ " -time nnn Total time to run, in seconds. Default is forever.\n"
+ " -ctime nnn Time between extra consistency checks, in seconds. Default 10\n"
+ " testname string | convert\n"
+ );
+ exit(1);
+ }
+}
+
+
+
+
+
+//----------------------------------------------------------------------
+//
+// threadMain The main function for each of the swarm of test threads.
+// Run in a loop, executing the runOnce() test function each time.
+//
+//
+//----------------------------------------------------------------------
+
+extern "C" {
+
+void threadMain (void *param)
+{
+ ThreadInfo *thInfo = (ThreadInfo *)param;
+
+ if (gRunInfo.verbose)
+ printf("Thread #%d: starting\n", thInfo->fThreadNum);
+ umtx_atomic_inc(&gRunInfo.runningThreads);
+
+ //
+ //
+ while (true)
+ {
+ if (gRunInfo.verbose )
+ printf("Thread #%d: starting loop\n", thInfo->fThreadNum);
+
+ //
+ // If the main thread is asking us to wait, do so by locking gStopMutex
+ // which will block us, since the main thread will be holding it already.
+ //
+ umtx_lock(&gInfoMutex);
+ UBool stop = gRunInfo.stopFlag; // Need mutex for processors with flakey memory models.
+ umtx_unlock(&gInfoMutex);
+
+ if (stop) {
+ if (gRunInfo.verbose) {
+ fprintf(stderr, "Thread #%d: suspending\n", thInfo->fThreadNum);
+ }
+ umtx_atomic_dec(&gRunInfo.runningThreads);
+ while (gRunInfo.stopFlag) {
+ umtx_lock(&gStopMutex);
+ umtx_unlock(&gStopMutex);
+ }
+ umtx_atomic_inc(&gRunInfo.runningThreads);
+ if (gRunInfo.verbose) {
+ fprintf(stderr, "Thread #%d: restarting\n", thInfo->fThreadNum);
+ }
+ }
+
+ //
+ // The real work of the test happens here.
+ //
+ gRunInfo.fTest->runOnce();
+
+ umtx_lock(&gInfoMutex);
+ thInfo->fHeartBeat = true;
+ thInfo->fCycles++;
+ UBool exitNow = gRunInfo.exitFlag;
+ umtx_unlock(&gInfoMutex);
+
+ //
+ // If main thread says it's time to exit, break out of the loop.
+ //
+ if (exitNow) {
+ break;
+ }
+ }
+
+ umtx_atomic_dec(&gRunInfo.runningThreads);
+
+ // Returning will kill the thread.
+ return;
+}
+
+}
+
+
+
+
+//----------------------------------------------------------------------
+//
+// main
+//
+//----------------------------------------------------------------------
+
+int main (int argc, char **argv)
+{
+ //
+ // Parse the command line options, and create the specified kind of test.
+ //
+ parseCommandLine(argc, argv);
+
+
+ //
+ // Fire off the requested number of parallel threads
+ //
+
+ if (gRunInfo.numThreads == 0)
+ exit(0);
+
+ gRunInfo.exitFlag = FALSE;
+ gRunInfo.stopFlag = TRUE; // Will cause the new threads to block
+ umtx_lock(&gStopMutex);
+
+ gThreadInfo = new ThreadInfo[gRunInfo.numThreads];
+ int threadNum;
+ for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++)
+ {
+ gThreadInfo[threadNum].fThreadNum = threadNum;
+ ThreadFuncs::startThread(threadMain, &gThreadInfo[threadNum]);
+ }
+
+
+ unsigned long startTime = ThreadFuncs::getCurrentMillis();
+ int elapsedSeconds = 0;
+ int timeSinceCheck = 0;
+
+ //
+ // Unblock the threads.
+ //
+ gRunInfo.stopFlag = FALSE; // Unblocks the worker threads.
+ umtx_unlock(&gStopMutex);
+
+ //
+ // Loop, watching the heartbeat of the worker threads.
+ // Each second,
+ // display "+" if all threads have completed at least one loop
+ // display "." if some thread hasn't since previous "+"
+ // Each "ctime" seconds,
+ // Stop all the worker threads at the top of their loop, then
+ // call the test's check function.
+ //
+ while (gRunInfo.totalTime == 0 || gRunInfo.totalTime > elapsedSeconds)
+ {
+ ThreadFuncs::Sleep(1000); // We sleep while threads do their work ...
+
+ if (gRunInfo.quiet == false && gRunInfo.verbose == false)
+ {
+ char c = '+';
+ int threadNum;
+ umtx_lock(&gInfoMutex);
+ for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++)
+ {
+ if (gThreadInfo[threadNum].fHeartBeat == false)
+ {
+ c = '.';
+ break;
+ };
+ }
+ umtx_unlock(&gInfoMutex);
+ fputc(c, stdout);
+ fflush(stdout);
+ if (c == '+')
+ for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++)
+ gThreadInfo[threadNum].fHeartBeat = false;
+ }
+
+ //
+ // Update running times.
+ //
+ timeSinceCheck -= elapsedSeconds;
+ elapsedSeconds = (ThreadFuncs::getCurrentMillis() - startTime) / 1000;
+ timeSinceCheck += elapsedSeconds;
+
+ //
+ // Call back to the test to let it check its internal validity
+ //
+ if (timeSinceCheck >= gRunInfo.checkTime) {
+ if (gRunInfo.verbose) {
+ fprintf(stderr, "Main: suspending all threads\n");
+ }
+ umtx_lock(&gStopMutex); // Block the worker threads at the top of their loop
+ gRunInfo.stopFlag = TRUE;
+ for (;;) {
+ umtx_lock(&gInfoMutex);
+ UBool done = gRunInfo.runningThreads == 0;
+ umtx_unlock(&gInfoMutex);
+ if (done) { break;}
+ ThreadFuncs::yield();
+ }
+
+
+
+ gRunInfo.fTest->check();
+ if (gRunInfo.quiet == false && gRunInfo.verbose == false) {
+ fputc('C', stdout);
+ }
+
+ if (gRunInfo.verbose) {
+ fprintf(stderr, "Main: starting all threads.\n");
+ }
+ gRunInfo.stopFlag = FALSE; // Unblock the worker threads.
+ umtx_unlock(&gStopMutex);
+ timeSinceCheck = 0;
+ }
+ };
+
+ //
+ // Time's up, we are done. (We only get here if this was a timed run)
+ // Tell the threads to exit.
+ //
+ gRunInfo.exitFlag = true;
+ for (;;) {
+ umtx_lock(&gInfoMutex);
+ UBool done = gRunInfo.runningThreads == 0;
+ umtx_unlock(&gInfoMutex);
+ if (done) { break;}
+ ThreadFuncs::yield();
+ }
+
+ //
+ // Tally up the total number of cycles completed by each of the threads.
+ //
+ double totalCyclesCompleted = 0;
+ for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++) {
+ totalCyclesCompleted += gThreadInfo[threadNum].fCycles;
+ }
+
+ double cyclesPerMinute = totalCyclesCompleted / (double(gRunInfo.totalTime) / double(60));
+ printf("\n%8.1f cycles per minute.", cyclesPerMinute);
+
+ //
+ // Memory should be clean coming out
+ //
+ delete gRunInfo.fTest;
+ delete [] gThreadInfo;
+ umtx_destroy(&gInfoMutex);
+ umtx_destroy(&gStopMutex);
+ u_cleanup();
+
+ return 0;
+}
+
+
diff --git a/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.dsp b/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.dsp
new file mode 100644
index 00000000000..63bfe223da3
--- /dev/null
+++ b/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.dsp
@@ -0,0 +1,166 @@
+# Microsoft Developer Studio Project File - Name="threadtest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=threadtest - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "threadtest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "threadtest.mak" CFG="threadtest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "threadtest - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "threadtest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "threadtest - Win64 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "threadtest - Win64 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "threadtest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /G6 /MD /W3 /GX /O2 /Ob2 /I "..\..\..\include" /I "..\..\..\source\common" /I "..\..\..\source\i18n" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib shell32.lib icuuc.lib icuin.lib icutu.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\lib\\"
+
+!ELSEIF "$(CFG)" == "threadtest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
+# ADD CPP /nologo /G6 /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\include" /I "..\..\..\source\common" /I "..\..\..\source\i18n" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib shell32.lib icuucd.lib icuind.lib icutud.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\lib\\"
+
+!ELSEIF "$(CFG)" == "threadtest - Win64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN64" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /I "..\..\..\include" /I "..\..\..\source\common" /I "..\..\..\source\i18n" /D"WIN64" /D"NDEBUG" /D"_CONSOLE" /D"_MBCS" /FD /c /O2 /GX /Op /D"_IA64_" /Zi /D"WIN64" /D"WIN32" /D"_AFX_NO_DAO_SUPPORT" /Zm600
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:IA64
+# ADD LINK32 kernel32.lib user32.lib shell32.lib icuuc.lib icuin.lib icutu.lib /nologo /subsystem:console /machine:IA64 /libpath:"..\..\..\lib\\" /incremental:no
+
+!ELSEIF "$(CFG)" == "threadtest - Win64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN64" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /I "..\..\..\include" /I "..\..\..\source\common" /I "..\..\..\source\i18n" /D"WIN64" /D"_DEBUG" /D"_CONSOLE" /D"_MBCS" /FR /FD /GZ /c /Od /GX /Op /D"_IA64_" /Zi /D"WIN64" /D"WIN32" /D"_AFX_NO_DAO_SUPPORT" /Zm600
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:IA64 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib shell32.lib icuucd.lib icuind.lib icutud.lib /nologo /subsystem:console /debug /machine:IA64 /pdbtype:sept /libpath:"..\..\..\lib\\" /incremental:no
+
+!ENDIF
+
+# Begin Target
+
+# Name "threadtest - Win32 Release"
+# Name "threadtest - Win32 Debug"
+# Name "threadtest - Win64 Release"
+# Name "threadtest - Win64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\converttest.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\stringtest.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\threadtest.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\threadtest.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.dsw b/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.dsw
new file mode 100644
index 00000000000..0e853c88796
--- /dev/null
+++ b/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "threadtest"=.\threadtest.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.h b/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.h
new file mode 100644
index 00000000000..1ad74cfe4ac
--- /dev/null
+++ b/Build/source/libs/icu/icu-49.1/test/threadtest/threadtest.h
@@ -0,0 +1,45 @@
+//
+//********************************************************************
+// Copyright (C) 2002-2011, International Business Machines
+// Corporation and others. All Rights Reserved.
+//********************************************************************
+//
+// File threadtest.h
+//
+#ifndef ABSTRACTTHREADTEST_H
+#define ABSTRACTTHREADTEST_H
+//------------------------------------------------------------------------------
+//
+// class AbstractThreadTest Base class for threading tests.
+// Use of this abstract base isolates the part of the
+// program that nows how to spin up and control threads
+// from the specific stuff being tested, and (hopefully)
+// simplifies adding new threading tests for different parts
+// of ICU.
+//
+// Derived classes: A running test will have exactly one instance of a
+// derived class, which will persist for the duration of the
+// test and be shared among all of the threads involved in
+// the test.
+//
+// The constructor will be called in a single-threaded environment,
+// and should set up any data that will need to persist for the
+// duration.
+//
+// runOnce() will be called repeatedly by the working threads of
+// the test in the full multi-threaded environment.
+//
+// check() will be called periodically in a single threaded
+// environment, with the worker threads temporarily suspended between
+// between calls to runOnce(). Do consistency checks here.
+//
+//------------------------------------------------------------------------------
+class AbstractThreadTest {
+public:
+ AbstractThreadTest() {};
+ virtual ~AbstractThreadTest();
+ virtual void check() = 0;
+ virtual void runOnce() = 0;
+};
+
+#endif // ABSTRACTTHREADTEST_H