1 // © 2016 and later: Unicode, Inc. and others. 
   2 // License & terms of use: http://www.unicode.org/copyright.html 
   3 /******************************************************************** 
   5  * Copyright (c) 1999-2015, International Business Machines Corporation and 
   6  * others. All Rights Reserved. 
   7  ********************************************************************/ 
  10 # ifndef _INCLUDE_POSIX_SOURCE 
  11 #  define _INCLUDE_POSIX_SOURCE 
  15 /* Define __EXTENSIONS__ for Solaris and old friends in strict mode. */ 
  16 #ifndef __EXTENSIONS__ 
  17 #define __EXTENSIONS__ 
  20 // Defines _XOPEN_SOURCE for access to POSIX functions. 
  21 // Must be before any other #includes. 
  22 #include "uposixdefs.h" 
  24 #include "simplethread.h" 
  26 #include "unicode/utypes.h" 
  27 #include "unicode/ustring.h" 
  32 #include "unicode/resbund.h" 
  33 #include "unicode/udata.h" 
  34 #include "unicode/uloc.h" 
  35 #include "unicode/locid.h" 
  41 #include <ctype.h>    // tolower, toupper 
  43 #if U_PLATFORM_USES_ONLY_WIN32_API 
  44     /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin). */ 
  46 #elif U_PLATFORM_IMPLEMENTS_POSIX 
  52 /* Needed by z/OS to get usleep */ 
  53 #if U_PLATFORM == U_PF_OS390 
  69 #if U_PLATFORM == U_PF_OS390 
  70 #include <sys/types.h> 
  73 #if U_PLATFORM != U_PF_OS390 
  77 /* Define _XPG4_2 for Solaris and friends. */ 
  82 /* Define __USE_XOPEN_EXTENDED for Linux and glibc. */ 
  83 #ifndef __USE_XOPEN_EXTENDED 
  84 #define __USE_XOPEN_EXTENDED  
  87 /* Define _INCLUDE_XOPEN_SOURCE_EXTENDED for HP/UX (11?). */ 
  88 #ifndef _INCLUDE_XOPEN_SOURCE_EXTENDED 
  89 #define _INCLUDE_XOPEN_SOURCE_EXTENDED 
 101 #include "unicode/putil.h" 
 104 #include "unicode/numfmt.h" 
 105 #include "unicode/choicfmt.h" 
 106 #include "unicode/msgfmt.h" 
 107 #include "unicode/locid.h" 
 108 #include "unicode/ucol.h" 
 109 #include "unicode/calendar.h" 
 112 #if U_PLATFORM_USES_ONLY_WIN32_API 
 115 #   define VC_EXTRALEAN 
 116 #   define WIN32_LEAN_AND_MEAN 
 124 //----------------------------------------------------------------------------------- 
 126 //   class SimpleThread   Windows Implementation 
 128 //----------------------------------------------------------------------------------- 
 129 struct Win32ThreadImplementation
 
 132     unsigned int   fThreadID
; 
 136 extern "C" unsigned int __stdcall 
SimpleThreadProc(void *arg
) 
 138     ((SimpleThread
*)arg
)->run(); 
 142 SimpleThread::SimpleThread() 
 145     Win32ThreadImplementation 
*imp 
= new Win32ThreadImplementation
; 
 147     fImplementation 
= imp
; 
 150 SimpleThread::~SimpleThread() 
 152     // Destructor.  Because we start the thread running with _beginthreadex(), 
 153     //              we own the Windows HANDLE for the thread and must  
 155     Win32ThreadImplementation 
