2 * Copyright 2001-2005 Internet2
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * shib-threads.cpp -- an abstraction around Pthreads
20 * Created by: Derek Atkins <derek@ihtfp.com>
22 * $Id: shib-threads.cpp,v 1.5 2003/01/30 15:18:36 warlord Exp $
26 #include "shib-threads.h"
30 #ifndef HAVE_PTHREAD_RWLOCK_INIT
34 #error "You need to create the proper thread implementation."
39 using namespace shibboleth::logging;
40 using namespace shibboleth;
43 // pthread implementation of the Shib Target Threads API
46 // "Private" Implementation
49 class ThreadImpl : public Thread {
51 ThreadImpl(void* (*start_routine)(void*), void* arg);
54 int detach() { return pthread_detach(thread_id); }
55 int join(void** thread_return) { return pthread_join(thread_id, thread_return); }
56 int kill(int signo) { return pthread_kill(thread_id, signo); }
61 class MutexImpl : public Mutex {
64 ~MutexImpl() { pthread_mutex_destroy (&mutex); }
66 int lock() { return pthread_mutex_lock (&mutex); }
67 int unlock() { return pthread_mutex_unlock (&mutex); }
69 pthread_mutex_t mutex;
72 class CondWaitImpl : public CondWait {
75 ~CondWaitImpl() { pthread_cond_destroy (&cond); }
77 int wait(Mutex* mutex) { return wait (dynamic_cast<MutexImpl*>(mutex)); }
78 int wait(MutexImpl* mutex) { return pthread_cond_wait (&cond, &(mutex->mutex)); }
79 int timedwait(Mutex* mutex, int delay_seconds)
80 { return timedwait (dynamic_cast<MutexImpl*>(mutex), delay_seconds); }
81 int timedwait(MutexImpl* mutex, int delay_seconds) {
83 memset (&ts, 0, sizeof(ts));
84 ts.tv_sec = time(NULL) + delay_seconds;
85 return pthread_cond_timedwait (&cond, &(mutex->mutex), &ts);
87 int signal() { return pthread_cond_signal (&cond); }
88 int broadcast() { return pthread_cond_broadcast (&cond); }
93 class RWLockImpl : public RWLock {
95 #ifdef HAVE_PTHREAD_RWLOCK_INIT
97 ~RWLockImpl() { pthread_rwlock_destroy (&lock); }
99 int rdlock() { return pthread_rwlock_rdlock (&lock); }
100 int wrlock() { return pthread_rwlock_wrlock (&lock); }
101 int unlock() { return pthread_rwlock_unlock (&lock); }
103 pthread_rwlock_t lock;
106 ~RWLockImpl() { rwlock_destroy (&lock); }
108 int rdlock() { return rw_rdlock (&lock); }
109 int wrlock() { return rw_wrlock (&lock); }
110 int unlock() { return rw_unlock (&lock); }
116 class ThreadKeyImpl : public ThreadKey {
118 ThreadKeyImpl(void (*destroy_fcn)(void*));
119 ~ThreadKeyImpl() { pthread_key_delete (key); }
121 int setData(void* data) { return pthread_setspecific (key,data); }
122 void* getData() { return pthread_getspecific (key); }
128 // Constructor Implementation follows...
131 ThreadImpl::ThreadImpl(void* (*start_routine)(void*), void* arg)
133 int rc=pthread_create(&thread_id, NULL, start_routine, arg);
135 #ifdef HAVE_STRERROR_R
137 strerror_r(rc,buf,sizeof(buf));
139 Category::getInstance(SHIB_LOGCAT".threads").error("pthread_create error (%d): %s",rc,buf);
141 Category::getInstance(SHIB_LOGCAT".threads").error("pthread_create error (%d): %s",rc,strerror(rc));
147 MutexImpl::MutexImpl()
149 int rc=pthread_mutex_init(&mutex, NULL);
151 #ifdef HAVE_STRERROR_R
153 strerror_r(rc,buf,sizeof(buf));
155 Category::getInstance(SHIB_LOGCAT".threads").error("pthread_mutex_init error (%d): %s",rc,buf);
157 Category::getInstance(SHIB_LOGCAT".threads").error("pthread_mutex_init error (%d): %s",rc,strerror(rc));
163 CondWaitImpl::CondWaitImpl()
165 int rc=pthread_cond_init(&cond, NULL);
167 #ifdef HAVE_STRERROR_R
169 strerror_r(rc,buf,sizeof(buf));
171 Category::getInstance(SHIB_LOGCAT".threads").error("pthread_cond_init error (%d): %s",rc,buf);
173 Category::getInstance(SHIB_LOGCAT".threads").error("pthread_cond_init error (%d): %s",rc,strerror(rc));
179 RWLockImpl::RWLockImpl()
181 #ifdef HAVE_PTHREAD_RWLOCK_INIT
182 int rc=pthread_rwlock_init(&lock, NULL);
184 int rc=rwlock_init(&lock, USYNC_THREAD, NULL);
187 #ifdef HAVE_STRERROR_R
189 strerror_r(rc,buf,sizeof(buf));
191 Category::getInstance(SHIB_LOGCAT".threads").error("pthread_rwlock_init error (%d): %s",rc,buf);
193 Category::getInstance(SHIB_LOGCAT".threads").error("pthread_rwlock_init error (%d): %s",rc,strerror(rc));
199 ThreadKeyImpl::ThreadKeyImpl(void (*destroy_fcn)(void*))
201 int rc=pthread_key_create(&key, destroy_fcn);
203 #ifdef HAVE_STRERROR_R
205 strerror_r(rc,buf,sizeof(buf));
207 Category::getInstance(SHIB_LOGCAT".threads").error("pthread_key_create error (%d): %s",rc,buf);
209 Category::getInstance(SHIB_LOGCAT".threads").error("pthread_key_create error (%d): %s",rc,strerror(rc));
216 // public "static" creation functions
219 Thread* Thread::create(void* (*start_routine)(void*), void* arg)
221 return new ThreadImpl(start_routine, arg);
224 void Thread::exit(void* return_val)
226 pthread_exit (return_val);
229 void Thread::mask_all_signals(void)
232 sigfillset(&sigmask);
233 Thread::mask_signals(SIG_BLOCK, &sigmask, NULL);
236 int Thread::mask_signals(int how, const sigset_t *newmask, sigset_t *oldmask)
238 return pthread_sigmask(how,newmask,oldmask);
241 Mutex * Mutex::create()
243 return new MutexImpl();
246 CondWait * CondWait::create()
248 return new CondWaitImpl();
251 RWLock * RWLock::create()
253 return new RWLockImpl();
256 ThreadKey* ThreadKey::create (void (*destroy_fcn)(void*))
258 return new ThreadKeyImpl(destroy_fcn);