Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Class and thread to manage debug output
Forum Updated to NodeBB v4.3 + New Features

Class and thread to manage debug output

Scheduled Pinned Locked Moved Unsolved General and Desktop
23 Posts 5 Posters 2.2k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • SPlattenS SPlatten

    @JonB Thats exactly what I do in a helper thread, however despite cutting it into chunks and outputting chunks in a thread it still doesn't output everything.

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by
    #12

    @SPlatten
    Have you at least verified that if you let cout/cerr go to file, you get everything correctly? So that you know it is some console handling issue? And I assume qDebug() has the same issue when sent to console?

    SPlattenS 2 Replies Last reply
    0
    • JonBJ JonB

      @SPlatten
      Have you at least verified that if you let cout/cerr go to file, you get everything correctly? So that you know it is some console handling issue? And I assume qDebug() has the same issue when sent to console?

      SPlattenS Offline
      SPlattenS Offline
      SPlatten
      wrote on last edited by
      #13

      @JonB , hello, this is two issues, one with not all the data appearing and the other trying to fix the thread to use QWaitCondition. I'll try writing to a file now and report back when I've done it.

      Kind Regards,
      Sy

      1 Reply Last reply
      0
      • JonBJ JonB

        @SPlatten
        Have you at least verified that if you let cout/cerr go to file, you get everything correctly? So that you know it is some console handling issue? And I assume qDebug() has the same issue when sent to console?

        SPlattenS Offline
        SPlattenS Offline
        SPlatten
        wrote on last edited by
        #14

        @JonB , if I write the entire string to a file:

        static FILE* fp = nullptr;
        void clsDebugService::close() {
            if ( fp != nullptr ) {
                fclose(fp);
                fp = nullptr;
            }
        }
        void clsDebugService::toFile(QString strData) {
            if ( fp == nullptr ) {
                fp = fopen("/Users/simonplatten/build-XMLMPAM-Desktop_Qt_5_14_2_clang_64bit-Debug/dump.txt", "wt");
            }
            fputs(strData.toLatin1().data(), fp);
            fflush(fp);
        }
        

        After calling this I close the file, the text file contains absolutely everything and is perfect, however if I then use the same routines in my test loop that breaks the string into 80 byte packets I don't get everything in the file. Which to me points to a problem in my loop.

        Kind Regards,
        Sy

        1 Reply Last reply
        0
        • SPlattenS SPlatten

          This is the new version of the class using a Wait Conditiion and Mutex, it isn't right, can someone help me fix it?

          Prototype:

          /**
           * File:    clsDebugService.h
           * Notes:   This file contains the prototype for the clsDebugService class.
           *******************************************************************************
           * Class:   clsDebugService
           *
           * Static Members:
           *  msMutex           Mutex
           *  msStack           Stack of messages to service
           *  msulngDbgSeqNo    Debugging sequence number
           *
           * Static Methods:
           *  pushDebug         Appends a debug message string to the log
           *  serviceDebugQueue Installs a thread to service the debug stack
           *  spMutex           Access method to get address of mutex
           *
           * Members:
           *  mblnTerminate     true to terminate thread
           *
           * Methods:
           *  clsDebugService   Class constructor
           *  ~clsDebugService  Class destructor
           *  run               Thread body
           *******************************************************************************
           * History: 2020/07/16 Created by Simon Platten
           */
          #ifndef CLSDEBUGSERVICE_H
              #define CLSDEBUGSERVICE_H
          
              #include <QStack>
              #include <QThread>
              #include <QWaitCondition>
          
              class clsDebugService : public QThread {
              private:
                  static ulong msulngDbgSeqNo;
                  static clsDebugService* mspService;
                  static QStack<QString> msStack;
                  static QMutex msMutex;
          
                  bool mblnTerminate;
                  QWaitCondition mWaitCondition;
          
                  void run();
          
              public:
                  explicit clsDebugService();
                  ~clsDebugService();
          
                  static void pushDebug(QString strMsg);
                  static void serviceDebugQueue();
                  static QMutex* spMutex() { return &msMutex; }
              };
          #endif // CLSDEBUGSERVICE_H
          

          Implementation:

          #include <iostream>
          
          #include <clsDebugService.h>
          #include <clsMainWnd.h>
          //Static members
          QMutex clsDebugService::msMutex;
          QStack<QString> clsDebugService::msStack;
          ulong clsDebugService::msulngDbgSeqNo = 0;
          clsDebugService* clsDebugService::mspService = nullptr;
          /**
           * @brief clsDebugService::clsDebugService
           */
          clsDebugService::clsDebugService() {
              mblnTerminate = false;
              start();
          }
          /**
           * @brief clsDebugService::~clsDebugService (Destructor)
           */
          clsDebugService::~clsDebugService() {
              mblnTerminate = true;
              terminate();
          }
          /**
           * @brief clsDebugService::pushDebug
           * @param strMsg : The message to log
           */
          void clsDebugService::pushDebug(QString strMsg) {
              if ( strMsg.length() > 0 ) {
          //Wait for mutex to be available then lock it            
                  QMutexLocker lock(clsDebugService::spMutex());
          //Insert next sequence number before message
                  if ( msulngDbgSeqNo >= 199 ) {                                          //HACK
                      strMsg += "!!!";                                                    //HACK
                      std::cout << strMsg.toLatin1().data() << std::endl << std::flush;   //HACK
                      std::cout << strMsg.length() << std::endl << std::flush;            //HACK
                  }                                                                       //HACK
                  strMsg = QString("S%1 ").arg(++msulngDbgSeqNo, 20, 10, QChar('0')) + strMsg;
                  msStack.push_front(strMsg);
              }
          }
          /**
           * @brief clsDebugService::run
           */
          void clsDebugService::run() {
              while ( mblnTerminate == false ) {
          //Get pointer to class mutex        
                  QMutex* pMutex = clsDebugService::spMutex();
          //Wait for mutex to be unlocked        
                  mWaitCondition.wait(pMutex);
          //Lock it whilst we access the stack        
                  QMutexLocker lock(pMutex);
                  QString strData = clsDebugService::msStack.pop();
          
                  if ( strData.isEmpty() == true ) {
                      continue;
                  }
                  std::cout << strData.toLatin1().data() << std::endl << std::flush;
              }
              std::cout << "How did I get here?" << std::endl << std::flush;
          }
          /**
           * @brief qDebugMsgHandler
           * @param type : type of message
           * @param context : message log context
           * @param strMsg : message
           */
          static void qDebugMsgHandler(QtMsgType type, const QMessageLogContext& context, const QString& strMsg) {
              static const QString scstrQJSONObject("QJsonObject(");
              static const quint16 cuint16InfoLengthLimit = 128;
          
              quint16 intMsgLength = static_cast<quint16>(strMsg.length());
              quint16 uint16Parts = intMsgLength / cuint16InfoLengthLimit;
              QString strFile, strFunction, strInfo, strPrefix;
              long lngLine = 0;
          
              switch( type ) {
              case QtDebugMsg:
                  strPrefix = "   Debug:";
                  break;
              case QtInfoMsg:
                  strPrefix = "    Info:";
                  break;
              case QtWarningMsg:
                  strPrefix = " Warning:";
                  break;
              case QtCriticalMsg:
                  strPrefix = "Critical:";
                  break;
              case QtFatalMsg:
                  strPrefix = "   Fatal:";
                  break;
              }
              if ( uint16Parts == 0 ) {
                  uint16Parts = 1;
              }
              for( quint16 uint16Part=0; uint16Part<uint16Parts; uint16Part++ ) {
                  QString strOutput(strPrefix)
                         ,strPart = strMsg.mid(uint16Part * cuint16InfoLengthLimit, cuint16InfoLengthLimit);
                  if ( strPart.startsWith(scstrQJSONObject) ) {
          //Message contains a JSON object, extract the details
                      int intLength = strPart.length() - (scstrQJSONObject.length() + 1);
                      QString strJSON = strPart.mid(scstrQJSONObject.length(), intLength);
                      QJsonDocument objDoc = QJsonDocument::fromJson(strJSON.toUtf8());
          
                      if ( objDoc.isNull() ) {
                          return;
                      }
                      QJsonObject objJSON = objDoc.object();
                      QString strLine(objJSON.take("line").toString());
                      strFile = objJSON.take("file").toString();
                      lngLine = strLine.toLong();
                      strInfo = objJSON.take("msg").toString();
                      type = static_cast<QtMsgType>(objJSON.take("type").toInt());
                  } else {
                      strFile = QString(context.file);
          
                      if ( context.function ) {
                          strFunction = QString(context.function);
                          strFunction = strFunction.mid(0, strFunction.indexOf(clsXMLnode::msccBrktOpen));
                      }
                      if ( context.line > 0 ) {
                          lngLine = context.line;
                      }
                      strInfo = strPart;
                  }
                  if ( uint16Part == 0 ) {
                      if ( lngLine > 0 ) {
                          strOutput += QString(" L%1:").arg(lngLine, 8, 10, QChar('0'));
                      }
                      if ( strFile.length() > 0 ) {
                          strOutput += strFile + " ";
                      }
                      if ( strFunction.length() > 0 ) {
                          strOutput += strFunction;
                      }
                      if ( strOutput.length() > 0 ) {
                          strOutput += ": ";
                      }
                      clsDebugService::pushDebug(strOutput);
                      clsDebugService::pushDebug(strPrefix + strInfo);
                  } else if ( uint16Parts > 1 ) {
                      strOutput += strInfo;
                      clsDebugService::pushDebug(strOutput);
                  }
              }
          }
          /**
           * @brief clsDebugService::serviceDebugQueue
           */
          void clsDebugService::serviceDebugQueue() {
              Q_ASSERT_X(clsDebugService::mspService==nullptr, "clsDebugService"
                                                             , "Service already started!");
              //Install message handler
              qInstallMessageHandler(qDebugMsgHandler);
              //Create instance of the service
              new clsDebugService();
          }
          

          The pushDebug method locks a mutex and the thread uses a wait condition on the same mutex to be available then locks it, but it doesn't work, when I launch this it jumps into:

          atomic_cxx11.h

             template <typename T> static inline
              T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
              {
                  return _q_value.fetch_add(valueToAdd, std::memory_order_release);
              }
          
          SPlattenS Offline
          SPlattenS Offline
          SPlatten
          wrote on last edited by
          #15

          @SPlatten said in Class and thread to manage debug output:

          This is the new version of the class using a Wait Conditiion and Mutex, it isn't right, can someone help me fix it?

          Prototype:

          /**
           * File:    clsDebugService.h
           * Notes:   This file contains the prototype for the clsDebugService class.
           *******************************************************************************
           * Class:   clsDebugService
           *
           * Static Members:
           *  msMutex           Mutex
           *  msStack           Stack of messages to service
           *  msulngDbgSeqNo    Debugging sequence number
           *
           * Static Methods:
           *  pushDebug         Appends a debug message string to the log
           *  serviceDebugQueue Installs a thread to service the debug stack
           *  spMutex           Access method to get address of mutex
           *
           * Members:
           *  mblnTerminate     true to terminate thread
           *
           * Methods:
           *  clsDebugService   Class constructor
           *  ~clsDebugService  Class destructor
           *  run               Thread body
           *******************************************************************************
           * History: 2020/07/16 Created by Simon Platten
           */
          #ifndef CLSDEBUGSERVICE_H
              #define CLSDEBUGSERVICE_H
          
              #include <QStack>
              #include <QThread>
              #include <QWaitCondition>
          
              class clsDebugService : public QThread {
              private:
                  static ulong msulngDbgSeqNo;
                  static clsDebugService* mspService;
                  static QStack<QString> msStack;
                  static QMutex msMutex;
          
                  bool mblnTerminate;
                  QWaitCondition mWaitCondition;
          
                  void run();
          
              public:
                  explicit clsDebugService();
                  ~clsDebugService();
          
                  static void pushDebug(QString strMsg);
                  static void serviceDebugQueue();
                  static QMutex* spMutex() { return &msMutex; }
              };
          #endif // CLSDEBUGSERVICE_H
          

          Implementation:

          #include <iostream>
          
          #include <clsDebugService.h>
          #include <clsMainWnd.h>
          //Static members
          QMutex clsDebugService::msMutex;
          QStack<QString> clsDebugService::msStack;
          ulong clsDebugService::msulngDbgSeqNo = 0;
          clsDebugService* clsDebugService::mspService = nullptr;
          /**
           * @brief clsDebugService::clsDebugService
           */
          clsDebugService::clsDebugService() {
              mblnTerminate = false;
              start();
          }
          /**
           * @brief clsDebugService::~clsDebugService (Destructor)
           */
          clsDebugService::~clsDebugService() {
              mblnTerminate = true;
              terminate();
          }
          /**
           * @brief clsDebugService::pushDebug
           * @param strMsg : The message to log
           */
          void clsDebugService::pushDebug(QString strMsg) {
              if ( strMsg.length() > 0 ) {
          //Wait for mutex to be available then lock it            
                  QMutexLocker lock(clsDebugService::spMutex());
          //Insert next sequence number before message
                  if ( msulngDbgSeqNo >= 199 ) {                                          //HACK
                      strMsg += "!!!";                                                    //HACK
                      std::cout << strMsg.toLatin1().data() << std::endl << std::flush;   //HACK
                      std::cout << strMsg.length() << std::endl << std::flush;            //HACK
                  }                                                                       //HACK
                  strMsg = QString("S%1 ").arg(++msulngDbgSeqNo, 20, 10, QChar('0')) + strMsg;
                  msStack.push_front(strMsg);
              }
          }
          /**
           * @brief clsDebugService::run
           */
          void clsDebugService::run() {
              while ( mblnTerminate == false ) {
          //Get pointer to class mutex        
                  QMutex* pMutex = clsDebugService::spMutex();
          //Wait for mutex to be unlocked        
                  mWaitCondition.wait(pMutex);
          //Lock it whilst we access the stack        
                  QMutexLocker lock(pMutex);
                  QString strData = clsDebugService::msStack.pop();
          
                  if ( strData.isEmpty() == true ) {
                      continue;
                  }
                  std::cout << strData.toLatin1().data() << std::endl << std::flush;
              }
              std::cout << "How did I get here?" << std::endl << std::flush;
          }
          /**
           * @brief qDebugMsgHandler
           * @param type : type of message
           * @param context : message log context
           * @param strMsg : message
           */
          static void qDebugMsgHandler(QtMsgType type, const QMessageLogContext& context, const QString& strMsg) {
              static const QString scstrQJSONObject("QJsonObject(");
              static const quint16 cuint16InfoLengthLimit = 128;
          
              quint16 intMsgLength = static_cast<quint16>(strMsg.length());
              quint16 uint16Parts = intMsgLength / cuint16InfoLengthLimit;
              QString strFile, strFunction, strInfo, strPrefix;
              long lngLine = 0;
          
              switch( type ) {
              case QtDebugMsg:
                  strPrefix = "   Debug:";
                  break;
              case QtInfoMsg:
                  strPrefix = "    Info:";
                  break;
              case QtWarningMsg:
                  strPrefix = " Warning:";
                  break;
              case QtCriticalMsg:
                  strPrefix = "Critical:";
                  break;
              case QtFatalMsg:
                  strPrefix = "   Fatal:";
                  break;
              }
              if ( uint16Parts == 0 ) {
                  uint16Parts = 1;
              }
              for( quint16 uint16Part=0; uint16Part<uint16Parts; uint16Part++ ) {
                  QString strOutput(strPrefix)
                         ,strPart = strMsg.mid(uint16Part * cuint16InfoLengthLimit, cuint16InfoLengthLimit);
                  if ( strPart.startsWith(scstrQJSONObject) ) {
          //Message contains a JSON object, extract the details
                      int intLength = strPart.length() - (scstrQJSONObject.length() + 1);
                      QString strJSON = strPart.mid(scstrQJSONObject.length(), intLength);
                      QJsonDocument objDoc = QJsonDocument::fromJson(strJSON.toUtf8());
          
                      if ( objDoc.isNull() ) {
                          return;
                      }
                      QJsonObject objJSON = objDoc.object();
                      QString strLine(objJSON.take("line").toString());
                      strFile = objJSON.take("file").toString();
                      lngLine = strLine.toLong();
                      strInfo = objJSON.take("msg").toString();
                      type = static_cast<QtMsgType>(objJSON.take("type").toInt());
                  } else {
                      strFile = QString(context.file);
          
                      if ( context.function ) {
                          strFunction = QString(context.function);
                          strFunction = strFunction.mid(0, strFunction.indexOf(clsXMLnode::msccBrktOpen));
                      }
                      if ( context.line > 0 ) {
                          lngLine = context.line;
                      }
                      strInfo = strPart;
                  }
                  if ( uint16Part == 0 ) {
                      if ( lngLine > 0 ) {
                          strOutput += QString(" L%1:").arg(lngLine, 8, 10, QChar('0'));
                      }
                      if ( strFile.length() > 0 ) {
                          strOutput += strFile + " ";
                      }
                      if ( strFunction.length() > 0 ) {
                          strOutput += strFunction;
                      }
                      if ( strOutput.length() > 0 ) {
                          strOutput += ": ";
                      }
                      clsDebugService::pushDebug(strOutput);
                      clsDebugService::pushDebug(strPrefix + strInfo);
                  } else if ( uint16Parts > 1 ) {
                      strOutput += strInfo;
                      clsDebugService::pushDebug(strOutput);
                  }
              }
          }
          /**
           * @brief clsDebugService::serviceDebugQueue
           */
          void clsDebugService::serviceDebugQueue() {
              Q_ASSERT_X(clsDebugService::mspService==nullptr, "clsDebugService"
                                                             , "Service already started!");
              //Install message handler
              qInstallMessageHandler(qDebugMsgHandler);
              //Create instance of the service
              new clsDebugService();
          }
          

          The pushDebug method locks a mutex and the thread uses a wait condition on the same mutex to be available then locks it, but it doesn't work, when I launch this it jumps into:

          atomic_cxx11.h

             template <typename T> static inline
              T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
              {
                  return _q_value.fetch_add(valueToAdd, std::memory_order_release);
              }
          

          Can anyone help me with this?

          Kind Regards,
          Sy

          JKSHJ 1 Reply Last reply
          0
          • SPlattenS SPlatten

            @SPlatten said in Class and thread to manage debug output:

            This is the new version of the class using a Wait Conditiion and Mutex, it isn't right, can someone help me fix it?

            Prototype:

            /**
             * File:    clsDebugService.h
             * Notes:   This file contains the prototype for the clsDebugService class.
             *******************************************************************************
             * Class:   clsDebugService
             *
             * Static Members:
             *  msMutex           Mutex
             *  msStack           Stack of messages to service
             *  msulngDbgSeqNo    Debugging sequence number
             *
             * Static Methods:
             *  pushDebug         Appends a debug message string to the log
             *  serviceDebugQueue Installs a thread to service the debug stack
             *  spMutex           Access method to get address of mutex
             *
             * Members:
             *  mblnTerminate     true to terminate thread
             *
             * Methods:
             *  clsDebugService   Class constructor
             *  ~clsDebugService  Class destructor
             *  run               Thread body
             *******************************************************************************
             * History: 2020/07/16 Created by Simon Platten
             */
            #ifndef CLSDEBUGSERVICE_H
                #define CLSDEBUGSERVICE_H
            
                #include <QStack>
                #include <QThread>
                #include <QWaitCondition>
            
                class clsDebugService : public QThread {
                private:
                    static ulong msulngDbgSeqNo;
                    static clsDebugService* mspService;
                    static QStack<QString> msStack;
                    static QMutex msMutex;
            
                    bool mblnTerminate;
                    QWaitCondition mWaitCondition;
            
                    void run();
            
                public:
                    explicit clsDebugService();
                    ~clsDebugService();
            
                    static void pushDebug(QString strMsg);
                    static void serviceDebugQueue();
                    static QMutex* spMutex() { return &msMutex; }
                };
            #endif // CLSDEBUGSERVICE_H
            

            Implementation:

            #include <iostream>
            
            #include <clsDebugService.h>
            #include <clsMainWnd.h>
            //Static members
            QMutex clsDebugService::msMutex;
            QStack<QString> clsDebugService::msStack;
            ulong clsDebugService::msulngDbgSeqNo = 0;
            clsDebugService* clsDebugService::mspService = nullptr;
            /**
             * @brief clsDebugService::clsDebugService
             */
            clsDebugService::clsDebugService() {
                mblnTerminate = false;
                start();
            }
            /**
             * @brief clsDebugService::~clsDebugService (Destructor)
             */
            clsDebugService::~clsDebugService() {
                mblnTerminate = true;
                terminate();
            }
            /**
             * @brief clsDebugService::pushDebug
             * @param strMsg : The message to log
             */
            void clsDebugService::pushDebug(QString strMsg) {
                if ( strMsg.length() > 0 ) {
            //Wait for mutex to be available then lock it            
                    QMutexLocker lock(clsDebugService::spMutex());
            //Insert next sequence number before message
                    if ( msulngDbgSeqNo >= 199 ) {                                          //HACK
                        strMsg += "!!!";                                                    //HACK
                        std::cout << strMsg.toLatin1().data() << std::endl << std::flush;   //HACK
                        std::cout << strMsg.length() << std::endl << std::flush;            //HACK
                    }                                                                       //HACK
                    strMsg = QString("S%1 ").arg(++msulngDbgSeqNo, 20, 10, QChar('0')) + strMsg;
                    msStack.push_front(strMsg);
                }
            }
            /**
             * @brief clsDebugService::run
             */
            void clsDebugService::run() {
                while ( mblnTerminate == false ) {
            //Get pointer to class mutex        
                    QMutex* pMutex = clsDebugService::spMutex();
            //Wait for mutex to be unlocked        
                    mWaitCondition.wait(pMutex);
            //Lock it whilst we access the stack        
                    QMutexLocker lock(pMutex);
                    QString strData = clsDebugService::msStack.pop();
            
                    if ( strData.isEmpty() == true ) {
                        continue;
                    }
                    std::cout << strData.toLatin1().data() << std::endl << std::flush;
                }
                std::cout << "How did I get here?" << std::endl << std::flush;
            }
            /**
             * @brief qDebugMsgHandler
             * @param type : type of message
             * @param context : message log context
             * @param strMsg : message
             */
            static void qDebugMsgHandler(QtMsgType type, const QMessageLogContext& context, const QString& strMsg) {
                static const QString scstrQJSONObject("QJsonObject(");
                static const quint16 cuint16InfoLengthLimit = 128;
            
                quint16 intMsgLength = static_cast<quint16>(strMsg.length());
                quint16 uint16Parts = intMsgLength / cuint16InfoLengthLimit;
                QString strFile, strFunction, strInfo, strPrefix;
                long lngLine = 0;
            
                switch( type ) {
                case QtDebugMsg:
                    strPrefix = "   Debug:";
                    break;
                case QtInfoMsg:
                    strPrefix = "    Info:";
                    break;
                case QtWarningMsg:
                    strPrefix = " Warning:";
                    break;
                case QtCriticalMsg:
                    strPrefix = "Critical:";
                    break;
                case QtFatalMsg:
                    strPrefix = "   Fatal:";
                    break;
                }
                if ( uint16Parts == 0 ) {
                    uint16Parts = 1;
                }
                for( quint16 uint16Part=0; uint16Part<uint16Parts; uint16Part++ ) {
                    QString strOutput(strPrefix)
                           ,strPart = strMsg.mid(uint16Part * cuint16InfoLengthLimit, cuint16InfoLengthLimit);
                    if ( strPart.startsWith(scstrQJSONObject) ) {
            //Message contains a JSON object, extract the details
                        int intLength = strPart.length() - (scstrQJSONObject.length() + 1);
                        QString strJSON = strPart.mid(scstrQJSONObject.length(), intLength);
                        QJsonDocument objDoc = QJsonDocument::fromJson(strJSON.toUtf8());
            
                        if ( objDoc.isNull() ) {
                            return;
                        }
                        QJsonObject objJSON = objDoc.object();
                        QString strLine(objJSON.take("line").toString());
                        strFile = objJSON.take("file").toString();
                        lngLine = strLine.toLong();
                        strInfo = objJSON.take("msg").toString();
                        type = static_cast<QtMsgType>(objJSON.take("type").toInt());
                    } else {
                        strFile = QString(context.file);
            
                        if ( context.function ) {
                            strFunction = QString(context.function);
                            strFunction = strFunction.mid(0, strFunction.indexOf(clsXMLnode::msccBrktOpen));
                        }
                        if ( context.line > 0 ) {
                            lngLine = context.line;
                        }
                        strInfo = strPart;
                    }
                    if ( uint16Part == 0 ) {
                        if ( lngLine > 0 ) {
                            strOutput += QString(" L%1:").arg(lngLine, 8, 10, QChar('0'));
                        }
                        if ( strFile.length() > 0 ) {
                            strOutput += strFile + " ";
                        }
                        if ( strFunction.length() > 0 ) {
                            strOutput += strFunction;
                        }
                        if ( strOutput.length() > 0 ) {
                            strOutput += ": ";
                        }
                        clsDebugService::pushDebug(strOutput);
                        clsDebugService::pushDebug(strPrefix + strInfo);
                    } else if ( uint16Parts > 1 ) {
                        strOutput += strInfo;
                        clsDebugService::pushDebug(strOutput);
                    }
                }
            }
            /**
             * @brief clsDebugService::serviceDebugQueue
             */
            void clsDebugService::serviceDebugQueue() {
                Q_ASSERT_X(clsDebugService::mspService==nullptr, "clsDebugService"
                                                               , "Service already started!");
                //Install message handler
                qInstallMessageHandler(qDebugMsgHandler);
                //Create instance of the service
                new clsDebugService();
            }
            

            The pushDebug method locks a mutex and the thread uses a wait condition on the same mutex to be available then locks it, but it doesn't work, when I launch this it jumps into:

            atomic_cxx11.h

               template <typename T> static inline
                T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
                {
                    return _q_value.fetch_add(valueToAdd, std::memory_order_release);
                }
            

            Can anyone help me with this?

            JKSHJ Offline
            JKSHJ Offline
            JKSH
            Moderators
            wrote on last edited by JKSH
            #16

            @SPlatten said in Class and thread to manage debug output:

            //Get pointer to class mutex        
                    QMutex* pMutex = clsDebugService::spMutex();
            //Wait for mutex to be unlocked        
                    mWaitCondition.wait(pMutex);
            //Lock it whilst we access the stack        
                    QMutexLocker lock(pMutex);
            

            You must lock the mutex before you call wait(), and you must not re-lock it after the wait. See the documentation: https://doc.qt.io/qt-5/qwaitcondition.html#wait-2 (Note: The same concept applies to std::condition_variable and boost::condition_variable. You might want to review your existing projects that use condition variables.)

            {
                pMutex->lock();
                mWaitCondition.wait(pMutex);
            
                /* Do work on the stack here */
            
                pMutex->unlock();
            }
            

            Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

            SPlattenS 1 Reply Last reply
            3
            • JKSHJ JKSH

              @SPlatten said in Class and thread to manage debug output:

              //Get pointer to class mutex        
                      QMutex* pMutex = clsDebugService::spMutex();
              //Wait for mutex to be unlocked        
                      mWaitCondition.wait(pMutex);
              //Lock it whilst we access the stack        
                      QMutexLocker lock(pMutex);
              

              You must lock the mutex before you call wait(), and you must not re-lock it after the wait. See the documentation: https://doc.qt.io/qt-5/qwaitcondition.html#wait-2 (Note: The same concept applies to std::condition_variable and boost::condition_variable. You might want to review your existing projects that use condition variables.)

              {
                  pMutex->lock();
                  mWaitCondition.wait(pMutex);
              
                  /* Do work on the stack here */
              
                  pMutex->unlock();
              }
              
              SPlattenS Offline
              SPlattenS Offline
              SPlatten
              wrote on last edited by
              #17

              @JKSH , I'm not sure what I'm missing but I just don't seem to be able to get this to work.

              Kind Regards,
              Sy

              JKSHJ 1 Reply Last reply
              0
              • SPlattenS SPlatten

                @JKSH , I'm not sure what I'm missing but I just don't seem to be able to get this to work.

                JKSHJ Offline
                JKSHJ Offline
                JKSH
                Moderators
                wrote on last edited by
                #18

                @SPlatten said in Class and thread to manage debug output:

                I'm not sure what I'm missing but I just don't seem to be able to get this to work.

                Get which part to work?

                Please post a minimal compilable example that contains the issue

                Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                1 Reply Last reply
                0
                • SPlattenS Offline
                  SPlattenS Offline
                  SPlatten
                  wrote on last edited by
                  #19

                  @JKSH , to be honest I'm not sure if it was my implementation (probably) as I'm not sure I understand how it works:

                  My thread loop:

                      QMutex* pMutex = clsDebugService::spMutex();
                      while ( mblnTerminate == false ) {
                          mWaitCondition.wait(pMutex);
                          pMutex->lock();
                          //...
                         pMutex->unlock();
                      }
                  

                  Then in another function which pushes content onto a stack which the thread is supposed to service:

                  void clsDebugService::pushDebug(QString strMsg) {
                      if ( strMsg.length() > 0 ) {
                  //Wait for mutex to be available then lock it
                          QMutexLocker lock(clsDebugService::spMutex());
                  //Insert next sequence number before message
                          strMsg = QString("S%1 ").arg(++msint64DbgSeqNo, 20, 10, QChar('0')) + strMsg;
                          msStack.push_front(strMsg);
                      }
                  }
                  

                  Kind Regards,
                  Sy

                  JKSHJ 1 Reply Last reply
                  0
                  • SPlattenS SPlatten

                    @JKSH , to be honest I'm not sure if it was my implementation (probably) as I'm not sure I understand how it works:

                    My thread loop:

                        QMutex* pMutex = clsDebugService::spMutex();
                        while ( mblnTerminate == false ) {
                            mWaitCondition.wait(pMutex);
                            pMutex->lock();
                            //...
                           pMutex->unlock();
                        }
                    

                    Then in another function which pushes content onto a stack which the thread is supposed to service:

                    void clsDebugService::pushDebug(QString strMsg) {
                        if ( strMsg.length() > 0 ) {
                    //Wait for mutex to be available then lock it
                            QMutexLocker lock(clsDebugService::spMutex());
                    //Insert next sequence number before message
                            strMsg = QString("S%1 ").arg(++msint64DbgSeqNo, 20, 10, QChar('0')) + strMsg;
                            msStack.push_front(strMsg);
                        }
                    }
                    
                    JKSHJ Offline
                    JKSHJ Offline
                    JKSH
                    Moderators
                    wrote on last edited by
                    #20

                    @SPlatten said in Class and thread to manage debug output:

                    @JKSH , to be honest I'm not sure if it was my implementation (probably) as I'm not sure I understand how it works:

                    My thread loop:

                        QMutex* pMutex = clsDebugService::spMutex();
                        while ( mblnTerminate == false ) {
                            mWaitCondition.wait(pMutex);
                            pMutex->lock();
                            //...
                           pMutex->unlock();
                        }
                    

                    As I wrote yesterday, you must lock the mutex before you call wait(). The same rule applies to QWaitCondition, std::condition_variable, and boost:condition_variable.

                    wait() unlocks the mutex while waiting and then re-locks it again before allowing your code to run.

                    Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                    SPlattenS 1 Reply Last reply
                    0
                    • JKSHJ JKSH

                      @SPlatten said in Class and thread to manage debug output:

                      @JKSH , to be honest I'm not sure if it was my implementation (probably) as I'm not sure I understand how it works:

                      My thread loop:

                          QMutex* pMutex = clsDebugService::spMutex();
                          while ( mblnTerminate == false ) {
                              mWaitCondition.wait(pMutex);
                              pMutex->lock();
                              //...
                             pMutex->unlock();
                          }
                      

                      As I wrote yesterday, you must lock the mutex before you call wait(). The same rule applies to QWaitCondition, std::condition_variable, and boost:condition_variable.

                      wait() unlocks the mutex while waiting and then re-locks it again before allowing your code to run.

                      SPlattenS Offline
                      SPlattenS Offline
                      SPlatten
                      wrote on last edited by SPlatten
                      #21

                      @JKSH , ok, but this is where I am a little confused, what does a wait add? because using mutex'es and lock, causes the lock function to wait until it is unlocked.

                      Kind Regards,
                      Sy

                      JKSHJ 1 Reply Last reply
                      0
                      • SPlattenS SPlatten

                        @JKSH , ok, but this is where I am a little confused, what does a wait add? because using mutex'es and lock, causes the lock function to wait until it is unlocked.

                        JKSHJ Offline
                        JKSHJ Offline
                        JKSH
                        Moderators
                        wrote on last edited by
                        #22

                        @SPlatten said in Class and thread to manage debug output:

                        what does a wait add? because using mutex'es and lock, causes the lock function to wait until it is unlocked.

                        While a thread is waiting, the mutex is unlocked so that other threads can use the mutex.

                        This might be useful: https://stackoverflow.com/questions/31913547/how-do-stdunique-lock-and-stdcondition-variable-work

                        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                        1 Reply Last reply
                        1
                        • A Offline
                          A Offline
                          Anonymous_Banned275
                          wrote on last edited by
                          #23

                          I am on Ubuntu 16
                          I first noticed this when I codded just four < 16 characters long test cout /cerr messages in a sequence.
                          I have not paid much attention to what C++ I am using on Qt, I got bigger problems than to worry about C/C++.

                          However, made en error
                          std:cout <<... << endl;
                          missed std:: before endl
                          it complied, run AND
                          got some strange warning.
                          Then each message got extra "1" character at the end.

                          Here is anther example of "timing cout /cerr "

                          CODE :

                          #ifdef TRACE
                          std::cerr << "@file @function @line " <<FILE<< " "<< FUNCTION << " " << LINE << " "<< std::endl;
                          #endif

                          #ifdef TRACE
                          std::cout << "@file @function @line " <<FILE<< " "<< FUNCTION << " " << LINE << " "<< std::endl;
                          #endif
                          #ifdef TRACE
                          std::cout << "@file @function @line " <<FILE<< " "<< FUNCTION << " " << LINE << " "<< std::endl;
                          #endif
                          #ifdef TRACE
                          std::cout << "@file @function @line " <<FILE<< " "<< FUNCTION << " " << LINE << " "<< std::endl;
                          #endif
                          #ifdef TRACE
                          std::cerr << "@file @function @line " <<FILE<< " "<< FUNCTION << " " << LINE << " "<< std::endl;
                          #endif

                          OUTPUT:

                          c105f2dc-a4b0-438d-a93b-4c26c455dbad-image.png

                          CONSTRUCTOR @file @function @line ../../../examples/bluetooth/btscanner/tabwidget.cpp TabWidget 14

                          output from cerr
                          @file @function @line ../../../examples/bluetooth/btscanner/tabwidget.cpp on_scan_pressed 37
                          @file @function @line ../../../examples/bluetooth/btscanner/tabwidget.cpp on_scan_pressed 51

                          ouptut from cout
                          @file @function @line ../../../examples/bluetooth/btscanner/tabwidget.cpp on_scan_pressed 42
                          @file @function @line ../../../examples/bluetooth/btscanner/tabwidget.cpp on_scan_pressed 45
                          @file @function @line ../../../examples/bluetooth/btscanner/tabwidget.cpp on_scan_pressed 48

                          Note the "lines" sequence.

                          I had some sucess adding flush() after cout , which acording to spec is not necessry since cout inlcudes flush.

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved