2 * Licensed to the University Corporation for Advanced Internet
3 * Development, Inc. (UCAID) under one or more contributor license
4 * agreements. See the NOTICE file distributed with this work for
5 * additional information regarding copyright ownership.
7 * UCAID licenses this file to you under the Apache License,
8 * Version 2.0 (the "License"); you may not use this file except
9 * in compliance with the License. You may obtain a copy of the
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17 * either express or implied. See the License for the specific
18 * language governing permissions and limitations under the License.
24 * Thread and locking wrappers for POSIX platforms
29 #include "util/Threads.h"
36 # ifndef HAVE_PTHREAD_RWLOCK_INIT
40 # error "This implementation is for POSIX platforms."
43 using namespace xmltooling::logging;
44 using namespace xmltooling;
47 namespace xmltooling {
49 class XMLTOOL_DLLLOCAL ThreadImpl : public Thread {
52 ThreadImpl(void* (*start_routine)(void*), void* arg, size_t stacksize);
53 virtual ~ThreadImpl() {}
56 return pthread_detach(thread_id);
59 int join(void** thread_return) {
60 return pthread_join(thread_id, thread_return);
64 return pthread_kill(thread_id, signo);
68 class XMLTOOL_DLLLOCAL MutexImpl : public Mutex {
69 pthread_mutex_t mutex;
70 friend class XMLTOOL_DLLLOCAL CondWaitImpl;
73 virtual ~MutexImpl() {
74 pthread_mutex_destroy(&mutex);
78 return pthread_mutex_lock(&mutex);
82 return pthread_mutex_unlock(&mutex);
86 class XMLTOOL_DLLLOCAL CondWaitImpl : public CondWait {
90 virtual ~CondWaitImpl() {
91 pthread_cond_destroy(&cond);
94 int wait(Mutex* mutex) {
95 return wait(static_cast<MutexImpl*>(mutex));
98 int wait(MutexImpl* mutex) {
99 return pthread_cond_wait(&cond, &(mutex->mutex));
102 int timedwait(Mutex* mutex, int delay_seconds) {
103 return timedwait(static_cast<MutexImpl*>(mutex), delay_seconds);
106 int timedwait(MutexImpl* mutex, int delay_seconds) {
108 memset(&ts, 0, sizeof(ts));
109 ts.tv_sec = time(nullptr) + delay_seconds;
110 return pthread_cond_timedwait(&cond, &(mutex->mutex), &ts);
114 return pthread_cond_signal(&cond);
118 return pthread_cond_broadcast(&cond);
122 class XMLTOOL_DLLLOCAL RWLockImpl : public RWLock {
123 #ifdef HAVE_PTHREAD_RWLOCK_INIT
124 pthread_rwlock_t lock;
127 virtual ~RWLockImpl() {
128 pthread_rwlock_destroy(&lock);
132 return pthread_rwlock_rdlock(&lock);
136 return pthread_rwlock_wrlock(&lock);
140 return pthread_rwlock_unlock(&lock);
146 virtual ~RWLockImpl() {
147 rwlock_destroy (&lock);
151 return rw_rdlock(&lock);
155 return rw_wrlock(&lock);
159 return rw_unlock(&lock);
164 class XMLTOOL_DLLLOCAL ThreadKeyImpl : public ThreadKey {
167 ThreadKeyImpl(void (*destroy_fcn)(void*));
168 virtual ~ThreadKeyImpl() {
169 pthread_key_delete(key);
172 int setData(void* data) {
173 return pthread_setspecific(key,data);
176 void* getData() const {
177 return pthread_getspecific(key);
183 ThreadImpl::ThreadImpl(void* (*start_routine)(void*), void* arg, size_t stacksize)
188 pthread_attr_t attrs;
189 rc = pthread_attr_init(&attrs);
191 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_attr_init error (%d)", rc);
192 throw ThreadingException("Thread creation failed.");
194 rc = pthread_attr_setstacksize(&attrs, stacksize);
196 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_attr_setstacksize error (%d)", rc);
197 throw ThreadingException("Thread creation failed.");
199 rc = pthread_create(&thread_id, &attrs, start_routine, arg);
202 rc = pthread_create(&thread_id, nullptr, start_routine, arg);
205 #ifdef HAVE_STRERROR_R
207 strerror_r(rc,buf,sizeof(buf));
209 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,buf);
211 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,strerror(rc));
213 throw ThreadingException("Thread creation failed.");
217 MutexImpl::MutexImpl()
219 int rc=pthread_mutex_init(&mutex, nullptr);
221 #ifdef HAVE_STRERROR_R
223 strerror_r(rc,buf,sizeof(buf));
225 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,buf);
227 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,strerror(rc));
229 throw ThreadingException("Mutex creation failed.");
233 CondWaitImpl::CondWaitImpl()
235 int rc=pthread_cond_init(&cond, nullptr);
237 #ifdef HAVE_STRERROR_R
239 strerror_r(rc,buf,sizeof(buf));
241 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,buf);
243 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,strerror(rc));
245 throw ThreadingException("Condition variable creation failed.");
249 RWLockImpl::RWLockImpl()
251 #ifdef HAVE_PTHREAD_RWLOCK_INIT
252 int rc=pthread_rwlock_init(&lock, nullptr);
254 int rc=rwlock_init(&lock, USYNC_THREAD, nullptr);
257 #ifdef HAVE_STRERROR_R
259 strerror_r(rc,buf,sizeof(buf));
261 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,buf);
263 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,strerror(rc));
265 throw ThreadingException("Shared lock creation failed.");
269 ThreadKeyImpl::ThreadKeyImpl(void (*destroy_fcn)(void*))
271 int rc=pthread_key_create(&key, destroy_fcn);
273 #ifdef HAVE_STRERROR_R
275 strerror_r(rc,buf,sizeof(buf));
277 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,buf);
279 Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,strerror(rc));
281 throw ThreadingException("Thread key creation failed.");
285 Thread* Thread::create(void* (*start_routine)(void*), void* arg, size_t stacksize)
287 return new ThreadImpl(start_routine, arg, stacksize);
290 void Thread::exit(void* return_val)
292 pthread_exit(return_val);
295 void Thread::sleep(int seconds)
300 void Thread::mask_all_signals(void)
303 sigfillset(&sigmask);
304 Thread::mask_signals(SIG_BLOCK, &sigmask, nullptr);
307 int Thread::mask_signals(int how, const sigset_t *newmask, sigset_t *oldmask)
309 return pthread_sigmask(how,newmask,oldmask);
312 Mutex * Mutex::create()
314 return new MutexImpl();
317 CondWait * CondWait::create()
319 return new CondWaitImpl();
322 RWLock * RWLock::create()
324 return new RWLockImpl();
327 ThreadKey* ThreadKey::create (void (*destroy_fcn)(void*))
329 return new ThreadKeyImpl(destroy_fcn);