1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1999-2015, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6
7#if defined(hpux)
8# ifndef _INCLUDE_POSIX_SOURCE
9#  define _INCLUDE_POSIX_SOURCE
10# endif
11#endif
12
13/* Define __EXTENSIONS__ for Solaris and old friends in strict mode. */
14#ifndef __EXTENSIONS__
15#define __EXTENSIONS__
16#endif
17
18// Defines _XOPEN_SOURCE for access to POSIX functions.
19// Must be before any other #includes.
20#include "uposixdefs.h"
21
22#include "simplethread.h"
23
24#include "unicode/utypes.h"
25#include "unicode/ustring.h"
26#include "umutex.h"
27#include "cmemory.h"
28#include "cstring.h"
29#include "uparse.h"
30#include "unicode/resbund.h"
31#include "unicode/udata.h"
32#include "unicode/uloc.h"
33#include "unicode/locid.h"
34#include "putilimp.h"
35#include "intltest.h"
36
37#include <stdio.h>
38#include <string.h>
39#include <ctype.h>    // tolower, toupper
40
41#if U_PLATFORM_USES_ONLY_WIN32_API
42    /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin). */
43#   undef POSIX
44#elif U_PLATFORM_IMPLEMENTS_POSIX
45#   define POSIX
46#else
47#   undef POSIX
48#endif
49
50/* Needed by z/OS to get usleep */
51#if U_PLATFORM == U_PF_OS390
52#define __DOT1 1
53#ifndef __UU
54#   define __UU
55#endif
56#ifndef _XPG4_2
57#   define _XPG4_2
58#endif
59#include <unistd.h>
60#endif
61
62#if defined(POSIX)
63#define HAVE_IMP
64
65#include <pthread.h>
66
67#if U_PLATFORM == U_PF_OS390
68#include <sys/types.h>
69#endif
70
71#if U_PLATFORM != U_PF_OS390
72#include <signal.h>
73#endif
74
75/* Define _XPG4_2 for Solaris and friends. */
76#ifndef _XPG4_2
77#define _XPG4_2
78#endif
79
80/* Define __USE_XOPEN_EXTENDED for Linux and glibc. */
81#ifndef __USE_XOPEN_EXTENDED
82#define __USE_XOPEN_EXTENDED
83#endif
84
85/* Define _INCLUDE_XOPEN_SOURCE_EXTENDED for HP/UX (11?). */
86#ifndef _INCLUDE_XOPEN_SOURCE_EXTENDED
87#define _INCLUDE_XOPEN_SOURCE_EXTENDED
88#endif
89
90#include <unistd.h>
91
92#endif
93/* HPUX */
94#ifdef sleep
95#undef sleep
96#endif
97
98
99#include "unicode/putil.h"
100
101/* for mthreadtest*/
102#include "unicode/numfmt.h"
103#include "unicode/choicfmt.h"
104#include "unicode/msgfmt.h"
105#include "unicode/locid.h"
106#include "unicode/ucol.h"
107#include "unicode/calendar.h"
108#include "ucaconf.h"
109
110#if U_PLATFORM_USES_ONLY_WIN32_API
111#define HAVE_IMP
112
113#   define VC_EXTRALEAN
114#   define WIN32_LEAN_AND_MEAN
115#   define NOUSER
116#   define NOSERVICE
117#   define NOIME
118#   define NOMCX
119#include <windows.h>
120#include <process.h>
121
122//-----------------------------------------------------------------------------------
123//
124//   class SimpleThread   Windows Implementation
125//
126//-----------------------------------------------------------------------------------
127struct Win32ThreadImplementation
128{
129    HANDLE         fHandle;
130    unsigned int   fThreadID;
131};
132
133
134extern "C" unsigned int __stdcall SimpleThreadProc(void *arg)
135{
136    ((SimpleThread*)arg)->run();
137    return 0;
138}
139
140SimpleThread::SimpleThread()
141:fImplementation(0)
142{
143    Win32ThreadImplementation *imp = new Win32ThreadImplementation;
144    imp->fHandle = 0;
145    fImplementation = imp;
146}
147
148SimpleThread::~SimpleThread()
149{
150    // Destructor.  Because we start the thread running with _beginthreadex(),
151    //              we own the Windows HANDLE for the thread and must
152    //              close it here.
153    Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation;
154    if (imp != 0) {
155        if (imp->fHandle != 0) {
156            CloseHandle(imp->fHandle);
157            imp->fHandle = 0;
158        }
159    }
160    delete (Win32ThreadImplementation*)fImplementation;
161}
162
163int32_t SimpleThread::start()
164{
165    Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation;
166    if(imp->fHandle != NULL) {
167        // The thread appears to have already been started.
168        //   This is probably an error on the part of our caller.
169        return -1;
170    }
171
172    imp->fHandle = (HANDLE) _beginthreadex(
173        NULL,                                 // Security
174        0x20000,                              // Stack Size
175        SimpleThreadProc,                     // Function to Run
176        (void *)this,                         // Arg List
177        0,                                    // initflag.  Start running, not suspended
178        &imp->fThreadID                       // thraddr
179        );
180
181    if (imp->fHandle == 0) {
182        // An error occured
183        int err = errno;
184        if (err == 0) {
185            err = -1;
186        }
187        return err;
188    }
189    return 0;
190}
191
192
193void SimpleThread::join() {
194    Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation;
195    if (imp->fHandle == 0) {
196        // No handle, thread must not be running.
197        return;
198    }
199    WaitForSingleObject(imp->fHandle, INFINITE);
200}
201
202#endif
203
204
205//-----------------------------------------------------------------------------------
206//
207//   class SimpleThread   POSIX implementation
208//
209//-----------------------------------------------------------------------------------
210#if defined(POSIX)
211#define HAVE_IMP
212
213struct PosixThreadImplementation
214{
215    pthread_t        fThread;
216};
217
218extern "C" void* SimpleThreadProc(void *arg)
219{
220    // This is the code that is run in the new separate thread.
221    SimpleThread *This = (SimpleThread *)arg;
222    This->run();
223    return 0;
224}
225
226SimpleThread::SimpleThread()
227{
228    PosixThreadImplementation *imp = new PosixThreadImplementation;
229    fImplementation = imp;
230}
231
232SimpleThread::~SimpleThread()
233{
234    PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation;
235    delete imp;
236    fImplementation = (void *)0xdeadbeef;
237}
238
239int32_t SimpleThread::start()
240{
241    int32_t        rc;
242    static pthread_attr_t attr;
243    static UBool attrIsInitialized = FALSE;
244
245    PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation;
246
247    if (attrIsInitialized == FALSE) {
248        rc = pthread_attr_init(&attr);
249#if U_PLATFORM == U_PF_OS390
250        {
251            int detachstate = 0;  // jdc30: detach state of zero causes
252                                  //threads created with this attr to be in
253                                  //an undetached state.  An undetached
254                                  //thread will keep its resources after
255                                  //termination.
256            pthread_attr_setdetachstate(&attr, &detachstate);
257        }
258#else
259        // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
260        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
261#endif
262        attrIsInitialized = TRUE;
263    }
264    rc = pthread_create(&(imp->fThread), &attr, &SimpleThreadProc, (void*)this);
265
266    if (rc != 0) {
267        // some kind of error occured, the thread did not start.
268    }
269
270    return rc;
271}
272
273void SimpleThread::join() {
274    PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation;
275    pthread_join(imp->fThread, NULL);
276}
277
278#endif
279// end POSIX
280
281
282#ifndef HAVE_IMP
283#error  No implementation for threads! Cannot test.
284#endif
285