*imp 
= (Win32ThreadImplementation
*)fImplementation
; 
 157         if (imp
->fHandle 
!= 0) { 
 158             CloseHandle(imp
->fHandle
); 
 162     delete (Win32ThreadImplementation
*)fImplementation
; 
 165 int32_t SimpleThread::start() 
 167     Win32ThreadImplementation 
*imp 
= (Win32ThreadImplementation
*)fImplementation
; 
 168     if(imp
->fHandle 
!= NULL
) { 
 169         // The thread appears to have already been started. 
 170         //   This is probably an error on the part of our caller. 
 174     imp
->fHandle 
= (HANDLE
) _beginthreadex( 
 176         0x20000,                              // Stack Size  
 177         SimpleThreadProc
,                     // Function to Run 
 178         (void *)this,                         // Arg List 
 179         0,                                    // initflag.  Start running, not suspended 
 180         &imp
->fThreadID                       
// thraddr 
 183     if (imp
->fHandle 
== 0) { 
 195 void SimpleThread::join() { 
 196     Win32ThreadImplementation 
*imp 
= (Win32ThreadImplementation
*)fImplementation
; 
 197     if (imp
->fHandle 
== 0) { 
 198         // No handle, thread must not be running. 
 201     WaitForSingleObject(imp
->fHandle
, INFINITE
); 
 207 //----------------------------------------------------------------------------------- 
 209 //   class SimpleThread   POSIX implementation 
 211 //----------------------------------------------------------------------------------- 
 215 struct PosixThreadImplementation
 
 220 extern "C" void* SimpleThreadProc(void *arg
) 
 222     // This is the code that is run in the new separate thread. 
 223     SimpleThread 
*This 
= (SimpleThread 
*)arg
; 
 228 SimpleThread::SimpleThread()  
 230     PosixThreadImplementation 
*imp 
= new PosixThreadImplementation
; 
 231     fImplementation 
= imp
; 
 234 SimpleThread::~SimpleThread() 
 236     PosixThreadImplementation 
*imp 
= (PosixThreadImplementation
*)fImplementation
; 
 238     fImplementation 
= (void *)0xdeadbeef; 
 241 int32_t SimpleThread::start() 
 244     static pthread_attr_t attr
; 
 245     static UBool attrIsInitialized 
= FALSE
; 
 247     PosixThreadImplementation 
*imp 
= (PosixThreadImplementation
*)fImplementation
; 
 249     if (attrIsInitialized 
== FALSE
) { 
 250         rc 
= pthread_attr_init(&attr
); 
 251 #if U_PLATFORM == U_PF_OS390 
 253             int detachstate 
= 0;  // jdc30: detach state of zero causes 
 254                                   //threads created with this attr to be in 
 255                                   //an undetached state.  An undetached 
 256                                   //thread will keep its resources after 
 258             pthread_attr_setdetachstate(&attr
, &detachstate
); 
 261         // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 
 262         pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_JOINABLE
); 
 264         attrIsInitialized 
= TRUE
; 
 266     rc 
= pthread_create(&(imp
->fThread
), &attr
, &SimpleThreadProc
, (void*)this); 
 269         // some kind of error occured, the thread did not start. 
 275 void SimpleThread::join() { 
 276     PosixThreadImplementation 
*imp 
= (PosixThreadImplementation
*)fImplementation
; 
 277     pthread_join(imp
->fThread
, NULL
); 
 285 #error  No implementation for threads! Cannot test. 
 289 class ThreadPoolThread
: public SimpleThread 
{ 
 291     ThreadPoolThread(ThreadPoolBase 
*pool
, int32_t threadNum
) : fPool(pool
), fNum(threadNum
) {}; 
 292     virtual void run() {fPool
->callFn(fNum
); } 
 293     ThreadPoolBase 
*fPool
; 
 298 ThreadPoolBase::ThreadPoolBase(IntlTest 
*test
, int32_t howMany
) : 
 299         fIntlTest(test
), fNumThreads(howMany
), fThreads(NULL
) { 
 300     fThreads 
= new SimpleThread 
*[fNumThreads
]; 
 301     if (fThreads 
== NULL
) { 
 302         fIntlTest
->errln("%s:%d memory allocation failure.", __FILE__
, __LINE__
); 
 306     for (int i
=0; i
<fNumThreads
; i
++) { 
 307         fThreads
[i
] = new ThreadPoolThread(this, i
); 
 308         if (fThreads
[i
] == NULL
) { 
 309             fIntlTest
->errln("%s:%d memory allocation failure.", __FILE__
, __LINE__
); 
 314 void ThreadPoolBase::start() { 
 315     for (int i
=0; i
<fNumThreads
; i
++) { 
 316         if (fThreads 
&& fThreads
[i
]) { 
 317             fThreads
[i
]->start(); 
 322 void ThreadPoolBase::join() { 
 323     for (int i
=0; i
<fNumThreads
; i
++) { 
 324         if (fThreads 
&& fThreads
[i
]) { 
 330 ThreadPoolBase::~ThreadPoolBase() { 
 332         for (int i
=0; i
<fNumThreads
; i
++) {