I am working on a data logger in QT framework. I Intend to save log strings to files and print to the console in a separate watcher thread. In that separate thread I need to watch my QStringList for new items added. If there are new items I deque them and log. I was wondering what is the mechanism used for this in Qt framework. In STD lib i used condition_variable
for this task like this:
/*!
* \brief puts a \ref logline_t object at the end of the queue
* @param s object to be added to queue
*/
void CLogger::push_back(logline_t* s)
{
unique_lock<mutex> ul(m_mutex2);
s->queSize = m_data.size();
m_data.emplace_back(move(s));
m_cv.notify_all();
}
/*!
* \brief takes a \ref logline_t object from the beggining of the queue
* @return first \ref logline_t object
*/
CLogger::logline_t CLogger::pop_front()
{
unique_lock<mutex> ul(m_mutex2);
m_cv.wait(ul, [this]() { return !m_data.empty(); });
assert(m_data.front());
logline_t retVal = move(*m_data.front());
delete m_data.front();
m_data.front() = NULL;
m_data.pop_front();
return retVal;
}
m_cv
is the conditional variable object. How can this functionality be acquired with QT? I bet there is a lot better way :). I would appreciate all help.
Ps: I know pointer functions parameters are not asserted, this is an old code... :P
There are a couple of ways of doing the notification in Qt.
Signals and Slots
Signals and slots can be sent between threads, when making the connection, you set the connection type to Qt::QueuedConnection or Qt::BlockingQueuedConnection.
You may want to create a wrapper class around the QStringList so that modifications can trigger the signals that other classes listen for.
QMutex and QWaitCondition
You can use the Qt thread synchronisation classes QMutex and QWaitCondition to do the classic manual synchronisation like you have done previously. When using QMutex, the QMutexLocker is useful for scope lock and release of a QMutex.
Here's an example of doing this signals and slots. You may want to do your own benchmarks to test whether this fits your needs. Please also note that while signals and slots guarantee thread-safety, they don't guarantee that the messages will appear in the same order they were sent. That being said, I've used this mechanism for years and it has yet to happen for me.
First, create a couple of classes:
Loggee
and the .cpp file:
Logger
and the .cpp file:
the rest
In this demo, I create a
QThread
and aLogger
, move handling of this newLogger
's slots to this new thread's event loop. Then I connectLoggee
's signal withLogger
's slot usingQt::AutoConnection
. This is the default but I stated it explicitly to show that you can change this (i.e. toQt::QueuedConnection
which would queue the execution of the slot even if both threads lived in the same thread).Then I cause the
Loggee
to emit¹ a singal. It gets properly scheduled and causes the logging slot to be executed in the receiver's thread.¹
emit
is#define emit /*null*/
, so you can omit it if you wantIf you are just looking for the Qt equivalents to the classes you have been using: