I am new to Qt, and today I've been trying to adapt my application to work with QFuture to concurrently run some tasks off the main thread.
I have a method which changes the saturation value of a QImage which returns a QPixmap object to be drawn to my QGraphicsView. This all worked fine not using threads, but obviously it is extremely intensive on the main thread so I wanted to move it off.
I read a few articles regarding Threading in Qt, and found that v5 supports a concurrent run functionality, this sounded perfect for my use case as I thought I would just be able to dispatch my functions onto a new thread as in the snippet below:
void MainWindow::on_slideSaturation_valueChanged(int value)
{
QFuture<QPixmap> future = QtConcurrent::run(slider->modifySaturation, value, image);
future.waitForFinished();
image = future.result();
renderImageToCanvas();
modified = true;
}
However I get the error reference to non-static member function must be called.
This error is being called from my Sliders class, I know I haven't declared the method as static, but when I do it causes a whole heap of errors - is there any way I can pass this method to my concurrent call without it being declared as static?
Sliders.h
class Sliders
{
public:
Sliders();
enum Member { RED, GREEN, BLUE, BRIGHTNESS, CONTRAST, HUE, SATURATION, LIGHTNESS };
QPixmap modifySaturation(int, QPixmap);
void setMember(enum Member, int);
int getMember(enum Member);
private:
int m_redValue;
int m_greenValue;
int m_blueValue;
int m_brightnessValue;
int m_contrastValue;
int m_hueValue;
int m_saturationValue;
int m_lightnessValue;
};
You should call QtConcurrent::run like this:
QFuture<QPixmap> future = QtConcurrent::run(slider,
&Sliders::modifySaturation,
value, image);
But I think you are using it wrong anyway. Your on_slideSaturation_valueChanged slot, which I assume to be executed in the main thread, will be blocked until future.waitForFinished() returns.
Related
I'm currently updating an existing codebase designed to be used with a GTK GUI to QT, so that it can implement multi threading, as the functions take hours to complete.
This codebase makes frequent calls to a function display(std::string), for the purpose of updating a text display widget. I redefined this function for the new QT version:
In Display.cpp:
void display(std::string output)
{
//
MainWindow * gui = MainWindow::getMainWinPtr(); //Gets instance of GUI
gui->DisplayInGUI(output); //Sends string to new QT display function
}
In MainWindow.cpp:
void MainWindow::DisplayInGUI(std::string output)
{
//converts output to qstring and displays in text edit widget
}
void MainWindow::mainFunction(){
//calls function in existing codebase, which itself is frequently calling display()
}
void MainWindow::on_mainFunctionButton_released()
{
QFuture<void> future = QtConcurrent::run(this,&MainWindow::mainFunction);
}
If I run the main function in a new thread, display(std::string) won't update the GUI until the thread completes. I understand why; the GUI can only be updated in the main thread. Everything else functions as intended.
What I want to implement, but I'm not sure how, is having display(std:string) send a signal back to the main thread to call MainWindow::DisplayInGUI(output_text) with the string that was passed to the display() function. I believe this is the correct way to do it, but correct me if I'm wrong. I want to avoid changing the existing codebase at all costs.
EDIT: I should add that for some dumb reasons entirely out of my control, I am forced to use C++98 (yeah, I know)
You must schedule the code that does UI calls to run in the main thread. I use a simple and easy to use wrapper for that:
#include <QApplication>
#include <QtGlobal>
#include <utility>
template<typename F>
void runInMainThread(F&& fun)
{
QObject tmp;
QObject::connect(&tmp, &QObject::destroyed, qApp, std::forward<F>(fun),
Qt::QueuedConnection);
}
You can now run code (using a lambda in this example, but any other callable will work) in the main thread like this:
runInMainThread([] { /* code */ });
In your case:
void display(std::string output)
{
runInMainThread([output = std::move(output)] {
MainWindow* gui = MainWindow::getMainWinPtr();
gui->DisplayInGUI(output);
});
}
Or you can leave display() as is and instead wrap the calls to it:
runInMainThread([str] { display(std::move(str)); );
The std::move is just an optimization to avoid another copy of the string since you should not pass the string by reference in this case (it would be a dangling reference once the string object goes out of scope.)
This is not a high performance inter-thread communication mechanism. Every call will result in the construction of a temporary QObject and a temporary signal/slot connection. For periodic UI updates, it's good enough and it allows you to run any code in the main thread without having to manually set up signal/slot connections for the various UI update operations. But for thousands of UI calls per second, it's probably not very efficient.
First of all: there's no way to make the getMainWinPtr method thread-safe, so this pseudo-singleton hack should probably go away. You can pass around some application-global context to all the objects that do application-global things like provide user feedback. Say, have a MyApplication : QObject (don't derive from QApplication, it's unnecessary). This can be passed around when new objects are created, and you'd then control the relative lifetime of the involved objects directly in the main() function:
void main(int argc, char **argv) {
QApplication app(argc, argv);
MainWindow win;
MyApplication foo;
win.setApplication(&foo);
// it is now guaranteed by the semantics of the language that
// the main window outlives `MyApplication`, and thus `MyApplication` is free to assume
// that the window exists and it's OK to call its methods
...
return app.exec();
}
Of course MyApplication must take care that the worker threads are stopped before its destructor returns.
To communicate asynchronous changes to QObject living in (non-overloaded) QThreads (including the main thread), leverage the built-in inter-thread communication inherent in Qt's design: the events, and the slot calls that traverse thread boundaries.
So, given the DisplayInGUI method, you need a thread-safe way of invoking it:
std::string newOutput = ...;
QMetaObject::invokeMethod(mainWindow, [mainWindow, newOutput]{
mainWindow->displayInGUI(newOutput);
});
This takes care of the thread-safety aspect. Now we have another problem: the main window can get hammered with those updates much faster than the screen refresh rate, so there's no point in the thread notifying the main window more often than some reasonable rate, it'll just waste resources.
This is best handled by making the DisplayInGUI method thread-safe, and leveraging the timing APIs in Qt:
class MainWindow : public QWidget {
Q_OBJECT
...
static constexpr m_updatePeriod = 1000/25; // in ms
QMutex m_displayMutex;
QBasicTimer m_displayRefreshTimer;
std::string m_newDisplayText;
bool m_pendingRefresh;
...
void timerEvent(QTimerEvent *event) override {
if (event->timerId() == m_displayRefreshTimer.timerId()) {
QMutexLocker lock(&m_displayMutex);
std::string text = std::move(m_newDisplayText);
m_pendingRefresh = false;
lock.release();
widget->setText(QString::fromStdString(text));
}
QWidget::timerEvent(event);
}
void DisplayInGUI(const std::string &str) {
// Note pass-by-reference, not pass-by-value. Pass by value gives us no benefit here.
QMutexLocker lock(&m_displayMutex);
m_newDisplayText = str;
if (m_pendingRefresh) return;
m_pendingRefresh = true;
lock.release();
QMetaObject::invokeMethod(this, &MainWindow::DisplayInGui_impl);
}
private:
Q_SLOT void DisplayInGui_impl() {
if (!m_displayRefreshTimer.isActive())
m_displayRefreshTimer.start(this, m_updatePeriod);
}
};
In a more complex situation you'd likely want to factor out the cross-thread property setting to some "adjunct" class that would perform such operations without the boilerplate.
You could take advantage of the fact that QTimer::singleShot has an overload which, when called with a zero time interval, allows you to effectively schedule a task to be run on a specified thread during that thread's next idle slot...
void QTimer::singleShot(int msec, const QObject *context, Functor functor);
So your MainWindow::mainFunction could be something along the lines of...
void MainWindow::mainFunction ()
{
...
std::string output = get_ouput_from_somewhere();
QTimer::singleShot(0, QApplication::instance(),
[output]()
{
display(output);
});
...
}
I'm creating a GLFWKeyCallback and because of how simple it is I've decided to use a lambda. This callback modifies a member variable, so I have to pass this into the capture list. Here is what my code looks like so far:
glfwSetKeyCallback(window,
[this](GLFWwindow* window, int key, int scancode, int action, int mods)
{
if(action == GLFW_PRESS)
{
//use a mutex
//Modify member variable
}
});
The problem is that whenever I pass this into the capture list, Visual Studio 2019 displays the following error:
no suitable conversion function from "lambda [] void (GLFWwindow *window, int key, int scancode, int action, int mods)->void" to GLFWKeyfun" exists
Have I missed something or is this code just invalid?
The GLFW callbacks don't take lambdas, or function objects: they take plain old function pointers. A non-capturing lambda can be converted to a function pointer, but not a capturing one.
However, you can get a similar effect by using glfwSetUserPointer and glfwGetUserPointer. The lambda still can't be capturing, but you can recover the this pointer.
For example,
struct MyClass {
GLFWwindow* window;
MyClass(GLFWwindow* window) : window(window) {
glfwSetWindowUserPointer(window, static_cast<void*>(this));
glfwSetKeyCallback(window,
[](GLFWwindow* window, int key, int scancode, int action, int mods) {
auto self = static_cast<MyClass*>(glfwGetWindowUserPointer(window));
// can access member variables through `self`
});
}
// make sure that either the class will last as long as GLFW will
// or clean up the user pointer and callbacks in here
~MyClass() {
// clean up
}
// don't be able to copy, probably, or bad things will happen
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
// other things...
};
Adding onto the other answer.
I see glfwSetWindowUserPointer brought up a lot as a solution to this issue. It works fine (and I use it myself, since I don't know of any other solution), but it comes with a caveat that I haven't seen anyone mention:
You can only store one pointer per Window using this method. If some other code sets a different pointer to your window, all of a sudden your lambda won't work anymore. I can think of two workarounds here:
When you retrieve the pointer in your lambda body, set it to a static variable. This way, it will persist across calls to the lambda, even if someone else sets a different pointer. Note: the static variable won't initialize until the first call to the lambda, so you'd be best to call the lambda once, yourself, after defining it.
Define a object or map of pointers. Give GLFWSetUserPointer a pointer to that map. I can't think of any way to enforce this pattern, but if you have complete control over your app, you can store multiple pointers in associated with a Window this way.
I'm thinking of creating a big new C++ project. The start is easy - just a simple window, maybe SDL2, maybe SFML, maybe even WIN32. Well, what should I take? Wouldn't it be much nicer to use any window I want to? Without changing much code so that other classes are independent of this window?
Said, done! Using a simple window interface, every class knows of something like a window and I'm able to choose between different types. The only requirement is having IWindow as a base class.
class IWindow {
public:
IWindow(std::string title, int posX, int posY, int width, int height);
IWindow getHandle();
void loop();
bool toggleFullscreen();
bool toggleFullscreen(bool fullscreen);
int getWidth();
int getHeight();
int getPosX();
int getPosY();
//And so on ...
};
But now, since I have to use virtual methods, every time my virtual function loop will be called by the game loop. And virtual functions are slower. About 10%, I've read.
Isn't the compiler able to see what my window will be? Of which type it'll be from? Couldn't it see "Jeah, this programmer guy creates an SDL window in this application, so just use it's methods everywhere."? I mean, I'm defining my window during the main loop and it'll never change. It's nothing dynamical. It's predictable.
So is the compiler able to optimize my predictable virtual function calls? These which will be evaluated every game loop cycle? Like in the following passage?
int main(int argc, char* argv[]) {
//Creates a window derived from IWindow
SDL::Window myWindow("Title", 0, 0, 300, 100);
//Storing it as IWindow in a wrapper class
Game myGame(&myWindow);
//Game loop
//myGame.run() calls the window's loop
while (myGame.run()) {
//... doing game stuff
}
}
With a Game class like this:
class Game {
protected:
IWindow* window;
public:
bool run() {
//Calls the window's virtual loop method.
//Will it be optimized? Any way to do so?
this->window->loop();
}
};
It would be nice to hear of your ideas and experiences.
Darth Moon
Does C++ compiler optimize virtual member calls?
Yes, a compiler might be able to de-virtualize virtual function calls if it can determine the concrete type at compile time.
No, a C++ compiler will not be able to de-virtualize all virtual function calls.
And virtual functions are slower. About 10%
Assuming the 10% difference is correct, consider that function call overhead is probably somewhere in magnitude of a few nano seconds. 10% of a few nano seconds is not a lot. You can fit many, many nano seconds in a single iteration of a soft real time simulation like a game.
Isn't the compiler able to see what my window will be?
So is the compiler able to optimize my predictable virtual function calls?
Maybe.
Firstly, call to run must be expanded inline in the context where the pointer is assigned. Otherwise it cannot make any assumptions about the pointed object. In order to be expanded inline, it must be defined in the same translation unit as where the function is called from (except, LTO may be able to lift this requirement).
Furthermore, the compiler must be able to prove that window is not modified at any point during the execution to point another object. This proof may be impossible depending on what your loop looks like, but there is a simple way to make it easy: declare the pointer const.
As for whether your compiler does optimize it... I don't know. But your compiler does, so I suggest directing your question to your compiler (i.e. ask it to compile your program and see what it does).
Let's sum up our comments.
Virtual calls are costly, but if the processor can detect a pattern, their calling cost gets decreased thanks to the predictors inside modern processors.
Now, let's check your code:
int main(int argc, char* argv[]) {
//Creates a window derived from IWindow
SDL::Window myWindow("Title", 0, 0, 300, 100);
//Storing it as IWindow in a wrapper class
Game myGame(&myWindow);
//Game loop
//myGame.run() calls the window's loop
while (myGame.run()) {
//... doing game stuff
}
}
Let's assume Game has a virtual run. In this instance, the compiler knows that myGame is of type Game and can directly put the call to your run function instead of going through the virtual table.
Now you have this in another file:
class Game {
protected:
IWindow* window;
public:
bool run() {
//Calls the window's virtual loop method.
//Will it be optimized? Any way to do so?
this->window->loop();
}
};
Unfortunately, in this case, there is nothing that the compiler can know by just looking at this file, and as such the call to SDL::Window will go through the virtual run coming from IWindow.
Now with lto (link time optimization), the compiler might be able to figure it out and de-virtualize the code, but it will probably not as the number of optimization options will grow with the number of files as well as the number of combinations.
I want to write an tool of objective annotation using qt5 MinGw32, which could annotate object in video file and diplay them during playing. So QGraphicsScene is inherited to implementation the function.
Something wrong happens when I change the QGraphicsScene's background frequently(e.g. 30 fps): most of time it works as expected while sometimes the background could not move.
Here is my code:
void MyGraphicsScene::UpdateFrame(QImage image)
{
QPixmap pixmap = QPixmap::fromImage(image);
//fix the view's size and scene's size
views().first()->setFixedSize(pixmap.size());
setSceneRect(0,0, pixmap.width(), pixmap.height());
setBackgroundBrush(QBrush(pixmap));
}
...
//In another thread
void Thread::run()
{
...
myScene.UpdateFrame(newImage);
...
}
I have search through the qt's document and found no answer.
However, there is something strange:
when wrong thing happens, I find the background continues to change, but it didn't show change on the screen unless I move the app to another screen (I have two screen). However, with the app moved, the QGraphicsScene's background just change once and becomes static afterwards.
I guess the background has been changed but doesn't repainted, so I used update(), but it didn't help.
BTW, I couldn't reproduce the occasion, sometiems it happens, somtimes not.
do I need to represented any methods? Or I called the methods in a wrong way? Or is there an alternative approach that would work?
Many thanks for your help in advance.
You should not change QtGui elements from a different thread by calling a method directly.
Use the Qt signal-slot concept.
Calling update() is not necessary.
class MyGraphicsScene{...
....
signals:
void singalFromThread(QImage image);
public:
//CTor
MyGraphicsScene()
{
connect(this, SIGNAL(singalFromThread(QImage)),this,SLOT(UpdateFrame(QImage)));
}
//Call this method from your thread
void updateForwarder(QImage image)
{
//Jump into gui thread
emit singalFromThread(image);
}
public slots:
void UpdateFrame(QImage image)
{
setBackgroundBrush(....);
}
};
I am trying to load multiple QImage objects from files using a threadpool. I have created my own QRunnable subclass to load the image from a file and copy it into a buffer:
class ImageLoader : public QRunnable
{
public:
ImageLoader(const QString &filename, char **buffer, int *size) :
QRunnable(),
filename(filename),
buffer(buffer),
size(size)
{}
// QRunnable interface
void run() {
QImage image(filename);
(*size) = image.byteCount();
(*buffer) = new char[(*size)];
memcpy_s(*buffer), (*size), image.constBits(), image.byteCount());
}
private:
const QString filename;
char **buffer;
int *size;
};
The code works fine if executed on the main thread, but as soon as I run the runnable on a QThreadPool, I get a huge bunch of errors, that basically all say the same:
QObject::moveToThread: Current thread (0x2a023ae6550) is not the object's thread (0x2a023ae65c0).
Cannot move to target thread (0x2a023aca0f0)
The first 2 addresses change each message, I assume they represent the different threads of the pool. Whats interesting:
The first and the second are never the same, however, they are all of the same "group", i.e. the first address of the first error can become the second address of the second error etc...
The third address always stays the same, it's the address of the main (gui) thread.
Any Ideas why that happens or how to fix it? I read the documentation of QImage but wasn't able to find anything about threads in there, except:
Because QImage is a QPaintDevice subclass, QPainter can be used to draw directly onto images. When using QPainter on a QImage, the painting can be performed in another thread than the current GUI thread.
Is solved the problem myself:
The path I passed to the QImage was invalid. I don't know how this was able to produce such an error, but after I fixed the path, it works just fine!