2 * Copyright 2001-2005 Internet2
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
20 * Thread and locking wrappers for POSIX platforms
\r
23 #include "internal.h"
\r
24 #include "util/Threads.h"
\r
27 #include <log4cpp/Category.hh>
\r
30 # include <pthread.h>
\r
31 # ifndef HAVE_PTHREAD_RWLOCK_INIT
\r
35 # error "This implementation is for POSIX platforms."
\r
38 using namespace xmltooling;
\r
39 using namespace log4cpp;
\r
40 using namespace std;
\r
42 namespace xmltooling {
\r
44 class XMLTOOL_DLLLOCAL ThreadImpl : public Thread {
\r
45 pthread_t thread_id;
\r
47 ThreadImpl(void* (*start_routine)(void*), void* arg);
\r
48 virtual ~ThreadImpl() {}
\r
51 return pthread_detach(thread_id);
\r
54 int join(void** thread_return) {
\r
55 return pthread_join(thread_id, thread_return);
\r
58 int kill(int signo) {
\r
59 return pthread_kill(thread_id, signo);
\r
63 class XMLTOOL_DLLLOCAL MutexImpl : public Mutex {
\r
64 pthread_mutex_t mutex;
\r
67 virtual ~MutexImpl() {
\r
68 pthread_mutex_destroy(&mutex);
\r
72 return pthread_mutex_lock(&mutex);
\r
76 return pthread_mutex_unlock(&mutex);
\r
80 class XMLTOOL_DLLLOCAL CondWaitImpl : public CondWait {
\r
81 pthread_cond_t cond;
\r
84 virtual ~CondWaitImpl() {
\r
85 pthread_cond_destroy(&cond);
\r
88 int wait(Mutex* mutex) {
\r
89 return wait(static_cast<MutexImpl*>(mutex));
\r
92 int wait(MutexImpl* mutex) {
\r
93 return pthread_cond_wait(&cond, &(mutex->mutex));
\r
96 int timedwait(Mutex* mutex, int delay_seconds) {
\r
97 return timedwait(static_cast<MutexImpl*>(mutex), delay_seconds);
\r
100 int timedwait(MutexImpl* mutex, int delay_seconds) {
\r
101 struct timespec ts;
\r
102 memset(&ts, 0, sizeof(ts));
\r
103 ts.tv_sec = time(NULL) + delay_seconds;
\r
104 return pthread_cond_timedwait(&cond, &(mutex->mutex), &ts);
\r
108 return pthread_cond_signal(&cond);
\r
112 return pthread_cond_broadcast(&cond);
\r
116 class XMLTOOL_DLLLOCAL RWLockImpl : public RWLock {
\r
117 #ifdef HAVE_PTHREAD_RWLOCK_INIT
\r
118 pthread_rwlock_t lock;
\r
121 virtual ~RWLockImpl() {
\r
122 pthread_rwlock_destroy(&lock);
\r
126 return pthread_rwlock_rdlock(&lock);
\r
130 return pthread_rwlock_wrlock(&lock);
\r
134 return pthread_rwlock_unlock(&lock);
\r
140 virtual ~RWLockImpl() {
\r
141 rwlock_destroy (&lock);
\r
145 return rw_rdlock(&lock);
\r
149 return rw_wrlock(&lock);
\r
153 return rw_unlock(&lock);
\r
158 class XMLTOOL_DLLLOCAL ThreadKeyImpl : public ThreadKey {
\r
161 ThreadKeyImpl(void (*destroy_fcn)(void*));
\r
162 virtual ~ThreadKeyImpl() {
\r
163 pthread_key_delete(key);
\r
166 int setData(void* data) {
\r
167 return pthread_setspecific(key,data);
\r
170 void* getData() const {
\r
171 return pthread_getspecific(key);
\r
177 ThreadImpl::ThreadImpl(void* (*start_routine)(void*), void* arg)
\r
179 int rc=pthread_create(&thread_id, NULL, start_routine, arg);
\r
181 #ifdef HAVE_STRERROR_R
\r
183 strerror_r(rc,buf,sizeof(buf));
\r
185 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,buf);
\r
187 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,strerror(rc));
\r
189 throw ThreadingException("Thread creation failed.");
\r
193 MutexImpl::MutexImpl()
\r
195 int rc=pthread_mutex_init(&mutex, NULL);
\r
197 #ifdef HAVE_STRERROR_R
\r
199 strerror_r(rc,buf,sizeof(buf));
\r
201 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,buf);
\r
203 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,strerror(rc));
\r
205 throw ThreadingException("Mutex creation failed.");
\r
209 CondWaitImpl::CondWaitImpl()
\r
211 int rc=pthread_cond_init(&cond, NULL);
\r
213 #ifdef HAVE_STRERROR_R
\r
215 strerror_r(rc,buf,sizeof(buf));
\r
217 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,buf);
\r
219 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,strerror(rc));
\r
221 throw ThreadingException("Condition variable creation failed.");
\r
225 RWLockImpl::RWLockImpl()
\r
227 #ifdef HAVE_PTHREAD_RWLOCK_INIT
\r
228 int rc=pthread_rwlock_init(&lock, NULL);
\r
230 int rc=rwlock_init(&lock, USYNC_THREAD, NULL);
\r
233 #ifdef HAVE_STRERROR_R
\r
235 strerror_r(rc,buf,sizeof(buf));
\r
237 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,buf);
\r
239 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,strerror(rc));
\r
241 throw ThreadingException("Shared lock creation failed.");
\r
245 ThreadKeyImpl::ThreadKeyImpl(void (*destroy_fcn)(void*))
\r
247 int rc=pthread_key_create(&key, destroy_fcn);
\r
249 #ifdef HAVE_STRERROR_R
\r
251 strerror_r(rc,buf,sizeof(buf));
\r
253 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,buf);
\r
255 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,strerror(rc));
\r
257 throw ThreadingException("Thread key creation failed.");
\r
261 Thread* Thread::create(void* (*start_routine)(void*), void* arg)
\r
263 return new ThreadImpl(start_routine, arg);
\r
266 void Thread::exit(void* return_val)
\r
268 pthread_exit(return_val);
\r
271 void Thread::mask_all_signals(void)
\r
274 sigfillset(&sigmask);
\r
275 Thread::mask_signals(SIG_BLOCK, &sigmask, NULL);
\r
278 int Thread::mask_signals(int how, const sigset_t *newmask, sigset_t *oldmask)
\r
280 return pthread_sigmask(how,newmask,oldmask);
\r
283 Mutex * Mutex::create()
\r
285 return new MutexImpl();
\r
288 CondWait * CondWait::create()
\r
290 return new CondWaitImpl();
\r
293 RWLock * RWLock::create()
\r
295 return new RWLockImpl();
\r
298 ThreadKey* ThreadKey::create (void (*destroy_fcn)(void*))
\r
300 return new ThreadKeyImpl(destroy_fcn);
\r