1 // $Header$ 2 // 3 // Copyright (C) 2000 - 2004, by 4 // 5 // Carlo Wood, Run on IRC <carlo@alinoe.com> 6 // RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt 7 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61 8 // 9 // This file may be distributed under the terms of the Q Public License 10 // version 1.0 as appearing in the file LICENSE.QPL included in the 11 // packaging of this file. 12 // 13 14 /** \file class_debug.h 15 * Do not include this header file directly, instead include \ref preparation_step2 "debug.h". 16 */ 17 18 #ifndef LIBCWD_CLASS_DEBUG_H 19 #define LIBCWD_CLASS_DEBUG_H 20 21 #ifndef LIBCWD_CONFIG_H 22 #include <libcwd/config.h> 23 #endif 24 #ifndef LIBCWD_CLASS_CHANNEL_SET_H 25 #include <libcwd/class_channel_set.h> 26 #endif 27 #ifndef LIBCWD_PRIVATE_STRUCT_TSD_H 28 #include <libcwd/private_struct_TSD.h> 29 #endif 30 #ifndef LIBCWD_STRUCT_DEBUG_TSD_H 31 #include <libcwd/struct_debug_tsd.h> 32 #endif 33 #ifndef LIBCWD_PRIVATE_LOCK_INTERFACE_H 34 #include <libcwd/private_lock_interface.h> 35 #endif 36 #ifndef LIBCW_IOSFWD 37 #define LIBCW_IOSFWD 38 #include <iosfwd> 39 #endif 40 41 namespace libcwd { 42 43 class buffer_ct; 44 45 #if CWDEBUG_ALLOC 46 namespace _private_ { 47 48 struct debug_message_st { 49 struct debug_message_st* next; 50 struct debug_message_st* prev; 51 int curlen; 52 char buf[sizeof(int)]; 53 }; 54 55 } // namespace _private_ 56 #endif 57 58 //=================================================================================================== 59 // class debug_ct 60 // 61 // Note: Debug output is printed already *before* this object is constructed, 62 // and is still printed when this object is already destructed. 63 // This is why initialization is done with method init() *before* construction 64 // and debug is turned off when this object is destructed. 65 // I hope that this is no problem because libcwd::libcw_do is a global object. 66 // It means however that this object can not contain any attributes that have 67 // a constructor of their own! 68 69 /** 70 * \class debug_ct debug.h libcwd/debug.h 71 * \ingroup group_debug_object 72 * 73 * \brief The %Debug Object class, this object represents one output device (<code>ostream</code>). 74 * 75 * See \ref group_debug_object. 76 */ 77 class debug_ct { 78 friend void debug_tsd_st::start(debug_ct&, channel_set_data_st& LIBCWD_COMMA_TSD_PARAM); 79 friend void debug_tsd_st::finish(debug_ct &, channel_set_data_st& LIBCWD_COMMA_TSD_PARAM); 80 #ifdef LIBCWD_DOXYGEN 81 protected: 82 #else 83 public: // Only public because macro LibcwDout needs acces, don't access this directly. 84 #endif 85 #if LIBCWD_THREAD_SAFE 86 int WNS_index; 87 static int S_index_count; 88 #else 89 //------------------------------------------------------------------------------------------------- 90 // Put the otherwise Thread Specific Data of this debug object 91 // directly into the object when we don't use threads. 92 // 93 94 debug_tsd_st tsd; 95 #endif 96 97 protected: 98 //------------------------------------------------------------------------------------------------- 99 // Protected attributes. 100 // 101 102 std::ostream* real_os; 103 // The original output ostream (as set with set_ostream()). 104 // 105 #if LIBCWD_THREAD_SAFE 106 friend class libcwd::buffer_ct; // buffer_ct::writeto() needs access. 107 _private_::lock_interface_base_ct* M_mutex; 108 // Pointer to the mutex that should be used for `real_os' or NULL when no lock is used. 109 // A value of NULL is only allowed prior to creating a second thread. 110 111 buffer_ct* unfinished_oss; 112 void const* newlineless_tsd; 113 #endif 114 115 private: 116 //------------------------------------------------------------------------------------------------- 117 // Private attributes: 118 // 119 120 bool WNS_initialized; 121 // Set to true when this object is initialized (by a call to NS_init()). 122 123 bool NS_being_initialized; 124 // Set to true when this object is being initialized (by a call to NS_init()). 125 126 #if CWDEBUG_DEBUG 127 long init_magic; 128 // Used to check if the trick with `WNS_initialized' really works. 129 #endif 130 131 bool interactive; 132 // Set true if the last or current debug output is to cerr 133 134 #if CWDEBUG_ALLOC 135 public: 136 _private_::debug_message_st* queue; 137 _private_::debug_message_st* queue_top; 138 // Queue of messages written inside malloc/realloc/calloc/free/new/delete. 139 // Locked by mutex provided through set_ostream. 140 #endif 141 142 public: 143 /** \addtogroup group_formatting */ 144 /** \{ */ 145 146 /** 147 * \brief The margin 148 * 149 * This is printed before the label. 150 * The margin can be manipulated directly using the methods of class debug_string_ct. 151 * 152 * \sa push_margin() 153 * \n pop_margin() 154 */ 155 debug_string_ct& margin(void); 156 debug_string_ct const& margin(void) const; 157 158 /** 159 * \brief The marker 160 * 161 * This is printed after the label. 162 * The marker can be manipulated directly using the methods of class debug_string_ct. 163 * 164 * \sa push_marker() 165 * \n pop_marker() 166 */ 167 debug_string_ct& marker(void); 168 debug_string_ct const& marker(void) const; 169 170 /** \} */ 171 172 public: 173 //------------------------------------------------------------------------------------------------- 174 // Manipulators and accessors for the "format" attributes: 175 // 176 177 void set_indent(unsigned short indentation); 178 void inc_indent(unsigned short indentation); 179 void dec_indent(unsigned short indentation); 180 unsigned short get_indent(void) const; 181 182 void push_margin(void); 183 void pop_margin(void); 184 void push_marker(void); 185 void pop_marker(void); 186 187 //------------------------------------------------------------------------------------------------- 188 // Other accessors 189 // 190 191 std::ostream* get_ostream(void) const; // The original ostream set with set_ostream. 192 193 private: 194 //------------------------------------------------------------------------------------------------- 195 // Initialization function. 196 // 197 198 friend class channel_ct; 199 friend class fatal_channel_ct; 200 friend void ST_initialize_globals(LIBCWD_TSD_PARAM); 201 #if CWDEBUG_LOCATION 202 friend bool cwbfd::ST_init(LIBCWD_TSD_PARAM); 203 #endif 204 bool NS_init(LIBCWD_TSD_PARAM); 205 // Initialize this object, needed because debug output can be written 206 // from the constructors of (other) global objects, and from the malloc() 207 // family when CWDEBUG_ALLOC is set to 1. 208 // This will return false when it is called recursively which can happen 209 // as part of initialization of libcwd via a call to malloc while creating 210 // laf_ct -> buffer_ct --> basic_stringbuf. In that case the initialization 211 // failed thus. On success, it returns true. 212 213 public: 214 //------------------------------------------------------------------------------------------------- 215 // Constructors and destructors. 216 // 217 218 debug_ct(void); 219 220 private: 221 void private_set_ostream(std::ostream* os); 222 223 public: 224 //------------------------------------------------------------------------------------------------- 225 // Manipulators: 226 // 227 228 void set_ostream(std::ostream* os); 229 #if LIBCWD_THREAD_SAFE || defined(LIBCWD_DOXYGEN) 230 template<class T> 231 void set_ostream(std::ostream* os, T* mutex); 232 #ifdef LIBCWD_DOXYGEN 233 // Specialization. 234 template<> 235 void set_ostream(std::ostream* os, pthread_mutex_t* mutex); 236 #endif 237 #endif 238 void off(void); 239 void on(void); 240 241 struct OnOffState { 242 int _off; 243 #if CWDEBUG_DEBUGOUTPUT 244 bool first_time; 245 #endif 246 }; 247 248 void force_on(OnOffState& state); 249 void restore(OnOffState const& state); 250 }; 251 252 #if LIBCWD_THREAD_SAFE && !defined(LIBCWD_DOXYGEN) 253 // Specialization. 254 template<> 255 void debug_ct::set_ostream(std::ostream* os, pthread_mutex_t* mutex); 256 #endif 257 258 } // namespace libcwd 259 260 #ifndef LIBCWD_SET_OSTREAM_INL 261 #include <libcwd/set_ostream.inl> 262 #endif 263 264 #endif // LIBCWD_CLASS_DEBUG_H 265 266