root/maint/gnulib/lib/glthread/tls.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


   1 /* Thread-local storage in multithreaded situations.
   2    Copyright (C) 2005, 2007-2021 Free Software Foundation, Inc.
   3 
   4    This file is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU Lesser General Public License as
   6    published by the Free Software Foundation; either version 2.1 of the
   7    License, or (at your option) any later version.
   8 
   9    This file is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU Lesser General Public License for more details.
  13 
  14    You should have received a copy of the GNU Lesser General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* Written by Bruno Haible <bruno@clisp.org>, 2005.  */
  18 
  19 /* This file contains thread-local storage primitives for use with a given
  20    thread library.  It does not contain primitives for creating threads or
  21    for other multithreading primitives.
  22 
  23      Type:                      gl_tls_key_t
  24      Initialization:            gl_tls_key_init (name, destructor);
  25      Getting per-thread value:  gl_tls_get (name)
  26      Setting per-thread value:  gl_tls_set (name, pointer);
  27      De-initialization:         gl_tls_key_destroy (name);
  28    Equivalent functions with control of error handling:
  29      Initialization:            err = glthread_tls_key_init (&name, destructor);
  30      Setting per-thread value:  err = glthread_tls_set (&name, pointer);
  31      De-initialization:         err = glthread_tls_key_destroy (&name);
  32 
  33    A per-thread value is of type 'void *'.
  34 
  35    A destructor is a function pointer of type 'void (*) (void *)', called
  36    when a thread exits, and taking the last per-thread value as argument.  It
  37    is unspecified whether the destructor function is called when the last
  38    per-thread value is NULL.  On some platforms, the destructor function is
  39    not called at all.
  40 */
  41 
  42 
  43 #ifndef _TLS_H
  44 #define _TLS_H
  45 
  46 #include <errno.h>
  47 #include <stdlib.h>
  48 
  49 #if !defined c11_threads_in_use
  50 # if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC
  51 #  define c11_threads_in_use() 1
  52 # elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
  53 #  include <threads.h>
  54 #  pragma weak thrd_exit
  55 #  define c11_threads_in_use() (thrd_exit != NULL)
  56 # else
  57 #  define c11_threads_in_use() 0
  58 # endif
  59 #endif
  60 
  61 /* ========================================================================= */
  62 
  63 #if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
  64 
  65 /* Use the ISO C threads library.  */
  66 
  67 # include <threads.h>
  68 
  69 /* ------------------------- gl_tls_key_t datatype ------------------------- */
  70 
  71 typedef tss_t gl_tls_key_t;
  72 # define glthread_tls_key_init(KEY, DESTRUCTOR) \
  73     (tss_create (KEY, DESTRUCTOR) != thrd_success ? EAGAIN : 0)
  74 # define gl_tls_get(NAME) \
  75     tss_get (NAME)
  76 # define glthread_tls_set(KEY, POINTER) \
  77     (tss_set (*(KEY), (POINTER)) != thrd_success ? ENOMEM : 0)
  78 # define glthread_tls_key_destroy(KEY) \
  79     (tss_delete (*(KEY)), 0)
  80 
  81 #endif
  82 
  83 /* ========================================================================= */
  84 
  85 #if USE_POSIX_THREADS
  86 
  87 /* Use the POSIX threads library.  */
  88 
  89 # include <pthread.h>
  90 
  91 # if PTHREAD_IN_USE_DETECTION_HARD
  92 
  93 /* The pthread_in_use() detection needs to be done at runtime.  */
  94 #  define pthread_in_use() \
  95      glthread_in_use ()
  96 extern int glthread_in_use (void);
  97 
  98 # endif
  99 
 100 # if USE_POSIX_THREADS_WEAK
 101 
 102 /* Use weak references to the POSIX threads library.  */
 103 
 104 #  pragma weak pthread_key_create
 105 #  pragma weak pthread_getspecific
 106 #  pragma weak pthread_setspecific
 107 #  pragma weak pthread_key_delete
 108 #  ifndef pthread_self
 109 #   pragma weak pthread_self
 110 #  endif
 111 
 112 #  if !PTHREAD_IN_USE_DETECTION_HARD
 113 #   pragma weak pthread_mutexattr_gettype
 114 #   define pthread_in_use() \
 115       (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
 116 #  endif
 117 
 118 # else
 119 
 120 #  if !PTHREAD_IN_USE_DETECTION_HARD
 121 #   define pthread_in_use() 1
 122 #  endif
 123 
 124 # endif
 125 
 126 /* ------------------------- gl_tls_key_t datatype ------------------------- */
 127 
 128 typedef union
 129         {
 130           void *singlethread_value;
 131           pthread_key_t key;
 132         }
 133         gl_tls_key_t;
 134 # define glthread_tls_key_init(KEY, DESTRUCTOR) \
 135     (pthread_in_use ()                              \
 136      ? pthread_key_create (&(KEY)->key, DESTRUCTOR) \
 137      : ((KEY)->singlethread_value = NULL, 0))
 138 # define gl_tls_get(NAME) \
 139     (pthread_in_use ()                  \
 140      ? pthread_getspecific ((NAME).key) \
 141      : (NAME).singlethread_value)
 142 # define glthread_tls_set(KEY, POINTER) \
 143     (pthread_in_use ()                             \
 144      ? pthread_setspecific ((KEY)->key, (POINTER)) \
 145      : ((KEY)->singlethread_value = (POINTER), 0))
 146 # define glthread_tls_key_destroy(KEY) \
 147     (pthread_in_use () ? pthread_key_delete ((KEY)->key) : 0)
 148 
 149 #endif
 150 
 151 /* ========================================================================= */
 152 
 153 #if USE_WINDOWS_THREADS
 154 
 155 # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
 156 # include <windows.h>
 157 
 158 # include "windows-tls.h"
 159 
 160 /* ------------------------- gl_tls_key_t datatype ------------------------- */
 161 
 162 typedef glwthread_tls_key_t gl_tls_key_t;
 163 # define glthread_tls_key_init(KEY, DESTRUCTOR) \
 164     glwthread_tls_key_create (KEY, DESTRUCTOR)
 165 # define gl_tls_get(NAME) \
 166     TlsGetValue (NAME)
 167 # define glthread_tls_set(KEY, POINTER) \
 168     (!TlsSetValue (*(KEY), POINTER) ? EINVAL : 0)
 169 # define glthread_tls_key_destroy(KEY) \
 170     glwthread_tls_key_delete (*(KEY))
 171 
 172 #endif
 173 
 174 /* ========================================================================= */
 175 
 176 #if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
 177 
 178 /* Provide dummy implementation if threads are not supported.  */
 179 
 180 /* ------------------------- gl_tls_key_t datatype ------------------------- */
 181 
 182 typedef struct
 183         {
 184           void *singlethread_value;
 185         }
 186         gl_tls_key_t;
 187 # define glthread_tls_key_init(KEY, DESTRUCTOR) \
 188     ((KEY)->singlethread_value = NULL, \
 189      (void) (DESTRUCTOR),              \
 190      0)
 191 # define gl_tls_get(NAME) \
 192     (NAME).singlethread_value
 193 # define glthread_tls_set(KEY, POINTER) \
 194     ((KEY)->singlethread_value = (POINTER), 0)
 195 # define glthread_tls_key_destroy(KEY) \
 196     0
 197 
 198 #endif
 199 
 200 /* ========================================================================= */
 201 
 202 /* Macros with built-in error handling.  */
 203 
 204 /* ------------------------- gl_tls_key_t datatype ------------------------- */
 205 
 206 #define gl_tls_key_init(NAME, DESTRUCTOR) \
 207    do                                                 \
 208      {                                                \
 209        if (glthread_tls_key_init (&NAME, DESTRUCTOR)) \
 210          abort ();                                    \
 211      }                                                \
 212    while (0)
 213 #define gl_tls_set(NAME, POINTER) \
 214    do                                         \
 215      {                                        \
 216        if (glthread_tls_set (&NAME, POINTER)) \
 217          abort ();                            \
 218      }                                        \
 219    while (0)
 220 #define gl_tls_key_destroy(NAME) \
 221    do                                        \
 222      {                                       \
 223        if (glthread_tls_key_destroy (&NAME)) \
 224          abort ();                           \
 225      }                                       \
 226    while (0)
 227 
 228 /* ========================================================================= */
 229 
 230 #endif /* _TLS_H */

/* [previous][next][first][last][top][bottom][index][help] */