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_CXX_COMPILER clang++)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS true)

View File

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

View File

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

View File

@ -8,9 +8,7 @@
extern "C" {
plugin_t plugin = {.version = 1, .init_method = &init, .destroy_method = &destroy};
bool init() {
int run() {
std::cout << "init" << std::endl;
point_t points[100];
for (int i = 0; i < 100; i++) {
@ -19,10 +17,12 @@ bool init() {
}
plugin.update_callback(0, "1st", points, 100);
return true;
return 0;
}
void destroy() {
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/spec.h>
#include <graph/server/ui_mainwindow.h>
#include <qfiledialog.h>
#include <qobject.h>
#include <qthread.h>
#include <QFileDialog>
#include <QMessageBox>
#include <iostream>
@ -126,9 +127,16 @@ void MainWindow::on_action_Load_triggered() {
for (QString file : fileDialog->selectedFiles()) {
try {
Plugin* plugin = new Plugin(file.toStdString());
plugin->init(&Graph::GUI::addData);
Plugin* plugin = new Plugin(file.toStdString(), &Graph::GUI::addData);
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) {
std::cout << e.what() << std::endl;
QMessageBox::critical(this, "Error", "Failed to load plugin:\n" + file, QMessageBox::StandardButton::Ignore);

View File

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