2 * Copyright 2001-2010 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, size_t stacksize);
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(nullptr) + 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, size_t stacksize)
184 pthread_attr_t attrs;
185 rc = pthread_attr_init(&attrs);
187 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_attr_init error (%d)", rc);
188 throw ThreadingException("Thread creation failed.");
190 rc = pthread_attr_setstacksize(&attrs, stacksize);
192 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_attr_setstacksize error (%d)", rc);
193 throw ThreadingException("Thread creation failed.");
195 rc = pthread_create(&thread_id, &attrs, start_routine, arg);
198 rc = pthread_create(&thread_id, nullptr, start_routine, arg);
201 #ifdef HAVE_STRERROR_R
203 strerror_r(rc,buf,sizeof(buf));
205 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,buf);
207 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,strerror(rc));
209 throw ThreadingException("Thread creation failed.");
213 MutexImpl::MutexImpl()
215 int rc=pthread_mutex_init(&mutex, nullptr);
217 #ifdef HAVE_STRERROR_R
219 strerror_r(rc,buf,sizeof(buf));
221 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,buf);
223 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,strerror(rc));
225 throw ThreadingException("Mutex creation failed.");
229 CondWaitImpl::CondWaitImpl()
231 int rc=pthread_cond_init(&cond, nullptr);
233 #ifdef HAVE_STRERROR_R
235 strerror_r(rc,buf,sizeof(buf));
237 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,buf);
239 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,strerror(rc));
241 throw ThreadingException("Condition variable creation failed.");
245 RWLockImpl::RWLockImpl()
247 #ifdef HAVE_PTHREAD_RWLOCK_INIT
248 int rc=pthread_rwlock_init(&lock, nullptr);
250 int rc=rwlock_init(&lock, USYNC_THREAD, nullptr);
253 #ifdef HAVE_STRERROR_R
255 strerror_r(rc,buf,sizeof(buf));
257 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,buf);
259 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,strerror(rc));
261 throw ThreadingException("Shared lock creation failed.");
265 ThreadKeyImpl::ThreadKeyImpl(void (*destroy_fcn)(void*))
267 int rc=pthread_key_create(&key, destroy_fcn);
269 #ifdef HAVE_STRERROR_R
271 strerror_r(rc,buf,sizeof(buf));
273 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,buf);
275 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,strerror(rc));
277 throw ThreadingException("Thread key creation failed.");
281 Thread* Thread::create(void* (*start_routine)(void*), void* arg, size_t stacksize)
283 return new ThreadImpl(start_routine, arg, stacksize);
286 void Thread::exit(void* return_val)
288 pthread_exit(return_val);
291 void Thread::sleep(int seconds)
296 void Thread::mask_all_signals(void)
299 sigfillset(&sigmask);
300 Thread::mask_signals(SIG_BLOCK, &sigmask, nullptr);
303 int Thread::mask_signals(int how, const sigset_t *newmask, sigset_t *oldmask)
305 return pthread_sigmask(how,newmask,oldmask);
308 Mutex * Mutex::create()
310 return new MutexImpl();
313 CondWait * CondWait::create()
315 return new CondWaitImpl();
318 RWLock * RWLock::create()
320 return new RWLockImpl();
323 ThreadKey* ThreadKey::create (void (*destroy_fcn)(void*))
325 return new ThreadKeyImpl(destroy_fcn);