2

An object lives in a thread and have some slots, that are called with

Qt::QueuedConnection 

or

Qt::BlockingQueuedConnection

Is there a way to know how many slot calls are in the queue? Or even know number of each slot calls in the that queue?

  • I would simply use debug output (either `qDebug()` or `printf`) in slots to print out each call, than analyze the log. – vahancho Apr 10 '18 at 12:35
  • Do you mean to get the number of queued slot call events in the event queue at the moment? Why would you need to know that? – Mike Apr 10 '18 at 12:44
  • What's the actual problem you're trying to solve? Right now this sounds a bit [XY](http://xyproblem.info/). – G.M. Apr 10 '18 at 12:47
  • @vahancho this thread is used for sound streaming/receiving, so lots of qDebug/printf would screw the timing up for sure. – Lisandrel Lord Apr 10 '18 at 12:55
  • Possible duplicate of [What are some best practices for debugging Qt signals and slots?](https://stackoverflow.com/questions/11938550/what-are-some-best-practices-for-debugging-qt-signals-and-slots) – Joseph D. Apr 10 '18 at 12:56
  • @Mike yes them. Thread start to consume lots of CPU time at some point and never comes back to normal (besides thread recreation). Unfortunately we can't reproduce the issue on any but one PC and even there it takes days to happen. So I need to debug as much information at that time as possible. One of that is an assumption that the object gets flooded with some slot calls. If it's true we can inspect the reason of the flood. – Lisandrel Lord Apr 10 '18 at 13:05
  • @G.M. I try to inspect if thread has problems with some slot called too many times. Not the statistics from the very program start, but current situation. – Lisandrel Lord Apr 10 '18 at 13:10

2 Answers2

0

Maybe a bit offtopic, but next pattern may help you (when you need only one slot call per several operations). For example, when you have a lot of unpredictable data changes and you need to update a view.

class SlotProxy : public QObject
{
  Q_OBJECT

signals:
  void triggered();

public:
  explicit SlotProxy( QObject *parent = nullptr );
  void trigger();

private:
  void onTimeout();

private:
  QPointer<QTimer> _timer;
};

SlotProxy::SlotProxy( QObject *parent = nullptr )
  : _timer{ new QTimer{ this } }
{
  _timer->setInterval( 0 );
  _timer->setSingleShot( true );
  connect( _timer, &QTimer::timeout, this, &SlotProxy::onTimeout );
}

void SlotProxy::trigger()
{
  _timer->start( 0 ); // May be not zero;
}

void SlotProxy::onTimeout()
{
  emit triggered();
}

Usage:

class MyForm : public QWidget
{
/*...*/
void updateGui();
};

class Worker : public QObject
{
/*...*/
signals:
  void updateRequest();

public:
  explicit Worker( QObject *parent = nullptr );

private:
  void heavyTask();

private:
  SlotProxy _proxy;
};

Worker::Worker( QObject *parent )
  : QObject{ parent }
{
  connect( _proxy, &SlotProxy::triggered, this, &Worker::updateRequest );
}

void Worker::heavyTask()
{
  for ( auto i = 0; i < 1000; i++ )
  {
    /*...*/
    _proxy.trigger();
  }
}

MyForm form;
Worker worker;

QObject::connect( &worker, &Worker::updateRequest, &form, &MyForm::updateGui );
worker.heavyTask();
// here you will have only 1 slot MyForm::updateGui in queue

Subject to improve. You may call _timer->start( 100 ); with non-zero timeout for better latency, but you need to somehow force emitting a signal periodically. It will do a code a bit more complex, please write a comment if you need help.

Dmitry Sazonov
  • 8,801
  • 1
  • 35
  • 61
0

See this question for details. You need to monitor (via a filter) the QMetaCallEvent events.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313