Страницы

Поиск по вопросам

суббота, 7 декабря 2019 г.

Многопоточность в С++: создать поток для конкретного объекта с передачей в конструктор имени нестатической функции

#cpp #многопоточность


Здравствуйте, недавно пришлось заняться разработкой многопоточного приложения (впервые)
и наткнулся на такую проблему: позарез нужно создать поток для конкретного объекта
с передачей в конструктор имени нестатической функции, гугл ничего путного не дал.


Подскажите, это вообще возможно? 
Если нет, то как это 'лечиться'?


В абстракции: есть класс System, у него есть нестатический метод private update()
который я должен отслеживать, путем инициализации указателя private thread* Thread
в конструкторе класса. 

P.S в update вызывается метод move(...), который привязан к объекту, т.е я не могу
сделать update статическим без создания контейнера, хранящего все данные о пользователях,
а это затратно

#include 
//еще включения ...
class System
{
    //некоторые поля и методы...
    //...
    thread* Thread;
    static thread* sThread;

    System() {
       Thread = new thread(update);//ошибка! отсутствуют экземпляры констуктора соответствующий
... для std::thread::thread (void())
    }
    void update() {
        //...
        move(...);
        //...
    }
    void move() {
    //работает с полями объекта
    }
};

{
//где-то создается System* system = System;
}


P.S(2) Перелез с c#, там можно инициализировать потоки нестатическими методами(вроде),
не судите строго
    


Ответы

Ответ 1



В документации говорится, что конструктор выглядит так: template< class Function, class... Args > explicit thread( Function&& f, Args&&... args ); поэтому могу предположить, что следует использовать лямбда-функцию как-то так: new thread([&]() { this.update(); }) В любом случае следует быть осторожным со временем жизни объектов.

Ответ 2



Также возможен вариант с использованием std::bind System() { Thread = new std::thread(std::bind(&System::update, this)); }

Ответ 3



Я абсолютно не уверен в том, что это хорошая идея, но используя лямбду вместо update и дополнительно дав компилятору опцию -pthread мне удалось запустить, и даже получить результат следующего кода: class System { //некоторые поля и методы... //... static thread* sThread; public: thread* Thread; System() { Thread = new thread([this]{ /*Это код метода update, который вызывает move, лямбда должна захватить указатель на текущий объект чтоб вызвать функцию объекта */ cout << "Updte\n"; this->move(); }); } private: void move() { cout << "Move\n"; } }; int main(){ System s; s.Thread->join(); return 0; } Повторю, что по-моему это все имеет кучу подводных камней, поэтому интересно увидеть ответы более знающих людей.

Ответ 4



А зачем сложно, если можно просто? Указать, что это функция-член, и добавить this? #include #include using namespace std; class Test { public: Test(int x):x(x){}; void out(int b) { cout << x << ":" << b << endl; } void run(int j) { thread t = thread(&Test::out,this,j); t.join(); } private: int x; }; int main() { Test t(12); t.run(3); }

Комментариев нет:

Отправить комментарий