threading?

This commit is contained in:
Benedek László 2024-05-15 13:17:53 +02:00
parent 71d6ad8763
commit 911a174006
6 changed files with 50 additions and 34 deletions

View File

@ -6,7 +6,7 @@ include(CMakePrintHelpers)
set(CMAKE_C_COMPILER clang) set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++) set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS true) set(CMAKE_EXPORT_COMPILE_COMMANDS true)

View File

@ -11,13 +11,13 @@ typedef struct {
double x, y; double x, y;
} point_t; } point_t;
typedef bool (*start_t)(); typedef int (*run_method_t)();
typedef void (*destroy_t)(); typedef void (*destroy_t)();
typedef void (*update_callback_t)(unsigned int chartIndex, const char* seriesName, const point_t* points, int count); typedef void (*update_callback_t)(unsigned int chartIndex, const char* seriesName, const point_t* points, int count);
typedef struct { typedef struct {
uint32_t version; uint32_t version;
start_t init_method; run_method_t run_method;
destroy_t destroy_method; destroy_t destroy_method;
update_callback_t update_callback; update_callback_t update_callback;
} plugin_t; } plugin_t;

View File

@ -1,24 +1,31 @@
#pragma once #pragma once
#include <graph/plugins/plugin.h> #include <graph/plugins/plugin.h>
#include <QThread>
#include <QAbstractListModel> #include <QAbstractListModel>
#include <string> #include <string>
namespace Graph { namespace Graph {
class Plugin { class Plugin : public QObject {
Q_OBJECT
private: private:
plugin_t* plugin; plugin_t* plugin;
const std::string path; const std::string path;
const void* handle; const void* handle;
public slots:
void run();
signals:
void exited(int code);
public: public:
Plugin(const std::string& path); Plugin(const std::string& path, update_callback_t callback);
~Plugin(); ~Plugin();
bool init(update_callback_t callback); const std::string& getPath() const { return this->path; }
const std::string& get_path() const { return this->path; }
}; };
class PluginModel : public QAbstractListModel { class PluginModel : public QAbstractListModel {

View File

@ -8,9 +8,7 @@
extern "C" { extern "C" {
plugin_t plugin = {.version = 1, .init_method = &init, .destroy_method = &destroy}; int run() {
bool init() {
std::cout << "init" << std::endl; std::cout << "init" << std::endl;
point_t points[100]; point_t points[100];
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
@ -19,10 +17,12 @@ bool init() {
} }
plugin.update_callback(0, "1st", points, 100); plugin.update_callback(0, "1st", points, 100);
return true; return 0;
} }
void destroy() { void destroy() {
std::cout << "destory" << std::endl; std::cout << "destory" << std::endl;
} }
plugin_t plugin = {.version = 1, .run_method = &run, .destroy_method = &destroy};
} }

View File

@ -4,7 +4,8 @@
#include <graph/server/plugin.h> #include <graph/server/plugin.h>
#include <graph/server/spec.h> #include <graph/server/spec.h>
#include <graph/server/ui_mainwindow.h> #include <graph/server/ui_mainwindow.h>
#include <qfiledialog.h> #include <qobject.h>
#include <qthread.h>
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
#include <iostream> #include <iostream>
@ -126,9 +127,16 @@ void MainWindow::on_action_Load_triggered() {
for (QString file : fileDialog->selectedFiles()) { for (QString file : fileDialog->selectedFiles()) {
try { try {
Plugin* plugin = new Plugin(file.toStdString()); Plugin* plugin = new Plugin(file.toStdString(), &Graph::GUI::addData);
plugin->init(&Graph::GUI::addData);
pluginModel->add(plugin); pluginModel->add(plugin);
QThread* thread = new QThread();
plugin->moveToThread(thread);
connect(plugin, &Plugin::exited, this, [](int code) { std::cout << "plugin exited: " << code << std::endl; });
connect(thread, &QThread::started, plugin, &Plugin::run);
connect(plugin, &Plugin::exited, thread, &QThread::quit);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
thread->start();
} catch (std::runtime_error e) { } catch (std::runtime_error e) {
std::cout << e.what() << std::endl; std::cout << e.what() << std::endl;
QMessageBox::critical(this, "Error", "Failed to load plugin:\n" + file, QMessageBox::StandardButton::Ignore); QMessageBox::critical(this, "Error", "Failed to load plugin:\n" + file, QMessageBox::StandardButton::Ignore);

View File

@ -1,42 +1,43 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <graph/server/plugin.h> #include <graph/server/plugin.h>
#include <qthread.h>
#include <iostream>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
namespace Graph { namespace Graph {
Plugin::Plugin(const std::string& path) : path(path) { Plugin::Plugin(const std::string& path, update_callback_t callback) : path(path) {
this->handle = dlopen(path.c_str(), RTLD_LAZY); handle = dlopen(path.c_str(), RTLD_LAZY);
if (!this->handle) if (!handle)
throw std::runtime_error(dlerror()); throw std::runtime_error(dlerror());
this->plugin = (plugin_t*)dlsym((void*)this->handle, "plugin"); plugin = (plugin_t*)dlsym((void*)this->handle, "plugin");
if (!this->plugin) if (!plugin)
throw std::runtime_error(dlerror()); throw std::runtime_error(dlerror());
this->plugin->update_callback = nullptr; plugin->update_callback = callback;
}
void Plugin::run() {
emit exited(plugin->run_method());
} }
Plugin::~Plugin() { Plugin::~Plugin() {
if (this->plugin->destroy_method) if (plugin->destroy_method)
this->plugin->destroy_method(); plugin->destroy_method();
if (handle) if (handle)
dlclose((void*)this->handle); dlclose((void*)handle);
}
bool Plugin::init(update_callback_t callback) {
this->plugin->update_callback = callback;
return this->plugin->init_method();
} }
PluginModel::~PluginModel() { PluginModel::~PluginModel() {
for (Plugin* plugin : this->plugins) { for (Plugin* plugin : plugins) {
delete plugin; delete plugin;
} }
} }
int PluginModel::rowCount(const QModelIndex& parent) const { int PluginModel::rowCount(const QModelIndex& parent) const {
return this->plugins.size(); return plugins.size();
} }
QVariant PluginModel::data(const QModelIndex& index, int role) const { QVariant PluginModel::data(const QModelIndex& index, int role) const {
@ -44,7 +45,7 @@ QVariant PluginModel::data(const QModelIndex& index, int role) const {
return QVariant(); return QVariant();
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
return QString(plugins[index.row()]->get_path().c_str()); return QString(plugins[index.row()]->getPath().c_str());
} }
return QVariant(); return QVariant();