maint: update copyright
[gnulib.git] / lib / glthread / thread.h
index bd8575f..6437071 100644 (file)
@@ -1,5 +1,5 @@
 /* Creating and controlling threads.
-   Copyright (C) 2005-2008 Free Software Foundation, Inc.
+   Copyright (C) 2005-2014 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -12,8 +12,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
 
 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
    Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
        current = gl_thread_self ();
        extern gl_thread_t gl_thread_self (void);
 
+   Getting a reference to the current thread as a pointer, for debugging:
+       ptr = gl_thread_self_pointer ();
+       extern void * gl_thread_self_pointer (void);
+
    Terminating the current thread:
        gl_thread_exit (return_value);
-       extern void gl_thread_exit (void *return_value) __attribute__ ((noreturn));
+       extern _Noreturn void gl_thread_exit (void *return_value);
 
    Requesting custom code to be executed at fork() time(not supported on all
    platforms):
 #include <errno.h>
 #include <stdlib.h>
 
+#ifndef _GL_INLINE_HEADER_BEGIN
+ #error "Please include config.h first."
+#endif
+_GL_INLINE_HEADER_BEGIN
+#ifndef _GLTHREAD_THREAD_INLINE
+# define _GLTHREAD_THREAD_INLINE _GL_INLINE
+#endif
+
 /* ========================================================================= */
 
 #if USE_POSIX_THREADS
@@ -112,7 +123,13 @@ extern int glthread_in_use (void);
    address of a function in libpthread that we don't use.  */
 
 #  pragma weak pthread_create
+
+#  ifdef __clang__
+  /* Without this, clang complains that pthread_sigmask is never declared.  */
+#   include <signal.h>
+#  endif
 #  pragma weak pthread_sigmask
+
 #  pragma weak pthread_join
 #  ifndef pthread_self
 #   pragma weak pthread_self
@@ -137,6 +154,9 @@ extern int glthread_in_use (void);
 
 /* -------------------------- gl_thread_t datatype -------------------------- */
 
+/* This choice of gl_thread_t assumes that
+     pthread_equal (a, b)  is equivalent to  ((a) == (b)).
+   This is the case on all platforms in use in 2008.  */
 typedef pthread_t gl_thread_t;
 # define glthread_create(THREADP, FUNC, ARG) \
     (pthread_in_use () ? pthread_create (THREADP, NULL, FUNC, ARG) : ENOSYS)
@@ -144,8 +164,20 @@ typedef pthread_t gl_thread_t;
     (pthread_in_use () ? pthread_sigmask (HOW, SET, OSET) : 0)
 # define glthread_join(THREAD, RETVALP) \
     (pthread_in_use () ? pthread_join (THREAD, RETVALP) : 0)
-# define gl_thread_self() \
-    (pthread_in_use () ? (void *) pthread_self () : NULL)
+# ifdef PTW32_VERSION
+   /* In pthreads-win32, pthread_t is a struct with a pointer field 'p' and
+      other fields.  */
+#  define gl_thread_self() \
+     (pthread_in_use () ? pthread_self () : gl_null_thread)
+#  define gl_thread_self_pointer() \
+     (pthread_in_use () ? pthread_self ().p : NULL)
+extern const gl_thread_t gl_null_thread;
+# else
+#  define gl_thread_self() \
+     (pthread_in_use () ? pthread_self () : (pthread_t) NULL)
+#  define gl_thread_self_pointer() \
+     (pthread_in_use () ? (void *) pthread_self () : NULL)
+# endif
 # define gl_thread_exit(RETVAL) \
     (pthread_in_use () ? pthread_exit (RETVAL) : 0)
 
@@ -156,6 +188,10 @@ typedef pthread_t gl_thread_t;
 #  define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
 # endif
 
+# ifdef __cplusplus
+}
+# endif
+
 #endif
 
 /* ========================================================================= */
@@ -198,11 +234,17 @@ typedef pth_t gl_thread_t;
 # define glthread_join(THREAD, RETVALP) \
     (pth_in_use () && !pth_join (THREAD, RETVALP) ? errno : 0)
 # define gl_thread_self() \
-    (pth_in_use () ? (void *) pth_self () : 0)
+    (pth_in_use () ? (void *) pth_self () : NULL)
+# define gl_thread_self_pointer() \
+    gl_thread_self ()
 # define gl_thread_exit(RETVAL) \
     (pth_in_use () ? pth_exit (RETVAL) : 0)
 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
 
