c22ae31cfb8b2243e5d65e8cf22ef6fe35c62192
[shibboleth/sp.git] / shib / shib-threads.cpp
1 /*
2  * shib-threads.cpp -- an abstraction around Pthreads
3  *
4  * Created by:  Derek Atkins <derek@ihtfp.com>
5  *
6  * $Id: shib-threads.cpp,v 1.5 2003/01/30 15:18:36 warlord Exp $
7  */
8
9 #include "internal.h"
10 #include "shib-threads.h"
11
12 #include <log4cpp/Category.hh>
13
14 #ifdef HAVE_PTHREAD
15 #include <pthread.h>
16 #ifndef HAVE_PTHREAD_RWLOCK_INIT
17 #include <synch.h>
18 #endif
19 #else
20 #error "You need to create the proper thread implementation"
21 #endif
22
23 #include <stdexcept>
24
25 using namespace std;
26 using namespace shibboleth;
27 using namespace log4cpp;
28
29 // pthread implementation of the Shib Target Threads API
30
31 //
32 // "Private" Implementation
33 //
34
35 class ThreadImpl : public Thread {
36 public:
37   ThreadImpl(void* (*start_routine)(void*), void* arg);
38   ~ThreadImpl() {}
39
40   int detach() { return pthread_detach(thread_id); }
41   int join(void** thread_return) { return pthread_join(thread_id, thread_return); }
42   int kill(int signo) { return pthread_kill(thread_id, signo); }
43
44   pthread_t     thread_id;
45 };
46
47 class MutexImpl : public Mutex {
48 public:
49   MutexImpl();
50   ~MutexImpl() { pthread_mutex_destroy (&mutex); }
51
52   int lock() { return pthread_mutex_lock (&mutex); }
53   int unlock() { return pthread_mutex_unlock (&mutex); }
54
55   pthread_mutex_t mutex;
56 };
57
58 class CondWaitImpl : public CondWait {
59 public:
60   CondWaitImpl();
61   ~CondWaitImpl() { pthread_cond_destroy (&cond); }
62
63   int wait(Mutex* mutex) { return wait (dynamic_cast<MutexImpl*>(mutex)); }
64   int wait(MutexImpl* mutex) { return pthread_cond_wait (&cond, &(mutex->mutex)); }
65   int timedwait(Mutex* mutex, int delay_seconds)
66         { return timedwait (dynamic_cast<MutexImpl*>(mutex), delay_seconds); }
67   int timedwait(MutexImpl* mutex, int delay_seconds) {
68     struct timespec ts;
69     memset (&ts, 0, sizeof(ts));
70     ts.tv_sec = time(NULL) + delay_seconds;
71     return pthread_cond_timedwait (&cond, &(mutex->mutex), &ts);
72   }
73   int signal() { return pthread_cond_signal (&cond); }
74   int broadcast() { return pthread_cond_broadcast (&cond); }
75
76   pthread_cond_t cond;
77 };
78
79 class RWLockImpl : public RWLock {
80 public:
81 #ifdef HAVE_PTHREAD_RWLOCK_INIT
82   RWLockImpl();
83   ~RWLockImpl() { pthread_rwlock_destroy (&lock); }
84
85   int rdlock() { return pthread_rwlock_rdlock (&lock); }
86   int wrlock() { return pthread_rwlock_wrlock (&lock); }
87   int unlock() { return pthread_rwlock_unlock (&lock); }
88
89   pthread_rwlock_t lock;
90 #else
91   RWLockImpl();
92   ~RWLockImpl() { rwlock_destroy (&lock); }
93
94   int rdlock() { return rw_rdlock (&lock); }
95   int wrlock() { return rw_wrlock (&lock); }
96   int unlock() { return rw_unlock (&lock); }
97
98   rwlock_t lock;
99 #endif
100 };
101
102 class ThreadKeyImpl : public ThreadKey {
103 public:
104   ThreadKeyImpl(void (*destroy_fcn)(void*));
105   ~ThreadKeyImpl() { pthread_key_delete (key); }
106
107   int setData(void* data) { return pthread_setspecific (key,data); }
108   void* getData() { return pthread_getspecific (key); }
109
110   pthread_key_t key;
111 };
112
113 //
114 // Constructor Implementation follows...
115 //
116
117 ThreadImpl::ThreadImpl(void* (*start_routine)(void*), void* arg)
118 {
119     int rc=pthread_create(&thread_id, NULL, start_routine, arg);
120     if (rc) {
121 #ifdef HAVE_STRERROR_R
122         char buf[256];
123         strerror_r(rc,buf,sizeof(buf));
124         buf[255]=0;
125         Category::getInstance(SHIB_LOGCAT".threads").error("pthread_create error (%d): %s",rc,buf);
126 #else
127         Category::getInstance(SHIB_LOGCAT".threads").error("pthread_create error (%d): %s",rc,strerror(rc));
128 #endif
129         throw rc;
130     }
131 }
132
133 MutexImpl::MutexImpl()
134 {
135     int rc=pthread_mutex_init(&mutex, NULL);
136     if (rc) {
137 #ifdef HAVE_STRERROR_R
138         char buf[256];
139         strerror_r(rc,buf,sizeof(buf));
140         buf[255]=0;
141         Category::getInstance(SHIB_LOGCAT".threads").error("pthread_mutex_init error (%d): %s",rc,buf);
142 #else
143         Category::getInstance(SHIB_LOGCAT".threads").error("pthread_mutex_init error (%d): %s",rc,strerror(rc));
144 #endif
145         throw rc;
146     }
147 }
148
149 CondWaitImpl::CondWaitImpl()
150 {
151     int rc=pthread_cond_init(&cond, NULL);
152     if (rc) {
153 #ifdef HAVE_STRERROR_R
154         char buf[256];
155         strerror_r(rc,buf,sizeof(buf));
156         buf[255]=0;
157         Category::getInstance(SHIB_LOGCAT".threads").error("pthread_cond_init error (%d): %s",rc,buf);
158 #else
159         Category::getInstance(SHIB_LOGCAT".threads").error("pthread_cond_init error (%d): %s",rc,strerror(rc));
160 #endif
161         throw rc;
162     }
163 }
164
165 RWLockImpl::RWLockImpl()
166 {
167 #ifdef HAVE_PTHREAD_RWLOCK_INIT
168     int rc=pthread_rwlock_init(&lock, NULL);
169 #else
170     int rc=rwlock_init(&lock, USYNC_THREAD, NULL);
171 #endif
172     if (rc) {
173 #ifdef HAVE_STRERROR_R
174         char buf[256];
175         strerror_r(rc,buf,sizeof(buf));
176         buf[255]=0;
177         Category::getInstance(SHIB_LOGCAT".threads").error("pthread_rwlock_init error (%d): %s",rc,buf);
178 #else
179         Category::getInstance(SHIB_LOGCAT".threads").error("pthread_rwlock_init error (%d): %s",rc,strerror(rc));
180 #endif
181         throw rc;
182     }
183 }
184
185 ThreadKeyImpl::ThreadKeyImpl(void (*destroy_fcn)(void*))
186 {
187     int rc=pthread_key_create(&key, destroy_fcn);
188     if (rc) {
189 #ifdef HAVE_STRERROR_R
190         char buf[256];
191         strerror_r(rc,buf,sizeof(buf));
192         buf[255]=0;
193         Category::getInstance(SHIB_LOGCAT".threads").error("pthread_key_create error (%d): %s",rc,buf);
194 #else
195         Category::getInstance(SHIB_LOGCAT".threads").error("pthread_key_create error (%d): %s",rc,strerror(rc));
196 #endif
197         throw rc;
198     }
199 }
200
201 //
202 // public "static" creation functions
203 //
204
205 Thread* Thread::create(void* (*start_routine)(void*), void* arg)
206 {
207   return new ThreadImpl(start_routine, arg);
208 }
209
210 void Thread::exit(void* return_val)
211 {
212   pthread_exit (return_val);
213 }
214     
215 void Thread::mask_all_signals(void)
216 {
217   sigset_t sigmask;
218   sigfillset(&sigmask);
219   Thread::mask_signals(SIG_BLOCK, &sigmask, NULL);
220 }
221
222 int Thread::mask_signals(int how, const sigset_t *newmask, sigset_t *oldmask)
223 {
224   return pthread_sigmask(how,newmask,oldmask);
225 }
226
227 Mutex * Mutex::create()
228 {
229   return new MutexImpl();
230 }
231
232 CondWait * CondWait::create()
233 {
234   return new CondWaitImpl();
235 }
236
237 RWLock * RWLock::create()
238 {
239   return new RWLockImpl();
240 }
241
242 ThreadKey* ThreadKey::create (void (*destroy_fcn)(void*))
243 {
244   return new ThreadKeyImpl(destroy_fcn);
245 }