C++ 尝试使用移动语义创建threadguard
这个标题不言自明。我试图获得一个线程保护的最小工作示例,它也可以支持std::threads所具有的移动语义C++ 尝试使用移动语义创建threadguard,c++,multithreading,parallel-processing,C++,Multithreading,Parallel Processing,这个标题不言自明。我试图获得一个线程保护的最小工作示例,它也可以支持std::threads所具有的移动语义 #include <iostream> #include <thread> #include <vector> #include <functional> class ThreadGuard { public: explicit ThreadGuard(std::thread input): t(std::move(input))
#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;
}
#包括
#包括
#包括
#包括
等级护丝板{
公众:
显式ThreadGuard(标准::线程输入):t(标准::移动(输入))
{}
~ThreadGuard(){
if(t.joinable()){
t、 join();
}
}
ThreadGuard(ThreadGuard const&t)=删除;
ThreadGuard&运算符=(ThreadGuard const&)=删除;
ThreadGuard和operator=(ThreadGuard和out){
this->t=out.transfer();
归还*这个;
}
std::线程传输(){
返回std::move(t);
}
私人:
标准:螺纹t;
};
void doWork(标准::字符串输入){
std::cout您需要将int
转换为std::string
:
tp[i] = ThreadGuard(std::thread(doWork, std::to_string(i)));
您也不需要编写自己的移动构造函数和移动分配运算符。请使用默认值:
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)...)
{}
还值得注意的是:在C++20中添加了join()
s,在销毁时自动执行。您需要将int
转换为std::string
:
tp[i] = ThreadGuard(std::thread(doWork, std::to_string(i)));
您也不需要编写自己的移动构造函数和移动分配运算符。请使用默认值:
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)...)
{}
另外值得注意的是:在C++20中添加了一个join()
s自动销毁。ThreadGuard&operator=(ThreadGuard&&)noexcept=default;
我认为这是错误的,你应该自己写。你需要检查this->t
是否可连接(并加入它)在你写之前。@MikeVine默认行为(OP也有)在这种情况下调用std::terminate
。这可能是OP想要的,也可能不是OP想要的,但我只是在答案中保留了相同的逻辑。是的,OP有这个错误(?)也是。在这种情况下,它将是一个非常奇怪的类,不会自行清理。修复起来很简单——或者如果你真的想在这种情况下终止,那么显式似乎是正确的。@MikeVine我想说,这是一个品味问题。这个薄包装器的行为就像std::thread
一样,只是在销毁时自动加入。另一方面,std::jthread
有一个更智能的移动分配操作符,它调用request\u stop()
,然后调用join()
。对于类似于使用std::thread
的操作,需要添加一个需要检查的原子。只需join()
ing可能会导致各种各样的麻烦。1+完整的答案。ThreadGuard&operator=(ThreadGuard&&)noexcept=default;
我认为这是错误的,你应该自己写。在写之前,你需要检查this->t
是否可连接(并连接它)。@MikeVine默认行为(OP也有)在这种情况下会调用std::terminate
。这可能是OP想要的,也可能不是OP想要的,但我只是在答案中保留了相同的逻辑。是的,OP有这个错误(?)也是。在这种情况下,它将是一个非常奇怪的类,不会自行清理。修复起来很简单——或者如果你真的想在这种情况下终止,那么显式似乎是正确的。@MikeVine我想说,这是一个品味问题。这个薄包装器的行为就像std::thread
一样,只是在销毁时自动加入。另一方面,std::jthread
有一个更智能的移动分配操作符,它调用request\u stop()
,然后调用join()
。对于类似于使用std::thread
的操作,需要添加一个需要检查的原子。只需join()
ing可能会导致各种各样的麻烦。完整答案为1+。