Gtk+ 3.0 Signal that trigger upon change in variable - c++

I am trying to use Gtk 3.0 to visualize a network of nodes in real-time. The network of nodes will make new nodes and new connections will be formed between the nodes in real-time. I'm thinking of using one thread to configure Gtk and begin Gtk's main loop, and another for the development of the nodal network. The variables of the network will be global so that both the network developing thread and the Gtk thread can see the network variables. I will use a mutex on both sides to ensure synchronization.
My Gtk event-handler function will draw the current network, and idealistically, it should get called every time the network changes (eg new nodes, new connections). Therefore I would like to know if there is a solution in Gtk 3.0 where the event-handler function gets signaled every time a variable changes, say a change in vector's size, because I am using vector to store the nodes and connections.
I wrote a simple test program just to see if what I'm trying to do is possible. I have a thread which keeps incrementing an integer whereas another thread does all the Gtk configurations and initiates the main loop. In this code below, the Gtk thread draws the current value of the integer which keeps getting incremented. This code however is a modification of another and it does not draw the current value only at times when the value changes. Moreover, this code doesn't compile in Gtk 3.0. Is there any way to make this code compile in Gtk 3.0? In addition, is it possible to make it signal the drawing function only when the integer's value change?
#include <gtk/gtk.h>
#include <math.h>
#include <thread>
#include <mutex>
#include <string>
unsigned long long counter;
std::mutex mtx;
gboolean timeout(gpointer data) {
GtkWidget *widget = GTK_WIDGET(data);
if (!widget->window) return TRUE;
gtk_widget_queue_draw(widget);
}
gboolean expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
cairo_t *cr = gdk_cairo_create(widget->window);
cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event- >area.height);
cairo_clip(cr);
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
cairo_select_font_face(cr, "Purisa", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
std::string str;
mtx.lock();
str = std::to_string(counter);
cairo_move_to(cr, 20, 30);
cairo_show_text(cr, str.c_str());
mtx.unlock();
return FALSE;
}
void setupGtk() {
gtk_init(NULL,NULL);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(GTK_WINDOW(window), "destroy",G_CALLBACK(gtk_main_quit), NULL);
GtkWidget *drawing_area = gtk_drawing_area_new();
g_signal_connect(drawing_area,"expose_event",G_CALLBACK(expose),NULL);
gtk_container_add(GTK_CONTAINER(window), drawing_area);
gtk_widget_show(drawing_area);
g_timeout_add(10, timeout, window);
if (!GTK_WIDGET_VISIBLE (window))
gtk_widget_show_all(window);
else {
gtk_widget_destroy (window);
window = NULL;
}
gtk_main();
}
void count() {
while(counter<100000000) {
mtx.lock();
counter++;
mtx.unlock();
}
}
int main(int argc, char *argv[]) {
std::thread gtk(setupGtk);
std::thread process(count);
gtk.join();
process.join();
return 1;
}

