Blame gettext-tools/libgettextpo/glthread/tls.h

Packit Bot 06c835
/* Thread-local storage in multithreaded situations.
Packit Bot 06c835
   Copyright (C) 2005, 2007-2015 Free Software Foundation, Inc.
Packit Bot 06c835
Packit Bot 06c835
   This program is free software: you can redistribute it and/or modify
Packit Bot 06c835
   it under the terms of the GNU General Public License as published by
Packit Bot 06c835
   the Free Software Foundation; either version 3 of the License, or
Packit Bot 06c835
   (at your option) any later version.
Packit Bot 06c835
Packit Bot 06c835
   This program is distributed in the hope that it will be useful,
Packit Bot 06c835
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Bot 06c835
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Bot 06c835
   GNU General Public License for more details.
Packit Bot 06c835
Packit Bot 06c835
   You should have received a copy of the GNU General Public License
Packit Bot 06c835
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Bot 06c835
Packit Bot 06c835
/* Written by Bruno Haible <bruno@clisp.org>, 2005.  */
Packit Bot 06c835
Packit Bot 06c835
/* This file contains thread-local storage primitives for use with a given
Packit Bot 06c835
   thread library.  It does not contain primitives for creating threads or
Packit Bot 06c835
   for other multithreading primitives.
Packit Bot 06c835
Packit Bot 06c835
     Type:                      gl_tls_key_t
Packit Bot 06c835
     Initialization:            gl_tls_key_init (name, destructor);
Packit Bot 06c835
     Getting per-thread value:  gl_tls_get (name)
Packit Bot 06c835
     Setting per-thread value:  gl_tls_set (name, pointer);
Packit Bot 06c835
     De-initialization:         gl_tls_key_destroy (name);
Packit Bot 06c835
   Equivalent functions with control of error handling:
Packit Bot 06c835
     Initialization:            err = glthread_tls_key_init (&name, destructor);
Packit Bot 06c835
     Setting per-thread value:  err = glthread_tls_set (&name, pointer);
Packit Bot 06c835
     De-initialization:         err = glthread_tls_key_destroy (&name);
Packit Bot 06c835
Packit Bot 06c835
   A per-thread value is of type 'void *'.
Packit Bot 06c835
Packit Bot 06c835
   A destructor is a function pointer of type 'void (*) (void *)', called
Packit Bot 06c835
   when a thread exits, and taking the last per-thread value as argument.  It
Packit Bot 06c835
   is unspecified whether the destructor function is called when the last
Packit Bot 06c835
   per-thread value is NULL.  On some platforms, the destructor function is
Packit Bot 06c835
   not called at all.
Packit Bot 06c835
*/
Packit Bot 06c835
Packit Bot 06c835
Packit Bot 06c835
#ifndef _TLS_H
Packit Bot 06c835
#define _TLS_H
Packit Bot 06c835
Packit Bot 06c835
#include <errno.h>
Packit Bot 06c835
#include <stdlib.h>
Packit Bot 06c835
Packit Bot 06c835
/* ========================================================================= */
Packit Bot 06c835
Packit Bot 06c835
#if USE_POSIX_THREADS
Packit Bot 06c835
Packit Bot 06c835
/* Use the POSIX threads library.  */
Packit Bot 06c835
Packit Bot 06c835
# include <pthread.h>
Packit Bot 06c835
Packit Bot 06c835
# if PTHREAD_IN_USE_DETECTION_HARD
Packit Bot 06c835
Packit Bot 06c835
/* The pthread_in_use() detection needs to be done at runtime.  */
Packit Bot 06c835
#  define pthread_in_use() \
Packit Bot 06c835
     glthread_in_use ()
