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