1 // Copyright (C) 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++) {