Packit Bot 06c835
extern int glthread_in_use (void);
Packit Bot 06c835
Packit Bot 06c835
# endif
Packit Bot 06c835
Packit Bot 06c835
# if USE_POSIX_THREADS_WEAK
Packit Bot 06c835
Packit Bot 06c835
/* Use weak references to the POSIX threads library.  */
Packit Bot 06c835
Packit Bot 06c835
#  pragma weak pthread_key_create
Packit Bot 06c835
#  pragma weak pthread_getspecific
Packit Bot 06c835
#  pragma weak pthread_setspecific
Packit Bot 06c835
#  pragma weak pthread_key_delete
Packit Bot 06c835
#  ifndef pthread_self
Packit Bot 06c835
#   pragma weak pthread_self
Packit Bot 06c835
#  endif
Packit Bot 06c835
Packit Bot 06c835
#  if !PTHREAD_IN_USE_DETECTION_HARD
Packit Bot 06c835
#   pragma weak pthread_cancel
Packit Bot 06c835
#   define pthread_in_use() (pthread_cancel != NULL)
Packit Bot 06c835
#  endif
Packit Bot 06c835
Packit Bot 06c835
# else
Packit Bot 06c835
Packit Bot 06c835
#  if !PTHREAD_IN_USE_DETECTION_HARD
Packit Bot 06c835
#   define pthread_in_use() 1
Packit Bot 06c835
#  endif
Packit Bot 06c835
Packit Bot 06c835
# endif
Packit Bot 06c835
Packit Bot 06c835
/* ------------------------- gl_tls_key_t datatype ------------------------- */
Packit Bot 06c835
Packit Bot 06c835
typedef union
Packit Bot 06c835
        {
Packit Bot 06c835
          void *singlethread_value;
Packit Bot 06c835
          pthread_key_t key;
Packit Bot 06c835
        }
Packit Bot 06c835
        gl_tls_key_t;
Packit Bot 06c835
# define glthread_tls_key_init(KEY, DESTRUCTOR) \
Packit Bot 06c835
    (pthread_in_use ()                              \
Packit Bot 06c835
     ? pthread_key_create (&(KEY)->key, DESTRUCTOR) \
Packit Bot 06c835
     : ((KEY)->singlethread_value = NULL, 0))
Packit Bot 06c835
# define gl_tls_get(NAME) \
Packit Bot 06c835
    (pthread_in_use ()                  \
Packit Bot 06c835
     ? pthread_getspecific ((NAME).key) \
Packit Bot 06c835
     : (NAME).singlethread_value)
Packit Bot 06c835
# define glthread_tls_set(KEY, POINTER) \
Packit Bot 06c835
    (pthread_in_use ()                             \
Packit Bot 06c835
     ? pthread_setspecific ((KEY)->key, (POINTER)) \
Packit Bot 06c835
     : ((KEY)->singlethread_value = (POINTER), 0))
Packit Bot 06c835
# define glthread_tls_key_destroy(KEY) \
Packit Bot 06c835
    (pthread_in_use () ? pthread_key_delete ((KEY)->key) : 0)
Packit Bot 06c835
Packit Bot 06c835
#endif
Packit Bot 06c835
Packit Bot 06c835
/* ========================================================================= */
Packit Bot 06c835
Packit Bot 06c835
#if USE_PTH_THREADS
Packit Bot 06c835
Packit Bot 06c835
/* Use the GNU Pth threads library.  */
Packit Bot 06c835
Packit Bot 06c835
# include <pth.h>
Packit Bot 06c835
Packit Bot 06c835
# if USE_PTH_THREADS_WEAK
Packit Bot 06c835
Packit Bot 06c835
/* Use weak references to the GNU Pth threads library.  */
Packit Bot 06c835
Packit Bot 06c835
#  pragma weak pth_key_create
Packit Bot 06c835
#  pragma weak pth_key_getdata
Packit Bot 06c835
#  pragma weak pth_key_setdata
Packit Bot 06c835
#  pragma weak pth_key_delete
Packit Bot 06c835
Packit Bot 06c835
#  pragma weak pth_cancel
Packit Bot 06c835
#  define pth_in_use() (pth_cancel != NULL)
Packit Bot 06c835
Packit Bot 06c835
# else
Packit Bot 06c835
Packit Bot 06c835
#  define pth_in_use() 1
Packit Bot 06c835
Packit Bot 06c835
# endif
Packit Bot 06c835
Packit Bot 06c835
/* ------------------------- gl_tls_key_t datatype ------------------------- */
Packit Bot 06c835
Packit Bot 06c835
typedef union
Packit Bot 06c835
        {
Packit Bot 06c835
          void *singlethread_value;
Packit Bot 06c835
          pth_key_t key;
Packit Bot 06c835
        }
Packit Bot 06c835
        gl_tls_key_t;
Packit Bot 06c835
# define glthread_tls_key_init(KEY, DESTRUCTOR) \
Packit Bot 06c835
    (pth_in_use ()                                             \
Packit Bot 06c835
     ? (!pth_key_create (&(KEY)->key, DESTRUCTOR) ? errno : 0) \
Packit Bot 06c835
     : ((KEY)->singlethread_value = NULL, 0))
