Results 1 to 8 of 8

Thread: QList::erase method does not work if I include an "emit signal" instruction

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,327
    Thanks
    317
    Thanked 871 Times in 858 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QList::erase method does not work if I include an "emit signal" instruction

    When you emit a signal, you return control to the Qt event loop. If you do not emit any signal from within checkTimeouts(), then your loops run completely to the end and checkTimeouts() exits before control returns to the event loop. When you emit the signal, then all pending events will be processed, including any new timeouts, which means you could be entering checkTimeouts() recursively. So basically, your list gets completely screwed up.

    You can probably verify this by putting some qDebug() statements at the beginning and end of checkTimeouts() and see if you get an "entering checkTimeouts()" and "exiting checkTimeouts()" occurring together in pairs of enter / exit. If you get two enters in a row, you have a second timeout being processed before the first one has finished.

    Time to re-think your design. Your basic problem is that it is taking longer to process all of the pending messages than the timeout period, so your timeouts are stacking up. So if your application allows you to ignore extra timeouts, then one easy way to avoid the problem is to keep a bool member variable in your PendingList class:

    Qt Code:
    1. void PendingList::checkTimeouts()
    2. {
    3.  
    4. qDebug() << "Entering checkTimeouts()";
    5.  
    6. if ( !inTimeout )
    7. {
    8. inTimeout = true; // this is a member variable of PendingList; initialize it to false in the constructor
    9.  
    10. qint64 t1 = QDateTime::currentMSecsSinceEpoch();
    11. for (int i = 0; i < MAX_CLIENTS; i++)
    12. {
    13. QList<PendingMsg>::iterator it;
    14. for (it = list[i].begin(); it != list[i].end(); )
    15. {
    16. quint64 t0 = it->request.getTimeStamp();
    17. quint64 dift = t1 - t0;
    18. if (dift >= it->timeout)
    19. {
    20. CMD cmd1 = it->cmd;
    21. CMD cmd2 = it->request.getCmd();
    22. it = list[i].erase(it);
    23. emitTimeout((System)i, cmd1, cmd2);
    24. }
    25. else
    26. it++;
    27. }
    28. }
    29. stopIfEmpty();
    30.  
    31. inTimeout = false;
    32. }
    33.  
    34. qDebug() << "Exiting checkTimeouts()";
    35. }
    To copy to clipboard, switch view to plain text mode 

    Another way to do it would be to stop the timer when you enter checkTimeouts() and start it when you exit. Or make it a single-shot, and simply restart it when you exit. That way you can be guaranteed that no new timeouts can be generated while you are processing the first one.
    Last edited by d_stranz; 1st May 2013 at 01:31.

Similar Threads

  1. Replies: 2
    Last Post: 27th January 2012, 17:29
  2. Why the signal "dataChanged" by QTableWidget not work?
    By Tao Clark in forum Qt Programming
    Replies: 1
    Last Post: 20th August 2011, 17:16
  3. Translation QFileDialog standart buttons ("Open"/"Save"/"Cancel")
    By victor.yacovlev in forum Qt Programming
    Replies: 4
    Last Post: 24th January 2008, 19:05
  4. Signal defined in "a.h" can not emit in "b.cpp"
    By Shawn in forum Qt Programming
    Replies: 9
    Last Post: 21st May 2007, 16:55
  5. Replies: 6
    Last Post: 3rd November 2006, 11:53

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.