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. Waiting for Signal using local Eventloop using multiple QThreads
Forum Updated to NodeBB v4.3 + New Features

Waiting for Signal using local Eventloop using multiple QThreads

Scheduled Pinned Locked Moved Solved General and Desktop
13 Posts 5 Posters 2.8k 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.
  • fcarneyF Offline
    fcarneyF Offline
    fcarney
    wrote on last edited by
    #4

    I took a look at QSerialPort. It seems like it might be possible to do polling to wait for the data to come back. Is that a possibility or do you need to make it event based for some reason?

    C++ is a perfectly valid school of magic.

    1 Reply Last reply
    0
    • dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on last edited by dheerendra
      #5

      @kain
      According to your logic it should work like send->recv->send->recv. Mismatch is only possible if they are executed from different threads. But thread is also same. This may not be issue.

      >emit sendCommand(command, destAddress, sendBuffer);
      

      My suspect is the above send. Can you tell me where is the connect for above signal ? I have strong feeling is that slot for the above signal is in different threads. Are you using the BlockedQueuedConnection for the above statement ?

      Dheerendra
      @Community Service
      Certified Qt Specialist
      http://www.pthinks.com

      1 Reply Last reply
      0
      • aha_1980A Offline
        aha_1980A Offline
        aha_1980
        Lifetime Qt Champion
        wrote on last edited by aha_1980
        #6

        @kain said in Waiting for Signal using local Eventloop using multiple QThreads:

        I am aware of that architecture and that synchronous calls are some kind of bad practice.

        If I would try to implement this in an asynchronous manner I would only shift that problem to a higher level of abstraction.

        No, that is not true. It simple depends on the architecture of your program. Qt provides asynchronous classes for exactly that kind of problem. There are a lot of network or serial port examples that show how to communicate that way.

        But: I need that mechanism that always only one object/worker is communicating on that SerialBus, i.e. that no one sends a second command before the answer of the first command is completely received.

        Fair point. But as the communication class is aware of that, all you need is a input FIFO that fills with commands and send the commands when the serial port is free to do so.
        When the answer is in, you give a signal containing the answer and continue sending the next command.

        So I would use some synchronization-mechanism via Mutex anyway.

        If you use signals&slots, no.

        Since I hide that synchronous calls in a seperate thread on a lower level I dont really care for the performance here.

        If it is really like that, why don't you use the waitForBytesWritten and waitForReadyRead functions? They will simplify your code a lot as you don't need the local event loop anymore.

        Regards

        Qt has to stay free or it will die.

        1 Reply Last reply
        1
        • K Offline
          K Offline
          kain
          wrote on last edited by
          #7

          Hey,

          first of all thank for the comments so far.
          @dheerendra
          This is how I connect my sendcommand to the object that handles the SerialBus communication:

          connect(this, &PeripherieCommunicator::sendCommand, this->mmcom.get(), &MultiMasterCommunicator::send, Qt::ConnectionType::BlockingQueuedConnection);
          

          It seems to me that when I use the QEventLoop for blocking the parent object returns to it own EventLoop and thus acceptinga new command resulting in a second "Send" before finishing the first "Receive". Is that possible?

          @aha_1980 :
          You are correct but to be honest I do not know how I would change the architecture to use only that non-blocking mechanisms. For example at some high layer I got some logic that move an axis using a motor, like (PSEUDO-CODE)

          int MoveAxisToPos(long pos);
          

          This would call some code which would do something like:

          int EnableAxis(bool someParam);
          int StartMovingOfAxis();
          do 
          {
            auto finished = ReadAxisState();
          } while (>0)
          if (finished < 0) emit error();
          else emit success();
          

          and each of these commands would result in some communication on that QSerialBus and that QSerialBus is going to be called from multiple threads (each of them controlling some device on that SerialBus). So I would connect and disconnect my signals/slots all the time. Also for each command I would need to create a seperate (lamba?) function that handles the answer of the underlying layer. With many commands that would result in some nested functions or using some kind of stateMachine (like QStateMachine), so every Command would be a seperate StateMachine. This for me seems to a big coding-overhead and that is why I chose to use that blocking/synchronous approach like above.

          aha_1980A 1 Reply Last reply
          0
          • K kain

            Hey,

            first of all thank for the comments so far.
            @dheerendra
            This is how I connect my sendcommand to the object that handles the SerialBus communication:

            connect(this, &PeripherieCommunicator::sendCommand, this->mmcom.get(), &MultiMasterCommunicator::send, Qt::ConnectionType::BlockingQueuedConnection);
            

            It seems to me that when I use the QEventLoop for blocking the parent object returns to it own EventLoop and thus acceptinga new command resulting in a second "Send" before finishing the first "Receive". Is that possible?

            @aha_1980 :
            You are correct but to be honest I do not know how I would change the architecture to use only that non-blocking mechanisms. For example at some high layer I got some logic that move an axis using a motor, like (PSEUDO-CODE)

            int MoveAxisToPos(long pos);
            

            This would call some code which would do something like:

            int EnableAxis(bool someParam);
            int StartMovingOfAxis();
            do 
            {
              auto finished = ReadAxisState();
            } while (>0)
            if (finished < 0) emit error();
            else emit success();
            

            and each of these commands would result in some communication on that QSerialBus and that QSerialBus is going to be called from multiple threads (each of them controlling some device on that SerialBus). So I would connect and disconnect my signals/slots all the time. Also for each command I would need to create a seperate (lamba?) function that handles the answer of the underlying layer. With many commands that would result in some nested functions or using some kind of stateMachine (like QStateMachine), so every Command would be a seperate StateMachine. This for me seems to a big coding-overhead and that is why I chose to use that blocking/synchronous approach like above.

            aha_1980A Offline
            aha_1980A Offline
            aha_1980
            Lifetime Qt Champion
            wrote on last edited by aha_1980
            #8

            Hi @kain,

            Are you talking about QSerialBus or QSerialPort? That are two different things!

            and that QSerialBus is going to be called from multiple threads

            Aha! In you last post, you said that only one thread is involved?! How does that fit together? And do you really need multiple threads? Why?

            So I would connect and disconnect my signals/slots all the time.

            No!

            This for me seems to a big coding-overhead and that is why I chose to use that blocking/synchronous approach like above.

            I'm pretty sure you just think too complicated. Because what you do now is big overhead.

            Probably it's better to first explain in words what exactly has to be done.

            Regards

            PS: Also note that in your last example you mixing Signals&Slots with blocking operations and that very likely to not work.

            Qt has to stay free or it will die.

            1 Reply Last reply
            1
            • dheerendraD Offline
              dheerendraD Offline
              dheerendra
              Qt Champions 2022
              wrote on last edited by dheerendra
              #9

              I feel your program does not work the way you wanted. Look at the following
              facts.

              1. sendReceive(..) method is called by - Thread 0x5e3c

              2. ->connect(mmcom.get(), &MultiMasterCommunicator::dataReceived
                Above connect statement indicates that slot needs to be executed. This slots needs to be executed in the context of Thread 0x5e3c only.

              3. You start the event loop here. So your Thread - 0x5e3c blocked here. It can exit only
                a. if the timeout or
                b. datareceived() signal of current object. This will never happen becz signal datareceived() should come from execution for lamda slot by Thread-0x5e3c.

              4. ->connect(this, &PeripherieCommunicator::sendCommand, this->mmcom.get(), &MultiMasterCommunicator::send
                This connect indicates that this->mmcom.get() object returned by this method is owned by another thread. Here again you would like to block yourself till the serial data collector finishes the work.

              5. I feel most the time your event loop exits becz of timeout rather than the signal dataRecved(..)

              It seems to me that when I use the QEventLoop for blocking the parent object returns to it own EventLoop
              

              It will be different eventloop for this purpose. It is not mixed with main event loop.

              Issue here is that thread which is blocked due to eventloop,

              1. may receive another sendRequest(..).
              2. Then it receives this dataReceived(..) signal may serial data collector thread.

              The moment Thread-0x5e3c is free because of Timeout, main eventloop starts the work. It picksup the sendRequest which is first event. This results in one more send.

              In general I felt logic/flows mixed up with so many blockings. Current logic blocks the same thread multiple times. Your idea is that Request to Serial Data Collection should go in sequence & get the response in serial mode.

              It can be simplified lot better with simple architecture. Signal/Slots provide simple mechanism to achieve this across the thread.

              Dheerendra
              @Community Service
              Certified Qt Specialist
              http://www.pthinks.com

              1 Reply Last reply
              1
              • dheerendraD Offline
                dheerendraD Offline
                dheerendra
                Qt Champions 2022
                wrote on last edited by dheerendra
                #10

                Another thing I forgot add is that your send method blocked before exec itself. Event loop starts only after data reading. This makes eventloop dummy. It does not serve any purpose.

                Dheerendra
                @Community Service
                Certified Qt Specialist
                http://www.pthinks.com

                1 Reply Last reply
                0
                • dheerendraD Offline
                  dheerendraD Offline
                  dheerendra
                  Qt Champions 2022
                  wrote on last edited by
                  #11

                  What happened to this issue ? Are you able to solve the issue ?

                  Dheerendra
                  @Community Service
                  Certified Qt Specialist
                  http://www.pthinks.com

                  1 Reply Last reply
                  0
                  • K Offline
                    K Offline
                    kain
                    wrote on last edited by
                    #12

                    I reworked my Class that handles my QSerialPort to just be synchronous using "waitReadyRead), etc since I blocked in the calling class anyway.
                    Then I changed my SendReceive-function to just that synchronous functions, that way I get rid of my local Eventloop.
                    So far this solution works for me as expected.

                    J.HilkJ 1 Reply Last reply
                    0
                    • K kain

                      I reworked my Class that handles my QSerialPort to just be synchronous using "waitReadyRead), etc since I blocked in the calling class anyway.
                      Then I changed my SendReceive-function to just that synchronous functions, that way I get rid of my local Eventloop.
                      So far this solution works for me as expected.

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

                      @kain
                      QAbstractSocket, that also inherits from QIODevice has this note in the waitForReadyRead documentation

                      Note: This function may fail randomly on Windows. Consider using the event loop and the readyRead() signal if your software will run on Windows.

                      granted QSerialPort is not an QAbstractSocket, so I'm nearly 100 % sure it won't effect you, but just in case you run into unexpected timeouts, keep that in mind ;)

                      Also don't forget to change the topic to sovled, if your problem/answer is actually solved.


                      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.

                      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