+# ifdef __cplusplus
+}
+# endif
+
 #endif
 
 /* ========================================================================= */
@@ -242,20 +284,73 @@ typedef thread_t gl_thread_t;
 # define glthread_create(THREADP, FUNC, ARG) \
     (thread_in_use () ? thr_create (NULL, 0, FUNC, ARG, 0, THREADP) : 0)
 # define glthread_sigmask(HOW, SET, OSET) \
-    (pthread_in_use () ? sigprocmask (HOW, SET, OSET) : 0)
+    (thread_in_use () ? sigprocmask (HOW, SET, OSET) : 0)
 # define glthread_join(THREAD, RETVALP) \
-    (pthread_in_use () ? thr_join (THREAD, NULL, RETVALP) : 0)
+    (thread_in_use () ? thr_join (THREAD, NULL, RETVALP) : 0)
 # define gl_thread_self() \
-    (pthread_in_use () ? (void *) thr_self () : 0)
+    (thread_in_use () ? (void *) thr_self () : NULL)
+# define gl_thread_self_pointer() \
+    gl_thread_self ()
 # define gl_thread_exit(RETVAL) \
-    (pthread_in_use () ? thr_exit (RETVAL) : 0)
+    (thread_in_use () ? thr_exit (RETVAL) : 0)
 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
+
+# ifdef __cplusplus
+}
+# endif
+
 #endif
 
+/* ========================================================================= */
+
+#if USE_WINDOWS_THREADS
+
+# define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+# include <windows.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* -------------------------- gl_thread_t datatype -------------------------- */
+
+/* The gl_thread_t is a pointer to a structure in memory.
+   Why not the thread handle?  If it were the thread handle, it would be hard
+   to implement gl_thread_self() (since GetCurrentThread () returns a pseudo-
+   handle, DuplicateHandle (GetCurrentThread ()) returns a handle that must be
+   closed afterwards, and there is no function for quickly retrieving a thread
+   handle from its id).
+   Why not the thread id?  I tried it.  It did not work: Sometimes ids appeared
+   that did not belong to running threads, and glthread_join failed with ESRCH.
+ */
+typedef struct gl_thread_struct *gl_thread_t;
+# define glthread_create(THREADP, FUNC, ARG) \
+    glthread_create_func (THREADP, FUNC, ARG)
+# define glthread_sigmask(HOW, SET, OSET) \
+    /* unsupported */ 0
+# define glthread_join(THREAD, RETVALP) \
+    glthread_join_func (THREAD, RETVALP)
+# define gl_thread_self() \
+    gl_thread_self_func ()
+# define gl_thread_self_pointer() \
+    gl_thread_self ()
+# define gl_thread_exit(RETVAL) \
+    gl_thread_exit_func (RETVAL)
+# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
+extern int glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg);
+extern int glthread_join_func (gl_thread_t thread, void **retvalp);
+extern gl_thread_t gl_thread_self_func (void);
+extern int gl_thread_exit_func (void *retval);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
 
 /* ========================================================================= */
 
-#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
+#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS)
 
 /* Provide dummy implementation if threads are not supported.  */
 
@@ -263,18 +358,23 @@ typedef int gl_thread_t;
 # define glthread_create(THREADP, FUNC, ARG) ENOSYS
 # define glthread_sigmask(HOW, SET, OSET) 0
 # define glthread_join(THREAD, RETVALP) 0
-# define gl_thread_self() NULL
+# define gl_thread_self() 0
+# define gl_thread_self_pointer() \
+    ((void *) gl_thread_self ())
 # define gl_thread_exit(RETVAL) 0
 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
 
 #endif
 
-
 /* ========================================================================= */
 
 /* Macros with built-in error handling.  */
 
-static inline gl_thread_t
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_GLTHREAD_THREAD_INLINE gl_thread_t
 gl_thread_create (void *(*func) (void *arg), void *arg)
 {
   gl_thread_t thread;
@@ -307,4 +407,10 @@ gl_thread_create (void *(*func) (void *arg), void *arg)
      }                                               \
    while (0)
 
+#ifdef __cplusplus
+}
+#endif
+
+_GL_INLINE_HEADER_END
+
 #endif /* _GLTHREAD_THREAD_H */