Unix thread support
authorScott Cantor <cantor.2@osu.edu>
Sun, 2 Jul 2006 02:55:41 +0000 (02:55 +0000)
committerScott Cantor <cantor.2@osu.edu>
Sun, 2 Jul 2006 02:55:41 +0000 (02:55 +0000)
acx_pthread.m4
configure.ac
xmltooling/Makefile.am
xmltooling/util/PThreads.cpp
xmltooling/util/Threads.h

index ba6c09c..1f2a56e 100644 (file)
-dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])\r
-dnl\r
-dnl This macro figures out how to build C programs using POSIX\r
-dnl threads.  It sets the PTHREAD_LIBS output variable to the threads\r
-dnl library and linker flags, and the PTHREAD_CFLAGS output variable\r
-dnl to any special C compiler flags that are needed.  (The user can also\r
-dnl force certain compiler flags/libs to be tested by setting these\r
-dnl environment variables.)\r
-dnl\r
-dnl Also sets PTHREAD_CC to any special C compiler that is needed for\r
-dnl multi-threaded programs (defaults to the value of CC otherwise).\r
-dnl (This is necessary on AIX to use the special cc_r compiler alias.)\r
-dnl\r
-dnl If you are only building threads programs, you may wish to\r
-dnl use these variables in your default LIBS, CFLAGS, and CC:\r
-dnl\r
-dnl        LIBS="$PTHREAD_LIBS $LIBS"\r
-dnl        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"\r
-dnl        CC="$PTHREAD_CC"\r
-dnl\r
-dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute\r
-dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE\r
-dnl to that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).\r
-dnl\r
-dnl ACTION-IF-FOUND is a list of shell commands to run if a threads\r
-dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands\r
-dnl to run it if it is not found.  If ACTION-IF-FOUND is not specified,\r
-dnl the default action will define HAVE_PTHREAD.\r
-dnl\r
-dnl Please let the authors know if this macro fails on any platform,\r
-dnl or if you have any other suggestions or comments.  This macro was\r
-dnl based on work by SGJ on autoconf scripts for FFTW (www.fftw.org)\r
-dnl (with help from M. Frigo), as well as ac_pthread and hb_pthread\r
-dnl macros posted by AFC to the autoconf macro repository.  We are also\r
-dnl grateful for the helpful feedback of numerous users.\r
-dnl\r
-dnl @author Steven G. Johnson <stevenj@alum.mit.edu> and Alejandro Forero Cuervo <bachue@bachue.com>\r
-\r
-AC_DEFUN([ACX_PTHREAD], [\r
-AC_REQUIRE([AC_CANONICAL_HOST])\r
-AC_LANG_SAVE\r
-AC_LANG_C\r
-acx_pthread_ok=no\r
-\r
-# We used to check for pthread.h first, but this fails if pthread.h\r
-# requires special compiler flags (e.g. on True64 or Sequent).\r
-# It gets checked for in the link test anyway.\r
-\r
-# First of all, check if the user has set any of the PTHREAD_LIBS,\r
-# etcetera environment variables, and if threads linking works using\r
-# them:\r
-if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then\r
-        save_CFLAGS="$CFLAGS"\r
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"\r
-        save_LIBS="$LIBS"\r
-        LIBS="$PTHREAD_LIBS $LIBS"\r
-        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])\r
-        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)\r
-        AC_MSG_RESULT($acx_pthread_ok)\r
-        if test x"$acx_pthread_ok" = xno; then\r
-                PTHREAD_LIBS=""\r
-                PTHREAD_CFLAGS=""\r
-        fi\r
-        LIBS="$save_LIBS"\r
-        CFLAGS="$save_CFLAGS"\r
-fi\r
-\r
-# We must check for the threads library under a number of different\r
-# names; the ordering is very important because some systems\r
-# (e.g. DEC) have both -lpthread and -lpthreads, where one of the\r
-# libraries is broken (non-POSIX).\r
-\r
-# Create a list of thread flags to try.  Items starting with a "-" are\r
-# C compiler flags, and other items are library names, except for "none"\r
-# which indicates that we try without any flags at all.\r
-\r
-acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt"\r
-\r
-# The ordering *is* (sometimes) important.  Some notes on the\r
-# individual items follow:\r
-\r
-# pthreads: AIX (must check this before -lpthread)\r
-# none: in case threads are in libc; should be tried before -Kthread and\r
-#       other compiler flags to prevent continual compiler warnings\r
-# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)\r
-# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)\r
-# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)\r
-# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)\r
-# -pthreads: Solaris/gcc\r
-# -mthreads: Mingw32/gcc, Lynx/gcc\r
-# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it\r
-#      doesn't hurt to check since this sometimes defines pthreads too;\r
-#      also defines -D_REENTRANT)\r
-# pthread: Linux, etcetera\r
-# --thread-safe: KAI C++\r
-\r
-case "${host_cpu}-${host_os}" in\r
-        *solaris*)\r
-\r
-        # On Solaris (at least, for some versions), libc contains stubbed\r
-        # (non-functional) versions of the pthreads routines, so link-based\r
-        # tests will erroneously succeed.  (We need to link with -pthread or\r
-        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather\r
-        # a function called by this macro, so we could check for that, but\r
-        # who knows whether they'll stub that too in a future libc.)  So,\r
-        # we'll just look for -pthreads and -lpthread first:\r
-\r
-        acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"\r
-        ;;\r
-esac\r
-\r
-if test x"$acx_pthread_ok" = xno; then\r
-for flag in $acx_pthread_flags; do\r
-\r
-        case $flag in\r
-                none)\r
-                AC_MSG_CHECKING([whether pthreads work without any flags])\r
-                ;;\r
-\r
-                -*)\r
-                AC_MSG_CHECKING([whether pthreads work with $flag])\r
-                PTHREAD_CFLAGS="$flag"\r
-                ;;\r
-\r
-                *)\r
-                AC_MSG_CHECKING([for the pthreads library -l$flag])\r
-                PTHREAD_LIBS="-l$flag"\r
-                ;;\r
-        esac\r
-\r
-        save_LIBS="$LIBS"\r
-        save_CFLAGS="$CFLAGS"\r
-        LIBS="$PTHREAD_LIBS $LIBS"\r
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"\r
-\r
-        # Check for various functions.  We must include pthread.h,\r
-        # since some functions may be macros.  (On the Sequent, we\r
-        # need a special flag -Kthread to make this header compile.)\r
-        # We check for pthread_join because it is in -lpthread on IRIX\r
-        # while pthread_create is in libc.  We check for pthread_attr_init\r
-        # due to DEC craziness with -lpthreads.  We check for\r
-        # pthread_cleanup_push because it is one of the few pthread\r
-        # functions on Solaris that doesn't have a non-functional libc stub.\r
-        # We try pthread_create on general principles.\r
-        AC_TRY_LINK([#include <pthread.h>],\r
-                    [pthread_t th; pthread_join(th, 0);\r
-                     pthread_attr_init(0); pthread_cleanup_push(0, 0);\r
-                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],\r
-                    [acx_pthread_ok=yes])\r
-\r
-        LIBS="$save_LIBS"\r
-        CFLAGS="$save_CFLAGS"\r
-\r
-        AC_MSG_RESULT($acx_pthread_ok)\r
-        if test "x$acx_pthread_ok" = xyes; then\r
-                break;\r
-        fi\r
-\r
-        PTHREAD_LIBS=""\r
-        PTHREAD_CFLAGS=""\r
-done\r
-fi\r
-\r
-# Various other checks:\r
-if test "x$acx_pthread_ok" = xyes; then\r
-        save_LIBS="$LIBS"\r
-        LIBS="$PTHREAD_LIBS $LIBS"\r
-        save_CFLAGS="$CFLAGS"\r
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"\r
-\r
-        # Detect AIX lossage: threads are created detached by default\r
-        # and the JOINABLE attribute has a nonstandard name (UNDETACHED).\r
-        AC_MSG_CHECKING([for joinable pthread attribute])\r
-        AC_TRY_LINK([#include <pthread.h>],\r
-                    [int attr=PTHREAD_CREATE_JOINABLE;],\r
-                    ok=PTHREAD_CREATE_JOINABLE, ok=unknown)\r
-        if test x"$ok" = xunknown; then\r
-                AC_TRY_LINK([#include <pthread.h>],\r
-                            [int attr=PTHREAD_CREATE_UNDETACHED;],\r
-                            ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)\r
-        fi\r
-        if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then\r
-                AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,\r
-                          [Define to the necessary symbol if this constant\r
-                           uses a non-standard name on your system.])\r
-        fi\r
-        AC_MSG_RESULT(${ok})\r
-        if test x"$ok" = xunknown; then\r
-                AC_MSG_WARN([we do not know how to create joinable pthreads])\r
-        fi\r
-\r
-        AC_MSG_CHECKING([if more special flags are required for pthreads])\r
-        flag=no\r
-        case "${host_cpu}-${host_os}" in\r
-                *-aix* | *-freebsd*)     flag="-D_THREAD_SAFE";;\r
-                *-osf* | *-hpux*) flag="-D_REENTRANT";;\r
-                *solaris*)\r
-                if test "$GCC" = "yes"; then\r
-                    flag="-D_REENTRANT"\r
-                else\r
-                    flag="-mt -D_REENTRANT"\r
-                fi\r
-                ;;\r
-        esac\r
-        AC_MSG_RESULT(${flag})\r
-        if test "x$flag" != xno; then\r
-                PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"\r
-        fi\r
-\r
-        LIBS="$save_LIBS"\r
-        CFLAGS="$save_CFLAGS"\r
-\r
-        # More AIX lossage: must compile with cc_r\r
-        AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})\r
-else\r
-        PTHREAD_CC="$CC"\r
-fi\r
-\r
-AC_SUBST(PTHREAD_LIBS)\r
-AC_SUBST(PTHREAD_CFLAGS)\r
-AC_SUBST(PTHREAD_CC)\r
-\r
-# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:\r
-if test x"$acx_pthread_ok" = xyes; then\r
-        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])\r
-        :\r
-else\r
-        acx_pthread_ok=no\r
-        $2\r
-fi\r
-AC_LANG_RESTORE\r
-])dnl ACX_PTHREAD\r
+dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl This macro figures out how to build C programs using POSIX
+dnl threads.  It sets the PTHREAD_LIBS output variable to the threads
+dnl library and linker flags, and the PTHREAD_CFLAGS output variable
+dnl to any special C compiler flags that are needed.  (The user can also
+dnl force certain compiler flags/libs to be tested by setting these
+dnl environment variables.)
+dnl
+dnl Also sets PTHREAD_CC to any special C compiler that is needed for
+dnl multi-threaded programs (defaults to the value of CC otherwise).
+dnl (This is necessary on AIX to use the special cc_r compiler alias.)
+dnl
+dnl If you are only building threads programs, you may wish to
+dnl use these variables in your default LIBS, CFLAGS, and CC:
+dnl
+dnl        LIBS="$PTHREAD_LIBS $LIBS"
+dnl        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+dnl        CC="$PTHREAD_CC"
+dnl
+dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
+dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE
+dnl to that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands
+dnl to run it if it is not found.  If ACTION-IF-FOUND is not specified,
+dnl the default action will define HAVE_PTHREAD.
+dnl
+dnl Please let the authors know if this macro fails on any platform,
+dnl or if you have any other suggestions or comments.  This macro was
+dnl based on work by SGJ on autoconf scripts for FFTW (www.fftw.org)
+dnl (with help from M. Frigo), as well as ac_pthread and hb_pthread
+dnl macros posted by AFC to the autoconf macro repository.  We are also
+dnl grateful for the helpful feedback of numerous users.
+dnl
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu> and Alejandro Forero Cuervo <bachue@bachue.com>
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test x"$acx_pthread_ok" = xno; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads too;
+#      also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+
+case "${host_cpu}-${host_os}" in
+        *solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed.  (We need to link with -pthread or
+        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
+        # a function called by this macro, so we could check for that, but
+        # who knows whether they'll stub that too in a future libc.)  So,
+        # we'll just look for -pthreads and -lpthread first:
+
+        acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+        ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+        case $flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $flag])
+                PTHREAD_CFLAGS="$flag"
+                ;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$flag])
+                PTHREAD_LIBS="-l$flag"
+                ;;
+        esac
+
+        save_LIBS="$LIBS"
+        save_CFLAGS="$CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+        AC_TRY_LINK([#include <pthread.h>],
+                    [pthread_t th; pthread_join(th, 0);
+                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
+                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+                    [acx_pthread_ok=yes])
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test "x$acx_pthread_ok" = xyes; then
+                break;
+        fi
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Detect AIX lossage: threads are created detached by default
+        # and the JOINABLE attribute has a nonstandard name (UNDETACHED).
+        AC_MSG_CHECKING([for joinable pthread attribute])
+        AC_TRY_LINK([#include <pthread.h>],
+                    [int attr=PTHREAD_CREATE_JOINABLE;],
+                    ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
+        if test x"$ok" = xunknown; then
+                AC_TRY_LINK([#include <pthread.h>],
+                            [int attr=PTHREAD_CREATE_UNDETACHED;],
+                            ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
+        fi
+        if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
+                AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
+                          [Define to the necessary symbol if this constant
+                           uses a non-standard name on your system.])
+        fi
+        AC_MSG_RESULT(${ok})
+        if test x"$ok" = xunknown; then
+                AC_MSG_WARN([we do not know how to create joinable pthreads])
+        fi
+
+        AC_MSG_CHECKING([if more special flags are required for pthreads])
+        flag=no
+        case "${host_cpu}-${host_os}" in
+                *-aix* | *-freebsd*)     flag="-D_THREAD_SAFE";;
+                *-osf* | *-hpux*) flag="-D_REENTRANT";;
+                *solaris*)
+                if test "$GCC" = "yes"; then
+                    flag="-D_REENTRANT"
+                else
+                    flag="-mt -D_REENTRANT"
+                fi
+                ;;
+        esac
+        AC_MSG_RESULT(${flag})
+        if test "x$flag" != xno; then
+                PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+        fi
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        # More AIX lossage: must compile with cc_r
+        AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+        PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        :
+else
+        acx_pthread_ok=no
+        $2
+fi
+
+saveCFLAGS="$CFLAGS"
+saveLIBS="$LIBS"
+CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+LIBS="$LIBS $PTHREAD_LIBS"
+AC_CHECK_FUNCS([pthread_rwlock_init])
+LIBS="$saveLIBS"
+CFLAGS="$saveCFLAGS"
+
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
index cf3b09c..1f269d9 100644 (file)
@@ -5,6 +5,7 @@ AM_CONFIG_HEADER(xmltooling/config_pub.h)
 AM_INIT_AUTOMAKE([xmltooling], [1.0])
 
 sinclude(doxygen.m4)
