LINUX.ORG.RU

Сообщения xyzzxy

 

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(&currentShare);
	worker.run();
}

void MainWindow::updateLabel(){
    std::unique_lock<std::mutex>  lock(currentShare.locker);
    info->setText( QString::number( currentShare.data ) );
}

 , ,

xyzzxy
()

RSS подписка на новые темы