]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/simplethread.cpp
ICU-57149.0.1.tar.gz
[apple/icu.git] / icuSources / test / intltest / simplethread.cpp
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1999-2015, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6
7 #if defined(hpux)
8 # ifndef _INCLUDE_POSIX_SOURCE
9 # define _INCLUDE_POSIX_SOURCE
10 # endif
11 #endif
12
13 /* Define __EXTENSIONS__ for Solaris and old friends in strict mode. */
14 #ifndef __EXTENSIONS__
15 #define __EXTENSIONS__
16 #endif
17
18 // Defines _XOPEN_SOURCE for access to POSIX functions.
19 // Must be before any other #includes.
20 #include "uposixdefs.h"
21
22 #include "simplethread.h"
23
24 #include "unicode/utypes.h"
25 #include "unicode/ustring.h"
26 #include "umutex.h"
27 #include "cmemory.h"
28 #include "cstring.h"
29 #include "uparse.h"
30 #include "unicode/resbund.h"
31 #include "unicode/udata.h"
32 #include "unicode/uloc.h"
33 #include "unicode/locid.h"
34 #include "putilimp.h"
35 #include "intltest.h"
36
37 #include <stdio.h>
38 #include <string.h>
39 #include <ctype.h> // tolower, toupper
40
41 #if U_PLATFORM_USES_ONLY_WIN32_API
42 /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin). */
43 # undef POSIX
44 #elif U_PLATFORM_IMPLEMENTS_POSIX
45 # define POSIX
46 #else
47 # undef POSIX
48 #endif
49
50 /* Needed by z/OS to get usleep */
51 #if U_PLATFORM == U_PF_OS390
52 #define __DOT1 1
53 #ifndef __UU
54 # define __UU
55 #endif
56 #ifndef _XPG4_2
57 # define _XPG4_2
58 #endif
59 #include <unistd.h>
60 #endif
61
62 #if defined(POSIX)
63 #define HAVE_IMP
64
65 #include <pthread.h>
66
67 #if U_PLATFORM == U_PF_OS390
68 #include <sys/types.h>
69 #endif
70
71 #if U_PLATFORM != U_PF_OS390
72 #include <signal.h>
73 #endif
74
75 /* Define _XPG4_2 for Solaris and friends. */
76 #ifndef _XPG4_2
77 #define _XPG4_2
78 #endif
79
80 /* Define __USE_XOPEN_EXTENDED for Linux and glibc. */
81 #ifndef __USE_XOPEN_EXTENDED
82 #define __USE_XOPEN_EXTENDED
83 #endif
84
85 /* Define _INCLUDE_XOPEN_SOURCE_EXTENDED for HP/UX (11?). */
86 #ifndef _INCLUDE_XOPEN_SOURCE_EXTENDED
87 #define _INCLUDE_XOPEN_SOURCE_EXTENDED
88 #endif
89
90 #include <unistd.h>
91
92 #endif
93 /* HPUX */
94 #ifdef sleep
95 #undef sleep
96 #endif
97
98
99 #include "unicode/putil.h"
100
101 /* for mthreadtest*/
102 #include "unicode/numfmt.h"
103 #include "unicode/choicfmt.h"
104 #include "unicode/msgfmt.h"
105 #include "unicode/locid.h"
106 #include "unicode/ucol.h"
107 #include "unicode/calendar.h"
108 #include "ucaconf.h"
109
110 #if U_PLATFORM_USES_ONLY_WIN32_API
111 #define HAVE_IMP
112
113 # define VC_EXTRALEAN
114 # define WIN32_LEAN_AND_MEAN
115 # define NOUSER
116 # define NOSERVICE
117 # define NOIME
118 # define NOMCX
119 #include <windows.h>
120 #include <process.h>
121
122 //-----------------------------------------------------------------------------------
123 //
124 // class SimpleThread Windows Implementation
125 //
126 //-----------------------------------------------------------------------------------
127 struct Win32ThreadImplementation
128 {
129 HANDLE fHandle;
130 unsigned int fThreadID;
131 };
132
133
134 extern "C" unsigned int __stdcall SimpleThreadProc(void *arg)
135 {
136 ((SimpleThread*)arg)->run();
137 return 0;
138 }
139
140 SimpleThread::SimpleThread()
141 :fImplementation(0)
142 {
143 Win32ThreadImplementation *imp = new Win32ThreadImplementation;
144 imp->fHandle = 0;
145 fImplementation = imp;
146 }
147
148 SimpleThread::~SimpleThread()
149 {
150 // Destructor. Because we start the thread running with _beginthreadex(),
151 // we own the Windows HANDLE for the thread and must
152 // close it here.
153 Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation;
154 if (imp != 0) {
155 if (imp->fHandle != 0) {
156 CloseHandle(imp->fHandle);
157 imp->fHandle = 0;
158 }
159 }
160 delete (Win32ThreadImplementation*)fImplementation;
161 }
162
163 int32_t SimpleThread::start()
164 {
165 Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation;
166 if(imp->fHandle != NULL) {
167 // The thread appears to have already been started.
168 // This is probably an error on the part of our caller.
169 return -1;
170 }
171
172 imp->fHandle = (HANDLE) _beginthreadex(
173 NULL, // Security
174 0x20000, // Stack Size
175 SimpleThreadProc, // Function to Run
176 (void *)this, // Arg List
177 0, // initflag. Start running, not suspended
178 &imp->fThreadID // thraddr
179 );
180
181 if (imp->fHandle == 0) {
182 // An error occured
183 int err = errno;
184 if (err == 0) {
185 err = -1;
186 }
187 return err;
188 }
189 return 0;
190 }
191
192
193 void SimpleThread::join() {
194 Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation;
195 if (imp->fHandle == 0) {
196 // No handle, thread must not be running.
197 return;
198 }
199 WaitForSingleObject(imp->fHandle, INFINITE);
200 }
201
202 #endif
203
204
205 //-----------------------------------------------------------------------------------
206 //
207 // class SimpleThread POSIX implementation
208 //
209 //-----------------------------------------------------------------------------------
210 #if defined(POSIX)
211 #define HAVE_IMP
212
213 struct PosixThreadImplementation
214 {
215 pthread_t fThread;
216 };
217
218 extern "C" void* SimpleThreadProc(void *arg)
219 {
220 // This is the code that is run in the new separate thread.
221 SimpleThread *This = (SimpleThread *)arg;
222 This->run();
223 return 0;
224 }
225
226 SimpleThread::SimpleThread()
227 {
228 PosixThreadImplementation *imp = new PosixThreadImplementation;
229 fImplementation = imp;
230 }
231
232 SimpleThread::~SimpleThread()
233 {
234 PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation;
235 delete imp;
236 fImplementation = (void *)0xdeadbeef;
237 }
238
239 int32_t SimpleThread::start()
240 {
241 int32_t rc;
242 static pthread_attr_t attr;
243 static UBool attrIsInitialized = FALSE;
244
245 PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation;
246
247 if (attrIsInitialized == FALSE) {
248 rc = pthread_attr_init(&attr);
249 #if U_PLATFORM == U_PF_OS390
250 {
251 int detachstate = 0; // jdc30: detach state of zero causes
252 //threads created with this attr to be in
253 //an undetached state. An undetached
254 //thread will keep its resources after
255 //termination.
256 pthread_attr_setdetachstate(&attr, &detachstate);
257 }
258 #else
259 // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
260 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
261 #endif
262 attrIsInitialized = TRUE;
263 }
264 rc = pthread_create(&(imp->fThread), &attr, &SimpleThreadProc, (void*)this);
265
266 if (rc != 0) {
267 // some kind of error occured, the thread did not start.
268 }
269
270 return rc;
271 }
272
273 void SimpleThread::join() {
274 PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation;
275 pthread_join(imp->fThread, NULL);
276 }
277
278 #endif
279 // end POSIX
280
281
282 #ifndef HAVE_IMP
283 #error No implementation for threads! Cannot test.
284 #endif
285
286
287 class ThreadPoolThread: public SimpleThread {
288 public:
289 ThreadPoolThread(ThreadPoolBase *pool, int32_t threadNum) : fPool(pool), fNum(threadNum) {};
290 virtual void run() {fPool->callFn(fNum); }
291 ThreadPoolBase *fPool;
292 int32_t fNum;
293 };
294
295
296 ThreadPoolBase::ThreadPoolBase(IntlTest *test, int32_t howMany) :
297 fIntlTest(test), fNumThreads(howMany), fThreads(NULL) {
298 fThreads = new SimpleThread *[fNumThreads];
299 if (fThreads == NULL) {
300 fIntlTest->errln("%s:%d memory allocation failure.", __FILE__, __LINE__);
301 return;
302 }
303
304 for (int i=0; i<fNumThreads; i++) {
305 fThreads[i] = new ThreadPoolThread(this, i);
306 if (fThreads[i] == NULL) {
307 fIntlTest->errln("%s:%d memory allocation failure.", __FILE__, __LINE__);
308 }
309 }
310 }
311
312 void ThreadPoolBase::start() {
313 for (int i=0; i<fNumThreads; i++) {
314 if (fThreads && fThreads[i]) {
315 fThreads[i]->start();
316 }
317 }
318 }
319
320 void ThreadPoolBase::join() {
321 for (int i=0; i<fNumThreads; i++) {
322 if (fThreads && fThreads[i]) {
323 fThreads[i]->join();
324 }
325 }
326 }
327
328 ThreadPoolBase::~ThreadPoolBase() {
329 if (fThreads) {
330 for (int i=0; i<fNumThreads; i++) {
331 delete fThreads[i];
332 fThreads[i] = NULL;
333 }
334 delete[] fThreads;
335 fThreads = NULL;
336 }
337 }
338
339
340