Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtmail / libDtMail / Common / Threads.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  *+SNOTICE
25  *
26  *
27  *      $TOG: Threads.C /main/5 1997/09/03 17:26:05 mgreess $
28  *
29  *      RESTRICTED CONFIDENTIAL INFORMATION:
30  *      
31  *      The information in this document is subject to special
32  *      restrictions in a confidential disclosure agreement bertween
33  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
35  *      Sun's specific written approval.  This documment and all copies
36  *      and derivative works thereof must be returned or destroyed at
37  *      Sun's request.
38  *
39  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40  *
41  *+ENOTICE
42  */
43
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #if defined(I_HAVE_SELECT_H)
48 #include <sys/select.h>
49 #endif
50
51 #if defined(POSIX_THREADS)
52 #include <thread.h>
53 #include <synch.h>
54 #endif
55
56 #include <DtMail/DtMail.hh>
57 #include <DtMail/Threads.hh>
58 #include <DtMail/IO.hh>
59
60 static long     DUMMY_MUTEX;
61
62 void *
63 MutexInit(void)
64 {
65 #if defined(POSIX_THREADS)
66     mutex_t     *mutex = (mutex_t *)malloc(sizeof(mutex_t));
67
68     mutex_init(mutex, USYNC_THREAD, NULL);
69     return(mutex);
70 #else
71     return(&DUMMY_MUTEX);
72 #endif
73 }
74
75 void
76 MutexDestroy(void * mutex)
77 {
78 #if defined(POSIX_THREADS)
79     mutex_destroy((mutex_t *)mutex);
80     free(mutex);
81 #else
82     mutex = NULL;
83 #endif
84
85     return;
86 }
87
88 MutexLock::MutexLock(void * mutex)
89 {
90 #if defined(POSIX_THREADS)
91     mutex_lock((mutex_t *)mutex);
92 #endif
93     _mutex = mutex;
94     _locked = 1;
95 }
96
97 MutexLock::~MutexLock(void)
98 {
99 #if defined(POSIX_THREADS)
100     if (_locked) {
101         mutex_unlock((mutex_t *)_mutex);
102     }
103 #endif
104
105 }
106
107 void
108 MutexLock::unlock(void)
109 {
110 #if defined(POSIX_THREADS)
111     if (_locked) {
112         mutex_unlock((mutex_t *)_mutex);
113     }
114     _locked = 0;
115 #endif
116
117 }
118
119 void
120 MutexLock::unlock_and_destroy(void)
121 {
122 #if defined(POSIX_THREADS)
123     if (_locked) {
124         mutex_unlock((mutex_t *)_mutex);
125     }
126     _locked = 0;
127     MutexDestroy(_mutex);
128 #endif
129 }
130
131 SafeScalarImpl::SafeScalarImpl(void)
132 {
133     _mutex = MutexInit();
134     _value = 0;
135 }
136
137 SafeScalarImpl::~SafeScalarImpl(void)
138 {
139     MutexDestroy(_mutex);
140 }
141
142 long
143 SafeScalarImpl::operator = (const long val)
144 {
145     MutexLock lock_scope(_mutex);
146
147     _value = val;
148     return(_value);
149 }
150
151 long
152 SafeScalarImpl::operator += (const long val)
153 {
154     MutexLock lock_scope(_mutex);
155
156     _value += val;
157     return(_value);
158 }
159
160 long
161 SafeScalarImpl::operator -= (const long val)
162 {
163     MutexLock lock_scope(_mutex);
164
165     _value -= val;
166     return(_value);
167 }
168
169 long
170 SafeScalarImpl::operator *= (const long val)
171 {
172     MutexLock lock_scope(_mutex);
173
174     _value *= val;
175     return(_value);
176 }
177
178 long
179 SafeScalarImpl::operator /= (const long val)
180 {
181     MutexLock lock_scope(_mutex);
182
183     _value /= val;
184     return(_value);
185 }
186
187 int
188 SafeScalarImpl::operator == (const long val)
189 {
190     MutexLock lock_scope(_mutex);
191
192     return(_value == val);
193 }
194
195 int
196 SafeScalarImpl::operator <= (const long val)
197 {
198     MutexLock lock_scope(_mutex);
199
200     return(_value <= val);
201 }
202
203 int
204 SafeScalarImpl::operator < (const long val)
205 {
206     MutexLock lock_scope(_mutex);
207
208     return(_value < val);
209 }
210
211 int
212 SafeScalarImpl::operator >= (const long val)
213 {
214     MutexLock lock_scope(_mutex);
215
216     return(_value >= val);
217 }
218
219 int
220 SafeScalarImpl::operator > (const long val)
221 {
222     MutexLock lock_scope(_mutex);
223
224     return(_value > val);
225 }
226
227 int
228 SafeScalarImpl::operator != (const long val)
229 {
230     MutexLock lock_scope(_mutex);
231
232     return(_value != val);
233 }
234
235 SafeScalarImpl::operator long(void)
236 {
237     MutexLock lock_scope(_mutex);
238
239     return(_value);
240 }
241
242 Condition::Condition(void)
243 {
244     _mutex = MutexInit();
245
246 #if defined(POSIX_THREADS)
247     _condition = malloc(sizeof(cond_t));
248     cond_init((cond_t *)_condition, USYNC_THREAD, NULL);
249 #endif
250
251 }
252
253 Condition::~Condition(void)
254 {
255     MutexDestroy(_mutex);
256
257 #if defined(POSIX_THREADS)
258     cond_destroy((cond_t *)_condition);
259     free(_condition);
260 #endif
261
262 }
263
264 void
265 Condition::setTrue(void)
266 {
267     MutexLock lock_scope(_mutex);
268
269     _state = 1;
270
271 #if defined(POSIX_THREADS)
272     cond_broadcast((cond_t *)_condition); // Wake all sleepers.
273 #endif
274
275 }
276
277 void
278 Condition::setFalse(void)
279 {
280     MutexLock lock_scope(_mutex);
281
282     _state = 0;
283
284 #if defined(POSIX_THREADS)
285     cond_broadcast((cond_t *)_condition); // Wake all sleepers.
286 #endif
287 }
288
289 int
290 Condition::operator=(int new_state)
291 {
292     MutexLock lock_scope(_mutex);
293
294     _state = new_state;
295
296 #if defined(POSIX_THREADS)
297     cond_broadcast((cond_t *)_condition); // Wake all sleepers.
298 #endif
299
300     return(new_state);
301 }
302
303 int
304 Condition::operator+=(int new_state)
305 {
306     MutexLock lock_scope(_mutex);
307
308     _state += new_state;
309
310 #if defined(POSIX_THREADS)
311     cond_broadcast((cond_t *)_condition); // Wake all sleepers.
312 #endif
313
314     return(_state);
315 }
316
317 Condition::operator int(void)
318 {
319     return(state());
320 }
321
322 int
323 Condition::state(void)
324 {
325     MutexLock lock_scope(_mutex);
326
327     int save_state = _state;
328
329     return(save_state);
330 }
331
332 void
333 Condition::wait(void)
334 {
335     // Wait for anything to change.
336     //
337 #if defined(POSIX_THREADS)
338     MutexLock lock_scope(_mutex);
339
340     timestruc_t abstime;
341     abstime.tv_sec = time(NULL) + 1; // Wait for 1 second.
342     abstime.tv_nsec = 0;
343
344     cond_timedwait((cond_t *)_condition, (mutex_t *)_mutex, &abstime);
345 #endif
346
347     return;
348 }
349
350 void
351 Condition::waitTrue(void)
352 {
353     // Wait for the condition to become true.
354     //
355 #if defined(POSIX_THREADS)
356     MutexLock lock_scope(_mutex);
357
358     while(!_state) {
359         cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
360     }
361 #else
362     _state = 1; // Must set of single threaded apps.
363 #endif
364
365     return;
366 }
367
368 #ifdef DEAD_WOOD
369 void
370 Condition::waitFalse(void)
371 {
372     // Wait for the condition to become true.
373     //
374 #if defined(POSIX_THREADS)
375     MutexLock lock_scope(_mutex);
376
377     while(_state) {
378         cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
379     }
380 #else
381     _state = 0;
382 #endif
383
384     return;
385 }
386
387 void
388 Condition::waitFor(int new_state)
389 {
390     // Wait for the condition to become true.
391     //
392 #if defined(POSIX_THREADS)
393     MutexLock lock_scope(_mutex);
394
395     while(_state != new_state) {
396         cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
397     }
398 #endif
399
400     return;
401 }
402
403 void
404 Condition::waitGT(int new_state)
405 {
406     // Wait for the condition to become true.
407     //
408 #if defined(POSIX_THREADS)
409     MutexLock lock_scope(_mutex);
410
411     while(_state > new_state) {
412         cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
413     }
414 #endif
415
416     return;
417 }
418
419 void
420 Condition::waitLT(int new_state)
421 {
422     // Wait for the condition to become true.
423     //
424 #if defined(POSIX_THREADS)
425     MutexLock lock_scope(_mutex);
426
427     while(_state < new_state) {
428         cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
429     }
430 #endif
431
432     return;
433 }
434
435 void
436 Condition::waitProcStatus(void)
437 {
438     // Wait for the condition to become true.
439     //
440 #if defined(POSIX_THREADS)
441     MutexLock lock_scope(_mutex);
442
443     while(_state < 0) {
444         cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
445     }
446 #else
447     _state = 0;
448 #endif
449
450     return;
451 }
452 #endif /* DEAD_WOOD */
453
454 Thread
455 ThreadCreate(
456 #if defined(POSIX_THREADS)
457         ThreadEntryPoint entry, void * client_data)
458 {
459     thread_t    id;
460
461     thr_create(NULL, 0, entry, client_data, THR_BOUND | THR_NEW_LWP, &id);
462     thr_continue(id);
463
464     return(id);
465 }
466 #else
467         ThreadEntryPoint, void*)
468 {
469     return(NULL);
470 }
471 #endif
472
473 Thread
474 ThreadSelf(void)
475 {
476 #if defined(POSIX_THREADS)
477     return(thr_self());
478 #else
479     return(NULL);
480 #endif
481
482 }
483
484 void
485 ThreadPrio(
486 #if defined(POSIX_THREADS)
487         Thread thread, const int prio)
488 {
489     thr_setprio((thread_t)thread, prio);
490 }
491 #else
492         Thread, const int)
493 {
494 }
495 #endif
496
497 void
498 ThreadKill(
499 #if defined(POSIX_THREADS)
500         Thread thread, const int sig)
501 {
502     thr_kill((thread_t)thread, sig);
503 }
504 #else
505         Thread, const int)
506 {
507 }
508 #endif
509
510 void
511 ThreadExit(
512 #if defined(POSIX_THREADS)
513         const int status)
514 {
515     thr_exit((void *)status);
516 }
517 #else
518         const int)
519 {
520 }
521 #endif
522
523 void
524 ThreadJoin(
525 #if defined(POSIX_THREADS)
526         Thread thread)
527 {
528     thr_join((thread_t)thread, NULL, NULL);
529 }
530 #else
531         Thread)
532 {
533 }
534 #endif
535
536 // The ThreadSleep function mimics the behavior of sleep(3), but
537 // uses select to prevent SIGALRM from being sent. This is bad
538 // on MT because often the main thread gets the signal and exits.
539 //
540 time_t
541 ThreadSleep(time_t secs)
542 {
543     time_t now = time(NULL);
544
545     timeval interval;
546
547     interval.tv_sec = secs;
548     interval.tv_usec = 0;
549
550     select(0, NULL, NULL, NULL, &interval);
551
552     time_t slept = time(NULL) - now;
553     if (slept < secs) {
554         return(secs - slept);
555     }
556
557     return(0);
558 }
559
560 #if defined(SPRO_V2)
561 void * operator new(size_t size)
562 {
563     return(malloc(size));
564 }
565
566 void operator delete(void * ptr)
567 {
568     free(ptr);
569 }
570 #endif