Попытка создать threadguard с семантикой перемещения - PullRequest
1 голос
/ 06 августа 2020

название говорит само за себя. Я пытаюсь получить минимальный рабочий пример защиты потока, который также может поддерживать семантику перемещения, которая есть у std :: thread.

#include <iostream>
#include <thread>
#include <vector>
#include <functional>

class ThreadGuard {
public:
    explicit ThreadGuard(std::thread input): t(std::move(input))
    {}
    ~ThreadGuard(){
        if(t.joinable()){
            t.join();
        }
    }
    ThreadGuard(ThreadGuard const& t) = delete;
    ThreadGuard& operator=(ThreadGuard const&) = delete;

    ThreadGuard& operator=(ThreadGuard&& out){
        this->t = out.transfer();
        return *this;
    }
    std::thread transfer(){
        return std::move(t);
    }
private:
    std::thread t;
};

void doWork(std::string input){
    std::cout << input << std::endl;
}

static const auto numThreads = 4;
int main()
{
    std::vector<ThreadGuard> tp;
    tp.reserve(numThreads);
    for(auto i = 0 ; i < numThreads; ++i){
        tp[i] = ThreadGuard(std::thread(doWork, i));
    }
    return 0;
}

В настоящее время сталкивается с препятствием. std :: invoke, подходящей перегруженной функции не найдено, и я не вижу, что здесь отсутствует.

1 Ответ

5 голосов
/ 07 августа 2020

Вам необходимо преобразовать int в std::string:

tp[i] = ThreadGuard(std::thread(doWork, std::to_string(i)));

Вам также не нужно писать собственный конструктор перемещения и оператор присваивания перемещения. Используйте default:

class ThreadGuard {
public:
    explicit ThreadGuard(std::thread&& input): t(std::move(input))
    {}
    ThreadGuard(ThreadGuard const& t) = delete;
    ThreadGuard(ThreadGuard&&) noexcept = default;
    ThreadGuard& operator=(ThreadGuard const&) = delete;
    ThreadGuard& operator=(ThreadGuard&&) noexcept = default;  
    ~ThreadGuard(){
        if(t.joinable()){
            t.join();
        }
    }

private:
    std::thread t;
};

. Вы также можете заставить конструктор преобразования принимать аргументы конструктора потока и пересылать их напрямую:

    template<typename...Args>
    explicit ThreadGuard(Args&&... args): t(std::forward<Args>(args)...)
    {}

, что позволило бы создать его следующим образом :

tp[i] = ThreadGuard(doWork, std::to_string(i));

Также стоит отметить: в C ++ было добавлено 20 std::jthread, которое join() автоматически при уничтожении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...