cpp-worker с расшаренным ресурсом для GUI как?
Требуется на C++ (std::*) написать модуль worker.cpp (затем библиотеку) - Worker и Share. Worker в отдельном потоке выполняет некоторые расчеты и в ходе работы записывает текущий результат в Share. Предназначен этот модуль для запуска в основном потоке GUI-приложения, при этом из из методов GUI приложения производится чтение и отображение содержимого Share.
Попробовал в методе run() Worker создать поток, запустить вычисления и обновлять ресурс с блокировкой. Но, при этом запуск run() блокирует графический интерфейс. Графический интерфейс разблокируется только после завершения run().
Помогите правильно организовать поток и блокировки. Поток нужно запускать в модуле worker.cpp, а не из GUI. Разработчик GUI знает только о методах чтения из структуры Share и не заботится об организации многопоточности и блокировок.
struct Share {
int data;
std::mutex locker;
};
class Worker {
public:
Worker(Share *sharePtr);
~Worker();
void run();
private:
Share* sharePtr;
void worker();
};
Worker::Worker(Share* shrPtr): sharePtr(shrPtr) {}
Worker::~Worker(){}
void Worker::run() {
std::thread t(&Worker::worker, this);
t.join();
}
void Worker::worker() {
int i = 0;
while (i<999) {
std::unique_lock<std::mutex> lock(sharePtr->locker);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
sharePtr->data = rand();
++i;
}
sharePtr->data = 555;
}
Проверка на примере Qt:
class MainWindow: public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void initUI();
public slots:
void Work();
void updateLabel();
private:
QLabel *info;
QPushButton *push;
QVBoxLayout *vLayout;
QTimer *tmr;
Share currentShare;
};
mainWindow::MainWindow(QWidget *parent): QWidget(parent){
initUI();
connect(push, SIGNAL(clicked()), this, SLOT(Work()));
tmr = new QTimer();
tmr->setInterval(100);
connect(tmr, SIGNAL(timeout()), this, SLOT(updateLabel()));
tmr->start();
}
MainWindow::~MainWindow(){
delete tmr;
}
void MainWindow::initUI(){
vLayout = new QVBoxLayout(this);
info = new QLabel("-_-");
push = new QPushButton("push");
vLayout->addWidget(info);
vLayout->addWidget(push);
}
void MainWindow::Work(){
Worker worker(¤tShare);
worker.run();
}
void MainWindow::updateLabel(){
std::unique_lock<std::mutex> lock(currentShare.locker);
info->setText( QString::number( currentShare.data ) );
}