summaryrefslogtreecommitdiff
path: root/TAO/IIOP/lib/runtime/thread.hh
blob: 372ca7bcfe81bfa50a30360fa3751c071b1f9203 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// @(#)thread.hh	1.3 95/09/29
// Copyright 1995 by Sun Microsystems, Inc
// All Rights Reserved
//
// THREADING:	simple thread utility classes
//
// Instances of these classes are placed at the beginning of a lexical
// scope to ensure that all exits from that scope restore thread or
// synchronization state to its original values.  Thread state includes
// ansynchronous cancellability, synchronization state includes locks
// that cover data structures that are shared between threads.
//
// NOTE:  supports only POSIX and SVR4 threads for the moment.  Win32
// threads can be supported sometime later.
//

#ifndef	_THREAD_HH
#define	_THREAD_HH

#ifdef	unix
#include	<unistd.h>		// may define _POSIX_THREADS
#endif	// unix

#ifdef	_POSIX_THREADS
#include	<pthread.h>

//
// This ugliness is called for by OSF/1 v3.0, which defines the POSIX.1c
// symbol "_POSIX_THREADS" even though it is noncompliant.
//
// We make the assumption that PTHREAD_MUTEX_INITIALIXER is a preprocessor
// symbol, although POSIX does not require that, since since it works on
// all the POSIX.1c implementations we've seen.
//
#	ifndef	PTHREAD_MUTEX_INITIALIZER
#		undef _POSIX_THREADS
#	endif	// not really POSIX.1c threads
#endif

//
// Use native threading on Solaris 2.2 and later.
//
// XXX this is a temporary kluge; "autoconf" should kick in the
// appropriate POSIX threads emulation when it's not native.
//
#if defined (sun) && !defined (_POSIX_THREADS) && !defined (FAKE_POSIX_THREADS) 
#	define	FAKE_POSIX_THREADS
#endif	// 2.2 <= "solaris version < 2.5


#ifdef	FAKE_POSIX_THREADS
//
// To use SVR4 native threads, enable FAKE_POSIX_THREADS.  This is
// intentionally not autoconfigured, since it's only really needed on
// Solaris versions before 2.5.  POSIX threads are the way to go
// longer term, on all compliant platforms.
//
// NOTE:  this is only a partial implementation !!!  Enough to make
// the IIOP engine work as it's coded as of 9-Aug-95.  If you start
// to use different POSIX options, these macros could stop working.
//
#define	_POSIX_THREADS		// only as much as is defined here!

#include	<thread.h>
#include	<synch.h>

typedef	thread_t		pthread_t;
typedef	mutex_t			pthread_mutex_t;
typedef cond_t			pthread_cond_t;
typedef	unsigned long		pthread_attr_t;
typedef thread_key_t		pthread_key_t;


#define	PTHREAD_MUTEX_INITIALIZER	DEFAULTMUTEX
#define	PTHREAD_COND_INITIALIZER	DEFAULTCV

#define	pthread_mutex_lock	mutex_lock
#define	pthread_mutex_unlock	mutex_unlock
#define	pthread_cond_wait	cond_wait

struct pthread_once_t {
    mutex_t	lock;
    int		called_once;
};

#define	PTHREAD_ONCE_INIT	{ DEFAULTMUTEX, 0 }

inline void
pthread_once (pthread_once_t *var, void (*fn)())
{
    mutex_lock (&var->lock);
    if (var->called_once == 0) {
	(fn)();
	var->called_once = 1;
    }
    mutex_unlock (&var->lock);
}

#define	pthread_self		thr_self

#define	pthread_key_create	thr_keycreate
#define	pthread_attr_init(ap)	((*ap) = 0)
#define	pthread_attr_setdetachstate(ap,v) ((*ap) |= (v))

#define	PTHREAD_CREATE_DETACHED	THR_DETACHED

inline void *
pthread_getspecific (pthread_key_t key)
{
    void		*vp;

    thr_getspecific (key, &vp);
    return vp;
}

#define	pthread_setspecific	thr_setspecific

inline int
pthread_create (
    pthread_t		*tidp,
    pthread_attr_t	*attrs,
    void		*(func)(void *),
    void		*arg
)
{
    return thr_create (0, 0, func, arg, *attrs, tidp);
}

#endif	// FAKE_POSIX_THREADS


#ifdef	_POSIX_THREADS
//
// Stick one of these at the beginning of a block that hosts a critical
// section, passing it a pointer to the lock guarding that section.  The
// destructor will release it on all code paths, eliminating one class of
// common threading errors.
//
class Critical {
  public:
			Critical (pthread_mutex_t *l) : lock (l)
				{ enter (); }

			~Critical ()
				{ leave (); }
			
    void		leave ()
				{ (void) pthread_mutex_unlock (lock); }
    void		enter ()
				{ (void) pthread_mutex_lock (lock); }
    void		pause (pthread_cond_t *condition)
			    { (void) pthread_cond_wait (condition, lock); }

  private:
    pthread_mutex_t	*lock;
};


//
// Stick one of these at the beginning of a block that can't support
// asynchronous cancellation, and which must be cancel-safe.
//
class ForceSynchronousCancel {
  public:
    //
    // MIT Pthreads 1.60 doesn't include cancellation; this is good, it
    // gives time to ensure that stack unwinding for cancellation (in C)
    // interoperates with unwinding for C++ exceptions so that both
    // resource reclamation systems interwork correctly.
    //
#ifdef	PTHREAD_CANCEL_DEFERRED
    ForceSynchronousCancel ()
    { (void) pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old_type); }

    ~ForceSynchronousCancel ()
    { (void) pthread_setcanceltype (old_type, &old_type); }

  private:
    int			old_type;
#endif	// PTHREAD_CANCEL_DEFERRED
};

#endif	// _POSIX_THREADS

#endif	// _THREAD_HH