You will need to create your own GObject class and either add a signal to that that you can emit when the value changes or add a property to represent the variable and use the notify signal.
Note that signal emission is not guaranteed to cross thread boundaries properly. You will need to use gdk_threads_idle_add() to ensure the signal gets sent on he main thread.
If your goal is simply to redraw a control, you can call gtk_widget_queue_draw() or related in the idle callback instead of emitting a signal.
Note that an idle callback runs asynchronously. If you want the callback to complete before your other thread continues, you will need to write the synchronization method yourself.
(Sorry for the terse answer; I'm in a rush.)

Related

Multithreading slows down main thread

I'll do my best to replicate this issue, since it's quite complicated. As an overview, I have a program that displays graphs using OpenGL. This is thread specific so I know the rendering is only done on one thread. My other thread queries a database and stores the data in a copy vector. Once the thread is finished, it swaps the data with the data the OpenGL thread is using (After joining the thread with the main one). In theory there is nothing about this that should make the program run so slow?
The extremely odd part of this is how it eventually "warms up" and runs much faster after a while (it varies quite a bit, sometimes almost instantaneously, sometimes after 30s of runtime). From value's side of thing to compare, the program begins running at about 30-60 fps whilst querying the data (as in, constantly loading it and swapping it and joining the threads), but then once it has warmed up it runs at 1000 fps.
I have tested some things out, beginning with making the query take A LONG time to run. During this, the fps is at a max of what it would be (3000+). It is only when the data is constantly being changed (swapping vectors) that is starts to run very slow. It doesn't make sense that this alone is causing the performance hit since it runs very well after it's "warmed up".
Edit:
I've managed to make a reasonable minimal reproducable example, and i've found some interesting result.
Here is the code:
#include <iostream>
#include <string>
#include <thread>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "ImGui/imgui.h"
#include "ImGui/imgui_impl_glfw.h"
#include "ImGui/imgui_impl_opengl3.h"
bool querying = false;
std::thread thread;
int m_Window_Width = 1280;
int m_Window_Height = 720;
static void LoadData()
{
querying = true;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
querying = false;
}
int main()
{
glfwInit();
const char* m_GLSL_Version = "#version 460";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
GLFWwindow* m_Window = glfwCreateWindow(m_Window_Width, m_Window_Height, "Program", NULL, NULL);
glfwMakeContextCurrent(m_Window);
glfwSwapInterval(0); // vsync
glewInit();
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGui::StyleColorsClassic();
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(m_Window, true);
ImGui_ImplOpenGL3_Init(m_GLSL_Version);
thread = std::thread(LoadData);
while (!glfwWindowShouldClose(m_Window))
{
glfwPollEvents();
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
char fps[12];
sprintf_s(fps, "%f", ImGui::GetIO().Framerate);
glfwSetWindowTitle(m_Window, fps);
//Load the data
if (thread.joinable() == false && querying == false) {
thread = std::thread(LoadData);
}
//Swap the data after thread is finished
if (thread.joinable() == true && querying == false) {
thread.join();
}
// Rendering
ImGui::Render();
glfwGetFramebufferSize(m_Window, &m_Window_Width, &m_Window_Height);
glViewport(0, 0, m_Window_Width, m_Window_Height);
glClearColor(0.45f, 0.55f, 0.60f, 1.00f);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(m_Window);
}
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(m_Window);
glfwTerminate();
return 0;
}
Now the interesting thing here is playing around with std::this_thread::sleep_for(). I have implemented this in so I can simulate the speed it actually takes when running the query on the main database. What is interesting is that it actually causes the main thread to stop running and freezes it. These threads should be separate and not impact one another, however that is not the case here. Is there any explanation for this? This seems to be the root issue for my main program and boiled down to this.
Edit 2
To use the libraries (in Visual Studio), download from here, the binaries, https://www.glfw.org/download.html and here aswell, http://glew.sourceforge.net/ and lastly, ImGui from here, https://github.com/ocornut/imgui
Preprocessor: GLEW_STATIC; WIN32;
Linker: glfw3.lib;glew32s.lib;opengl32.lib;Gdi32.lib;Shell32.lib;user32.lib;Gdi32.lib
This may or may not be your issue, but here:
//Load the data
if (thread.joinable() == false && querying == false) {
thread = std::thread(LoadData);
}
//Swap the data after thread is finished
if (thread.joinable() == true && querying == false) {
thread.join();
}
it is possible that you start the thread in the first if block, then get to the second one before LoadData modifies that bool, causing the wait for that tread to finish.
I would set querying = true; in the main thread, right after you created LoadData thread. Also, I would use some kind of synchronization, for example declare querying as atomic<bool>.
EDIT:
It appears that you do not need to check joinable() - you know when the thread is joinable: when you enter the loop, and after you re-start that thread. This looks cleaner:
std::atomic<bool> querying = true;
void LoadData()
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
querying = false;
}
and later in your loop:
//Swap the data after thread is finished
if (!querying) {
thread.join();
querying = true;
thread = std::thread(LoadData);
}

