Not crap after all...
[amarok.git] / src / debug.h
blob80c68219c18e1c772d298cf876d2acc1f74fdb75
1 // Author: Max Howell <max.howell@methylblue.com>, (C) 2003-5
2 // Copyright: See COPYING file that comes with this distribution
3 //
5 #ifndef AMAROK_DEBUG_H
6 #define AMAROK_DEBUG_H
8 #include <kdebug.h>
9 #include <QByteArray>
10 #include <QMutex>
11 #include <QObject>
12 //Added by qt3to4:
13 #include <Q3ValueList>
14 #include <sys/time.h>
16 #include <QApplication>
17 #include <iostream>
19 #include "amarok_export.h"
21 #ifdef _WIN32
22 #define __PRETTY_FUNCTION__ __FUNCTION__
23 #endif
25 /**
26 * @namespace Debug
27 * @short kdebug with indentation functionality and convenience macros
28 * @author Max Howell <max.howell@methylblue.com>
30 * Usage:
32 * #define DEBUG_PREFIX "Blah"
33 * #include "debug.h"
35 * void function()
36 * {
37 * Debug::Block myBlock( __PRETTY_FUNCTION__ );
39 * debug() << "output1" << endl;
40 * debug() << "output2" << endl;
41 * }
43 * Will output:
45 * app: BEGIN: void function()
46 * app: [Blah] output1
47 * app: [Blah] output2
48 * app: END: void function(): Took 0.1s
50 * @see Block
51 * @see CrashHelper
52 * @see ListStream
55 namespace Debug
57 extern AMAROK_EXPORT QMutex mutex; // defined in app.cpp
59 // we can't use a statically instantiated QCString for the indent, because
60 // static namespaces are unique to each dlopened library. So we piggy back
61 // the QCString on the KApplication instance
63 #define qOApp reinterpret_cast<QObject*>(qApp)
64 class Indent : QObject
66 friend QByteArray &modifieableIndent();
67 Indent() : QObject( qOApp ) { setObjectName( "DEBUG_indent" ); }
68 QByteArray m_string;
71 inline QByteArray &modifieableIndent()
73 QObject* o = qOApp ? qOApp->findChild<QObject*>( "DEBUG_indent" ) : 0;
74 QByteArray &ret = (o ? static_cast<Indent*>( o ) : new Indent)->m_string;
75 return ret;
78 inline QByteArray indent()
80 return modifieableIndent();
82 #undef qApp
85 #ifdef NDEBUG
86 static inline kndbgstream debug() { return kndbgstream(); }
87 static inline kndbgstream warning() { return kndbgstream(); }
88 static inline kndbgstream error() { return kndbgstream(); }
89 static inline kndbgstream fatal() { return kndbgstream(); }
91 typedef kndbgstream DebugStream;
92 #else
93 #ifndef DEBUG_PREFIX
94 #define AMK_PREFIX ""
95 #else
96 #define AMK_PREFIX "[" DEBUG_PREFIX "] "
97 #endif
99 //from kdebug.h
100 enum DebugLevels {
101 KDEBUG_INFO = 0,
102 KDEBUG_WARN = 1,
103 KDEBUG_ERROR = 2,
104 KDEBUG_FATAL = 3
107 static inline kdbgstream debug() { mutex.lock(); QByteArray ind = indent(); mutex.unlock(); return kdbgstream( ind.data(), 0, KDEBUG_INFO ) << AMK_PREFIX; }
108 static inline kdbgstream warning() { mutex.lock(); QByteArray ind = indent(); mutex.unlock(); return kdbgstream( ind.data(), 0, KDEBUG_WARN ) << AMK_PREFIX << "[WARNING!] "; }
109 static inline kdbgstream error() { mutex.lock(); QByteArray ind = indent(); mutex.unlock(); return kdbgstream( ind.data(), 0, KDEBUG_ERROR ) << AMK_PREFIX << "[ERROR!] "; }
110 static inline kdbgstream fatal() { mutex.lock(); QByteArray ind = indent(); mutex.unlock(); return kdbgstream( ind.data(), 0, KDEBUG_FATAL ) << AMK_PREFIX; }
112 typedef kdbgstream DebugStream;
114 #undef AMK_PREFIX
115 #endif
117 typedef kndbgstream NoDebugStream;
120 using Debug::debug;
121 using Debug::warning;
122 using Debug::error;
123 using Debug::fatal;
124 using Debug::DebugStream;
126 /// Standard function announcer
127 #define DEBUG_FUNC_INFO { Debug::mutex.lock(); kDebug() << Debug::indent() << k_funcinfo << endl; Debug::mutex.unlock(); }
129 /// Announce a line
130 #define DEBUG_LINE_INFO { Debug::mutex.lock(); kDebug() << Debug::indent() << k_funcinfo << "Line: " << __LINE__ << endl; Debug::mutex.unlock(); }
132 /// Convenience macro for making a standard Debug::Block
133 #define DEBUG_BLOCK Debug::Block uniquelyNamedStackAllocatedStandardBlock( __PRETTY_FUNCTION__ );
135 /// Use this to remind yourself to finish the implementation of a function
136 #define AMAROK_NOTIMPLEMENTED warning() << "NOT-IMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
138 /// Use this to alert other developers to stop using a function
139 #define AMAROK_DEPRECATED warning() << "DEPRECATED: " << __PRETTY_FUNCTION__ << endl;
142 namespace Debug
145 * @class Debug::Block
146 * @short Use this to label sections of your code
148 * Usage:
150 * void function()
152 * Debug::Block myBlock( "section" );
154 * debug() << "output1" << endl;
155 * debug() << "output2" << endl;
158 * Will output:
160 * app: BEGIN: section
161 * app: [prefix] output1
162 * app: [prefix] output2
163 * app: END: section - Took 0.1s
167 class Block
169 timeval m_start;
170 const char *m_label;
172 public:
173 Block( const char *label )
174 : m_label( label )
176 mutex.lock();
177 gettimeofday( &m_start, 0 );
179 kDebug() << "BEGIN: " << label << "\n";
180 Debug::modifieableIndent() += " ";
181 mutex.unlock();
184 ~Block()
186 mutex.lock();
187 timeval end;
188 gettimeofday( &end, 0 );
190 end.tv_sec -= m_start.tv_sec;
191 if( end.tv_usec < m_start.tv_usec) {
192 // Manually carry a one from the seconds field.
193 end.tv_usec += 1000000;
194 end.tv_sec--;
196 end.tv_usec -= m_start.tv_usec;
198 double duration = double(end.tv_sec) + (double(end.tv_usec) / 1000000.0);
200 Debug::modifieableIndent().truncate( Debug::indent().length() - 2 );
201 kDebug() << "END__: " << m_label
202 << " - Took " << QString::number( duration, 'g', 2 ) << "s\n";
203 mutex.unlock();
209 * @name Debug::stamp()
210 * @short To facilitate crash/freeze bugs, by making it easy to mark code that has been processed
212 * Usage:
215 * Debug::stamp();
216 * function1();
217 * Debug::stamp();
218 * function2();
219 * Debug::stamp();
222 * Will output (assuming the crash occurs in function2()
224 * app: Stamp: 1
225 * app: Stamp: 2
229 inline void stamp()
231 static int n = 0;
232 debug() << "| Stamp: " << ++n << endl;
237 #include <QVariant>
239 namespace Debug
242 * @class Debug::List
243 * @short You can pass anything to this and it will output it as a list
245 * debug() << (Debug::List() << anInt << aString << aQStringList << aDouble) << endl;
248 typedef Q3ValueList<QVariant> List;
251 #endif