Added cpp style mechanisme to queue callables on window thread.

This commit is contained in:
Eelke Klein 2016-12-30 10:14:26 +01:00
parent 8af6bc4ac5
commit 2432be9d72
2 changed files with 52 additions and 1 deletions

View file

@ -5,6 +5,7 @@
#include "QueryExplainModel.h" #include "QueryExplainModel.h"
#include "sqlhighlighter.h" #include "sqlhighlighter.h"
#include <QTextTable> #include <QTextTable>
#include <QTimer>
#include <windows.h> #include <windows.h>
#include "json/json.h" #include "json/json.h"
#include "explaintreemodelitem.h" #include "explaintreemodelitem.h"
@ -59,6 +60,34 @@ MainWindow::MainWindow(QWidget *parent) :
MainWindow::~MainWindow() MainWindow::~MainWindow()
{} {}
void MainWindow::QueueTask(callable c)
{
std::lock_guard<std::mutex> lg(m_mutexCallableQueue);
m_callableQueue.emplace_back(std::move(c));
// Theoretically this needs to be only called if the queue was empty because otherwise it already would
// be busy emptying the queue. For now however I think it is safer to call it just to make sure.
QMetaObject::invokeMethod(this, "processCallableQueue", Qt::QueuedConnection); // queues on main thread
}
void MainWindow::processCallableQueue()
{
bool empty;
callable c;
{ // narrow scope for lock guard
std::lock_guard<std::mutex> lg(m_mutexCallableQueue);
c = m_callableQueue.back();
m_callableQueue.pop_back();
empty = m_callableQueue.empty();
}
c();
if (!empty) {
// This gives other events a chance to be processed to keep the UI snappy.
QTimer::singleShot(0, this, SLOT(processCallableQueue()));
}
}
void MainWindow::startConnect() void MainWindow::startConnect()
{ {
if (connection == nullptr) { if (connection == nullptr) {
@ -125,6 +154,7 @@ void MainWindow::performQuery()
QMetaObject::invokeMethod(this, "query_ready", Qt::QueuedConnection); // queues on main thread QMetaObject::invokeMethod(this, "query_ready", Qt::QueuedConnection); // queues on main thread
return res; return res;
}); });
} }
void MainWindow::query_ready() void MainWindow::query_ready()

View file

@ -22,15 +22,36 @@ namespace Pgsql {
} }
#include <deque>
#include <mutex>
class TaskQueue {
public:
private:
};
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
using callable = std::function<void()>;
explicit MainWindow(QWidget *parent = 0); explicit MainWindow(QWidget *parent = 0);
~MainWindow(); ~MainWindow();
/* Meant to be called from other threads to pass a code block
* that has to be executed in the context of the thread of the window.
*/
void QueueTask(callable c);
private: private:
using t_CallableQueue = std::deque<callable>;
std::mutex m_mutexCallableQueue;
t_CallableQueue m_callableQueue;
std::unique_ptr<Ui::MainWindow> ui; std::unique_ptr<Ui::MainWindow> ui;
std::unique_ptr<SqlHighlighter> highlighter; std::unique_ptr<SqlHighlighter> highlighter;
@ -65,7 +86,7 @@ private slots:
void cancel_query(); void cancel_query();
void receiveNotice(Pgsql::ErrorDetails notice); void receiveNotice(Pgsql::ErrorDetails notice);
void processCallableQueue();
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H