gtk_widget_add_tick_callback() and gtk_main_iteration()

I have two GTK windows
Normal (main) window that runs animation, draws stuff in callback registered by gtk_widget_add_tick_callback().
At some point secondary window is created that runs modal loop:
void show_modal()
{
GtkWindow* gw = gtkwindow(this);
if( parent() )
gtk_window_set_transient_for(gw, gtkwindow( parent() ));
gtk_widget_show(GTK_WIDGET(gw));
gtk_window_set_modal(gw,TRUE);
gtk_window_set_keep_above(gw,TRUE);
this->update_window_state(gool::WINDOW_SHOWN);
while( this->is_valid_window() )
{
if(this->_window_state == WINDOW_HIDDEN) break;
if(this->_window_state == WINDOW_STATE_NA) break;
gtk_main_iteration(); // gtk_main_iteration_do(true);
}
}
Problem: Animation in main window works fine until show_modal() is invoked. It appears as gtk_main_iteration(); blocks ticks added by gtk_widget_add_tick_callback() function. As soon as I close secondary window and so while() {gtk_main_iteration();} loop exits then animations in main window start running again.
Any idea of how to make "animation friendly" modal loops in GTK?
UPDATE: it appears as gtk_main_iteration(); blocks not only ticks but any updates of any windows other than "current" - they are simply frozen. What is the reasoning of such GTK behavior?
UPDATE #2:
gtk_dialog_run(); behaves exactly as gtk_main_iteration(); - locks any updates on any window in process other than active window.
It seems to be by definition: link
gboolean gtk_main_iteration (void);
Runs a single iteration of the mainloop. If no events are waiting to be processed GTK+ will block until the next event is noticed. If you don’t want to block look at gtk_main_iteration_do() or check if any events are pending with gtk_events_pending() first.
The explanation suggests to use gtk_main_iteration_do(FALSE) if you don't want blocking:
gboolean gtk_main_iteration_do (gboolean blocking);
Runs a single iteration of the mainloop. If no events are available either return or block depending on the value of blocking:
TRUE if you want GTK+ to block if no events are pending
As for gtk_dialog_run: it also blocks by design link
gint gtk_dialog_run (GtkDialog *dialog);
Blocks in a recursive main loop until the dialog either emits the “response” signal, or is destroyed.[...]
I read about people solving this using multiple threads: handle the GUI in the main thread and do background work in another one. There's an article about it here that might be useful.
I assume that show_modal is called from a callback or other activity in main context. You could try adding your modal window into main context using invoke or signal_idle.
This way execution of show_modal will end.
#include <gtkmm.h>
#include <string>
int main()
{
auto Application = Gtk::Application::create();
Gtk::Window window;
Gtk::Window* window2;
Gtk::Button button;
window.add(button);
//I hope timeout behaves similar to ticks. I have no idea how animations in GTK work
int i=0;
Glib::MainContext::get_default()->signal_timeout().connect([&]()->bool{
button.set_label(std::to_string(i++));
return true;
}, 1000);
button.signal_clicked().connect([&]{
Glib::MainContext::get_default()->invoke([&]()->bool{
window2 = new Gtk::Window;
window2->set_modal(true);
window2->set_keep_above(true);
window2->signal_delete_event().connect([&](GdkEventAny* any_event)->bool{
delete window2;
return false;
});
window2->show_all();
return false;
});
});
window.show_all();
return Application->run(window);
}

Updating Qt Images does not work until exec is called

