OLD | NEW |
1 /******************************************************************** | 1 /******************************************************************** |
2 * COPYRIGHT: | 2 * COPYRIGHT: |
3 * Copyright (c) 1999-2013, International Business Machines Corporation and | 3 * Copyright (c) 1999-2015, International Business Machines Corporation and |
4 * others. All Rights Reserved. | 4 * others. All Rights Reserved. |
5 ********************************************************************/ | 5 ********************************************************************/ |
6 | 6 |
7 #if defined(hpux) | 7 #if defined(hpux) |
8 # ifndef _INCLUDE_POSIX_SOURCE | 8 # ifndef _INCLUDE_POSIX_SOURCE |
9 # define _INCLUDE_POSIX_SOURCE | 9 # define _INCLUDE_POSIX_SOURCE |
10 # endif | 10 # endif |
11 #endif | 11 #endif |
12 | 12 |
13 /* Define __EXTENSIONS__ for Solaris and old friends in strict mode. */ | 13 /* Define __EXTENSIONS__ for Solaris and old friends in strict mode. */ |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 #endif | 55 #endif |
56 #ifndef _XPG4_2 | 56 #ifndef _XPG4_2 |
57 # define _XPG4_2 | 57 # define _XPG4_2 |
58 #endif | 58 #endif |
59 #include <unistd.h> | 59 #include <unistd.h> |
60 #endif | 60 #endif |
61 | 61 |
62 #if defined(POSIX) | 62 #if defined(POSIX) |
63 #define HAVE_IMP | 63 #define HAVE_IMP |
64 | 64 |
65 #if (ICU_USE_THREADS == 1) | |
66 #include <pthread.h> | 65 #include <pthread.h> |
67 #endif | |
68 | |
69 #if defined(__hpux) && defined(HPUX_CMA) | |
70 # if defined(read) // read being defined as cma_read causes trouble with iostre
am::read | |
71 # undef read | |
72 # endif | |
73 #endif | |
74 | 66 |
75 #if U_PLATFORM == U_PF_OS390 | 67 #if U_PLATFORM == U_PF_OS390 |
76 #include <sys/types.h> | 68 #include <sys/types.h> |
77 #endif | 69 #endif |
78 | 70 |
79 #if U_PLATFORM != U_PF_OS390 | 71 #if U_PLATFORM != U_PF_OS390 |
80 #include <signal.h> | 72 #include <signal.h> |
81 #endif | 73 #endif |
82 | 74 |
83 /* Define _XPG4_2 for Solaris and friends. */ | 75 /* Define _XPG4_2 for Solaris and friends. */ |
(...skipping 13 matching lines...) Expand all Loading... |
97 | 89 |
98 #include <unistd.h> | 90 #include <unistd.h> |
99 | 91 |
100 #endif | 92 #endif |
101 /* HPUX */ | 93 /* HPUX */ |
102 #ifdef sleep | 94 #ifdef sleep |
103 #undef sleep | 95 #undef sleep |
104 #endif | 96 #endif |
105 | 97 |
106 | 98 |
107 #if (ICU_USE_THREADS==0) | |
108 SimpleThread::SimpleThread() | |
109 {} | |
110 | |
111 SimpleThread::~SimpleThread() | |
112 {} | |
113 | |
114 int32_t | |
115 SimpleThread::start() | |
116 { return -1; } | |
117 | |
118 void | |
119 SimpleThread::run() | |
120 {} | |
121 | |
122 void | |
123 SimpleThread::sleep(int32_t millis) | |
124 {} | |
125 | |
126 UBool | |
127 SimpleThread::isRunning() { | |
128 return FALSE; | |
129 } | |
130 #else | |
131 | |
132 #include "unicode/putil.h" | 99 #include "unicode/putil.h" |
133 | 100 |
134 /* for mthreadtest*/ | 101 /* for mthreadtest*/ |
135 #include "unicode/numfmt.h" | 102 #include "unicode/numfmt.h" |
136 #include "unicode/choicfmt.h" | 103 #include "unicode/choicfmt.h" |
137 #include "unicode/msgfmt.h" | 104 #include "unicode/msgfmt.h" |
138 #include "unicode/locid.h" | 105 #include "unicode/locid.h" |
139 #include "unicode/ucol.h" | 106 #include "unicode/ucol.h" |
140 #include "unicode/calendar.h" | 107 #include "unicode/calendar.h" |
141 #include "ucaconf.h" | 108 #include "ucaconf.h" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 int err = errno; | 183 int err = errno; |
217 if (err == 0) { | 184 if (err == 0) { |
218 err = -1; | 185 err = -1; |
219 } | 186 } |
220 return err; | 187 return err; |
221 } | 188 } |
222 return 0; | 189 return 0; |
223 } | 190 } |
224 | 191 |
225 | 192 |
226 UBool SimpleThread::isRunning() { | 193 void SimpleThread::join() { |
227 // | |
228 // Test whether the thread associated with the SimpleThread object is | |
229 // still actually running. | |
230 // | |
231 // NOTE: on Win64 on Itanium processors, a crashes | |
232 // occur if the main thread of a process exits concurrently with some | |
233 // other thread(s) exiting. To avoid the possibility, we wait until the | |
234 // OS indicates that all threads have terminated, rather than waiting | |
235 // only until the end of the user's Run function has been reached. | |
236 // | |
237 // I don't know whether the crashes represent a Windows bug, or whether | |
238 // main() programs are supposed to have to wait for their threads. | |
239 // | |
240 Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation
; | 194 Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation
; |
241 | |
242 bool success; | |
243 DWORD threadExitCode; | |
244 | |
245 if (imp->fHandle == 0) { | 195 if (imp->fHandle == 0) { |
246 // No handle, thread must not be running. | 196 // No handle, thread must not be running. |
247 return FALSE; | 197 return; |
248 } | 198 } |
249 success = GetExitCodeThread(imp->fHandle, &threadExitCode) != 0; | 199 WaitForSingleObject(imp->fHandle, INFINITE); |
250 if (! success) { | |
251 // Can't get status, thread must not be running. | |
252 return FALSE; | |
253 } | |
254 return (threadExitCode == STILL_ACTIVE); | |
255 } | |
256 | |
257 | |
258 void SimpleThread::sleep(int32_t millis) | |
259 { | |
260 ::Sleep(millis); | |
261 } | |
262 | |
263 //------------------------------------------------------------------------------
----- | |
264 // | |
265 // class SimpleThread NULL Implementation | |
266 // | |
267 //------------------------------------------------------------------------------
----- | |
268 #elif U_PLATFORM == U_PF_CLASSIC_MACOS | |
269 | |
270 // since the Mac has no preemptive threading (at least on MacOS 8), only | |
271 // cooperative threading, threads are a no-op. We have no yield() calls | |
272 // anywhere in the ICU, so we are guaranteed to be thread-safe. | |
273 | |
274 #define HAVE_IMP | |
275 | |
276 SimpleThread::SimpleThread() | |
277 {} | |
278 | |
279 SimpleThread::~SimpleThread() | |
280 {} | |
281 | |
282 int32_t | |
283 SimpleThread::start() | |
284 { return 0; } | |
285 | |
286 void | |
287 SimpleThread::run() | |
288 {} | |
289 | |
290 void | |
291 SimpleThread::sleep(int32_t millis) | |
292 {} | |
293 | |
294 UBool | |
295 SimpleThread::isRunning() { | |
296 return FALSE; | |
297 } | 200 } |
298 | 201 |
299 #endif | 202 #endif |
300 | 203 |
301 | 204 |
302 //------------------------------------------------------------------------------
----- | 205 //------------------------------------------------------------------------------
----- |
303 // | 206 // |
304 // class SimpleThread POSIX implementation | 207 // class SimpleThread POSIX implementation |
305 // | 208 // |
306 // A note on the POSIX vs the Windows implementations of this class.. | |
307 // On Windows, the main thread must verify that other threads have finish
ed | |
308 // before exiting, or crashes occasionally occur. (Seen on Itanium Win64
only) | |
309 // The function SimpleThread::isRunning() is used for this purpose. | |
310 // | |
311 // On POSIX, there is NO reliable non-blocking mechanism to determine | |
312 // whether a thread has exited. pthread_kill(thread, 0) almost works, | |
313 // but the system can recycle thread ids immediately, so seeing that a | |
314 // thread exists with this call could mean that the original thread has | |
315 // finished and a new one started with the same ID. Useless. | |
316 // | |
317 // So we need to do the check with user code, by setting a flag just befo
re | |
318 // the thread function returns. A technique that is guaranteed to fail | |
319 // on Windows, because it indicates that the thread is done before all | |
320 // system level cleanup has happened. | |
321 // | |
322 //------------------------------------------------------------------------------
----- | 209 //------------------------------------------------------------------------------
----- |
323 #if defined(POSIX) | 210 #if defined(POSIX) |
324 #define HAVE_IMP | 211 #define HAVE_IMP |
325 | 212 |
326 struct PosixThreadImplementation | 213 struct PosixThreadImplementation |
327 { | 214 { |
328 pthread_t fThread; | 215 pthread_t fThread; |
329 UBool fRunning; | |
330 UBool fRan; // True if the thread was successfully start
ed | |
331 }; | 216 }; |
332 | 217 |
333 extern "C" void* SimpleThreadProc(void *arg) | 218 extern "C" void* SimpleThreadProc(void *arg) |
334 { | 219 { |
335 // This is the code that is run in the new separate thread. | 220 // This is the code that is run in the new separate thread. |
336 SimpleThread *This = (SimpleThread *)arg; | 221 SimpleThread *This = (SimpleThread *)arg; |
337 This->run(); // Run the user code. | 222 This->run(); |
338 | |
339 // The user function has returned. Set the flag indicating that this thread | |
340 // is done. Need a mutex for memory barrier purposes only, so that other th
read | |
341 // will reliably see that the flag has changed. | |
342 PosixThreadImplementation *imp = (PosixThreadImplementation*)This->fImplemen
tation; | |
343 umtx_lock(NULL); | |
344 imp->fRunning = FALSE; | |
345 umtx_unlock(NULL); | |
346 return 0; | 223 return 0; |
347 } | 224 } |
348 | 225 |
349 SimpleThread::SimpleThread() | 226 SimpleThread::SimpleThread() |
350 { | 227 { |
351 PosixThreadImplementation *imp = new PosixThreadImplementation; | 228 PosixThreadImplementation *imp = new PosixThreadImplementation; |
352 imp->fRunning = FALSE; | |
353 imp->fRan = FALSE; | |
354 fImplementation = imp; | 229 fImplementation = imp; |
355 } | 230 } |
356 | 231 |
357 SimpleThread::~SimpleThread() | 232 SimpleThread::~SimpleThread() |
358 { | 233 { |
359 PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation
; | 234 PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation
; |
360 if (imp->fRan) { | |
361 pthread_join(imp->fThread, NULL); | |
362 } | |
363 delete imp; | 235 delete imp; |
364 fImplementation = (void *)0xdeadbeef; | 236 fImplementation = (void *)0xdeadbeef; |
365 } | 237 } |
366 | 238 |
367 int32_t SimpleThread::start() | 239 int32_t SimpleThread::start() |
368 { | 240 { |
369 int32_t rc; | 241 int32_t rc; |
370 static pthread_attr_t attr; | 242 static pthread_attr_t attr; |
371 static UBool attrIsInitialized = FALSE; | 243 static UBool attrIsInitialized = FALSE; |
372 | 244 |
373 PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation
; | 245 PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation
; |
374 imp->fRunning = TRUE; | |
375 imp->fRan = TRUE; | |
376 | 246 |
377 #ifdef HPUX_CMA | |
378 if (attrIsInitialized == FALSE) { | |
379 rc = pthread_attr_create(&attr); | |
380 attrIsInitialized = TRUE; | |
381 } | |
382 rc = pthread_create(&(imp->fThread),attr,&SimpleThreadProc,(void*)this); | |
383 #else | |
384 if (attrIsInitialized == FALSE) { | 247 if (attrIsInitialized == FALSE) { |
385 rc = pthread_attr_init(&attr); | 248 rc = pthread_attr_init(&attr); |
386 #if U_PLATFORM == U_PF_OS390 | 249 #if U_PLATFORM == U_PF_OS390 |
387 { | 250 { |
388 int detachstate = 0; // jdc30: detach state of zero causes | 251 int detachstate = 0; // jdc30: detach state of zero causes |
389 //threads created with this attr to be in | 252 //threads created with this attr to be in |
390 //an undetached state. An undetached | 253 //an undetached state. An undetached |
391 //thread will keep its resources after | 254 //thread will keep its resources after |
392 //termination. | 255 //termination. |
393 pthread_attr_setdetachstate(&attr, &detachstate); | 256 pthread_attr_setdetachstate(&attr, &detachstate); |
394 } | 257 } |
395 #else | 258 #else |
396 // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | 259 // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
397 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); | 260 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); |
398 #endif | 261 #endif |
399 attrIsInitialized = TRUE; | 262 attrIsInitialized = TRUE; |
400 } | 263 } |
401 rc = pthread_create(&(imp->fThread),&attr,&SimpleThreadProc,(void*)this); | 264 rc = pthread_create(&(imp->fThread), &attr, &SimpleThreadProc, (void*)this); |
402 #endif | |
403 | 265 |
404 if (rc != 0) { | 266 if (rc != 0) { |
405 // some kind of error occured, the thread did not start. | 267 // some kind of error occured, the thread did not start. |
406 imp->fRan = FALSE; | |
407 imp->fRunning = FALSE; | |
408 } | 268 } |
409 | 269 |
410 return rc; | 270 return rc; |
411 } | 271 } |
412 | 272 |
413 | 273 void SimpleThread::join() { |
414 UBool | |
415 SimpleThread::isRunning() { | |
416 // Note: Mutex functions are used here not for synchronization, | |
417 // but to force memory barriors to exist, to ensure that one thread | |
418 // can see changes made by another when running on processors | |
419 // with memory models having weak coherency. | |
420 PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation
; | 274 PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation
; |
421 umtx_lock(NULL); | 275 pthread_join(imp->fThread, NULL); |
422 UBool retVal = imp->fRunning; | |
423 umtx_unlock(NULL); | |
424 return retVal; | |
425 } | |
426 | |
427 | |
428 void SimpleThread::sleep(int32_t millis) | |
429 { | |
430 #if U_PLATFORM == U_PF_SOLARIS | |
431 sigignore(SIGALRM); | |
432 #endif | |
433 | |
434 #ifdef HPUX_CMA | |
435 cma_sleep(millis/100); | |
436 #elif U_PLATFORM == U_PF_HPUX || U_PLATFORM == U_PF_OS390 | |
437 millis *= 1000; | |
438 while(millis >= 1000000) { | |
439 usleep(999999); | |
440 millis -= 1000000; | |
441 } | |
442 if(millis > 0) { | |
443 usleep(millis); | |
444 } | |
445 #else | |
446 usleep(millis * 1000); | |
447 #endif | |
448 } | 276 } |
449 | 277 |
450 #endif | 278 #endif |
451 // end POSIX | 279 // end POSIX |
452 | 280 |
453 | 281 |
454 #ifndef HAVE_IMP | 282 #ifndef HAVE_IMP |
455 #error No implementation for threads! Cannot test. | 283 #error No implementation for threads! Cannot test. |
456 0 = 216; //die | |
457 #endif | 284 #endif |
458 | |
459 //------------------------------------------------------------------------------
------------- | |
460 // | |
461 // class ThreadWithStatus - a thread that we can check the status and error cond
ition of | |
462 // | |
463 //------------------------------------------------------------------------------
------------- | |
464 class ThreadWithStatus : public SimpleThread | |
465 { | |
466 public: | |
467 UBool getError() { return (fErrors > 0); } | |
468 UBool getError(UnicodeString& fillinError) { fillinError = fErrorString; re
turn (fErrors > 0); } | |
469 virtual ~ThreadWithStatus(){} | |
470 protected: | |
471 ThreadWithStatus() : fErrors(0) {} | |
472 void error(const UnicodeString &error) { | |
473 fErrors++; fErrorString = error; | |
474 SimpleThread::errorFunc(); | |
475 } | |
476 void error() { error("An error occured."); } | |
477 private: | |
478 int32_t fErrors; | |
479 UnicodeString fErrorString; | |
480 }; | |
481 | |
482 #endif // ICU_USE_THREADS | |
OLD | NEW |