libcwd: The C++ Debugging Support Library - Reference Manual
Author: Carlo Wood
Description: C++ debugging support library with ostream debug output
Keywords: libcwd, debug output, debug facility, debug channel, object orientation, OO, C++, nested debug output, ostream, memory allocation, debugging, source file and line number

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$
    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_TSD_PARAM_UNUSED ::libcwd::_private_::TSD_st&
    00065                                                         // Same without parameter.
    00066 #define LIBCWD_COMMA_TSD_PARAM , LIBCWD_TSD_PARAM       // Idem, but as second or higher parameter.
    00067 #define LIBCWD_COMMA_TSD_PARAM_UNUSED , LIBCWD_TSD_PARAM_UNUSED
    00068                                                         // Idem, without parameter.
    00069 #define LIBCWD_TSD_INSTANCE ::libcwd::_private_::TSD_st::instance()
    00070                                                         // For directly passing the `__libcwd_tsd' instance to a function (foo(TSD::instance())).
    00071 #define LIBCWD_COMMA_TSD_INSTANCE , LIBCWD_TSD_INSTANCE // Idem, but as second or higher parameter.
    00072 #define LIBCWD_TSD_DECLARATION ::libcwd::_private_::TSD_st& __libcwd_tsd(::libcwd::_private_::TSD_st::instance())
    00073                                                         // Declaration of local `__libcwd_tsd' structure reference.
    00074 #define LIBCWD_DO_TSD(debug_object) (*__libcwd_tsd.do_array[(debug_object).WNS_index])
    00075                                                         // For use inside class debug_ct to access member `m'.
    00076 #define LIBCWD_TSD_MEMBER_OFF (__libcwd_tsd.do_off_array[WNS_index])
    00077                                                         // For use inside class debug_ct to access member `_off'.
    00078 #define LIBCWD_DO_TSD_MEMBER_OFF(debug_object) (__libcwd_tsd.do_off_array[(debug_object).WNS_index])
    00079                                                         // To access member _off of debug object.
    00080
    00081 #else // !LIBCWD_THREAD_SAFE
    00082
    00083 #define LIBCWD_TSD
    00084 #define LIBCWD_COMMA_TSD
    00085 #define LIBCWD_TSD_PARAM void
    00086 #define LIBCWD_TSD_PARAM_UNUSED void
    00087 #define LIBCWD_COMMA_TSD_PARAM
    00088 #define LIBCWD_COMMA_TSD_PARAM_UNUSED
    00089 #define LIBCWD_TSD_INSTANCE
    00090 #define LIBCWD_COMMA_TSD_INSTANCE
    00091 #define LIBCWD_TSD_DECLARATION
    00092 #define LIBCWD_DO_TSD(debug_object) ((debug_object).tsd)
    00093 #define LIBCWD_TSD_MEMBER_OFF (tsd._off)
    00094 #define LIBCWD_DO_TSD_MEMBER_OFF(debug_object) ((debug_object).tsd._off)
    00095
    00096 #endif // !LIBCWD_THREAD_SAFE
    00097
    00098 #define LIBCWD_DO_TSD_MEMBER(debug_object, m) (LIBCWD_DO_TSD(debug_object).m)
    00099 #define LIBCWD_TSD_MEMBER(m) LIBCWD_DO_TSD_MEMBER(*this, m)
    00100
    00101 // These includes use the above macros.
    00102 #ifndef LIBCWD_STRUCT_DEBUG_TSD_H
    00103 #include <libcwd/struct_debug_tsd.h>
    00104 #endif
    00105 #if LIBCWD_THREAD_SAFE
    00106 #ifndef LIBCWD_PRIVATE_THREAD_H
    00107 #include <libcwd/private_thread.h>
    00108 #endif
    00109 #endif
    00110
    00111 namespace libcwd {
    00112
    00113 #if CWDEBUG_LOCATION
    00114
    00122 typedef unsigned short int location_format_t;
    00123  // End of group 'group_locations'
    00125 #endif
    00126
    00127   namespace _private_ {
    00128
    00129 extern int WST_initializing_TSD;
    00130 class thread_ct;
    00131
    00132 struct TSD_st {
    00133 public:
    00134 #if CWDEBUG_ALLOC
    00135   int internal;                         // libsysrecord.so relies on this being the first element.
    00136   int library_call;                     // libsysrecord.so relies on this being the second element.
    00137   int inside_malloc_or_free;            // Set when entering a (de)allocation routine non-internal.
    00138   int invisible;                        // When set, allocation done must be invisible.
    00139 #endif // CWDEBUG_ALLOC
    00140 #if CWDEBUG_LOCATION
    00141   location_format_t format;             // Determines how to print location_ct to an ostream.
    00142 #endif
    00143 #if LIBCWD_THREAD_SAFE
    00144   threadlist_t::iterator thread_iter;   // Persistant thread specific data (might even stay after this object is destructed).
    00145   bool thread_iter_valid;
    00146   thread_ct* target_thread;
    00147   int terminating;
    00148   bool pthread_lock_interface_is_locked;// Set while writing debugout to the final ostream.
    00149   bool list_allocations_on_show_allthreads;
    00150   int inside_free;                      // Set when entering free().
    00151 #endif
    00152 #if CWDEBUG_DEBUGM
    00153   int marker;
    00154 #if CWDEBUG_MAGIC
    00155   int annotation;
    00156 #endif
    00157 #endif
    00158   bool recursive_fatal;                 // Detect loop involving dc::fatal or dc::core.
    00159 #if CWDEBUG_DEBUG
    00160   bool recursive_assert;                // Detect loop involving LIBCWD_ASSERT.
    00161 #endif
    00162 #if CWDEBUG_DEBUGT
    00163   int cancel_explicitely_deferred;
    00164   int cancel_explicitely_disabled;
    00165   int inside_critical_area;
    00166   int cleanup_handler_installed;
    00167   int internal_debugging_code;
    00168   mutex_ct* waiting_for_mutex;          // mutex_ct that this thread is waiting for.
    00169   int waiting_for_lock;                 // The instance of the lock that this thread is waiting for.
    00170   int waiting_for_rdlock;               // The instance of the rdlock that this thread is waiting for.
    00171   int instance_rdlocked[instance_rdlocked_size];
    00172   pthread_t rdlocked_by1[instance_rdlocked_size];
    00173   pthread_t rdlocked_by2[instance_rdlocked_size];
    00174   void const* rdlocked_from1[instance_rdlocked_size];
    00175   void const* rdlocked_from2[instance_rdlocked_size];
    00176 #endif
    00177 #if LIBCWD_THREAD_SAFE
    00178   pthread_t tid;                        // Thread ID.
    00179   pid_t pid;                            // Process ID.
    00180   int do_off_array[LIBCWD_DO_MAX];      // Thread Specific on/off counter for Debug Objects.
    00181   debug_tsd_st* do_array[LIBCWD_DO_MAX];// Thread Specific Data of Debug Objects or NULL when no debug object.
    00182   void cleanup_routine(void);
    00183   int off_cnt_array[LIBCWD_DC_MAX];     // Thread Specific Data of Debug Channels.
    00184 private:
    00185   int tsd_destructor_count;
    00186 #endif
    00187
    00188 public:
    00189   void thread_destructed(void);
    00190
    00191 #if LIBCWD_THREAD_SAFE
    00192 //-------------------------------------------------------
    00193 // Static data and methods.
    00194 private:
    00195   static TSD_st& S_create(int from_free);
    00196   static pthread_key_t S_tsd_key;
    00197   static pthread_once_t S_tsd_key_once;
    00198   static void S_tsd_key_alloc(void);
    00199   static void S_cleanup_routine(void* arg);
    00200
    00201 public:
    00202   static TSD_st& instance(void);
    00203   static TSD_st& instance_free(void);
    00204   static void free_instance(TSD_st&);
    00205 #endif // LIBCWD_THREAD_SAFE
    00206 };
    00207
    00208 // Thread Specific Data (TSD) is stored in a structure TSD_st
    00209 // and is accessed through a reference to `__libcwd_tsd'.
    00210
    00211 #if !LIBCWD_THREAD_SAFE
    00212 // When LIBCWD_THREAD_SAFE is set then `__libcwd_tsd' is a local variable that references
    00213 // the Thread Specific Data as returned by TSD_st::instance(), otherwise it is simply a
    00214 // global object in namespace _private_:
    00215 extern TSD_st __libcwd_tsd;
    00216 #else
    00217 extern bool WST_tsd_key_created;
    00218
    00219 inline
    00220 TSD_st& TSD_st::instance(void)
    00221 {
    00222   TSD_st* instance;
    00223   if (!WST_tsd_key_created || !(instance = (TSD_st*)pthread_getspecific(S_tsd_key)))
    00224     return S_create(0);
    00225   return *instance;
    00226 }
    00227
    00228 // This function is called at the start of free().
    00229 inline
    00230 TSD_st& TSD_st::instance_free(void)
    00231 {
    00232   TSD_st* instance;
    00233   if (!WST_tsd_key_created || !(instance = (TSD_st*)pthread_getspecific(S_tsd_key)))
    00234     return S_create(1);
    00235   else
    00236     instance->inside_free++;
    00237   return *instance;
    00238 }
    00239 #endif
    00240
    00241   } // namespace _private_
    00242 } // namespace libcwd
    00243
    00244 #if !LIBCWD_THREAD_SAFE
    00245 // Put __libcwd_tsd in global namespace because anywhere we always refer to it
    00246 // as `__libcwd_tsd' because when LIBCWD_THREAD_SAFE is set it is local variable.
    00247 using ::libcwd::_private_::__libcwd_tsd;
    00248 #endif
    00249
    00250 #endif // LIBCWD_PRIVATE_STRUCT_TSD_H