Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Strange exception.
Qt 6.11 is out! See what's new in the release blog

Strange exception.

Scheduled Pinned Locked Moved Unsolved General and Desktop
18 Posts 4 Posters 2.7k Views
  • 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.
  • VRoninV VRonin

    @jenya7 said in Strange exception.:

    @VRonin
    I see. Where I should place a QMutex ?

    Depends, where do you define g_queue?

    J Offline
    J Offline
    jenya7
    wrote on last edited by jenya7
    #7

    @VRonin said in Strange exception.:

    @jenya7 said in Strange exception.:

    @VRonin
    I see. Where I should place a QMutex ?

    Depends, where do you define g_queue?

    in udp.cpp
    QQueue<QByteArray> g_queue;

    in udp.h
    extern QQueue<QByteArray> g_queue;

    in parser.cpp
    #include "udp.h"

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #8

      Oh, it's a global.... terrible idea but this is an argument for another time. The mutex will go in the same scope

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      J 1 Reply Last reply
      1
      • VRoninV VRonin

        Oh, it's a global.... terrible idea but this is an argument for another time. The mutex will go in the same scope

        J Offline
        J Offline
        jenya7
        wrote on last edited by
        #9

        @VRonin said in Strange exception.:

        Oh, it's a global.... terrible idea but this is an argument for another time. The mutex will go in the same scope
        OK.
        in udp.cpp

        void UDP::ReadyRead()
        {
            QHostAddress sender;
            quint16 senderPort;
            int size;
        
            int count = 0;
        
           g_mutex.lock();
        
            while (socket->hasPendingDatagrams())
            {
                  socket->readDatagram(udp_buffer.data(), udp_buffer.size(),
                                       &sender, &senderPort);
        
                  g_queue.enqueue(udp_buffer);
                  count++;
            }
        
            g_mutex.unlock();
        
            qDebug() << "datagrams: " << count;
        }
        

        and what in void PARSER::Run() ? There is no flag in mutex like g_mutex.isFree() or something.

        1 Reply Last reply
        0
        • J jenya7

          @JonB said in Strange exception.:

          @jenya7
          @VRonin types much faster than I can! ;-)

          Completely unrelated comment:

          void PARSER::Run()
          {
              while(1)
          

          Are you aware not to use this "for real"? Have you looked at the load on (some thread/core in) your CPU?

          How it could be done without while(1)? I want to constantly check if there are some data in queue.

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

          @jenya7 said in Strange exception.:

          How it could be done without while(1)? I want to constantly check if there are some data in queue.

          Your code does:

          void PARSER::Run()
          {
              while(1)
              {
                  if (!g_queue.isEmpty())
                  {
          

          That means you are calling g_queue.isEmpty() as fast/many times as your thread/core/CPU can manage it. Even though it's in its own thread, which at least (theoretically/hopefully) means that some time will still be given to your UI/other threads, it will/should basically occupy a complete core running 100% of the time. Good if you want to use your host device as a "heater" for your room, bad if you care about electricity/battery life/wear & tear! And it may interfere with the responsiveness of your other threads.

          You have a couple of possibilities:

          • Make your thread run a Qt event loop (this is the default for QThread), so that you can use QTimer. Only read the queue state every so often in time, to give the thread a chance to sleep. You can achieve this simply using QThread::msleep().

          • Again with a Qt event loop in the thread. Have a signal raised by whatever puts something onto the queue, and the thread has a slot for that which only needs to do:

          while (!g_queue.isEmpty())
              dequeue_and_process();
          

          and then the slot exits, returning to the thread's event loop.

          In this case the second option is very easy, because you know when you put something new onto the queue: it's the g_queue.enqueue(udp_buffer); in your UDP thread. So just have that emit a signal immediately after queueing a new element.

          J 1 Reply Last reply
          1
          • JonBJ JonB

            @jenya7 said in Strange exception.:

            How it could be done without while(1)? I want to constantly check if there are some data in queue.

            Your code does:

            void PARSER::Run()
            {
                while(1)
                {
                    if (!g_queue.isEmpty())
                    {
            

            That means you are calling g_queue.isEmpty() as fast/many times as your thread/core/CPU can manage it. Even though it's in its own thread, which at least (theoretically/hopefully) means that some time will still be given to your UI/other threads, it will/should basically occupy a complete core running 100% of the time. Good if you want to use your host device as a "heater" for your room, bad if you care about electricity/battery life/wear & tear! And it may interfere with the responsiveness of your other threads.

            You have a couple of possibilities:

            • Make your thread run a Qt event loop (this is the default for QThread), so that you can use QTimer. Only read the queue state every so often in time, to give the thread a chance to sleep. You can achieve this simply using QThread::msleep().

            • Again with a Qt event loop in the thread. Have a signal raised by whatever puts something onto the queue, and the thread has a slot for that which only needs to do:

            while (!g_queue.isEmpty())
                dequeue_and_process();
            

            and then the slot exits, returning to the thread's event loop.

            In this case the second option is very easy, because you know when you put something new onto the queue: it's the g_queue.enqueue(udp_buffer); in your UDP thread. So just have that emit a signal immediately after queueing a new element.

            J Offline
            J Offline
            jenya7
            wrote on last edited by
            #11

            @JonB
            Good points. May in this case I don't need any mutex?

            JonBJ 1 Reply Last reply
            0
            • J jenya7

              @JonB
              Good points. May in this case I don't need any mutex?

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

              @jenya7 said in Strange exception.:

              May in this case I don't need any mutex?

              No, you will still need that. Partly for safety anyway, but mostly even after the UDP thread adds to the queue and emits a signal, you still have a potential race condition between (a) the parser thread pulling the item from the queue as soon as the slot is called versus (b) the UDP thread going round and receiving a new datagram to append to the queue.

              J 1 Reply Last reply
              0
              • JonBJ JonB

                @jenya7 said in Strange exception.:

                May in this case I don't need any mutex?

                No, you will still need that. Partly for safety anyway, but mostly even after the UDP thread adds to the queue and emits a signal, you still have a potential race condition between (a) the parser thread pulling the item from the queue as soon as the slot is called versus (b) the UDP thread going round and receiving a new datagram to append to the queue.

                J Offline
                J Offline
                jenya7
                wrote on last edited by
                #13

                @JonB
                How do I do that
                the first thread

                 g_mutex.lock();
                //do some stuff
                g_mutex.unlock();
                

                and the second one - how to I test the mutex for unlocked?

                J.HilkJ JonBJ 2 Replies Last reply
                0
                • J jenya7

                  @JonB
                  How do I do that
                  the first thread

                   g_mutex.lock();
                  //do some stuff
                  g_mutex.unlock();
                  

                  and the second one - how to I test the mutex for unlocked?

                  J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote on last edited by
                  #14

                  @jenya7
                  with https://doc.qt.io/qt-5/qmutex.html#tryLock

                  it will wait, until timeout or until the other thread called unlock


                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  J 1 Reply Last reply
                  1
                  • J.HilkJ J.Hilk

                    @jenya7
                    with https://doc.qt.io/qt-5/qmutex.html#tryLock

                    it will wait, until timeout or until the other thread called unlock

                    J Offline
                    J Offline
                    jenya7
                    wrote on last edited by
                    #15

                    @J-Hilk said in Strange exception.:

                    @jenya7
                    with https://doc.qt.io/qt-5/qmutex.html#tryLock

                    it will wait, until timeout or until the other thread called unlock

                    So if in the second thread tryLock returns true - should I unlock immediately after g_queue.dequeue(); ?

                    JonBJ 1 Reply Last reply
                    0
                    • J jenya7

                      @JonB
                      How do I do that
                      the first thread

                       g_mutex.lock();
                      //do some stuff
                      g_mutex.unlock();
                      

                      and the second one - how to I test the mutex for unlocked?

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

                      @jenya7
                      In this particular case your parser thread could actually do an unconditional g_mutex.lock(); too. That would block if the UDP thread has already taken the lock. But because you have "nothing else to do" in your thread it doesn't matter anyway.

                      However, you may prefer to use @J-Hilk's suggestion of tryLock(), as it may sound more "intuitive". There are other cases --- where your thread does have other things to do if a lock cannot be taken immediately --- where you would require tryLock(), so it may be a habit you want to get into.

                      1 Reply Last reply
                      0
                      • J jenya7

                        @J-Hilk said in Strange exception.:

                        @jenya7
                        with https://doc.qt.io/qt-5/qmutex.html#tryLock

                        it will wait, until timeout or until the other thread called unlock

                        So if in the second thread tryLock returns true - should I unlock immediately after g_queue.dequeue(); ?

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

                        @jenya7 said in Strange exception.:

                        So if in the second thread tryLock returns true - should I unlock immediately after g_queue.dequeue(); ?

                        Yep :) And don't forget to do so immediately after dequeuing, not after you have processed the element.

                        J 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @jenya7 said in Strange exception.:

                          So if in the second thread tryLock returns true - should I unlock immediately after g_queue.dequeue(); ?

                          Yep :) And don't forget to do so immediately after dequeuing, not after you have processed the element.

                          J Offline
                          J Offline
                          jenya7
                          wrote on last edited by jenya7
                          #18

                          Thank you guys. With mutex it works good. Sometimes I get broken datagrams but it seems like I overload the network card. For 27500 packets I get 11 broken.

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