Unix thread support
[shibboleth/cpp-xmltooling.git] / xmltooling / util / PThreads.cpp
index 0678e2e..2f9a1d0 100644 (file)
-/*\r
- *  Copyright 2001-2005 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * PThreads.cpp\r
- * \r
- * Thread and locking wrappers for POSIX platforms\r
- */\r
-\r
-#include "internal.h"\r
-#include "util/Threads.h"\r
-\r
-#include <ctime>\r
-#include <log4cpp/Category.hh>\r
-\r
-#ifdef HAVE_PTHREAD\r
-# include <pthread.h>\r
-# ifndef HAVE_PTHREAD_RWLOCK_INIT\r
-#  include <synch.h>\r
-# endif\r
-#else\r
-# error "This implementation is for POSIX platforms."\r
-#endif\r
-\r
-using namespace xmltooling;\r
-using namespace log4cpp;\r
-using namespace std;\r
-\r
-namespace xmltooling {\r
-\r
-    class XMLTOOL_DLLLOCAL ThreadImpl : public Thread {\r
-        pthread_t thread_id;\r
-    public:\r
-        ThreadImpl(void* (*start_routine)(void*), void* arg);\r
-        virtual ~ThreadImpl() {}\r
-    \r
-        int detach() {\r
-            return pthread_detach(thread_id);\r
-        }\r
-        \r
-        int join(void** thread_return) {\r
-            return pthread_join(thread_id, thread_return);\r
-        }\r
-        \r
-        int kill(int signo) {\r
-            return pthread_kill(thread_id, signo);\r
-        }\r
-    };\r
-    \r
-    class XMLTOOL_DLLLOCAL MutexImpl : public Mutex {\r
-        pthread_mutex_t mutex;\r
-    public:\r
-        MutexImpl();\r
-        virtual ~MutexImpl() {\r
-            pthread_mutex_destroy(&mutex);\r
-        }\r
-    \r
-        int lock() {\r
-            return pthread_mutex_lock(&mutex);\r
-        }\r
-        \r
-        int unlock() {\r
-            return pthread_mutex_unlock(&mutex);\r
-        }\r
-    };\r
-    \r
-    class XMLTOOL_DLLLOCAL CondWaitImpl : public CondWait {\r
-        pthread_cond_t cond;\r
-    public:\r
-        CondWaitImpl();\r
-        virtual ~CondWaitImpl() {\r
-            pthread_cond_destroy(&cond);\r
-        }\r
-    \r
-        int wait(Mutex* mutex) {\r
-            return wait(static_cast<MutexImpl*>(mutex));\r
-        }\r
-        \r
-        int wait(MutexImpl* mutex) {\r
-            return pthread_cond_wait(&cond, &(mutex->mutex));\r
-        }\r
-        \r
-        int timedwait(Mutex* mutex, int delay_seconds) {\r
-            return timedwait(static_cast<MutexImpl*>(mutex), delay_seconds);\r
-        }\r
-        \r
-        int timedwait(MutexImpl* mutex, int delay_seconds) {\r
-            struct timespec ts;\r
-            memset(&ts, 0, sizeof(ts));\r
-            ts.tv_sec = time(NULL) + delay_seconds;\r
-            return pthread_cond_timedwait(&cond, &(mutex->mutex), &ts);\r
-        }\r
-        \r
-        int signal() {\r
-            return pthread_cond_signal(&cond);\r
-        }\r
-        \r
-        int broadcast() {\r
-            return pthread_cond_broadcast(&cond);\r
-        }\r
-    };\r
-    \r
-    class XMLTOOL_DLLLOCAL RWLockImpl : public RWLock {\r
-#ifdef HAVE_PTHREAD_RWLOCK_INIT\r
-        pthread_rwlock_t lock;\r
-    public:\r
-        RWLockImpl();\r
-        virtual ~RWLockImpl() {\r
-            pthread_rwlock_destroy(&lock);\r
-        }\r
-    \r
-        int rdlock() {\r
-            return pthread_rwlock_rdlock(&lock);\r
-        }\r
-        \r
-        int wrlock() {\r
-            return pthread_rwlock_wrlock(&lock);\r
-        }\r
-        \r
-        int unlock() {\r
-            return pthread_rwlock_unlock(&lock);\r
-        }\r
-#else\r
-        rwlock_t lock;\r
-    public:\r
-        RWLockImpl();\r
-        virtual ~RWLockImpl() {\r
-            rwlock_destroy (&lock);\r
-        }\r
-    \r
-        int rdlock() {\r
-            return rw_rdlock(&lock);\r
-        }\r
-        \r
-        int wrlock() {\r
-            return rw_wrlock(&lock);\r
-        }\r
-        \r
-        int unlock() {\r
-            return rw_unlock(&lock);\r
-        }\r
-#endif\r
-    };\r
-    \r
-    class XMLTOOL_DLLLOCAL ThreadKeyImpl : public ThreadKey {\r
-        pthread_key_t key;\r
-    public:\r
-        ThreadKeyImpl(void (*destroy_fcn)(void*));\r
-        virtual ~ThreadKeyImpl() {\r
-            pthread_key_delete(key);\r
-        }\r
-    \r
-        int setData(void* data) {\r
-            return pthread_setspecific(key,data);\r
-        }\r
-        \r
-        void* getData() const {\r
-            return pthread_getspecific(key);\r
-        }\r
-    };\r
-\r
-};\r
-\r
-ThreadImpl::ThreadImpl(void* (*start_routine)(void*), void* arg)\r
-{\r
-    int rc=pthread_create(&thread_id, NULL, start_routine, arg);\r
-    if (rc) {\r
-#ifdef HAVE_STRERROR_R\r
-        char buf[256];\r
-        strerror_r(rc,buf,sizeof(buf));\r
-        buf[255]=0;\r
-        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,buf);\r
-#else\r
-        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,strerror(rc));\r
-#endif\r
-        throw ThreadingException("Thread creation failed.");\r
-    }\r
-}\r
-\r
-MutexImpl::MutexImpl()\r
-{\r
-    int rc=pthread_mutex_init(&mutex, NULL);\r
-    if (rc) {\r
-#ifdef HAVE_STRERROR_R\r
-        char buf[256];\r
-        strerror_r(rc,buf,sizeof(buf));\r
-        buf[255]=0;\r
-        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,buf);\r
-#else\r
-        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,strerror(rc));\r
-#endif\r
-        throw ThreadingException("Mutex creation failed.");\r
-    }\r
-}\r
-\r
-CondWaitImpl::CondWaitImpl()\r
-{\r
-    int rc=pthread_cond_init(&cond, NULL);\r
-    if (rc) {\r
-#ifdef HAVE_STRERROR_R\r
-        char buf[256];\r
-        strerror_r(rc,buf,sizeof(buf));\r
-        buf[255]=0;\r
-        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,buf);\r
-#else\r
-        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,strerror(rc));\r
-#endif\r
-        throw ThreadingException("Condition variable creation failed.");\r
-    }\r
-}\r
-\r
-RWLockImpl::RWLockImpl()\r
-{\r
-#ifdef HAVE_PTHREAD_RWLOCK_INIT\r
-    int rc=pthread_rwlock_init(&lock, NULL);\r
-#else\r
-    int rc=rwlock_init(&lock, USYNC_THREAD, NULL);\r
-#endif\r
-    if (rc) {\r
-#ifdef HAVE_STRERROR_R\r
-        char buf[256];\r
-        strerror_r(rc,buf,sizeof(buf));\r
-        buf[255]=0;\r
-        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,buf);\r
-#else\r
-        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,strerror(rc));\r
-#endif\r
-        throw ThreadingException("Shared lock creation failed.");\r
-    }\r
-}\r
-\r
-ThreadKeyImpl::ThreadKeyImpl(void (*destroy_fcn)(void*))\r
-{\r
-    int rc=pthread_key_create(&key, destroy_fcn);\r
-    if (rc) {\r
-#ifdef HAVE_STRERROR_R\r
-        char buf[256];\r
-        strerror_r(rc,buf,sizeof(buf));\r
-        buf[255]=0;\r
-        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,buf);\r
-#else\r
-        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,strerror(rc));\r
-#endif\r
-        throw ThreadingException("Thread key creation failed.");\r
-    }\r
-}\r
-\r
-Thread* Thread::create(void* (*start_routine)(void*), void* arg)\r
-{\r
-    return new ThreadImpl(start_routine, arg);\r
-}\r
-\r
-void Thread::exit(void* return_val)\r
-{\r
-    pthread_exit(return_val);\r
-}\r
-    \r
-void Thread::mask_all_signals(void)\r
-{\r
-    sigset_t sigmask;\r
-    sigfillset(&sigmask);\r
-    Thread::mask_signals(SIG_BLOCK, &sigmask, NULL);\r
-}\r
-\r
-int Thread::mask_signals(int how, const sigset_t *newmask, sigset_t *oldmask)\r
-{\r
-    return pthread_sigmask(how,newmask,oldmask);\r
-}\r
-\r
-Mutex * Mutex::create()\r
-{\r
-    return new MutexImpl();\r
-}\r
-\r
-CondWait * CondWait::create()\r
-{\r
-    return new CondWaitImpl();\r
-}\r
-\r
-RWLock * RWLock::create()\r
-{\r
-    return new RWLockImpl();\r
-}\r
-\r
-ThreadKey* ThreadKey::create (void (*destroy_fcn)(void*))\r
-{\r
-    return new ThreadKeyImpl(destroy_fcn);\r
-}\r
+/*
+ *  Copyright 2001-2005 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * PThreads.cpp
+ * 
+ * Thread and locking wrappers for POSIX platforms
+ */
+
+#include "internal.h"
+#include "util/Threads.h"
+
+#include <ctime>
+#include <signal.h>
+#include <log4cpp/Category.hh>
+
+#ifdef HAVE_PTHREAD
+# include <pthread.h>
+# ifndef HAVE_PTHREAD_RWLOCK_INIT
+#  include <synch.h>
+# endif
+#else
+# error "This implementation is for POSIX platforms."
+#endif
+
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+
+namespace xmltooling {
+
+    class XMLTOOL_DLLLOCAL ThreadImpl : public Thread {
+        pthread_t thread_id;
+    public:
+        ThreadImpl(void* (*start_routine)(void*), void* arg);
+        virtual ~ThreadImpl() {}
+    
+        int detach() {
+            return pthread_detach(thread_id);
+        }
+        
+        int join(void** thread_return) {
+            return pthread_join(thread_id, thread_return);
+        }
+        
+        int kill(int signo) {
+            return pthread_kill(thread_id, signo);
+        }
+    };
+    
+    class XMLTOOL_DLLLOCAL MutexImpl : public Mutex {
+        pthread_mutex_t mutex;
+        friend class XMLTOOL_DLLLOCAL CondWaitImpl;
+    public:
+        MutexImpl();
+        virtual ~MutexImpl() {
+            pthread_mutex_destroy(&mutex);
+        }
+    
+        int lock() {
+            return pthread_mutex_lock(&mutex);
+        }
+        
+        int unlock() {
+            return pthread_mutex_unlock(&mutex);
+        }
+    };
+    
+    class XMLTOOL_DLLLOCAL CondWaitImpl : public CondWait {
+        pthread_cond_t cond;
+    public:
+        CondWaitImpl();
+        virtual ~CondWaitImpl() {
+            pthread_cond_destroy(&cond);
+        }
+    
+        int wait(Mutex* mutex) {
+            return wait(static_cast<MutexImpl*>(mutex));
+        }
+        
+        int wait(MutexImpl* mutex) {
+            return pthread_cond_wait(&cond, &(mutex->mutex));
+        }
+        
+        int timedwait(Mutex* mutex, int delay_seconds) {
+            return timedwait(static_cast<MutexImpl*>(mutex), delay_seconds);
+        }
+        
+        int timedwait(MutexImpl* mutex, int delay_seconds) {
+            struct timespec ts;
+            memset(&ts, 0, sizeof(ts));
+            ts.tv_sec = time(NULL) + delay_seconds;
+            return pthread_cond_timedwait(&cond, &(mutex->mutex), &ts);
+        }
+        
+        int signal() {
+            return pthread_cond_signal(&cond);
+        }
+        
+        int broadcast() {
+            return pthread_cond_broadcast(&cond);
+        }
+    };
+    
+    class XMLTOOL_DLLLOCAL RWLockImpl : public RWLock {
+#ifdef HAVE_PTHREAD_RWLOCK_INIT
+        pthread_rwlock_t lock;
+    public:
+        RWLockImpl();
+        virtual ~RWLockImpl() {
+            pthread_rwlock_destroy(&lock);
+        }
+    
+        int rdlock() {
+            return pthread_rwlock_rdlock(&lock);
+        }
+        
+        int wrlock() {
+            return pthread_rwlock_wrlock(&lock);
+        }
+        
+        int unlock() {
+            return pthread_rwlock_unlock(&lock);
+        }
+#else
+        rwlock_t lock;
+    public:
+        RWLockImpl();
+        virtual ~RWLockImpl() {
+            rwlock_destroy (&lock);
+        }
+    
+        int rdlock() {
+            return rw_rdlock(&lock);
+        }
+        
+        int wrlock() {
+            return rw_wrlock(&lock);
+        }
+        
+        int unlock() {
+            return rw_unlock(&lock);
+        }
+#endif
+    };
+    
+    class XMLTOOL_DLLLOCAL ThreadKeyImpl : public ThreadKey {
+        pthread_key_t key;
+    public:
+        ThreadKeyImpl(void (*destroy_fcn)(void*));
+        virtual ~ThreadKeyImpl() {
+            pthread_key_delete(key);
+        }
+    
+        int setData(void* data) {
+            return pthread_setspecific(key,data);
+        }
+        
+        void* getData() const {
+            return pthread_getspecific(key);
+        }
+    };
+
+};
+
+ThreadImpl::ThreadImpl(void* (*start_routine)(void*), void* arg)
+{
+    int rc=pthread_create(&thread_id, NULL, start_routine, arg);
+    if (rc) {
+#ifdef HAVE_STRERROR_R
+        char buf[256];
+        strerror_r(rc,buf,sizeof(buf));
+        buf[255]=0;
+        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,buf);
+#else
+        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_create error (%d): %s",rc,strerror(rc));
+#endif
+        throw ThreadingException("Thread creation failed.");
+    }
+}
+
+MutexImpl::MutexImpl()
+{
+    int rc=pthread_mutex_init(&mutex, NULL);
+    if (rc) {
+#ifdef HAVE_STRERROR_R
+        char buf[256];
+        strerror_r(rc,buf,sizeof(buf));
+        buf[255]=0;
+        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,buf);
+#else
+        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_mutex_init error (%d): %s",rc,strerror(rc));
+#endif
+        throw ThreadingException("Mutex creation failed.");
+    }
+}
+
+CondWaitImpl::CondWaitImpl()
+{
+    int rc=pthread_cond_init(&cond, NULL);
+    if (rc) {
+#ifdef HAVE_STRERROR_R
+        char buf[256];
+        strerror_r(rc,buf,sizeof(buf));
+        buf[255]=0;
+        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,buf);
+#else
+        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_cond_init error (%d): %s",rc,strerror(rc));
+#endif
+        throw ThreadingException("Condition variable creation failed.");
+    }
+}
+
+RWLockImpl::RWLockImpl()
+{
+#ifdef HAVE_PTHREAD_RWLOCK_INIT
+    int rc=pthread_rwlock_init(&lock, NULL);
+#else
+    int rc=rwlock_init(&lock, USYNC_THREAD, NULL);
+#endif
+    if (rc) {
+#ifdef HAVE_STRERROR_R
+        char buf[256];
+        strerror_r(rc,buf,sizeof(buf));
+        buf[255]=0;
+        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,buf);
+#else
+        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_rwlock_init error (%d): %s",rc,strerror(rc));
+#endif
+        throw ThreadingException("Shared lock creation failed.");
+    }
+}
+
+ThreadKeyImpl::ThreadKeyImpl(void (*destroy_fcn)(void*))
+{
+    int rc=pthread_key_create(&key, destroy_fcn);
+    if (rc) {
+#ifdef HAVE_STRERROR_R
+        char buf[256];
+        strerror_r(rc,buf,sizeof(buf));
+        buf[255]=0;
+        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,buf);
+#else
+        Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("pthread_key_create error (%d): %s",rc,strerror(rc));
+#endif
+        throw ThreadingException("Thread key creation failed.");
+    }
+}
+
+Thread* Thread::create(void* (*start_routine)(void*), void* arg)
+{
+    return new ThreadImpl(start_routine, arg);
+}
+
+void Thread::exit(void* return_val)
+{
+    pthread_exit(return_val);
+}
+    
+void Thread::mask_all_signals(void)
+{
+    sigset_t sigmask;
+    sigfillset(&sigmask);
+    Thread::mask_signals(SIG_BLOCK, &sigmask, NULL);
+}
+
+int Thread::mask_signals(int how, const sigset_t *newmask, sigset_t *oldmask)
+{
+    return pthread_sigmask(how,newmask,oldmask);
+}
+
+Mutex * Mutex::create()
+{
+    return new MutexImpl();
+}
+
+CondWait * CondWait::create()
+{
+    return new CondWaitImpl();
+}
+
+RWLock * RWLock::create()
+{
+    return new RWLockImpl();
+}
+
+ThreadKey* ThreadKey::create (void (*destroy_fcn)(void*))
+{
+    return new ThreadKeyImpl(destroy_fcn);
+}