| 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 |