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.
  • 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