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] Question about QIODevice::readyRead() signal
Forum Updated to NodeBB v4.3 + New Features

[Solved] Question about QIODevice::readyRead() signal

Scheduled Pinned Locked Moved General and Desktop
7 Posts 5 Posters 18.9k 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.
  • S Offline
    S Offline
    SeedOfLife
    wrote on last edited by
    #1

    Hi all,
    In the Qt documentation it states that "readyRead()":http://doc.qt.nokia.com/4.7/qiodevice.html#readyRead will be emitted each time there is new data in the socket waiting to be read. It also states that "readyRead() is not emitted recursively". What exactly does this mean ?

    In my situation I use a QTcpSocket to process network data. Does this mean that when my slot attached to the readyRead() signal is busy processing data from the socket and there is new data available, the same slot would not be called due to the fact that execution is already in the readyRead handler ? In essence don't the readyRead() signals get queued up and emitted like most other events ? I'm having doubts since I rely solely on readyRead() to notify me of network data and I am getting missed packets while processing is busy in readyRead().

    thanks.

    1 Reply Last reply
    0
    • F Offline
      F Offline
      fluca1978
      wrote on last edited by
      #2

      Just an idea:

      bq. readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted (although waitForReadyRead() may still return true).

      it means to me that once the slot finished its work the signal will not be re-emitted even if there is still data unconsumed by the lost itself. This is just my interpretation.

      1 Reply Last reply
      0
      • A Offline
        A Offline
        andre
        wrote on last edited by
        #3

        That is also how I read it. The behaviour makes perfect sense as well.

        What you can do, is make your handler itself a while loop: while there is still more data to read, you keep on reading. If more data arrives while you were processing a data block, it will show up at the next iteration and you can immediately handle the new data.

        1 Reply Last reply
        0
        • S Offline
          S Offline
          SeedOfLife
          wrote on last edited by
          #4

          Well that's how I thought so too. Seems to be it is correct. That is readyRead() won't be called again (or queued for later processing) if the application is already handling the slot for readyRead().
          I overcame this by checking the QTcpSocket::bytesAvailable() function in a while loop as suggested above. Thanks.

          @void SocketsLayer::OnSocketReadyRead()
          {
          int iBytesAvailable = p_ClientSocket->bytesAvailable();
          while(iBytesAvailable > 0)
          {
          if(p_ClientSocket->isValid())
          {
          char* pzBuff = new char[iBytesAvailable];
          int iReadBytes = p_ClientSocket->read(pzBuff, iBytesAvailable);
          if( iReadBytes > 0 )
          {
          // do something
          }
          else
          qDebug("read bytes count is not valid !!"); // possibly an error
          }
          else
          {
          QMessageBox::warning(p_ParentWidget, "Warning", "Socket is not valid to read data from");
          break;
          }

          iBytesAvailable = p_ClientSocket->bytesAvailable();
          }
          }@

          1 Reply Last reply
          0
          • P Offline
            P Offline
            philroy
            wrote on last edited by
            #5

            I have just recently run into the same problem....

            In my readyRead signal handler, I read all bytesAvailable() bytes (once) and process them. Occasionally, after returning from the handler, it is not called again, though bytesAvailable() returns non-zero.

            I, too, "fixed" the problem by having my handler loop on non-zero bytesAvailable() return.

            But I'm still not completely comfortable, because:

            • The documentation says: "readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted" I am not either calling waitForReadyRead() or (as far as I know) reentering the event loop. I know I'm not reentering the event loop deliberately. I suppose there's a chance that I'm calling a routine that reenters the event loop to get it's work done, but I don't think so. (Is there any list of such routines anywhere?) I've set a break point on every QEventLoop method I could find, and only the outer processEvents() is ever being called. None are called from my slot. Since the documentation seems to imply that, if you don't reenter the event handler or call waitForReadyRead() in your slot, readyRead signals will be queued, that's what I expect to happen. But it doesn't seem to be.
            • It appears that all I have done is shrunk the timing window. The trouble happens if bytes come in while you're in your slot. When I was only checking bytesAvailable() at the beginning of my slot, this was a long window. Now that the last thing I do in my slot is get a 0 return from bytesAvailable() the window is very small. But not closed. Couldn't the following sequence occur?:
              • My slot checks bytesAvailable(), which returns 0
              • New bytes arrive, I'm still in my slot, so readyRead() will not be signaled
              • My slot returns, the event loop does nothing
                If so, what's the right way to handle it? (Of course, I could have a timer periodically check bytesAvailable(), but that doesn't seem very elegant.)
            1 Reply Last reply
            0
            • P Offline
              P Offline
              philroy
              wrote on last edited by
              #6

              Er, kindly disregard my previous post.

              I just discovered that the readyRead signal my slot is receiving is not from a vanilla QIODevice, but from a derivative -- QextSerialPort.

              And QextSerialPort::readyRead implementation has nothing to do with QIODevice::readyRead -- it's actually emitted from a QSocketNotifier::active() handler (at least, for unix, which is where I am).

              And since QextSerialPort is an add-on -- not part of the Qt distribution -- I reckon problems with it ought not be posted here.

              1 Reply Last reply
              0
              • N Offline
                N Offline
                neveralull
                wrote on last edited by
                #7

                [quote author="SeedOfLife" date="1317282267"]Well that's how I thought so too. Seems to be it is correct. That is readyRead() won't be called again (or queued for later processing) if the application is already handling the slot for readyRead(). I overcame this by checking the QTcpSocket::bytesAvailable() function in a while loop as suggested above. Thanks. @void SocketsLayer::OnSocketReadyRead() { int iBytesAvailable = p_ClientSocket->bytesAvailable(); while(iBytesAvailable > 0) { if(p_ClientSocket->isValid()) { char* pzBuff = new char[iBytesAvailable]; int iReadBytes = p_ClientSocket->read(pzBuff, iBytesAvailable); if( iReadBytes > 0 ) { // do something } else qDebug("read bytes count is not valid !!"); // possibly an error } else { QMessageBox::warning(p_ParentWidget, "Warning", "Socket is not valid to read data from"); break; } iBytesAvailable = p_ClientSocket->bytesAvailable(); } }@[/quote]
                Basically that is the proper design. You could tighten up the code a bit so there is only one read of bytesAvailable() in the beginning of the loop instead of outside the loop, and then again inside the loop at the end. It's just a matter of personal preference.

                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