I need to create a simple GUI which displays images, the images in this example can change and the GUI will need to update it's contents.
I wrote the following update function in my widget class:
void myClass::updatePic() {
QPixmap pix("./pic.png");
int width = ui->picLabel->width();
int height = ui->picLabel->height();
ui->picLabel->setPixmap(pix.scaled(width,height,Qt::KeepAspectRatio));}
I try to use it in the following manner:
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
myClass w;
w.show();
sleep(3);
w.updatePic();
sleep(3);
w.updatePic();
sleep(3);
return a.exec();}
But the window just opens and does not display the images until we get to the a.exec() line, and then it opens the last image. What am I doing wrong?
EDIT:
Clarification, the trigger for changing the images comes from an external program (specifically, the gui will be a node in ros, and will be triggered by another node). Is there a way to push a button not from the gui via an external program? the timer will work but I dislike this "busy wait" style solutions.
Thanks for the suggestions so far
exec runs the QT event loop, which includes rendering widgets.
So move your updatePic call into your widget and activate it by for example a button or in the show event
At first learn more about event loop. In particular, you must know that all events like paintEvent or resizeEvent are usually called on corresponding events handle. The events handle is usually called by the event loop, i.e. inside of exec function.
Let's unite answers of #MohaBou and #RvdK. You need to handle timer shots after the exec call. Use QObject::timerEvent for this.
myClass::myClass()
{
<...>
// This two variables are members of myClass.
_timerId = startTimer(3000);
_updatesCount = 0;
}
myClass::~myClass()
{
<...>
// For any case. As far as I remember, otherwise the late event
// may be handled after the destructor. Maybe it is false, do
// not remember...
if (_timerId >= 0) {
killTimer(_timerId);
_timerId = - 1;
}
}
myClass::timerEvent(QTimerEvent *event)
{
if (event->timerId() == _timerId) {
if (_updatesCount < 2) {
updatePic();
++_updatesCount;
} else {
killTimer(_timerId);
_timerId = - 1;
}
}
}
The startTimer method here adds especial timer event to the event query every 3 seconds. As all events, it may be handled only when the event loop will take control and all earlier events are handled. Because of it you can have a duration if many "heavy" events are handled.
EDIT: sorry, I didn't understand #MohaBou at first read. His answer with explicit QTimer is also good enough (but I still don't understand a part about modality).
The function exec also renders the child widgets. exec() blocks the application flow while show() doesn't. So, exec is mainly used for modal dialogs.
I recommend to update it in your custom witget by using a refresh timer. Use a QTimer to update the image every 3 secs:
QTimer* timer = new QTimer(this);
timer->setInterval(3000);
connect(timer, SINGAL(timeout()), this, SLOT(updatPicture()));
Update your picture in your custom slot:
MainWindow::updatePicture() {
updatePic()
}
If you want, you could use a lambda function:
connect(timer, &QTimer::timeout, this, [&w]() {
updatePic()
});

qt serial port memory leak

