| /******************************************************************** |
| * COPYRIGHT: |
| * Copyright (c) 1999-2015, International Business Machines Corporation and |
| * others. All Rights Reserved. |
| ********************************************************************/ |
| |
| #if defined(hpux) |
| # ifndef _INCLUDE_POSIX_SOURCE |
| # define _INCLUDE_POSIX_SOURCE |
| # endif |
| #endif |
| |
| /* Define __EXTENSIONS__ for Solaris and old friends in strict mode. */ |
| #ifndef __EXTENSIONS__ |
| #define __EXTENSIONS__ |
| #endif |
| |
| // Defines _XOPEN_SOURCE for access to POSIX functions. |
| // Must be before any other #includes. |
| #include "uposixdefs.h" |
| |
| #include "simplethread.h" |
| |
| #include "unicode/utypes.h" |
| #include "unicode/ustring.h" |
| #include "umutex.h" |
| #include "cmemory.h" |
| #include "cstring.h" |
| #include "uparse.h" |
| #include "unicode/resbund.h" |
| #include "unicode/udata.h" |
| #include "unicode/uloc.h" |
| #include "unicode/locid.h" |
| #include "putilimp.h" |
| #include "intltest.h" |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <ctype.h> // tolower, toupper |
| |
| #if U_PLATFORM_USES_ONLY_WIN32_API |
| /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin). */ |
| # undef POSIX |
| #elif U_PLATFORM_IMPLEMENTS_POSIX |
| # define POSIX |
| #else |
| # undef POSIX |
| #endif |
| |
| /* Needed by z/OS to get usleep */ |
| #if U_PLATFORM == U_PF_OS390 |
| #define __DOT1 1 |
| #ifndef __UU |
| # define __UU |
| #endif |
| #ifndef _XPG4_2 |
| # define _XPG4_2 |
| #endif |
| #include <unistd.h> |
| #endif |
| |
| #if defined(POSIX) |
| #define HAVE_IMP |
| |
| #include <pthread.h> |
| |
| #if U_PLATFORM == U_PF_OS390 |
| #include <sys/types.h> |
| #endif |
| |
| #if U_PLATFORM != U_PF_OS390 |
| #include <signal.h> |
| #endif |
| |
| /* Define _XPG4_2 for Solaris and friends. */ |
| #ifndef _XPG4_2 |
| #define _XPG4_2 |
| #endif |
| |
| /* Define __USE_XOPEN_EXTENDED for Linux and glibc. */ |
| #ifndef __USE_XOPEN_EXTENDED |
| #define __USE_XOPEN_EXTENDED |
| #endif |
| |
| /* Define _INCLUDE_XOPEN_SOURCE_EXTENDED for HP/UX (11?). */ |
| #ifndef _INCLUDE_XOPEN_SOURCE_EXTENDED |
| #define _INCLUDE_XOPEN_SOURCE_EXTENDED |
| #endif |
| |
| #include <unistd.h> |
| |
| #endif |
| /* HPUX */ |
| #ifdef sleep |
| #undef sleep |
| #endif |
| |
| |
| #include "unicode/putil.h" |
| |
| /* for mthreadtest*/ |
| #include "unicode/numfmt.h" |
| #include "unicode/choicfmt.h" |
| #include "unicode/msgfmt.h" |
| #include "unicode/locid.h" |
| #include "unicode/ucol.h" |
| #include "unicode/calendar.h" |
| #include "ucaconf.h" |
| |
| #if U_PLATFORM_USES_ONLY_WIN32_API |
| #define HAVE_IMP |
| |
| # define VC_EXTRALEAN |
| # define WIN32_LEAN_AND_MEAN |
| # define NOUSER |
| # define NOSERVICE |
| # define NOIME |
| # define NOMCX |
| #include <windows.h> |
| #include <process.h> |
| |
| //----------------------------------------------------------------------------------- |
| // |
| // class SimpleThread Windows Implementation |
| // |
| //----------------------------------------------------------------------------------- |
| struct Win32ThreadImplementation |
| { |
| HANDLE fHandle; |
| unsigned int fThreadID; |
| }; |
| |
| |
| extern "C" unsigned int __stdcall SimpleThreadProc(void *arg) |
| { |
| ((SimpleThread*)arg)->run(); |
| return 0; |
| } |
| |
| SimpleThread::SimpleThread() |
| :fImplementation(0) |
| { |
| Win32ThreadImplementation *imp = new Win32ThreadImplementation; |
| imp->fHandle = 0; |
| fImplementation = imp; |
| } |
| |
| SimpleThread::~SimpleThread() |
| { |
| // Destructor. Because we start the thread running with _beginthreadex(), |
| // we own the Windows HANDLE for the thread and must |
| // close it here. |
| Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation; |
| if (imp != 0) { |
| if (imp->fHandle != 0) { |
| CloseHandle(imp->fHandle); |
| imp->fHandle = 0; |
| } |
| } |
| delete (Win32ThreadImplementation*)fImplementation; |
| } |
| |
| int32_t SimpleThread::start() |
| { |
| Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation; |
| if(imp->fHandle != NULL) { |
| // The thread appears to have already been started. |
| // This is probably an error on the part of our caller. |
| return -1; |
| } |
| |
| imp->fHandle = (HANDLE) _beginthreadex( |
| NULL, // Security |
| 0x20000, // Stack Size |
| SimpleThreadProc, // Function to Run |
| (void *)this, // Arg List |
| 0, // initflag. Start running, not suspended |
| &imp->fThreadID // thraddr |
| ); |
| |
| if (imp->fHandle == 0) { |
| // An error occured |
| int err = errno; |
| if (err == 0) { |
| err = -1; |
| } |
| return err; |
| } |
| return 0; |
| } |
| |
| |
| void SimpleThread::join() { |
| Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation; |
| if (imp->fHandle == 0) { |
| // No handle, thread must not be running. |
| return; |
| } |
| WaitForSingleObject(imp->fHandle, INFINITE); |
| } |
| |
| #endif |
| |
| |
| //----------------------------------------------------------------------------------- |
| // |
| // class SimpleThread POSIX implementation |
| // |
| //----------------------------------------------------------------------------------- |
| #if defined(POSIX) |
| #define HAVE_IMP |
| |
| struct PosixThreadImplementation |
| { |
| pthread_t fThread; |
| }; |
| |
| extern "C" void* SimpleThreadProc(void *arg) |
| { |
| // This is the code that is run in the new separate thread. |
| SimpleThread *This = (SimpleThread *)arg; |
| This->run(); |
| return 0; |
| } |
| |
| SimpleThread::SimpleThread() |
| { |
| PosixThreadImplementation *imp = new PosixThreadImplementation; |
| fImplementation = imp; |
| } |
| |
| SimpleThread::~SimpleThread() |
| { |
| PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation; |
| delete imp; |
| fImplementation = (void *)0xdeadbeef; |
| } |
| |
| int32_t SimpleThread::start() |
| { |
| int32_t rc; |
| static pthread_attr_t attr; |
| static UBool attrIsInitialized = FALSE; |
| |
| PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation; |
| |
| if (attrIsInitialized == FALSE) { |
| rc = pthread_attr_init(&attr); |
| #if U_PLATFORM == U_PF_OS390 |
| { |
| int detachstate = 0; // jdc30: detach state of zero causes |
| //threads created with this attr to be in |
| //an undetached state. An undetached |
| //thread will keep its resources after |
| //termination. |
| pthread_attr_setdetachstate(&attr, &detachstate); |
| } |
| #else |
| // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); |
| #endif |
| attrIsInitialized = TRUE; |
| } |
| rc = pthread_create(&(imp->fThread), &attr, &SimpleThreadProc, (void*)this); |
| |
| if (rc != 0) { |
| // some kind of error occured, the thread did not start. |
| } |
| |
| return rc; |
| } |
| |
| void SimpleThread::join() { |
| PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation; |
| pthread_join(imp->fThread, NULL); |
| } |
| |
| #endif |
| // end POSIX |
| |
| |
| #ifndef HAVE_IMP |
| #error No implementation for threads! Cannot test. |
| #endif |