2 * Copyright 2001-2007 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.
20 * Thread and locking wrappers for POSIX platforms
25 #include "util/Threads.h"
32 # ifndef HAVE_PTHREAD_RWLOCK_INIT
36 # error "This implementation is for POSIX platforms."
39 using namespace xmltooling::logging;
40 using namespace xmltooling;
43 namespace xmltooling {
45 class XMLTOOL_DLLLOCAL ThreadImpl : public Thread {
48 ThreadImpl(void* (*start_routine)(void*), void* arg);
49 virtual ~ThreadImpl() {}
52 return pthread_detach(thread_id);
55 int join(void** thread_return) {
56 return pthread_join(thread_id, thread_return);
60 return pthread_kill(thread_id, signo);
64 class XMLTOOL_DLLLOCAL MutexImpl : public Mutex {
65 pthread_mutex_t mutex;
66 friend class XMLTOOL_DLLLOCAL CondWaitImpl;
69 virtual ~MutexImpl() {
70 pthread_mutex_destroy(&mutex);
74 return pthread_mutex_lock(&mutex);
78 return pthread_mutex_unlock(&mutex);
82 class XMLTOOL_DLLLOCAL CondWaitImpl : public CondWait {
86 virtual ~CondWaitImpl() {
87 pthread_cond_destroy(&cond);
90 int wait(Mutex* mutex) {
91 return wait(static_cast<MutexImpl*>(mutex));
94 int wait(MutexImpl* mutex) {
95 return pthread_cond_wait(&cond, &(mutex->mutex));
98 int timedwait(Mutex* mutex, int delay_seconds) {
99 return timedwait(static_cast<MutexImpl*>(mutex), delay_seconds);
102 int timedwait(MutexImpl* mutex, int delay_seconds) {
104 memset(&ts, 0, sizeof(ts));
105 ts.tv_sec = time(NULL) + delay_seconds;
106 return pthread_cond_timedwait(&cond, &(mutex->mutex), &ts);
110 return pthread_cond_signal(&cond);
114 return pthread_cond_broadcast(&cond);
118 class XMLTOOL_DLLLOCAL RWLockImpl : public RWLock {
119 #ifdef HAVE_PTHREAD_RWLOCK_INIT
120 pthread_rwlock_t lock;
123 virtual ~RWLockImpl() {
124 pthread_rwlock_destroy(&lock);
128 return pthread_rwlock_rdlock(&lock);
132 return pthread_rwlock_wrlock(&lock);
136 return pthread_rwlock_unlock(&lock);
142 virtual ~RWLockImpl() {
143 rwlock_destroy (&lock);
147 return rw_rdlock(&lock);
151 return rw_wrlock(&lock);
155 return rw_unlock(&lock);
160 class XMLTOOL_DLLLOCAL ThreadKeyImpl : public ThreadKey {
163 ThreadKeyImpl(void (*destroy_fcn)(void*));
164 virtual ~ThreadKeyImpl() {
165 pthread_key_delete(key);
168 int setData(void* data) {
169 return pthread_setspecific(key,data);
172 void* getData() const {
173 return pthread_getspecific(key);
179 ThreadImpl::ThreadImpl(void* (*start_routine)(void*), void* arg)
181 int rc=pthread_create(&thread_id, NULL, start_routine, arg);
183 #ifdef HAVE_STRERROR_R
185 strerror_r(rc,buf,sizeof(buf));
187 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,buf);
189 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,strerror(rc));
191 throw ThreadingException("Thread creation failed.");
195 MutexImpl::MutexImpl()
197 int rc=pthread_mutex_init(&mutex, NULL);
199 #ifdef HAVE_STRERROR_R
201 strerror_r(rc,buf,sizeof(buf));
203 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,buf);
205 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,strerror(rc));
207 throw ThreadingException("Mutex creation failed.");
211 CondWaitImpl::CondWaitImpl()
213 int rc=pthread_cond_init(&cond, NULL);
215 #ifdef HAVE_STRERROR_R
217 strerror_r(rc,buf,sizeof(buf));
219 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,buf);
221 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,strerror(rc));
223 throw ThreadingException("Condition variable creation failed.");
227 RWLockImpl::RWLockImpl()
229 #ifdef HAVE_PTHREAD_RWLOCK_INIT
230 int rc=pthread_rwlock_init(&lock, NULL);
232 int rc=rwlock_init(&lock, USYNC_THREAD, NULL);
235 #ifdef HAVE_STRERROR_R
237 strerror_r(rc,buf,sizeof(buf));
239 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,buf);
241 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,strerror(rc));
243 throw ThreadingException("Shared lock creation failed.");
247 ThreadKeyImpl::ThreadKeyImpl(void (*destroy_fcn)(void*))
249 int rc=pthread_key_create(&key, destroy_fcn);
251 #ifdef HAVE_STRERROR_R
253 strerror_r(rc,buf,sizeof(buf));
255 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,buf);
257 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,strerror(rc));
259 throw ThreadingException("Thread key creation failed.");
263 Thread* Thread::create(void* (*start_routine)(void*), void* arg)
265 return new ThreadImpl(start_routine, arg);
268 void Thread::exit(void* return_val)
270 pthread_exit(return_val);
273 void Thread::sleep(int seconds)
278 void Thread::mask_all_signals(void)
281 sigfillset(&sigmask);
282 Thread::mask_signals(SIG_BLOCK, &sigmask, NULL);
285 int Thread::mask_signals(int how, const sigset_t *newmask, sigset_t *oldmask)
287 return pthread_sigmask(how,newmask,oldmask);
290 Mutex * Mutex::create()
292 return new MutexImpl();
295 CondWait * CondWait::create()
297 return new CondWaitImpl();
300 RWLock * RWLock::create()
302 return new RWLockImpl();
305 ThreadKey* ThreadKey::create (void (*destroy_fcn)(void*))
307 return new ThreadKeyImpl(destroy_fcn);