I use the following code to talk to a USB-serial port device:
#include "masterthread.h"
#include <QtSerialPort/QSerialPort>
#include <QTime>
#include "Windows.h"
#include "Psapi.h"
#include <QDebug>
QT_USE_NAMESPACE
MasterThread::MasterThread(QObject *parent)
: QThread(parent), waitTimeout(0), quit(false)
{
}
MasterThread::~MasterThread()
{
mutex.lock();
quit = true;
cond.wakeOne();
mutex.unlock();
wait();
}
void MasterThread::run()
{
bool currentPortNameChanged = false;
QSerialPort serial;
serial.setPortName("COM3");
serial.setBaudRate(57600);
serial.setStopBits(static_cast<QSerialPort::StopBits>(1));
serial.setDataBits(static_cast<QSerialPort::DataBits>(8));
serial.setParity(static_cast<QSerialPort::Parity>(0));
serial.open(QIODevice::ReadWrite);
//Tell the serial port connected device to start talking
//--------------------------------------
const char init[] = { 0x0d, 0x0d, 0x0d };
serial.write(init, sizeof(init));
const char* cmd = "mavlink stop\n";
serial.write(cmd, strlen(cmd));
serial.write(init, 2);
cmd = "uorb start";
serial.write(cmd, strlen(cmd));
serial.write(init, 2);
cmd = "sh /etc/init.d/rc.usb\n";
serial.write(cmd, strlen(cmd));
serial.write(init, 4);
serial.waitForBytesWritten(100);
int i = 0;
int j = 0;
forever
{
//Write test data out
//-----------------------------
QByteArray test(2000, 't');
serial.write(test);
bool check = serial.waitForBytesWritten(100);
if (!check)
{
qDebug() << "FAIL: " << j++;
}
if (serial.waitForReadyRead(20))
{
QByteArray responseData = serial.readAll();
while (serial.waitForReadyRead(10))
responseData += serial.readAll();
QString response(responseData);
qDebug() << response;
}
QThread::msleep(20);
//Print memory usage
//---------------------------------------------------
if (i++ % 10 == 0)
{
PROCESS_MEMORY_COUNTERS memcount;
if (!GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) return;
qDebug()<<"----------------------------" << memcount.WorkingSetSize / 1024 << "KB memory used";
}
} // end foever
qDebug() << "Exiting forever loop";
}
with a simple main.cpp as:
#include <QApplication>
#include "masterthread.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MasterThread thread;
thread.start();
return app.exec();
}
But the memory usage keeps increasing, like 5~10MB per hour as if there are some leakage.
The device is suppose to be connected for days and weeks...
What am I doing wrong here? I am on Qt5.6 windows7 debug
Many Qt Components have an implicit dependency on its event loop.
While you are starting the main threads event loop with the call to app.exec(); you are not handling events generated by the QObjects created in the QThread MasterThread thread;. The details and nuances of Event handling in Qt are very well described on this page: https://wiki.qt.io/Threads_Events_QObjects#Threads_and_QObjects
But the solution boils down to: if you want to be able to process queued up Qt events in a thread where you are processing some long-running task you should call QCoreApplication::processEvents(); from time to time. This will prevent Qt events from endlessly queueing up.
EDITED after looking on the code Qt 5.7,5.6,5.5 and reading docs.
As an answer is already accepted, I would just add some thoughts here as it's too long for comments.
Keep things short - an answer you accepted is wrong..
There are two sides of the story. And as SO answers often taken 'as it is as long as they work' I'd like to explain myself...
If you look on a code provided - there is nothing wrong with it. All objects are properly stack allocated and should be destroyed automatically.
Point is that QtSerial uses deleteLater() and then a question - how to delete those allocations properly.
If any module/object/code uses deleteLater() it requires an event loop, if deleteLater() called on a thread without event loop, object will be deleted after thread is terminated. As long as there is no event loop running for code above, processEvents will no work.. actually processEvents() is not something which is used for this, because a whole idea to return from the context which is called deleteLater() and have a next run, and that's checked in the Qt Source Code, so calling processEvent() straight after without incrementing loop count will do nothing at all, that's why answer you accepted is totally wrong.
Conclusion:
If any object requires event loop running it should be EXPLICITELY stated in the documentation as there is nothing wrong in using QIODevice in sync mode outside event loop.
So at my opinion,point is - its a bug in the QT Serial itself which I suggest you report.
In general it's really wrong practice for Qt to run never-ending loops..
It's much much better and cleaner to use QObject Worker tactic which is pushed to the thread, have proper even loop running etc.
For small 'threaded' tasks it's much better to use QtConcurrent.
Proper Workaround:
you will have a thread with properly running event loop and a timer firing at 20ms to do your things
// main thread:
class Worker: public QObject {
public:
Worker();
public slots:
onInit() {
// initialize everything
startTimer(20);
}
protected:
void timerEvent(..) {
// do your things every 20ms
}
}
...
QThread * pWorkerThread = new QThread();
pWorkerThread->setObjectName(QString("Serial"));
Worker * pWorker = new Worker();
Worker->setObjectName(QString("Common Storage Impl"));
Worker->moveToThread(WorkerThread);
connect(pWorkerThread, SIGNAL(started()), pWorker, SLOT(onInit()));
connect(pWorkerThread, SIGNAL(finished()), pWorker, SLOT(deleteLater()));
connect(pWorkerThread, SIGNAL(finished()), pWorkerThread, SLOT(deleteLater()));
pWorkerThread->start();
...

using libev with multiple threads