Packit Bot 06c835
# define gl_tls_get(NAME) \
Packit Bot 06c835
    (pth_in_use ()                  \
Packit Bot 06c835
     ? pth_key_getdata ((NAME).key) \
Packit Bot 06c835
     : (NAME).singlethread_value)
Packit Bot 06c835
# define glthread_tls_set(KEY, POINTER) \
Packit Bot 06c835
    (pth_in_use ()                                            \
Packit Bot 06c835
     ? (!pth_key_setdata ((KEY)->key, (POINTER)) ? errno : 0) \
Packit Bot 06c835
     : ((KEY)->singlethread_value = (POINTER), 0))
Packit Bot 06c835
# define glthread_tls_key_destroy(KEY) \
Packit Bot 06c835
    (pth_in_use ()                                \
Packit Bot 06c835
     ? (!pth_key_delete ((KEY)->key) ? errno : 0) \
Packit Bot 06c835
     : 0)
Packit Bot 06c835
Packit Bot 06c835
#endif
Packit Bot 06c835
Packit Bot 06c835
/* ========================================================================= */
Packit Bot 06c835
Packit Bot 06c835
#if USE_SOLARIS_THREADS
Packit Bot 06c835
Packit Bot 06c835
/* Use the old Solaris threads library.  */
Packit Bot 06c835
Packit Bot 06c835
# include <thread.h>
Packit Bot 06c835
Packit Bot 06c835
# if USE_SOLARIS_THREADS_WEAK
Packit Bot 06c835
Packit Bot 06c835
/* Use weak references to the old Solaris threads library.  */
Packit Bot 06c835
Packit Bot 06c835
#  pragma weak thr_keycreate
Packit Bot 06c835
#  pragma weak thr_getspecific
Packit Bot 06c835
#  pragma weak thr_setspecific
Packit Bot 06c835
Packit Bot 06c835
#  pragma weak thr_suspend
Packit Bot 06c835
#  define thread_in_use() (thr_suspend != NULL)
Packit Bot 06c835
Packit Bot 06c835
# else
Packit Bot 06c835
Packit Bot 06c835
#  define thread_in_use() 1
Packit Bot 06c835
Packit Bot 06c835
# endif
Packit Bot 06c835
Packit Bot 06c835
/* ------------------------- gl_tls_key_t datatype ------------------------- */
Packit Bot 06c835
Packit Bot 06c835
typedef union
Packit Bot 06c835
        {
Packit Bot 06c835
          void *singlethread_value;
Packit Bot 06c835
          thread_key_t key;
Packit Bot 06c835
        }
Packit Bot 06c835
        gl_tls_key_t;
Packit Bot 06c835
# define glthread_tls_key_init(KEY, DESTRUCTOR) \
Packit Bot 06c835
    (thread_in_use ()                          \
Packit Bot 06c835
     ? thr_keycreate (&(KEY)->key, DESTRUCTOR) \
Packit Bot 06c835
     : ((KEY)->singlethread_value = NULL, 0))
Packit Bot 06c835
# define gl_tls_get(NAME) \
Packit Bot 06c835
    (thread_in_use ()                \
Packit Bot 06c835
     ? glthread_tls_get_multithreaded ((NAME).key) \
Packit Bot 06c835
     : (NAME).singlethread_value)
Packit Bot 06c835
extern void *glthread_tls_get_multithreaded (thread_key_t key);
Packit Bot 06c835
# define glthread_tls_set(KEY, POINTER) \
Packit Bot 06c835
    (thread_in_use ()                              \
Packit Bot 06c835
     ? thr_setspecific ((KEY)->key, (POINTER))     \
Packit Bot 06c835
     : ((KEY)->singlethread_value = (POINTER), 0))
Packit Bot 06c835
# define glthread_tls_key_destroy(KEY) \
Packit Bot 06c835
    /* Unsupported.  */ \
Packit Bot 06c835
    0
