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