I'm making a Qt frontend for a Rust libary which exposes a C++ function that blocks the execution thread it resides in, but allows to pass a callback function for communication between the two ends.
So I thought of using Qt's threading technologies to make the library execution on another thread, and I'd like to do it with the least amount of modifications as possible to the Rust library.
This is my approach using QThreads:
backend.cpp:
typedef void(*callback_t)(void *,const char *);
extern "C" call_rust_library(const char *config, void *cb_data, callback_t cb);
template<typename T>
void call_wrapper(void *ptr, const char*data) {
(*static_cast<T*>(ptr))(data);
}
class BackEnd : public QObject {
Q_OBJECT
public slots:
void do_computations(ConfigObject *config) {
//...parse configuration from the frontend...
char* parsed_configuration;
BackEnd* backend = this;
auto callback = [backend](char* data) {
//...process obtained data from the library...
QString type,contents;
backend->emit send_message(type,contents);
}
call_rust_library(parsed_configuration,(void *)&callback,call_wrapper<decltype(callback)>);
}
signals:
void send_message(QString type, QString contents);
}
frontend.cpp:
class FrontEnd : public QMainWindow {
Q_OBJECT
QThread thread;
ConfigObject *config;
public slots:
void process_message(QString type, QString contents) {
//...do GUI things with the message
}
private slots:
void on_request_start_thread() {
// called by a GUI event
BackEnd* backend = new BackEnd;
backend->moveToThread(&thread);
connect(&thread,&QThread::finished,backend,&QObject::deleteLater);
connect(this,&FrontEnd::run_thread,backend,&BackEnd::do_computations);
connect(backend,&BackEnd::send_message,frontend,&FrontEnd::process_message);
emit run_thread(config)
}
signals:
void run_thread(ConfigObject *config);
}
However I have a couple of problems with this:
First off, nothing from the backend gets executed. If I don't move the BackEnd object to another thread it does seem to run everything but crashes somewhere on a system library (my best guess is that is because Qt forbids blocking the GUI thread and/or handling GUI functions from another thread).
How would Qt be able to abort the Rust library execution thread? (via closing the application or the user clicking a button) The Rust library doesn't seem to expose any mechanism to stop its execution, so I'm wondering if I have to make modifications to the library to expose a function to abort whatever it's doing.
Recently I've found this example repository that allows for binding Qt with Rust libraries but doesn't seem to delve into multithreading, and might require my project to be ported from CMake to qmake. But from my understanding the Rust executions should be residing in another thread, so I'm not sure how is it achieved here.
The implementation is correct, save for the fact that I forgot a thread->start() call at the end of on_request_thread() function.
The crash happened because of a problem while parsing the ConfigObject, so it had nothing to do with the making of a thread.
Related
I am trying to setup an infinite loop in another thread. The purpose is to download some data from an URL, send the data to the main thread and sleep for some seconds:
DataFetcher::DataFetcher(QUrl url, int fetchRateSec) :
url {url},
fetchRateSec {fetchRateSec}
{
}
void DataFetcher::run()
{
QNetworkAccessManager* manager = new QNetworkAccessManager();
QObject::connect(manager, &QNetworkAccessManager::finished, this, &DataFetcher::onReply);
while (true) {
QNetworkRequest req;
req.setUrl(url);
manager->get(req);
qDebug() << "run";
sleep(fetchRateSec);
}
}
void DataFetcher::onReply(QNetworkReply* reply)
{
qDebug() << "repl";
emit fetched(reply->readAll());
}
class DataFetcher : public QThread
{
Q_OBJECT
public:
DataFetcher(QUrl, int);
void run() override;
signals:
void fetched(QString);
private:
const QUrl url;
const int fetchRateSec;
private slots:
void onReply(QNetworkReply*);
};
But onReply is never called.
It is interesting because the qDebug in the while loop is executed as it should.
Im a bit nooby with QT so i might have missed something regarding how to connect the slots / signals but i think i got it right following some other examples.
It looks about right from the accepted answer in How do I write a Qt HTTP GET request?
what could be the problem here?
Per the discussion in the comments, it seems like the whole business of threading is not needed.
One of Qt's strongest attributes is that it is event-driven. You generally create a program by describing what you want to happen (slots) in response to certain events (signals). Explicitly waiting or sleeping is very rare in Qt-based applications (usually only testing), and is generally considered a no-no in event-driven development.
For your specific problem, a solution might look like this. You can create a QTimer in the main thread and connect its timeout signal to a function to make your HTTP request. You can then connect a slot to the QNetworkAccessManager::finished signal, which will run when your response completes. All of this can take place in the main thread, relying on the thread's event loop to manage the callbacks. No need to manage a separate thread yourself, and no looping, sleeping, blocking, or anything like that.
For the better part of the last few hours I've been trying to get a clue on how to approach this problem - I have an application where I need to get information from a thread into some intermediary module, which then sends it to the Qt GUI using Qt signals (which I've previously used, but only inside a Qt GUI). So now I'm facing this issue - I have a thread that does some processing, for example :
class TrialLogic
{
public:
void operator()();
TrialLogic(TrialModel *m);
~TrialLogic();
private:
TrialModel *model;
void emitSignal();
int testNum;
};
When the class TrialLogic is created, it is given the pointer to TrialModel, which does some additional processing before passing them to the GUI.
Now here's the problem - how do I get my thread to emit a signal that, for example, passes the testNum value to the TrialModel class, which has a function that can take the testNum as an argument?
First this is my first development using bb10 sdk and also with qml + c++, I had
I'm trying to capture the moment when the user slids from the blackberry logo, to minimize or switch app. Acording to their official documentation http://developer.blackberry.com/native/documentation/core/com.qnx.doc.native_sdk.devguide/com.qnx.doc.native_sdk.devguide/topic/c_appfund_applifecycle.html
There is a state windows NAVIGATOR_WINDOW_INACTIVE that comes when the invisible() method is called,
the thing here: is that the documentation and searches I've done on internet, doesn't explain anything about were to override a method that listens for this event.
Any help would be greatly appreciated.
You need to create a subclass of QObject. If you use the project creation wizard Momentics will do this for you as applicationui.hpp and applicationui.cpp. In this class declare the following slots in application.hpp:
public slots:
void asleep();
void awake();
void invisible();
void thumbnail();
void fullscreen();
Then in the class creation function attach the Application signals to your slots:
bool c = QObject::connect(Application::instance(), SIGNAL(asleep()),
this, SLOT(asleep()));
Q_ASSERT(c);
c = QObject::connect(Application::instance(), SIGNAL(awake()),
this, SLOT(awake()));
Q_ASSERT(c);
c = QObject::connect(Application::instance(),
SIGNAL(invisible()), this, SLOT(invisible()));
Q_ASSERT(c);
c = QObject::connect(Application::instance(),
SIGNAL(thumbnail()), this, SLOT(thumbnail()));
Q_ASSERT(c);
c = QObject::connect(Application::instance(),
SIGNAL(fullscreen()), this, SLOT(fullscreen()));
Q_ASSERT(c);
Q_UNUSED(c);
Then define the slot functions to perform what you need to do when the application state changes into the one corresponding to the signal (I've only included one here):
void applicationui::asleep() {
//configure application for sleep mode. Suspend or reduce processing, etc.
}
I'm trying to implement some small app which is a gui app and has some heavy work to do as a one of it's main tasks. Obviously I'm putting this "work" into a separate thread and starting this thread by invoking start fnc on this obj. Unfortunatelly nothing happens. On the other hands when instead of start I invoke implemented fnc run computations are performed as they should although of course in same thread as gui. What to do?
So I have class inheriting QThread:
class Working_Thread : public QThread
{
Q_OBJECT
public:
typedef boost::filesystem3::path path_t;
private:
bool& cancel_flag_;
const std::set<path_t>& paths_;
int search_depth_;
typedef void (Dir_File_Select_Dialog::*fnc_ptr)(const std::set<path_t>&,int);
fnc_ptr fnc_;
Dir_File_Select_Dialog* parent_;
protected:
void run()
{
(parent_->*fnc_)(paths_,search_depth_);
}
public:
Working_Thread(bool& cancel_flag,const std::set<path_t>&,int&,fnc_ptr fnc,Dir_File_Select_Dialog* parent);
};
And here is fragment from gui thread when I try to start new thread:
Working_Thread* working_thread = new Working_Thread(cancel_flag,paths,search_depth,&Dir_File_Select_Dialog::extract_files_,this);
working_thread->start();//this desn't invoke run fnc
but when I do:
working_thread->run();//this will perform computations although in gui thread
UPDATE:
Little change I did which now performs computations when using start fnc but it still blocks GUI.
Working_Thread* working_thread = new Working_Thread(cancel_flag,paths,search_depth,&Dir_File_Select_Dialog::extract_files_,this);
working_thread->start();//hangs
working_thread->wait();//when I call wait here computation is performed but GUI is blocked.
I don't know how your code is actually done, but as a first step i suggest you to follow the best practice suggested at the end of the new revision of the Qt documentation of QThread :
http://qt-project.org/doc/qt-4.8/QThread.html (look for bottom of this page)
For a similar tutorial you also may check this article: http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
Every time i tried to directly make my treatment in a QThread I ended up having big problems with threads (most of time, the treatment beeing done in the caller's tread).
This documentation has been added in 4.8 and the examples provided by documentation of previous versions were missleading.
(code copied from the Qt documentation)
Consider the following pattern as your default way to use QThread:
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork() {
/* ... */
}
};
/* ... */
QThread *thread = new QThread;
Worker *worker = new Worker;
//obj is a pointer to a QObject that will trigger the work to start. It could just be this
connect(obj, SIGNAL(startWork()), worker, SLOT(doWork()));
worker->moveToThread(thread);
thread->start();
//obj will need to emit startWork() to get the work going.
Alternatively, you could do:
//based on the same Worker class as above:
/* ... */
QThread *thread = new QThread;
Worker *worker = new Worker;
worker->moveToThread(thread);
thread->start();
QMetaObject::invokeMethod(worker, "doWork", Qt::QueuedConnection);
It is normal that the GUI blocks if you call wait() on a thread, because this will wait for the thread to finish, and also you haven't specified any timeout for wait in this case.
Now regarding the initial problem (when you don't call wait()), I have used QThread successfully in similar scenarios. I do not know though what is wrong in your code, but what I would check is if your execution doesn't hang in other places, like in the invocation of
(parent_->*fnc_)(paths_,search_depth_);
So maybe inserting some log / debug message before and after this call, and also in the function that is invoke here might help isolating the problem. At least then you'll know if the run() method is invoked or not. For example:
qDebug() << "In thread.run()";
(parent_->*fnc_)(paths_,search_depth_);
qDebug() << "In thread.run(), calculations are done";
Also I find it suspicious that you perform calculation using a GUI object (Dir_File_Select_Dialog). This is not normal in Qt, Gui objects should normally be used in the GUI thread. Why not implement the calculations directly in run? Or at least move it to a non-GUI object, just to be sure and keep GUI implementations separated from background operations.
If you call wait, the GUI is going to be blocked.
If this program hangs when you do a start, it seems that the problem is in this call: (parent_->*fnc_)(paths_,search_depth_);
You could place a qDebug call just before and after this call.
I have asked this problem on many popular forums but no concrete response. My applciation uses serial communication to interface with external systems each having its own interface protocol. The data that is received from the systems is displayed on a GUI made in Qt 4.2.1.
Structure of application is such that
When app begins we have a login page
with a choice of four modules. This
is implemented as a maindisplay
class. Each of the four modules is a
separate class in itself. The concerned module here is of action class which is responsible of gathering and displaying data from various systems.
User authentication gets him/her
into the action screen. The
constructor of the action screen
class executes and apart from
mundane initialisation it starts the
individual systems threads which are
implemented as singleton.
Each system protocol is implemented as a singleton thread of the form:
class SensorProtocol:public QThread {
static SensorProtocol* s_instance;
SensorProtocol(){}
SensorProtocol(const SensorProtocol&);
operator=(const SensorProtocol&);
public:
static SensorProtocol* getInstance();
//miscellaneous system related data to be used for
// data acquisition and processing
};
In implementation file *.cpp:
SensorProtocol* SensorProtocol::s_instance=0;
SensorProtocol* SensorProtocol::getInstance()
{
//DOUBLE CHECKED LOCKING PATTERN I have used singletons
// without this overrated pattern also but just fyi
if(!s_instance)
{
mutex.lock();
if(!s_instance)
s_instance=new SensorProtocol();
mutex.unlock();
}
}
Structure of run function
while(!mStop)
{
mutex.lock()
while(!WaitCondition.wait(&mutex,5)
{
if(mStop)
return;
}
//code to read from port when data becomes available
// and process it and store in variables
mutex.unlock();
}
In the action screen class I have define an InputSignalHandler using sigaction and saio. This is a function pointer which is activated as soon as data arrives on any of the serial ports.
It is a global function (we cannot change it as it is specific to Linux) which is just used to compare the file descriptors of the serial port where data has arrived and the fd's of the sensor systems, if a match is found WaitCondition.wakeOne is invoked on that thread and it comes out the wait and reads and processes the data.
In the action screen class the individual threads are started as SensorProtocol::getInstance()->start().
Each system's protocol has a frame rate at which it sends data. Based on this fact, in actions screen we set up update timers to time out at refresh rate of protocols. When these timers time out the UpdateSensorProtocol() function of operation screen is called
connect(&timer, SIGNAL(timeout), this,SLOT(UpdateSensorProtocol()));
This grabs an instance of sensor singleton as
SensorProtocol* pSingleton=SensorProtocol::getInstance();
if(pSingleton->mUpdate)
{
//update data on action screen GUI
pSingleton->mUpdate=false; //NOTE : this variable is set to
// true in the singleton thread
// while one frame is processed completely
}
For all uses of singleton instance SensorProtocol::getInstance() is used. Given the above scenario, One of my protocols is hanging no matter what changes I do.
The hang occurs in the while displaying data using UpdateSensorProtocol() If I comment ShowSensorData() function in the UpdateSensorProtocol() it works fine. But otherwise it hangs and the GUI freezes. Any suggestions!
Also, Since the main thread grabs the running instance of singleton, is it really multithreading because we are essentially changing mUpdate in singleton itself albeit from action screen.
I am confused in this.
Also, Can somebody suggest an alternate design as to what I am doing now.
Thanks In Advance
First off all don't make the Systems singletons. Use some kind of Context Encapsulation
for the different system.
If you ignoe this advice and still want to create "singletons" threads at least use QApplication::instance(); as the parent of the thread and put QThread::wait() in the singleton destructors otherwise your program will crash at the program exit.
if(!s_instance){
QMutexLocker lock(&mutex);
if(!s_instance)
s_instance=new SensorProtocol( QApplication::instance());
}
But this isn't going to solve your problem ...
Qt is event driven so try to exployed this very nice event-driven architecture and create a eventloop for each system thread. Then you can create "SystemProtocols" that live in another threads and you can create timers, send events between threads, ... without using low level synchronization objects.
Have a look at the blog entry from Bradley T. Hughes Treading without the headache
Code is not compiled but should give you a good idea where to start ...
class GuiComponent : public QWidget {
//...
signals:
void start(int); // button triggerd signal
void stop(); // button triggerd singal
public slots:
// don't forget to register DataPackage at the metacompiler
// qRegisterMetaType<DataPackage>();
void dataFromProtocol( DataPackage ){
// update the gui the the new data
}
};
class ProtocolSystem : public QObject {
//...
int timerId;
signals:
void dataReady(DataPackage);
public slots:
void stop() {
killTimer(timerId);
}
void start( int interval ) {
timerId = startTimer();
}
protected:
void timerEvent(QTimerEvent * event) {
//code to read from port when data becomes available
// and process it and store in dataPackage
emit dataReady(dataPackage);
}
};
int main( int argc, char ** argv ) {
QApplication app( argc, argv );
// construct the system and glue them together
ProtocolSystem protocolSystem;
GuiComponent gui;
gui.connect(&protocolSystem, SIGNAL(dataReady(DataPackage)), SLOT(dataFromProtocol(DataPackage)));
protocolSystem.connect(&gui, SIGNAL(start(int)), SLOT(start(int)));
protocolSystem.connect(&gui, SIGNAL(stop()), SLOT(stop()));
// move communication to its thread
QThread protocolThread;
protocolSystem.moveToThread(&protocolThread);
protocolThread.start();
// repeat this for other systems ...
// start the application
gui.show();
app.exec();
// stop eventloop to before closing the application
protocolThread.quit();
protocolThread.wait();
return 0;
}
Now you have total independent systems, gui and protocols don't now each other and don't even know that the program is multithreaded. You can unit test all systems independently in a single threaded environement and just glue them together in the real application and if you need to, divided them between different threads.
That is the program architecture that I would use for this problem. Mutlithreading without a single low level synchronization element. No race conditions, no locks, ...
Problems:
Use RAII to lock/unlock your mutexes. They are currently not exception safe.
while(!mStop)
{
mutex.lock()
while(!WaitCondition.wait(&mutex,5))
{
if(mStop)
{
// PROBLEM 1: You mutex is still locked here.
// So returning here will leave the mutex locked forever.
return;
}
// PROBLEM 2: If you leave here via an exception.
// This will not fire, and again you will the mutex locked forever.
mutex.unlock();
// Problem 3: You are using the WaitCondition() incorrectly.
// You unlock the mutex here. The next thing that happens is a call
// WaitCondition.wait() where the mutex MUST be locked
}
// PROBLEM 4
// You are using the WaitCondition() incorrectly.
// On exit the mutex is always locked. So nwo the mutex is locked.
What your code should look like:
while(!mStop)
{
MutextLocker lock(mutex); // RAII lock and unlock mutex.
while(!WaitCondition.wait(&mutex,5))
{
if(mStop)
{
return;
}
//code to read from port when data becomes available
// and process it and store in variables
}
By using RAII it solves all the problems I spotted above.
On a side note.
Your double checked locking will not work correctly.
By using the static function variable suggested by 'Anders Karlsson' you solve the problem because g++ guarantees that static function variables will only be initialized once. In addition this method guaranteed that the singelton will be correctly destroyed (via destructor). Currently unless you are doing some fancy stuff via onexit() you will be leaking memory.
See here for lots of details about better implementation of singleton.
C++ Singleton design pattern
See here why your double checked locking does not work.
What are all the common undefined behaviours that a C++ programmer should know about?
I would start by using RAII (Resource Acquisition Is Initialization) to improve the safety of your locking code. You have code that look like this:
mutex.lock();
...logic...
mutex.unlock();
Wrap the mutex code inside a class where the mutex gets acquired in the ctor and released in the dtor. Now your code looks like this:
MyMutex mutex;
...logic...
The major improvement is that if any exceptions throw in the logic part, your mutex still gets released.
Also, don't let any exceptions leak out of your threads! Catch them even if you don't know how to handle them other than logging it somewhere.
I can't be completely sure what the problem is since I have no clue what the ShowSensorData() function (method?) is doing, but there are some multithreading issues with the code that you have included.
mUpdate should be protected by a mutex if it is accessed by more than one thread.
The run() method looks like it will lock the mutex and never release it if mStop is true.
You should consider using RAII practices to grab and release the mutex. I don't know if you are using Qt mutexes or not but you should look into using QMutexLocker to lock and unlock your mutexes.
I would consider changing your SensorProtocol class to use the condition variable and a flag or some sort of event (not sure what Qt has to offer here) to handle the update inside of a method associated with the object instance. Something like:
/*static*/ void
SensorProtocol::updateSensorProtocol() {
SensorProtocol *inst = SensorProtocol::getInstance();
inst->update();
}
Then make sure that the update() method grabs the mutex before reading or writing any of the members that are shared between the reader and display.
A more complete approach would be to separate your UI display, the sensors, and their linkage using a Model-View-Controller architecture. Refactoring the solution into an MVC architecture would probably simplify things quite a bit. Not to mention that it makes applications like this a lot less error-prone. Take a look at the QAbstractItemView and QAbstractItemDelegate classes for an idea on how this can be implemented. From what I remember, there is a tutorial about implementing MVC using Qt somewhere... it's been quite a few years since I have played with Qt though.
your getInstance method could maybe be written like this as well to avoid having the s_instance var:
SensorProtocol& getInstance()
{
static SensorProtocol instance;
return instance;
}
The double checked locking pattern is broken in C++. This is well documented all over the internet. I don't know what your problem is but clearly you will need to resolve this in your code.
Take a look at QextSerialPort:
QextSerialPort is a cross-platform
serial port class. This class
encapsulates a serial port on both
POSIX and Windows systems.
QextSerialPort inherits from QIODevice and makes serial port communications integrate more smoothly with the rest of the Qt API.
Also, you could use a message passing scheme for communications between the I/O and GUI threads instead of shared memory. This is often much less error prone. You can use the QApplication::postEvent function to send custom QEvent messages to a QObject to be processed in the GUI thread with the QObject::customeEvent handler. It will take care of synchronization for you and alleviate your deadlock problems..
Here is a quick and dirty example:
class IODataEvent : public QEvent
{
public:
IODataEvent() : QEvent(QEvent::User) {}
// put all of your data here
};
class IOThread : public QThread
{
public:
IOThread(QObject * parent) : QThread(parent) {}
void run()
{
for (;;) {
// do blocking I/O and protocol parsing
IODataEvent *event = new IODataEvent;
// put all of your data for the GUI into the event
qApp->postEvent(parent(), event);
// QApplication will take ownership of the event
}
}
};
class GUIObject : public QObject
{
public:
GUIObject() : QObject(), thread(new IOThread(this)) { thread->start() }
protected:
void customEvent(QEvent *event)
{
if (QEvent::User == event->type) {
IODataEvent *data = (IODataEvent *) event;
// get data and update GUI here
event->accept();
} else {
event->ignore();
}
// the event loop will release the IODataEvent memory automatically
}
private:
IOThread *thread;
};
Also, Qt 4 supports queing signals and slots across threads.
Have three sepearate threads for send, receive and display.
Raise an event whenever data is received and handle that within the display thread.
Edit in response to comment 1
I'll admit that I know nothing of qt but from what you've said it would still appear that you can create your serial port object which in turn starts up two worker threads (by use of a start method) for the input and output buffer control.
If the serial port class has a "Connect to port" method to gain use of the serial port; an "Open port" method which starts up your worker threads and opens the port; a "Close port" method to shutdown the send and receive threads and a property for setting the "On Data Received" event handler then you should be all set.
The class shouldn't need to be a singleton as you'll find that most operating systems wont allow more than one process to control a serial port at any one time, instead you'll get an exception (which you need to handle) when you try and connect if it is already in use. The worker threads ensure that the port is held under you're control.