Main Page   Reference Manual   Namespace List   Compound List   Namespace Members   Compound Members   File Members  

libcwd/private_struct_TSD.h

Go to the documentation of this file.
00001 // $Header: /cvsroot/libcwd/libcwd/include/libcwd/private_struct_TSD.h,v 1.14 2004/08/31 18:25:46 libcw Exp $
00002 //
00003 // Copyright (C) 2001 - 2004, by
00004 //
00005 // Carlo Wood, Run on IRC <carlo@alinoe.com>
00006 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
00007 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
00008 //
00009 // This file may be distributed under the terms of the Q Public License
00010 // version 1.0 as appearing in the file LICENSE.QPL included in the
00011 // packaging of this file.
00012 // 
00013 
00018 #ifndef LIBCWD_PRIVATE_STRUCT_TSD_H
00019 #define LIBCWD_PRIVATE_STRUCT_TSD_H
00020 
00021 #ifndef LIBCWD_CONFIG_H
00022 #include <libcwd/config.h>
00023 #endif
00024 #ifndef LIBCWD_PRIVATE_ASSERT_H
00025 #include <libcwd/private_assert.h>
00026 #endif
00027 #ifndef LIBCWD_PRIVATE_MUTEX_INSTANCES_H
00028 #include <libcwd/private_mutex_instances.h>
00029 #endif
00030 #ifndef LIBCW_CSTRING
00031 #define LIBCW_CSTRING
00032 #include <cstring>      // Needed for std::memset.
00033 #endif
00034 #ifndef LIBCW_LIMITS_H
00035 #define LIBCW_LIMITS_H
00036 #include <limits.h>     // For PTHREAD_THREADS_MAX
00037 #endif
00038 #if LIBCWD_THREAD_SAFE
00039 #include <libcwd/private_mutex.h>
00040 #ifdef LIBCWD_HAVE_PTHREAD
00041 #ifndef LIBCW_PTHREAD_H
00042 #define LIBCW_PTHREAD_H
00043 #include <pthread.h>
00044 #endif
00045 #endif
00046 #endif
00047 
00048 namespace libcwd {
00049   namespace _private_ {
00050     struct TSD_st;
00051   } // namespace _private_
00052 } // namespace libcwd
00053 
00054 // When LIBCWD_THREAD_SAFE is set then `__libcwd_tsd' is a local variable
00055 // (see LIBCWD_TSD_DECLARATION) or function parameter (LIBCWD_TSD_PARAM and LIBCWD_COMMA_TSD_PARAM).
00056 // This approach means that many function signatures are different because with thread support a
00057 // `__libcwd_tsd' reference needs to be passed.  We use several helper macros for this:
00058 #if LIBCWD_THREAD_SAFE
00059 
00060 #define LIBCWD_TSD __libcwd_tsd                         // Optional `__libcwd_tsd' parameter (foo() or foo(__libcwd_tsd)).
00061 #define LIBCWD_COMMA_TSD , LIBCWD_TSD                   // Idem, but as second or higher parameter.
00062 #define LIBCWD_TSD_PARAM ::libcwd::_private_::TSD_st& __libcwd_tsd
00063                                                         // Optional function parameter (foo(void) or foo(TSD_st& __libcwd_tsd)).
00064 #define LIBCWD_COMMA_TSD_PARAM , LIBCWD_TSD_PARAM       // Idem, but as second or higher parameter.
00065 #define LIBCWD_TSD_INSTANCE ::libcwd::_private_::TSD_st::instance()
00066                                                         // For directly passing the `__libcwd_tsd' instance to a function (foo(TSD::instance())).
00067 #define LIBCWD_COMMA_TSD_INSTANCE , LIBCWD_TSD_INSTANCE // Idem, but as second or higher parameter.
00068 #define LIBCWD_TSD_DECLARATION ::libcwd::_private_::TSD_st& __libcwd_tsd(::libcwd::_private_::TSD_st::instance())
00069                                                         // Declaration of local `__libcwd_tsd' structure reference.
00070 #define LIBCWD_DO_TSD(debug_object) (*__libcwd_tsd.do_array[(debug_object).WNS_index])
00071                                                         // For use inside class debug_ct to access member `m'.
00072 #define LIBCWD_TSD_MEMBER_OFF (__libcwd_tsd.do_off_array[WNS_index])
00073                                                         // For use inside class debug_ct to access member `_off'.
00074 #define LIBCWD_DO_TSD_MEMBER_OFF(debug_object) (__libcwd_tsd.do_off_array[(debug_object).WNS_index])
00075                                                         // To access member _off of debug object.
00076 
00077 #else // !LIBCWD_THREAD_SAFE
00078 
00079 #define LIBCWD_TSD
00080 #define LIBCWD_COMMA_TSD
00081 #define LIBCWD_TSD_PARAM void
00082 #define LIBCWD_COMMA_TSD_PARAM
00083 #define LIBCWD_TSD_INSTANCE
00084 #define LIBCWD_COMMA_TSD_INSTANCE
00085 #define LIBCWD_TSD_DECLARATION
00086 #define LIBCWD_DO_TSD(debug_object) ((debug_object).tsd)
00087 #define LIBCWD_TSD_MEMBER_OFF (tsd._off)
00088 #define LIBCWD_DO_TSD_MEMBER_OFF(debug_object) ((debug_object).tsd._off)
00089 
00090 #endif // !LIBCWD_THREAD_SAFE
00091 
00092 #define LIBCWD_DO_TSD_MEMBER(debug_object, m) (LIBCWD_DO_TSD(debug_object).m)
00093 #define LIBCWD_TSD_MEMBER(m) LIBCWD_DO_TSD_MEMBER(*this, m)
00094 
00095 // These includes use the above macros.
00096 #ifndef LIBCWD_STRUCT_DEBUG_TSD_H
00097 #include <libcwd/struct_debug_tsd.h>
00098 #endif
00099 #if LIBCWD_THREAD_SAFE
00100 #ifndef LIBCWD_PRIVATE_THREAD_H
00101 #include <libcwd/private_thread.h>
00102 #endif
00103 #endif
00104 
00105 namespace libcwd {
00106 
00107 #if CWDEBUG_LOCATION
00108 
00116 typedef unsigned short int location_format_t;
00117  // End of group 'group_locations'
00119 #endif
00120 
00121   namespace _private_ {
00122 
00123 extern int WST_initializing_TSD;
00124 class thread_ct;
00125 
00126 struct TSD_st {
00127 public:
00128 #if CWDEBUG_ALLOC
00129   int internal;                         // libsysrecord.so relies on this being the first element.
00130   int library_call;                     // libsysrecord.so relies on this being the second element.
00131   int inside_malloc_or_free;            // Set when entering a (de)allocation routine non-internal.
00132   int invisible;                        // When set, allocation done must be invisible.
00133 #endif // CWDEBUG_ALLOC
00134 #if CWDEBUG_LOCATION
00135   location_format_t format;             // Determines how to print location_ct to an ostream.
00136 #endif
00137 #if LIBCWD_THREAD_SAFE
00138   threadlist_t::iterator thread_iter;   // Persistant thread specific data (might even stay after this object is destructed).
00139   bool thread_iter_valid;
00140   thread_ct* target_thread;
00141   int terminating;
00142   bool pthread_lock_interface_is_locked;// Set while writing debugout to the final ostream.
00143   bool list_allocations_on_show_allthreads;
00144   int inside_free;                      // Set when entering free().
00145 #endif
00146 #if CWDEBUG_DEBUGM
00147   int marker;
00148 #if CWDEBUG_MAGIC
00149   int annotation;
00150 #endif
00151 #endif
00152   bool recursive_fatal;                 // Detect loop involving dc::fatal or dc::core.
00153 #if CWDEBUG_DEBUG
00154   bool recursive_assert;                // Detect loop involving LIBCWD_ASSERT.
00155 #endif
00156 #if CWDEBUG_DEBUGT
00157   int cancel_explicitely_deferred;
00158   int cancel_explicitely_disabled;
00159   int inside_critical_area;
00160   int cleanup_handler_installed;
00161   int internal_debugging_code;
00162   mutex_ct* waiting_for_mutex;          // mutex_ct that this thread is waiting for.
00163   int waiting_for_lock;                 // The instance of the lock that this thread is waiting for.
00164   int waiting_for_rdlock;               // The instance of the rdlock that this thread is waiting for.
00165   int instance_rdlocked[instance_rdlocked_size];
00166   pthread_t rdlocked_by1[instance_rdlocked_size];
00167   pthread_t rdlocked_by2[instance_rdlocked_size];
00168   void const* rdlocked_from1[instance_rdlocked_size];
00169   void const* rdlocked_from2[instance_rdlocked_size];
00170 #endif
00171 #if LIBCWD_THREAD_SAFE
00172   pthread_t tid;                        // Thread ID.
00173   pid_t pid;                            // Process ID.
00174   int do_off_array[LIBCWD_DO_MAX];      // Thread Specific on/off counter for Debug Objects.
00175   debug_tsd_st* do_array[LIBCWD_DO_MAX];// Thread Specific Data of Debug Objects or NULL when no debug object.
00176   void cleanup_routine(void);
00177   int off_cnt_array[LIBCWD_DC_MAX];     // Thread Specific Data of Debug Channels.
00178 private:
00179   int tsd_destructor_count;
00180 #endif
00181 
00182 public:
00183   void thread_destructed(void);
00184 
00185 #if LIBCWD_THREAD_SAFE
00186 //-------------------------------------------------------
00187 // Static data and methods.
00188 private:
00189   static TSD_st& S_create(int from_free);
00190   static pthread_key_t S_tsd_key;
00191   static pthread_once_t S_tsd_key_once;
00192   static void S_tsd_key_alloc(void);
00193   static void S_cleanup_routine(void* arg);
00194 
00195 public:
00196   static TSD_st& instance(void);
00197   static TSD_st& instance_free(void);
00198   static void free_instance(TSD_st&);
00199 #endif // LIBCWD_THREAD_SAFE
00200 };
00201 
00202 // Thread Specific Data (TSD) is stored in a structure TSD_st
00203 // and is accessed through a reference to `__libcwd_tsd'.
00204 
00205 #if !LIBCWD_THREAD_SAFE
00206 // When LIBCWD_THREAD_SAFE is set then `__libcwd_tsd' is a local variable that references
00207 // the Thread Specific Data as returned by TSD_st::instance(), otherwise it is simply a
00208 // global object in namespace _private_:
00209 extern TSD_st __libcwd_tsd;
00210 #else
00211 extern bool WST_tsd_key_created;
00212 
00213 inline
00214 TSD_st& TSD_st::instance(void)
00215 {
00216   TSD_st* instance;
00217   if (!WST_tsd_key_created || !(instance = (TSD_st*)pthread_getspecific(S_tsd_key)))
00218     return S_create(0);
00219   return *instance;
00220 }
00221 
00222 // This function is called at the start of free().
00223 inline
00224 TSD_st& TSD_st::instance_free(void)
00225 {
00226   TSD_st* instance;
00227   if (!WST_tsd_key_created || !(instance = (TSD_st*)pthread_getspecific(S_tsd_key)))
00228     return S_create(1);
00229   else
00230     instance->inside_free++;
00231   return *instance;
00232 }
00233 #endif
00234 
00235   } // namespace _private_
00236 } // namespace libcwd
00237  
00238 #if !LIBCWD_THREAD_SAFE
00239 // Put __libcwd_tsd in global namespace because anywhere we always refer to it
00240 // as `__libcwd_tsd' because when LIBCWD_THREAD_SAFE is set it is local variable.
00241 using ::libcwd::_private_::__libcwd_tsd;
00242 #endif
00243 
00244 #endif // LIBCWD_PRIVATE_STRUCT_TSD_H
Copyright © 2001 - 2004 Carlo Wood.  All rights reserved.