Packit Bot 06c835
Packit Bot 06c835
#endif
Packit Bot 06c835
Packit Bot 06c835
/* ========================================================================= */
Packit Bot 06c835
Packit Bot 06c835
#if USE_WINDOWS_THREADS
Packit Bot 06c835
Packit Bot 06c835
# define WIN32_LEAN_AND_MEAN  /* avoid including junk */
Packit Bot 06c835
# include <windows.h>
Packit Bot 06c835
Packit Bot 06c835
/* ------------------------- gl_tls_key_t datatype ------------------------- */
Packit Bot 06c835
Packit Bot 06c835
typedef DWORD gl_tls_key_t;
Packit Bot 06c835
# define glthread_tls_key_init(KEY, DESTRUCTOR) \
Packit Bot 06c835
    /* The destructor is unsupported.  */    \
Packit Bot 06c835
    ((*(KEY) = TlsAlloc ()) == (DWORD)-1 ? EAGAIN : ((void) (DESTRUCTOR), 0))
Packit Bot 06c835
# define gl_tls_get(NAME) \
Packit Bot 06c835
    TlsGetValue (NAME)
Packit Bot 06c835
# define glthread_tls_set(KEY, POINTER) \
Packit Bot 06c835
    (!TlsSetValue (*(KEY), POINTER) ? EINVAL : 0)
Packit Bot 06c835
# define glthread_tls_key_destroy(KEY) \
Packit Bot 06c835
    (!TlsFree (*(KEY)) ? EINVAL : 0)
Packit Bot 06c835
Packit Bot 06c835
#endif
Packit Bot 06c835
Packit Bot 06c835
/* ========================================================================= */
Packit Bot 06c835
Packit Bot 06c835
#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS)
Packit Bot 06c835
Packit Bot 06c835
/* Provide dummy implementation if threads are not supported.  */
Packit Bot 06c835
Packit Bot 06c835
/* ------------------------- gl_tls_key_t datatype ------------------------- */
Packit Bot 06c835
Packit Bot 06c835
typedef struct
Packit Bot 06c835
        {
Packit Bot 06c835
          void *singlethread_value;
Packit Bot 06c835
        }
Packit Bot 06c835
        gl_tls_key_t;
Packit Bot 06c835
# define glthread_tls_key_init(KEY, DESTRUCTOR) \
Packit Bot 06c835
    ((KEY)->singlethread_value = NULL, \
Packit Bot 06c835
     (void) (DESTRUCTOR),              \
Packit Bot 06c835
     0)
Packit Bot 06c835
# define gl_tls_get(NAME) \
Packit Bot 06c835
    (NAME).singlethread_value
Packit Bot 06c835
# define glthread_tls_set(KEY, POINTER) \
Packit Bot 06c835
    ((KEY)->singlethread_value = (POINTER), 0)
Packit Bot 06c835
# define glthread_tls_key_destroy(KEY) \
Packit Bot 06c835
    0
Packit Bot 06c835
Packit Bot 06c835
#endif
Packit Bot 06c835
Packit Bot 06c835
/* ========================================================================= */
Packit Bot 06c835
Packit Bot 06c835
/* Macros with built-in error handling.  */
Packit Bot 06c835
Packit Bot 06c835
/* ------------------------- gl_tls_key_t datatype ------------------------- */
Packit Bot 06c835
Packit Bot 06c835
#define gl_tls_key_init(NAME, DESTRUCTOR) \
Packit Bot 06c835
   do                                                 \
Packit Bot 06c835
     {                                                \
Packit Bot 06c835
       if (glthread_tls_key_init (&NAME, DESTRUCTOR)) \
Packit Bot 06c835
         abort ();                                    \
Packit Bot 06c835
     }                                                \
Packit Bot 06c835
   while (0)
Packit Bot 06c835
#define gl_tls_set(NAME, POINTER) \
Packit Bot 06c835
   do                                         \
Packit Bot 06c835
     {                                        \
Packit Bot 06c835
       if (glthread_tls_set (&NAME, POINTER)) \
Packit Bot 06c835
         abort ();                            \
Packit Bot 06c835
     }                                        \
Packit Bot 06c835
   while (0)
Packit Bot 06c835
#define gl_tls_key_destroy(NAME) \
Packit Bot 06c835
   do                                        \
Packit Bot 06c835
     {                                       \
Packit Bot 06c835
       if (glthread_tls_key_destroy (&NAME)) \
Packit Bot 06c835
         abort ();                           \
Packit Bot 06c835
     }                                       \
Packit Bot 06c835
   while (0)
Packit Bot 06c835
Packit Bot 06c835
/* ========================================================================= */
Packit Bot 06c835
Packit Bot 06c835
#endif /* _TLS_H */