inc/cntdebug.h
changeset 46 efe85016a067
child 50 77bc263e1626
child 59 a642906a277a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/cntdebug.h	Wed Jun 23 18:02:44 2010 +0300
@@ -0,0 +1,409 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Trace macro declarations.
+*
+*/
+
+
+#ifndef CNTDEBUG_H
+#define CNTDEBUG_H
+
+#include <QDebug>   // QDebug
+#include <QtGlobal> // qDebug()
+
+// #define TRACK_MEMORY_LEAKS
+
+/*!
+    \def CNT_UNUSED(name)
+    \brief Declares a single variable as unused when tracing is disabled.
+
+    CNT_UNUSED allows variables (usually method parameters) to be declared as used only if
+    tracing is enabled. Without this variables that are included in trace macros, but not otherwise
+    used, would cause unused variable warnings on compilation. If tracing is enabled, CNT_UNUSED
+    has no effect.
+
+    Consider the following class method where the parameter number is not used at all, except for
+    tracing its value on entry:
+
+    \code
+    #include <cntdebug.h>
+
+    void MyClass::myMethod(int number)
+    {
+        CNT_UNUSED(number)
+        CNT_ENTRY("number =" << number)
+
+        // ...some more code where the parameter number is not used.
+
+        CNT_EXIT
+    }
+    \endcode
+
+    Compiling this method with tracing completely disabled at compile time would cause an unused
+    variable warning to be issued unless the CNT_UNUSED macro is used to declare the variable as
+    trace-only.
+
+    \param name The name of the variable to declare as unused if tracing is disabled. To mark
+    several variables as trace-only, add a separate CNT_UNUSED statement for each.
+    \sa CNT_STATIC_ENTRY_ARGS(args), CNT_ENTRY_ARGS(args).
+*/
+
+/*!
+    \def CNT_STATIC_ENTRY
+    \brief A method entry trace macro for static class methods or global functions.
+
+    Invoking CNT_STATIC_ENTRY outputs a timestamp followed by the scope in which the macro
+    was invoked and the word "entry".
+
+    CNT_STATIC_ENTRY is intended to be used as the first line of static class methods or
+    global functions. There is a corresponding exit macro, CNT_EXIT.
+
+    The following example shows proper usage of the CNT_STATIC_ENTRY macro. Assuming a class
+    has been declared with a static method that is implemented like this:
+
+    \code
+    #include <cntdebug.h>
+
+    void MyClass::myStaticMethod()
+    {
+        CNT_STATIC_ENTRY
+
+        int i = 1;
+        i++;
+
+        CNT_EXIT
+    }
+    \endcode
+
+    calling MyClass::myStaticMethod() generates output lines of the following format:
+
+    \code
+    2009-03-25 11:00:50.171 : static void MyClass::myStaticMethod() entry
+    2009-03-25 11:00:50.171 : static void MyClass::myStaticMethod() exit
+    \endcode
+
+    \sa CNT_STATIC_ENTRY_ARGS(args), CNT_EXIT.
+*/
+
+/*!
+    \def CNT_STATIC_ENTRY_ARGS(args)
+    \brief A method entry trace macro with arguments for static class methods or global functions.
+
+    CNT_STATIC_ENTRY_ARGS(args) is similar to CNT_STATIC_ENTRY but it allows arguments to be
+    output on the same line without needing to resort to a separate CNT_LOG_ARGS call. This is
+    especially handy for outputting the parameters of the method call.
+
+    The following example shows proper usage of the CNT_STATIC_ENTRY_ARGS(args) macro. Assuming
+    a class has been declared with a static method that is implemented like this:
+
+    \code
+    #include <QString>
+    #include <cntdebug.h>
+
+    void MyClass::myStaticMethod(const QString &text, int number)
+    {
+        CNT_STATIC_ENTRY_ARGS("text =" << text << "number =" << number);
+
+        int i = 1;
+        i++;
+
+        CNT_EXIT
+    }
+    \endcode
+
+    calling MyClass::myStaticMethod(QString("foo"), 74) generates output lines of the following
+    format:
+
+    \code
+    2009-03-25 11:00:50.171 : static void MyClass::myStaticMethod(const QString&, int) entry, text = "foo" number = 74
+    2009-03-25 11:00:50.171 : static void MyClass::myStaticMethod(const QString&, int) exit
+    \endcode
+
+    \param args Any number of arguments that can be streamed into a QTextStream, joined together
+    by the streaming operator <<.
+    \sa CNT_STATIC_ENTRY.
+*/
+
+/*!
+    \def CNT_ENTRY
+    \brief A method entry trace macro for class methods.
+
+    Invoking CNT_ENTRY outputs a timestamp followed by the scope in which the macro
+    was invoked, the word "entry" and the this pointer value of the instance invoking the
+    macro.
+
+    The this pointer value included in the debug output can help make the output more readable, as
+    it allows different instances of the same class to be distinguished from each other.
+
+    CNT_ENTRY is intended to be used as the first line of class methods. There is a corresponding
+    exit macro, CNT_EXIT.
+
+    The following example shows proper usage of the CNT_ENTRY macro. Assuming a class has been
+    declared with a non-static method that is implemented like this:
+
+    \code
+    #include <cntdebug.h>
+
+    void MyClass::myMethod()
+    {
+        CNT_ENTRY
+
+        int i = 1;
+        i++;
+
+        CNT_EXIT
+    }
+    \endcode
+
+    calling myMethod() on an instance of MyClass generates output lines of the following format:
+
+    \code
+    2009-03-25 11:00:50.171 : void MyClass::myMethod() this 0x6cdab90 entry
+    2009-03-25 11:00:50.171 : void MyClass::myMethod() exit
+    \endcode
+
+    \sa CNT_ENTRY_ARGS(args), CNT_EXIT.
+*/
+
+/*!
+    \def CNT_ENTRY_ARGS(args)
+    \brief A method entry trace macro with arguments for class methods.
+
+    CNT_ENTRY_ARGS(args) is similar to CNT_ENTRY but it allows arguments to be output on the
+    same line without needing to resort to a separate CNT_LOG_ARGS call. This is especially
+    handy for outputting the parameters of the method call.
+
+    The following example shows proper usage of the CNT_ENTRY_ARGS(args)) macro. Assuming a
+    class has been declared with a non-static method that is implemented like this:
+
+    \code
+    #include <QString>
+    #include <cntdebug.h>
+
+    void MyClass::myMethod(const QString &text, int number)
+    {
+        CNT_ENTRY_ARGS("text =" << text << "number =" << number);
+
+        int i = 1;
+        i++;
+
+        CNT_EXIT
+    }
+    \endcode
+
+    calling myMethod(QString("foo"), 74) on an instance of MyClass generates output lines of the
+    following format:
+
+    \code
+    2009-03-25 11:00:50.171 : void MyClass::myMethod(const QString&, int) this 0x6cdab90 entry, text = "foo" number = 74
+    2009-03-25 11:00:50.171 : void MyClass::myMethod(const QString&, int) exit
+    \endcode
+
+    \param args Any number of arguments that can be streamed into a QTextStream, joined together
+    by the streaming operator <<.
+    \sa CNT_ENTRY, CNT_EXIT.
+*/
+
+/*!
+    \def CNT_EXIT
+    \brief A method exit trace macro for class methods or global functions.
+
+    Invoking CNT_EXIT outputs a timestamp followed by the scope in which the macro
+    was invoked and the word "exit".
+
+    CNT_EXIT is intended to be used as the last line of class methods and global functions,
+    just before the return statement, if any. There are two corresponding entry macros,
+    CNT_ENTRY and CNT_STATIC_ENTRY, depending on whether the method being traced is a
+    non-static or a static class method. CNT_EXIT makes no distinction between these two types
+    of methods and is to be used for both.
+
+    See CNT_ENTRY or CNT_STATIC_ENTRY for an example of how to use CNT_EXIT.
+
+    \sa CNT_EXIT_ARGS(args), CNT_ENTRY, CNT_STATIC_ENTRY.
+*/
+
+/*!
+    \def CNT_EXIT_ARGS(args)
+    \brief A method exit trace macro with arguments for class methods or global functions.
+
+    CNT_EXIT_ARGS(args) is similar to CNT_EXIT but it allows arguments to be output on the
+    same line without needing to resort to a separate CNT_LOG_ARGS call. This is especially
+    handy for outputting the return value of the method call.
+
+    The following example shows proper usage of the CNT_EXIT_ARGS(args) macro. Assuming a
+    class has been declared with a static method that is implemented like this:
+
+    \code
+    #include <QString>
+    #include <cntdebug.h>
+
+    int MyClass::myStaticMethod(const QString &text)
+    {
+        CNT_STATIC_ENTRY_ARGS("text =" << text);
+
+        int length = text.length();
+
+        CNT_EXIT_ARGS("length" << length);
+
+        return length;
+    }
+    \endcode
+
+    calling MyClass::myStaticMethod(QString("foo")) generates output lines of the following format:
+
+    \code
+    2009-03-25 13:20:36.448 : static int MyClass::myStaticMethod(const QString&) entry, text = "foo"
+    2009-03-25 13:20:36.448 : static int MyClass::myStaticMethod(const QString&) exit, length 3
+    \endcode
+
+    Although the example above is a static method, CNT_EXIT_ARGS(args) works identically for
+    non-static class methods and global functions.
+
+    \param args Any number of arguments that can be streamed into a QTextStream, joined together
+    by the streaming operator <<.
+    \sa CNT_EXIT
+*/
+
+/*!
+    \def CNT_LOG
+    \brief A trace macro for class methods or global functions.
+
+    Invoking CNT_LOG outputs a timestamp followed by the scope in which the macro
+    was invoked and the this pointer value of the instance invoking the
+    macro.
+
+    CNT_LOG is similar to CNT_ENTRY but it is especially handy for marking calls to methods that
+    cannot fail, such as an empty constructor, without needing to resort to a separate CNT_EXIT call.
+
+    The following example shows proper usage of the CNT_LOG(args) macro. Assuming a
+    class has been declared with a static method that is implemented like this:
+
+    \code
+    #include <QString>
+    #include <cntdebug.h>
+
+    MyClass::MyClass()
+    {
+        CNT_LOG
+    }
+    \endcode
+
+    calling new MyClass() generates output lines of the following format:
+
+    \code
+    2009-03-25 13:20:36.448 : MyClass::MyClass() this 0x6cdab90
+    \endcode
+
+    \sa CNT_LOG_ARGS
+*/
+
+/*!
+    \def CNT_LOG_ARGS(args)
+    \brief A generic trace macro with arguments for class methods or global functions.
+
+    The following example shows how to produce arbitrary debug output:
+
+    \code
+    #include <QString>
+    #include <cntdebug.h>
+
+    void MyClass::myMethod()
+    {
+        CNT_ENTRY
+
+        QString myString("This is a string.");
+        int myValue = 109;
+
+        CNT_LOG_ARGS("this is a debug message, myString =" << myString << "myValue =" << myValue)
+
+        CNT_EXIT
+    }
+    \endcode
+
+    calling myMethod() on an instance of MyClass generates output lines of the following format:
+
+    \code
+    2009-03-25 13:45:22.083 : void MyClass::myMethod() this 0x6cdab90 entry
+    2009-03-25 13:45:22.083 : void MyClass::myMethod() this is a debug message, myString = "This is a string." myValue = 109
+    2009-03-25 13:45:22.083 : void MyClass::myMethod() exit
+    \endcode
+
+    Any number of arguments may be printed by chaining them together with the streaming operator
+    <<. Notice that a single space character is automatically added between each streamed
+    argument, hence the hardcoded strings in the example above, such as "myValue =", do not have
+    a space at the beginning and end of the string. This automatic space addition is a feature
+    of qDebug() streaming and cannot be disabled.
+
+    \param args Any number of arguments that can be streamed into a QTextStream, joined together
+    by the streaming operator <<.
+*/
+
+
+#ifdef _DEBUG
+    #define CNT_UNUSED(name)
+    #define CNT_STATIC_ENTRY qDebug() << __PRETTY_FUNCTION__ << "entry";
+    #define CNT_STATIC_ENTRY_ARGS(args) qDebug() << __PRETTY_FUNCTION__ << "entry," << args;
+    #define CNT_ENTRY qDebug() << __PRETTY_FUNCTION__ << "this" << (void *)this << "entry";
+    #define CNT_ENTRY_ARGS(args) qDebug() << __PRETTY_FUNCTION__ << "this" << (void *)this << "entry," << args;
+    #define CNT_EXIT qDebug() << __PRETTY_FUNCTION__ << "exit";
+    #define CNT_EXIT_ARGS(args) qDebug() << __PRETTY_FUNCTION__ << "exit," << args;
+    #define CNT_LOG qDebug() << __PRETTY_FUNCTION__ << "this" << (void *)this;
+    #define CNT_LOG_ARGS(args) qDebug() << __PRETTY_FUNCTION__ << args;
+#else
+    #define CNT_UNUSED(name) Q_UNUSED(name)
+    #define CNT_STATIC_ENTRY
+    #define CNT_STATIC_ENTRY_ARGS(args)
+    #define CNT_ENTRY
+    #define CNT_ENTRY_ARGS(args)
+    #define CNT_EXIT
+    #define CNT_EXIT_ARGS(args)
+    #define CNT_LOG
+    #define CNT_LOG_ARGS(args)
+#endif // _DEBUG
+
+// for tracing memory leaks
+#ifdef TRACK_MEMORY_LEAKS
+    #include <hbapplication.h>
+
+    #define CNT_TRACK_QOBJECTLIFE(obj) { new CntQObjectTracker(obj, __FILE__, __LINE__); }
+    #define CNT_TRACK_QOBJECTLIVES(objects) { foreach (QObject* object, objects) new CntQObjectTracker(object, __FILE__, __LINE__); }
+
+    class CntQObjectTracker : public QObject
+    {
+        Q_OBJECT
+        public:
+            CntQObjectTracker(QObject *obj, QString fileName, int fileLine) {
+                objectName = obj->metaObject()->className();
+                createdInFile = fileName;
+                createdAtLine = fileLine;
+                connect(obj, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
+                connect(HbApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(reportMemoryLeak()));
+            }
+        public slots:
+            void objectDestroyed() { delete this; }
+        private slots:
+            void reportMemoryLeak() { qDebug() << "MEMORY LEAK: The" << objectName << "object in" << createdInFile << "at line" << createdAtLine << "was never destroyed."; delete this; }
+        private: // functions
+            ~CntQObjectTracker() {}
+        private: // data
+            QString  objectName;
+            QString  createdInFile;
+            int      createdAtLine;
+    };
+#else
+    #define CNT_TRACK_QOBJECTLIFE(obj)
+    #define CNT_TRACK_QOBJECTLIVES(obj)
+#endif
+
+#endif // CNTDEBUG_H