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
++) {