1 /********************************************************************
3 * Copyright (c) 1999-2011, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
8 # ifndef _INCLUDE_POSIX_SOURCE
9 # define _INCLUDE_POSIX_SOURCE
13 /* Define __EXTENSIONS__ for Solaris and old friends in strict mode. */
14 #ifndef __EXTENSIONS__
15 #define __EXTENSIONS__
18 // Defines _XOPEN_SOURCE for access to POSIX functions.
19 // Must be before any other #includes.
20 #include "uposixdefs.h"
22 #include "simplethread.h"
24 #include "unicode/utypes.h"
25 #include "unicode/ustring.h"
30 #include "unicode/resbund.h"
31 #include "unicode/udata.h"
32 #include "unicode/uloc.h"
33 #include "unicode/locid.h"
38 #include <ctype.h> // tolower, toupper
40 #if U_PLATFORM_USES_ONLY_WIN32_API
41 /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin). */
43 #elif U_PLATFORM_IMPLEMENTS_POSIX
49 /* Needed by z/OS to get usleep */
50 #if U_PLATFORM == U_PF_OS390
62 #if (ICU_USE_THREADS == 1)
66 #if defined(__hpux) && defined(HPUX_CMA)
67 # if defined(read) // read being defined as cma_read causes trouble with iostream::read
72 #if U_PLATFORM == U_PF_OS390
73 #include <sys/types.h>
76 #if U_PLATFORM != U_PF_OS390
80 /* Define _XPG4_2 for Solaris and friends. */
85 /* Define __USE_XOPEN_EXTENDED for Linux and glibc. */
86 #ifndef __USE_XOPEN_EXTENDED
87 #define __USE_XOPEN_EXTENDED
90 /* Define _INCLUDE_XOPEN_SOURCE_EXTENDED for HP/UX (11?). */
91 #ifndef _INCLUDE_XOPEN_SOURCE_EXTENDED
92 #define _INCLUDE_XOPEN_SOURCE_EXTENDED
104 #if (ICU_USE_THREADS==0)
105 SimpleThread::SimpleThread()
108 SimpleThread::~SimpleThread()
112 SimpleThread::start()
120 SimpleThread::sleep(int32_t millis
)
124 SimpleThread::isRunning() {
129 #include "unicode/putil.h"
132 #include "unicode/numfmt.h"
133 #include "unicode/choicfmt.h"
134 #include "unicode/msgfmt.h"
135 #include "unicode/locid.h"
136 #include "unicode/ucol.h"
137 #include "unicode/calendar.h"
140 #if U_PLATFORM_USES_ONLY_WIN32_API
143 # define VC_EXTRALEAN
144 # define WIN32_LEAN_AND_MEAN
152 //-----------------------------------------------------------------------------------
154 // class SimpleThread Windows Implementation
156 //-----------------------------------------------------------------------------------
157 struct Win32ThreadImplementation
160 unsigned int fThreadID
;
164 extern "C" unsigned int __stdcall
SimpleThreadProc(void *arg
)
166 ((SimpleThread
*)arg
)->run();
170 SimpleThread::SimpleThread()
173 Win32ThreadImplementation
*imp
= new Win32ThreadImplementation
;
175 fImplementation
= imp
;
178 SimpleThread::~SimpleThread()
180 // Destructor. Because we start the thread running with _beginthreadex(),
181 // we own the Windows HANDLE for the thread and must
183 Win32ThreadImplementation
*imp
= (Win32ThreadImplementation
*)fImplementation
;
185 if (imp
->fHandle
!= 0) {
186 CloseHandle(imp
->fHandle
);
190 delete (Win32ThreadImplementation
*)fImplementation
;
193 int32_t SimpleThread::start()
195 Win32ThreadImplementation
*imp
= (Win32ThreadImplementation
*)fImplementation
;
196 if(imp
->fHandle
!= NULL
) {
197 // The thread appears to have already been started.
198 // This is probably an error on the part of our caller.
202 imp
->fHandle
= (HANDLE
) _beginthreadex(
204 0x20000, // Stack Size
205 SimpleThreadProc
, // Function to Run
206 (void *)this, // Arg List
207 0, // initflag. Start running, not suspended
208 &imp
->fThreadID
// thraddr
211 if (imp
->fHandle
== 0) {
223 UBool
SimpleThread::isRunning() {
225 // Test whether the thread associated with the SimpleThread object is
226 // still actually running.
228 // NOTE: on Win64 on Itanium processors, a crashes
229 // occur if the main thread of a process exits concurrently with some
230 // other thread(s) exiting. To avoid the possibility, we wait until the
231 // OS indicates that all threads have terminated, rather than waiting
232 // only until the end of the user's Run function has been reached.
234 // I don't know whether the crashes represent a Windows bug, or whether
235 // main() programs are supposed to have to wait for their threads.
237 Win32ThreadImplementation
*imp
= (Win32ThreadImplementation
*)fImplementation
;
240 DWORD threadExitCode
;
242 if (imp
->fHandle
== 0) {
243 // No handle, thread must not be running.
246 success
= GetExitCodeThread(imp
->fHandle
, &threadExitCode
) != 0;
248 // Can't get status, thread must not be running.
251 return (threadExitCode
== STILL_ACTIVE
);
255 void SimpleThread::sleep(int32_t millis
)
260 //-----------------------------------------------------------------------------------
262 // class SimpleThread NULL Implementation
264 //-----------------------------------------------------------------------------------
265 #elif U_PLATFORM == U_PF_CLASSIC_MACOS
267 // since the Mac has no preemptive threading (at least on MacOS 8), only
268 // cooperative threading, threads are a no-op. We have no yield() calls
269 // anywhere in the ICU, so we are guaranteed to be thread-safe.
273 SimpleThread::SimpleThread()
276 SimpleThread::~SimpleThread()
280 SimpleThread::start()
288 SimpleThread::sleep(int32_t millis
)
292 SimpleThread::isRunning() {
299 //-----------------------------------------------------------------------------------
301 // class SimpleThread POSIX implementation
303 // A note on the POSIX vs the Windows implementations of this class..
304 // On Windows, the main thread must verify that other threads have finished
305 // before exiting, or crashes occasionally occur. (Seen on Itanium Win64 only)
306 // The function SimpleThread::isRunning() is used for this purpose.
308 // On POSIX, there is NO reliable non-blocking mechanism to determine
309 // whether a thread has exited. pthread_kill(thread, 0) almost works,
310 // but the system can recycle thread ids immediately, so seeing that a
311 // thread exists with this call could mean that the original thread has
312 // finished and a new one started with the same ID. Useless.
314 // So we need to do the check with user code, by setting a flag just before
315 // the thread function returns. A technique that is guaranteed to fail
316 // on Windows, because it indicates that the thread is done before all
317 // system level cleanup has happened.
319 //-----------------------------------------------------------------------------------
323 struct PosixThreadImplementation
327 UBool fRan
; // True if the thread was successfully started
330 extern "C" void* SimpleThreadProc(void *arg
)
332 // This is the code that is run in the new separate thread.
333 SimpleThread
*This
= (SimpleThread
*)arg
;
334 This
->run(); // Run the user code.
336 // The user function has returned. Set the flag indicating that this thread
337 // is done. Need a mutex for memory barrier purposes only, so that other thread
338 // will reliably see that the flag has changed.
339 PosixThreadImplementation
*imp
= (PosixThreadImplementation
*)This
->fImplementation
;
341 imp
->fRunning
= FALSE
;
346 SimpleThread::SimpleThread()
348 PosixThreadImplementation
*imp
= new PosixThreadImplementation
;
349 imp
->fRunning
= FALSE
;
351 fImplementation
= imp
;
354 SimpleThread::~SimpleThread()
356 PosixThreadImplementation
*imp
= (PosixThreadImplementation
*)fImplementation
;
358 pthread_join(imp
->fThread
, NULL
);
361 fImplementation
= (void *)0xdeadbeef;
364 int32_t SimpleThread::start()
367 static pthread_attr_t attr
;
368 static UBool attrIsInitialized
= FALSE
;
370 PosixThreadImplementation
*imp
= (PosixThreadImplementation
*)fImplementation
;
371 imp
->fRunning
= TRUE
;
375 if (attrIsInitialized
== FALSE
) {
376 rc
= pthread_attr_create(&attr
);
377 attrIsInitialized
= TRUE
;
379 rc
= pthread_create(&(imp
->fThread
),attr
,&SimpleThreadProc
,(void*)this);
381 if (attrIsInitialized
== FALSE
) {
382 rc
= pthread_attr_init(&attr
);
383 #if U_PLATFORM == U_PF_OS390
385 int detachstate
= 0; // jdc30: detach state of zero causes
386 //threads created with this attr to be in
387 //an undetached state. An undetached
388 //thread will keep its resources after
390 pthread_attr_setdetachstate(&attr
, &detachstate
);
393 // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
394 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_JOINABLE
);
396 attrIsInitialized
= TRUE
;
398 rc
= pthread_create(&(imp
->fThread
),&attr
,&SimpleThreadProc
,(void*)this);
402 // some kind of error occured, the thread did not start.
404 imp
->fRunning
= FALSE
;
412 SimpleThread::isRunning() {
413 // Note: Mutex functions are used here not for synchronization,
414 // but to force memory barriors to exist, to ensure that one thread
415 // can see changes made by another when running on processors
416 // with memory models having weak coherency.
417 PosixThreadImplementation
*imp
= (PosixThreadImplementation
*)fImplementation
;
419 UBool retVal
= imp
->fRunning
;
425 void SimpleThread::sleep(int32_t millis
)
427 #if U_PLATFORM == U_PF_SOLARIS
432 cma_sleep(millis
/100);
433 #elif U_PLATFORM == U_PF_HPUX || U_PLATFORM == U_PF_OS390
435 while(millis
>= 1000000) {
443 usleep(millis
* 1000);
452 #error No implementation for threads! Cannot test.
456 //-------------------------------------------------------------------------------------------
458 // class ThreadWithStatus - a thread that we can check the status and error condition of
460 //-------------------------------------------------------------------------------------------
461 class ThreadWithStatus
: public SimpleThread
464 UBool
getError() { return (fErrors
> 0); }
465 UBool
getError(UnicodeString
& fillinError
) { fillinError
= fErrorString
; return (fErrors
> 0); }
466 virtual ~ThreadWithStatus(){}
468 ThreadWithStatus() : fErrors(0) {}
469 void error(const UnicodeString
&error
) {
470 fErrors
++; fErrorString
= error
;
471 SimpleThread::errorFunc();
473 void error() { error("An error occured."); }
476 UnicodeString fErrorString
;
479 #endif // ICU_USE_THREADS