+sinclude(acx_pthread.m4)
 
 # Docygen features
 DX_HTML_FEATURE(ON)
index 9681b81..a907fb2 100644 (file)
@@ -89,7 +89,7 @@ xmlsec_sources =
 endif
 
 if BUILD_PTHREAD
-thread_sources = PThread.cpp
+thread_sources = util/PThreads.cpp
 else
 thread_sources =
 endif
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);
+}
index ef9231b..2d6c5c3 100644 (file)
-/*\r
- *  Copyright 2001-2006 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
- * @file Threads.h\r
- * \r
- * Thread and locking wrappers \r
- */\r
-\r
-#ifndef _xmltooling_threads_h\r
-#define _xmltooling_threads_h\r
-\r
-#include <xmltooling/base.h>\r
-#include <xmltooling/exceptions.h>\r
-\r
-namespace xmltooling\r
-{\r
-    DECL_XMLTOOLING_EXCEPTION(ThreadingException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions during threading/locking operations);\r
-    \r
-    /**\r
-     * A class for manual thread creation and synchronization.\r
-     */\r
-    class XMLTOOL_API Thread\r
-    {\r
-        MAKE_NONCOPYABLE(Thread);\r
-    public:\r
-        Thread() {}\r
-        virtual ~Thread() {}\r
-\r
-        /**\r
-         * Disassociate from the thread.\r
-         * \r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int detach()=0;\r
-        \r
-        /**\r
-         * Join with the thread and wait for its completion.\r
-         * \r
-         * @param thread_return holds the return value of the thread routine\r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int join(void** thread_return)=0;\r
-        \r
-        /**\r
-         * Kill the thread.\r
-         * \r
-         * @param signo the signal to send to the thread\r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int kill(int signo)=0;\r
-        \r
-        /**\r
-         * Creates a new thread object to run the supplied start routine.\r
-         * \r
-         * @param start_routine the function to execute on the thread\r
-         * @param arg           a parameter for the start routine\r
-         * @return  the created and running thread object \r
-         */\r
-        static Thread* create(void* (*start_routine)(void*), void* arg);\r
-        \r
-        /**\r
-         * Exits a thread gracefully.\r
-         * \r
-         * @param return_val    the return value for the thread\r
-         */\r
-        static void exit(void* return_val);\r
-        \r
-#ifndef WIN32\r
-        /**\r
-         * Masks all signals from a thread. \r
-         */\r
-        static void mask_all_signals(void);\r
-        \r
-        /**\r
-         * Masks specific signals from a thread.\r
-         * \r
-         * @param how\r
-         * @param newmask   the new signal mask\r
-         * @param oldmask   the old signal mask\r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        static int mask_signals(int how, const sigset_t *newmask, sigset_t *oldmask);\r
-#endif\r
-    };\r
-\r
-    /**\r
-     * A class for managing Thread Local Storage values.\r
-     */\r
-    class XMLTOOL_API ThreadKey\r
-    {\r
-        MAKE_NONCOPYABLE(ThreadKey);\r
-    public:\r
-        ThreadKey() {}\r
-        virtual ~ThreadKey() {}\r
-\r
-        /**\r
-         * Sets the value for a TLS key.\r
-         * \r
-         * @param data  the value to set\r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int setData(void* data)=0;\r
-\r
-        /**\r
-         * Returns the value for a TLS key.\r
-         * \r
-         * @return the value or NULL\r
-         */        \r
-        virtual void* getData() const=0;\r
-\r
-        /**\r
-         * Creates a new TLS key.\r
-         * \r
-         * @param destroy_fn    a functon to cleanup key values\r
-         * @return the new key\r
-         */\r
-        static ThreadKey* create(void (*destroy_fn)(void*));\r
-    };\r
-\r
-    /**\r
-     * A class for managing exclusive access to resources.\r
-     */\r
-    class XMLTOOL_API Mutex\r
-    {\r
-        MAKE_NONCOPYABLE(Mutex);\r
-    public:\r
-        Mutex() {}\r
-        virtual ~Mutex() {}\r
-\r
-        /**\r
-         * Locks the mutex for exclusive access.\r
-         * \r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int lock()=0;\r
-        \r
-        /**\r
-         * Unlocks the mutex for exclusive access.\r
-         * \r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int unlock()=0;\r
-\r
-        /**\r
-         * Creates a new mutex object.\r
-         * \r
-         * @return the new mutex\r
-         */\r
-        static Mutex* create();\r
-    };\r
-    \r
-    /**\r
-     * A class for managing shared and exclusive access to resources.\r
-     */\r
-    class XMLTOOL_API RWLock\r
-    {\r
-        MAKE_NONCOPYABLE(RWLock);\r
-    public:\r
-        RWLock() {}\r
-        virtual ~RWLock() {}\r
-\r
-        /**\r
-         * Obtains a shared lock.\r
-         * \r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int rdlock()=0;\r
-        \r
-        /**\r
-         * Obtains an exclusive lock.\r
-         * \r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int wrlock()=0;\r
-\r
-        /**\r
-         * Unlocks the lock.\r
-         * \r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int unlock()=0;\r
-\r
-        /**\r
-         * Creates a new read/write lock.\r
-         * \r
-         * @return the new lock\r
-         */\r
-        static RWLock* create();\r
-    };\r
-    \r
-    /**\r
-     * A class for establishing queues on a mutex based on a periodic condition.\r
-     */\r
-    class XMLTOOL_API CondWait\r
-    {\r
-        MAKE_NONCOPYABLE(CondWait);\r
-    public:\r
-        CondWait() {}\r
-        virtual ~CondWait() {}\r
-        \r
-        /**\r
-         * Waits for a condition variable using the supplied mutex as a queue.\r
-         * \r
-         * @param lock  mutex to queue on\r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int wait(Mutex* lock)=0;\r
-        \r
-        /**\r
-         * Waits for a condition variable using the supplied mutex as a queue,\r
-         * but only for a certain time limit.\r
-         * \r
-         * @param lock          mutex to queue on\r
-         * @param delay_seconds maximum time to wait before waking up\r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int timedwait(Mutex* lock, int delay_seconds)=0;\r
-        \r
-        /**\r
-         * Signal a single thread to wake up if a condition changes.\r
-         * \r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int signal()=0;\r
-        \r
-        /**\r
-         * Signal all threads to wake up if a condition changes.\r
-         * \r
-         * @return 0 for success, non-zero for failure\r
-         */\r
-        virtual int broadcast()=0;\r
-\r
-        /**\r
-         * Creates a new condition variable.\r
-         * \r
-         * @return the new condition variable\r
-         */\r
-        static CondWait* create();\r
-    };\r
-    \r
-    /**\r
-     * RAII wrapper for a mutex lock.\r
-     */\r
-    class XMLTOOL_API Lock {\r
-        MAKE_NONCOPYABLE(Lock);\r
-    public:\r
-        /**\r
-         * Locks and wraps the designated mutex.\r
-         * \r
-         * @param mtx mutex to lock \r
-         */\r
-        Lock(Mutex* mtx) : mutex(mtx) {\r
-            mutex->lock();\r
-        }\r
-        \r
-        /**\r
-         * Unlocks the wrapped mutex.\r
-         */\r
-        ~Lock() {\r
-            mutex->unlock();\r
-        }\r
-    \r
-    private:\r
-        Mutex* mutex;\r
-    };\r
-    \r
-    /**\r
-     * RAII wrapper for a shared lock.\r
-     */\r
-    class XMLTOOL_API ReadLock {\r
-        MAKE_NONCOPYABLE(ReadLock);\r
-    public:\r
-        /**\r
-         * Locks and wraps the designated shared lock.\r
-         * \r
-         * @param lock lock to acquire \r
-         */\r
-        ReadLock(RWLock* lock) : rwlock(lock) {\r
-            rwlock->rdlock();\r
-        }\r
-        \r
-        /**\r
-         * Unlocks the wrapped shared lock.\r
-         */\r
-        ~ReadLock() {\r
-            rwlock->unlock();\r
-        }\r
-    \r
-    private:\r
-        RWLock* rwlock;\r
-    };\r
-\r
-}\r
-\r
-#endif /* _xmltooling_threads_h */\r
+/*
+ *  Copyright 2001-2006 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.
+ */
+
+/**
+ * @file Threads.h
+ * 
+ * Thread and locking wrappers 
+ */
+
+#ifndef _xmltooling_threads_h
+#define _xmltooling_threads_h
+
+#include <xmltooling/base.h>
+#include <xmltooling/exceptions.h>
+
+namespace xmltooling
+{
+    DECL_XMLTOOLING_EXCEPTION(ThreadingException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions during threading/locking operations);
+    
+    /**
+     * A class for manual thread creation and synchronization.
+     */
+    class XMLTOOL_API Thread
+    {
+        MAKE_NONCOPYABLE(Thread);
+    public:
+        Thread() {}
+        virtual ~Thread() {}
+
+        /**
+         * Disassociate from the thread.
+         * 
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int detach()=0;
+        
+        /**
+         * Join with the thread and wait for its completion.
+         * 
+         * @param thread_return holds the return value of the thread routine
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int join(void** thread_return)=0;
+        
+        /**
+         * Kill the thread.
+         * 
+         * @param signo the signal to send to the thread
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int kill(int signo)=0;
+        
+        /**
+         * Creates a new thread object to run the supplied start routine.
+         * 
+         * @param start_routine the function to execute on the thread
+         * @param arg           a parameter for the start routine
+         * @return  the created and running thread object 
+         */
+        static Thread* create(void* (*start_routine)(void*), void* arg);
+        
+        /**
+         * Exits a thread gracefully.
+         * 
+         * @param return_val    the return value for the thread
+         */
+        static void exit(void* return_val);
+        
+#ifndef WIN32
+        /**
+         * Masks all signals from a thread. 
+         */
+        static void mask_all_signals(void);
+        
+        /**
+         * Masks specific signals from a thread.
+         * 
+         * @param how
+         * @param newmask   the new signal mask
+         * @param oldmask   the old signal mask
+         * @return 0 for success, non-zero for failure
+         */
+        static int mask_signals(int how, const sigset_t *newmask, sigset_t *oldmask);
+#endif
+    };
+
+    /**
+     * A class for managing Thread Local Storage values.
+     */
+    class XMLTOOL_API ThreadKey
+    {
+        MAKE_NONCOPYABLE(ThreadKey);
+    public:
+        ThreadKey() {}
+        virtual ~ThreadKey() {}
+
+        /**
+         * Sets the value for a TLS key.
+         * 
+         * @param data  the value to set
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int setData(void* data)=0;
+
+        /**
+         * Returns the value for a TLS key.
+         * 
+         * @return the value or NULL
+         */        
+        virtual void* getData() const=0;
+
+        /**
+         * Creates a new TLS key.
+         * 
+         * @param destroy_fn    a functon to cleanup key values
+         * @return the new key
+         */
+        static ThreadKey* create(void (*destroy_fn)(void*));
+    };
+
+    /**
+     * A class for managing exclusive access to resources.
+     */
+    class XMLTOOL_API Mutex
+    {
+        MAKE_NONCOPYABLE(Mutex);
+    public:
+        Mutex() {}
+        virtual ~Mutex() {}
+
+        /**
+         * Locks the mutex for exclusive access.
+         * 
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int lock()=0;
+        
+        /**
+         * Unlocks the mutex for exclusive access.
+         * 
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int unlock()=0;
+
+        /**
+         * Creates a new mutex object.
+         * 
+         * @return the new mutex
+         */
+        static Mutex* create();
+    };
+    
+    /**
+     * A class for managing shared and exclusive access to resources.
+     */
+    class XMLTOOL_API RWLock
+    {
+        MAKE_NONCOPYABLE(RWLock);
+    public:
+        RWLock() {}
+        virtual ~RWLock() {}
+
+        /**
+         * Obtains a shared lock.
+         * 
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int rdlock()=0;
+        
+        /**
+         * Obtains an exclusive lock.
+         * 
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int wrlock()=0;
+
+        /**
+         * Unlocks the lock.
+         * 
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int unlock()=0;
+
+        /**
+         * Creates a new read/write lock.
+         * 
+         * @return the new lock
+         */
+        static RWLock* create();
+    };
+    
+    /**
+     * A class for establishing queues on a mutex based on a periodic condition.
+     */
+    class XMLTOOL_API CondWait
+    {
+        MAKE_NONCOPYABLE(CondWait);
+    public:
+        CondWait() {}
+        virtual ~CondWait() {}
+        
+        /**
+         * Waits for a condition variable using the supplied mutex as a queue.
+         * 
+         * @param lock  mutex to queue on
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int wait(Mutex* lock)=0;
+        
+        /**
+         * Waits for a condition variable using the supplied mutex as a queue,
+         * but only for a certain time limit.
+         * 
+         * @param lock          mutex to queue on
+         * @param delay_seconds maximum time to wait before waking up
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int timedwait(Mutex* lock, int delay_seconds)=0;
+        
+        /**
+         * Signal a single thread to wake up if a condition changes.
+         * 
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int signal()=0;
+        
+        /**
+         * Signal all threads to wake up if a condition changes.
+         * 
+         * @return 0 for success, non-zero for failure
+         */
+        virtual int broadcast()=0;
+
+        /**
+         * Creates a new condition variable.
+         * 
+         * @return the new condition variable
+         */
+        static CondWait* create();
+    };
+    
+    /**
+     * RAII wrapper for a mutex lock.
+     */
+    class XMLTOOL_API Lock {
+        MAKE_NONCOPYABLE(Lock);
+    public:
+        /**
+         * Locks and wraps the designated mutex.
+         * 
+         * @param mtx mutex to lock 
+         */
+        Lock(Mutex* mtx) : mutex(mtx) {
+            mutex->lock();
+        }
+        
+        /**
+         * Unlocks the wrapped mutex.
+         */
+        ~Lock() {
+            mutex->unlock();
+        }
+    
+    private:
+        Mutex* mutex;
+    };
+    
+    /**
+     * RAII wrapper for a shared lock.
+     */
+    class XMLTOOL_API ReadLock {
+        MAKE_NONCOPYABLE(ReadLock);
+    public:
+        /**
+         * Locks and wraps the designated shared lock.
+         * 
+         * @param lock lock to acquire 
+         */
+        ReadLock(RWLock* lock) : rwlock(lock) {
+            rwlock->rdlock();
+        }
+        
+        /**
+         * Unlocks the wrapped shared lock.
+         */
+        ~ReadLock() {
+            rwlock->unlock();
+        }
+    
+    private:
+        RWLock* rwlock;
+    };
+
+}
+
+#endif /* _xmltooling_threads_h */