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. [SOLVED] run a multithreaded program on a single core machine
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] run a multithreaded program on a single core machine

Scheduled Pinned Locked Moved General and Desktop
13 Posts 2 Posters 5.4k Views 1 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.
  • X Offline
    X Offline
    XGuy
    wrote on last edited by
    #1

    Hi all,
    i have a program in which i use QThreads and it runs perfectly on multicore machines. however i have a VM which has only one CPU core and when i run the application the cpu usage gets to 100%!!! and then i have to restart the machine.

    in my application when the program begins, 3 threads will be started but one of them runs in a while loop and waiting(blocking) for user reactions, and it only gets finished when the application quits. so in my application lifetime i always have 2 threads running(main thread, and the while loop thread) and i will start new threads from the main thread as needed.

    1 Reply Last reply
    0
    • JKSHJ Online
      JKSHJ Online
      JKSH
      Moderators
      wrote on last edited by
      #2

      Hi,

      When a multithreaded program behaves differently on different machines, it's very possible that the program has a "race condition":http://stackoverflow.com/questions/34510/what-is-a-race-condition. Please show us your thread code.

      It is definitely possible to run a multithreaded program on a single core CPU, but you should follow good design patterns. In Qt, you should process GUI reactions on the main thread, using signals and slots (do not use a separate thread to wait for user reactions). Have you used signals and slots before?

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

      1 Reply Last reply
      0
      • X Offline
        X Offline
        XGuy
        wrote on last edited by
        #3

        now that you mentioned race condition i think you are right becuase i'm using the same QMutex object for locking the threads! i think multiple threads try to access Qmutex and the race begins!
        here is my code:

        @
        wroker class header:
        class wroker : public QObject
        {
        Q_OBJECT
        public:
        QMutex m_mutex;
        // isFinished: slot event
        bool isFinished;
        }

        wroker class cpp:
        Worker::Worker(QObject *parent) :
        QObject(parent),
        m_mutex(QMutex::Recursive)
        {

        }

        // one thread will run this function and this is executed in a while loop /// until program is closed
        void worker::waitForSlotEvent()
        {
        while (!isFinished)
        {
        // WAIT FOR USB EVENT, ex: MASS STORAGE FLASH INSERTION/REMOVAL
        .
        .
        .
        emit slotEvent();
        }
        }

        int Worker::getData()
        {
        QMutexLocker mutexLocker(&m_mutex);
        .
        .
        .

        emit getDataFinished(returnValue);
        }

        int Worker::getAllConns()
        {
        QMutexLocker mutexLocker(&m_mutex);
        .
        .
        .

        emit getConnFinished(returnValue);

        }
        here is Mainwindow header:
        class Mainwindow : public QDialog {
        Q_OBJECT
        public:
        QThread thrSlotEvent;
        Worker objSlotEvent;
        QThread thrData;
        Worker objData;
        Worker objConn;
        QThread thrConn;
        }

        here is Mainwindow cpp:
        // app begins from here
        void Mainwindow::initApp()
        {
        .
        .
        .
        objData.moveToThread(&thrData);
        QObject::connect(&thrData, SIGNAL(started()), &objData, SLOT(getData()));
        QObject::connect(&objData, SIGNAL(getDataFinished(int)), this, SLOT(updateData(int)));
        thrData.start();
        .
        .
        .
        }

        void Mainwindow::updateData(int returnValue)
        {
        // RUN SLOT EVENT DETECTION
        startSlotEvent();

        //CHECK FOR ERRORS
        if(returnValue)
        {
            msg(returnValue);
            return;
        }
        
        // START THREAD Conn
        QObject::disconnect(&objConn, 0, 0, 0);
        QObject::disconnect(&thrConn, 0, 0, 0);
        objConn.moveToThread(&thrConn);
        QObject::connect(&thrConn, SIGNAL(started()), &objConn, SLOT(getAllConns()));
        QObject::connect(&objConn, SIGNAL(getConnFinished(int)),   this,  SLOT(getConnFinished(int)));
        thrConn.start();
        

        }

        void Mainwindow::startSlotEvent()
        {
        objSlotEvent.moveToThread(&thrSlotEvent);
        objSlotEvent.isFinished = false;
        QObject::connect(&thrSlotEvent, SIGNAL(started()), &objSlotEvent, SLOT(waitForSlotEvent()));
        QObject::connect(&objSlotEvent, SIGNAL(slotEvent()), this, SLOT(refreshList()));
        thrSlotEvent.start();
        }

        void Mainwindow::refreshList()
        {
        // here i update a QTreeView
        }

        }
        @

        1 Reply Last reply
        0
        • JKSHJ Online
          JKSHJ Online
          JKSH
          Moderators
          wrote on last edited by
          #4

          What is the mutex for? I can't see any multi-thread access.

          Why do you disconnect and re-connect signals in MainWindow::updateData()?

          What is objConnCert (Line #95)? Why do you move it every time MainWindow::updateData() is called?

          objSlotEvent, objData and objConn do 3 different jobs. Why are they instantiated from the same class?

          You should not use a blocking while loop (line #22) when the thread has an event loop. Use a QTimer instead to call a slot at regular intervals.

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

          1 Reply Last reply
          0
          • X Offline
            X Offline
            XGuy
            wrote on last edited by
            #5

            [quote author="JKSH" date="1386052604"]# What is the mutex for? I can't see any multi-thread access.

            because i haven't copied and paste the whole code in here!

            Why do you disconnect and re-connect signals in MainWindow::updateData()?

            What is objConnCert (Line #95)? Why do you move it every time

            MainWindow::updateData() is called?

            • objConnCert was a type mistake sorry for that!
            • yes you are right i must move it in the constructor once

            objSlotEvent, objData and objConn do 3 different jobs. Why are they instantiated from the same class?

            the Mainwindow class is where my application starts from and as it starts i need 3 threads to start, these threads all run a different function in Worker class.

            You should not use a blocking while loop (line #22) when the thread has an event loop. Use a QTimer instead to call a slot at regular intervals.
            i will replace this and notify you.
            thanks for your help :-)
            [/quote]

            1 Reply Last reply
            0
            • X Offline
              X Offline
              XGuy
              wrote on last edited by
              #6

              here is my updated code:

              @

              // wroker class header:
              class wroker : public QObject
              {
              Q_OBJECT
              public:
              QMutex m_mutex;
              // isFinished: slot event
              bool isFinished;
              }

              // wroker class cpp:
              Worker::Worker(QObject *parent) :
              QObject(parent),
              m_mutex(QMutex::Recursive)
              {

              }

              // one thread will run this function and this is executed in a while loop /// until program is closed
              void worker::waitForSlotEvent()
              {
              // no using while loop anymore, instead i call the function recursively
              // while (!isFinished)
              // {
              // WAIT FOR USB EVENT, ex: MASS STORAGE FLASH INSERTION/REMOVAL
              .
              .
              .

                  emit slotEvent();
                  waitForSlotEvent(); // recursive call
              

              // }
              }

              int Worker::getData()
              {
              QMutexLocker mutexLocker(&m_mutex);
              .
              .
              .

              emit getDataFinished(returnValue);
              

              }

              int Worker::getAllConns()
              {
              QMutexLocker mutexLocker(&m_mutex);
              .
              .
              .

              emit getConnFinished(returnValue);
              

              }

              // here is Mainwindow header:
              class Mainwindow : public QDialog
              {
              Q_OBJECT
              public:
              QThread thrSlotEvent;
              Worker objSlotEvent;
              QThread thrData;
              Worker objData;
              Worker objConn;
              QThread thrConn;
              }

              Mainwindow::Mainwindow() :
              QDialog()
              {
              // ================================<< THREAD DATA >>================================
              objData.moveToThread(&thrData);
              QObject::connect(&thrData, SIGNAL(started()), &objData, SLOT(getConns()));
              QObject::connect(&objData, SIGNAL(getDataFinished(int)), this, SLOT(updateData(int)));

              // ================================<< THREAD CONN >>================================
              objConn.moveToThread(&thrConn);
              QObject::connect(&thrConn, SIGNAL(started()),                   &objConn,   SLOT(getAllConns()));
              QObject::connect(&objConn, SIGNAL(getConnFinished(int)),   this,  SLOT(getConnFinished(int)));
              
              // ================================<< THREAD SLOT EVENT  >>================================
              objSlotEvent.moveToThread(&thrSlotEvent);
              QObject::connect(&thrSlotEvent, SIGNAL(started()),  &objSlotEvent, SLOT(waitForSlotEvent()));
              QObject::connect(&objSlotEvent, SIGNAL(slotEvent()), this,         SLOT(refreshList()));
              

              }

              void Mainwindow::initApp()
              {
              // =================================<< START THREAD DATA >>=================================
              // some code here
              thrData.start();
              // some code here
              }

              void Mainwindow::updateData(int returnValue)
              {
              // ================================<< RUN SLOT EVENT DETECTION >>================================
              waitForSlotEvent(false);

              // ================================<< CHECK FOR ERRORS >>================================
              if(returnValue)
              {
                  // delete all threads
                  getConnFinished(returnValue);
                  return;
              }
              
              // ================================<< START THREAD CONN >>================================
              thrConn.start();
              
              // ================================<< REFRESH THE LIST >>================================
              this->refreshList();
              

              }

              void Mainwindow::waitForSlotEvent(bool isFinished)
              {
              if(isFinished)
              {
              objSlotEvent.isFinished = true;
              thrSlotEvent.quit();
              thrSlotEvent.deleteLater();
              objSlotEvent.deleteLater();
              return;
              }

              objSlotEvent.isFinished = false;
              thrSlotEvent.start();
              

              }

              void Mainwindow::getConnFinished(int returnValue)
              {
              // ================================<< CHECK FOR RETURN VALUE >>================================
              if(returnValue)
              {
              Message::errNoTOerrStr(this, returnValue);
              }

              // ================================<< QUIT THREAD CONN>>================================
              thrConn.quit();
              thrConn.exit(0);
              
              // ================================<< QUIT THREAD DATA >>================================
              thrData.quit();
              thrData.exit(0);
              

              }

              void Mainwindow::refreshList()
              {
              // update QTreeView
              }

              @

              1 Reply Last reply
              0
              • X Offline
                X Offline
                XGuy
                wrote on last edited by
                #7

                i shouldn't have blocked for slot event! instead i used sleep(), although the problem is not completely solved and the CPU usage is still high.

                1 Reply Last reply
                0
                • JKSHJ Online
                  JKSHJ Online
                  JKSH
                  Moderators
                  wrote on last edited by
                  #8

                  Hi,

                  Sorry for the late reply. I'm still a bit unsure about your architecture. Usually, developers choose between two architectures:

                  1. The traditional, low level way:
                  • Subclass QThread
                  • Implement an infinite while loop. Use sleep() to lower CPU usage.
                  • Pass data between threads using shared variables, guarded by with mutexes/wait-conditions
                  • Stop the thread by setting a "quit" flag, which breaks the infinite while loop.
                  1. The high-level, Qt way:
                  • Don't subclass QThread
                  • Use an event loop, which automatically lowers CPU usage when there are no events/signals to process (no infinite-while-loop, no sleep())
                  • Pass data between threads using signals + slots. No locking is required.
                  • Stop the thread by invoking QThread::quit(), which stops the event loop.

                  It sounds like you've combined both methods. Can you choose one instead? I think that will make your code work better.

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

                  1 Reply Last reply
                  0
                  • X Offline
                    X Offline
                    XGuy
                    wrote on last edited by
                    #9

                    [quote author="JKSH" date="1386946314"]Hi,

                    Sorry for the late reply. I'm still a bit unsure about your architecture. Usually, developers choose between two architectures:

                    1. The traditional, low level way:
                    • Subclass QThread
                    • Implement an infinite while loop. Use sleep() to lower CPU usage.
                    • Pass data between threads using shared variables, guarded by with mutexes/wait-conditions
                    • Stop the thread by setting a "quit" flag, which breaks the infinite while loop.
                    1. The high-level, Qt way:
                    • Don't subclass QThread
                    • Use an event loop, which automatically lowers CPU usage when there are no events/signals to process (no infinite-while-loop, no sleep())
                    • Pass data between threads using signals + slots. No locking is required.
                    • Stop the thread by invoking QThread::quit(), which stops the event loop.

                    It sounds like you've combined both methods. Can you choose one instead? I think that will make your code work better.[/quote]

                    Thanks for your reply :-)
                    to be honest, i'm a newbie in qt and also Threads. actually i want to implement my code like the 2nd approach you just mentioned.
                    would you mind providing me with an example which is using threads inside an event loop(i don't know how to use event loops :-( ).

                    and by the way, you mentioned no locking is required when using signals and slots. would you explain a little more?

                    1 Reply Last reply
                    0
                    • X Offline
                      X Offline
                      XGuy
                      wrote on last edited by
                      #10

                      [quote author="JKSH" date="1386946314"]Hi,

                      Sorry for the late reply. I'm still a bit unsure about your architecture. Usually, developers choose between two architectures:

                      1. The traditional, low level way:
                      • Subclass QThread
                      • Implement an infinite while loop. Use sleep() to lower CPU usage.
                      • Pass data between threads using shared variables, guarded by with mutexes/wait-conditions
                      • Stop the thread by setting a "quit" flag, which breaks the infinite while loop.
                      1. The high-level, Qt way:
                      • Don't subclass QThread
                      • Use an event loop, which automatically lowers CPU usage when there are no events/signals to process (no infinite-while-loop, no sleep())
                      • Pass data between threads using signals + slots. No locking is required.
                      • Stop the thread by invoking QThread::quit(), which stops the event loop.

                      It sounds like you've combined both methods. Can you choose one instead? I think that will make your code work better.[/quote]

                      Thanks for your great help :-)
                      i searched for this and found a good example, here is the code:

                      @#include <QtCore>

                      class Worker : public QObject
                      {
                      Q_OBJECT
                      private slots:
                      void onTimeout()
                      {
                      qDebug()<<"Worker::onTimeout get called from?: "<<QThread::currentThreadId();
                      }
                      };

                      #include "main.moc"

                      int main(int argc, char *argv[])
                      {
                      QCoreApplication a(argc, argv);
                      qDebug()<<"From main thread: "<<QThread::currentThreadId();

                      QThread t;
                      QTimer timer;
                      Worker worker;
                      
                      QObject::connect(&timer, SIGNAL(timeout()), &worker, SLOT(onTimeout()));
                      timer.start(1000);
                      
                      timer.moveToThread(&t);
                      worker.moveToThread(&t);
                      
                      t.start();
                      
                      return a.exec&#40;&#41;;
                      

                      }
                      @
                      the link is "How to Use QThread in the Right Way":http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/

                      i appreciate it if you confirm this.
                      but i still want you to explain why we don't need using locking when using signals and slots.

                      1 Reply Last reply
                      0
                      • JKSHJ Online
                        JKSHJ Online
                        JKSH
                        Moderators
                        wrote on last edited by
                        #11

                        You're welcome :)

                        I recommend reading http://qt-project.org/doc/qt-5/threads-synchronizing.html as a start.

                        Basically, if a variable/object is shared between threads, you need to make sure that it doesn't get modified by a thread while a 2nd thread is reading it. That's why you need locks.

                        With signals and slots, you don't need to share variables/objects. When you emit a signal that contains data, Qt will automatically make a copy for you behind the scenes. Then, it passes that copy to the 2nd thread. There is no sharing, so you don't have to worry about data corruption, so you don't need locks.

                        Note: Qt's container classes (e.g. QVector, QString, QList) are "implicitly shared":http://qt-project.org/doc/qt-5/implicit-sharing.html so copying them is very efficient. However, if you want to copy custom data structures, you may need to watch out for performance issues.

                        Are you confident with using signals and slots (in general) yet?

                        [quote]
                        @
                        #include "main.moc"
                        @
                        [/quote]You shouldn't include *.moc files directly. You should declare all your QObject-derived classes in .h files, and moc will process them automatically.

                        [quote]
                        @
                        QObject::connect(&timer, SIGNAL(timeout()), &worker, SLOT(onTimeout()));
                        timer.start(1000);

                        timer.moveToThread(&t);
                        worker.moveToThread(&t);
                        
                        t.start();
                        

                        @
                        [/quote]You don't need to move your timer.

                        Other than that, it looks good :)

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

                        1 Reply Last reply
                        0
                        • X Offline
                          X Offline
                          XGuy
                          wrote on last edited by
                          #12

                          [quote author="JKSH" date="1387599076"]You're welcome :)

                          I recommend reading http://qt-project.org/doc/qt-5/threads-synchronizing.html as a start.

                          this was a very useful link thanks.

                          [quote]
                          @
                          #include "main.moc"
                          @
                          [/quote]You shouldn't include *.moc files directly. You should declare all your QObject-derived classes in .h files, and moc will process them automatically.

                          yes you are right. actually i have copied this part from the link i provided earlier, and I'm not including "main.moc" in my project.
                          [quote]
                          @
                          QObject::connect(&timer, SIGNAL(timeout()), &worker, SLOT(onTimeout()));
                          timer.start(1000);

                          timer.moveToThread(&t);
                          worker.moveToThread(&t);
                          
                          t.start();
                          

                          @
                          [/quote]You don't need to move your timer.

                          Other than that, it looks good :)[/quote]

                          and by the way, by using Qtimer now cpu usage looks good. thanks for your great help.

                          1 Reply Last reply
                          0
                          • JKSHJ Online
                            JKSHJ Online
                            JKSH
                            Moderators
                            wrote on last edited by
                            #13

                            Glad to hear, and you're welcome. Happy coding!

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

                            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