I want to use libev with multiple threads for the handling of tcp connections. What I want to is:
The main thread listen on incoming connections, accept the
connections and forward the connection to a workerthread.
I have a pool of workerthreads. The number of threads depends on the
number of cpu's. Each worker-thread has an event loop. The worker-thread listen if I can write on the tcp socket or if
somethings available for reading.
I looked into the documentation of libev and I known this can be done with libev, but I can't find any example how I have to do that.
Does someone has an example?
I think that I have to use the ev_loop_new() api, for the worker-threads and for the main thread I have to use the ev_default_loop() ?
Regards
The following code can be extended to multiple threads
//This program is demo for using pthreads with libev.
//Try using Timeout values as large as 1.0 and as small as 0.000001
//and notice the difference in the output
//(c) 2009 debuguo
//(c) 2013 enthusiasticgeek for stack overflow
//Free to distribute and improve the code. Leave credits intact
#include <ev.h>
#include <stdio.h> // for puts
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t lock;
double timeout = 0.00001;
ev_timer timeout_watcher;
int timeout_count = 0;
ev_async async_watcher;
int async_count = 0;
struct ev_loop* loop2;
void* loop2thread(void* args)
{
printf("Inside loop 2"); // Here one could initiate another timeout watcher
ev_loop(loop2, 0); // similar to the main loop - call it say timeout_cb1
return NULL;
}
static void async_cb (EV_P_ ev_async *w, int revents)
{
//puts ("async ready");
pthread_mutex_lock(&lock); //Don't forget locking
++async_count;
printf("async = %d, timeout = %d \n", async_count, timeout_count);
pthread_mutex_unlock(&lock); //Don't forget unlocking
}
static void timeout_cb (EV_P_ ev_timer *w, int revents) // Timer callback function
{
//puts ("timeout");
if (ev_async_pending(&async_watcher)==false) { //the event has not yet been processed (or even noted) by the event loop? (i.e. Is it serviced? If yes then proceed to)
ev_async_send(loop2, &async_watcher); //Sends/signals/activates the given ev_async watcher, that is, feeds an EV_ASYNC event on the watcher into the event loop.
}
pthread_mutex_lock(&lock); //Don't forget locking
++timeout_count;
pthread_mutex_unlock(&lock); //Don't forget unlocking
w->repeat = timeout;
ev_timer_again(loop, &timeout_watcher); //Start the timer again.
}
int main (int argc, char** argv)
{
if (argc < 2) {
puts("Timeout value missing.\n./demo <timeout>");
return -1;
}
timeout = atof(argv[1]);
struct ev_loop *loop = EV_DEFAULT; //or ev_default_loop (0);
//Initialize pthread
pthread_mutex_init(&lock, NULL);
pthread_t thread;
// This loop sits in the pthread
loop2 = ev_loop_new(0);
//This block is specifically used pre-empting thread (i.e. temporary interruption and suspension of a task, without asking for its cooperation, with the intention to resume that task later.)
//This takes into account thread safety
ev_async_init(&async_watcher, async_cb);
ev_async_start(loop2, &async_watcher);
pthread_create(&thread, NULL, loop2thread, NULL);
ev_timer_init (&timeout_watcher, timeout_cb, timeout, 0.); // Non repeating timer. The timer starts repeating in the timeout callback function
ev_timer_start (loop, &timeout_watcher);
// now wait for events to arrive
ev_loop(loop, 0);
//Wait on threads for execution
pthread_join(thread, NULL);
pthread_mutex_destroy(&lock);
return 0;
}
Using libev within different threads at the same time is fine as long as each of them runs its own loop[1].
The c++ wrapper in libev (ev++.h) always uses the default loop instead of letting you specify which one you want to use. You should use the C header instead (ev.h) which allows you to specify which loop to use (e.g. ev_io_start takes a pointer to an ev_loop but the ev::io::start doesn't).
You can signal another thread's ev_loop safely through ev_async.
[1]http://doc.dvgu.ru/devel/ev.html#threads_and_coroutines