Multithreading std::thread的作用域线程包装器
我正在尝试创建一个作用域线程Multithreading std::thread的作用域线程包装器,multithreading,c++11,move-semantics,clang++,stdthread,Multithreading,C++11,Move Semantics,Clang++,Stdthread,我正在尝试创建一个作用域线程 #include <iostream> #include <thread> class ScopedThread { public: template< class Function, class... Args> explicit ScopedThread( int id, Function&& f, Args&&... args) : m_thread( st
#include <iostream>
#include <thread>
class ScopedThread {
public:
template< class Function, class... Args>
explicit ScopedThread( int id, Function&& f, Args&&... args)
: m_thread( std::ref(f), std::forward<Args>(args)...)
, id(std::move(id)) {
}
int getId() const { return id; }
~ScopedThread() { m_thread.join(); }
private:
std::thread m_thread;
int id;
};
class Worker {
public:
Worker(int id): thd(id, &Worker::work, this) { }
void work() {
for( int i = 0; i < 10; i++)
std::cout << "I am working" << std::endl;
}
private:
ScopedThread thd;
};
int main() {
Worker(1);
Worker(2);
Worker(3);
Worker(4);
}
#包括
#包括
类作用域线程{
公众:
模板<类函数,类…参数>
显式ScopedThread(int-id、函数和函数、参数和…参数)
:m_线程(标准::参考(f),标准::正向(参数)…)
,id(标准::移动(id)){
}
int getId()常量{return id;}
~ScopedThread(){m_thread.join();}
私人:
标准:螺纹m_螺纹;
int-id;
};
班主任{
公众:
Worker(intid):thd(id,&Worker::work,this){}
无效工作(){
对于(int i=0;i<10;i++)
std::cout在ScopedThread
的实现中有几个问题
不需要单独处理函数和&f
。只需将其作为args…
包的一部分处理即可
无需移动id
template< class... Args>
explicit ScopedThread( int id, Args&&... args)
: m_thread( std::forward<Args>(args)...)
, id(id) {
}
应用这些更改
罪魁祸首是std::ref(f)
-您正在创建一个临时reference\u包装
,并将其传递给std::thread
的构造函数,该构造函数使用std::invoke
调用它
根据g++
和未定义的行为准则:
/usr/local/gcc-head/include/c++/7.0.1/bits/invoke.h:73:46:
运行时错误:对的未对齐地址0x7fff939ec8d3的成员调用
键入“struct Worker”,需要8字节对齐
问题是,您正在使用std::ref(f)
创建对临时工的引用,其中临时工是&Worker::work
我给任何研究该主题的人5美分
我清理了代码并实现了删除的构造函数:
class ScopedThread{
public:
template<class ...Args>
explicit ScopedThread(Args &&...args) : thread_(std::forward<Args>(args)...){}
ScopedThread(ScopedThread &&other){
thread_ = std::move(other.thread_);
}
ScopedThread &operator=(ScopedThread &&other){
thread_ = std::move(other.thread_);
return *this;
}
std::thread &operator*(){
return thread_;
}
std::thread const &operator*() const{
return thread_;
}
std::thread *operator->(){
return & operator*();
}
std::thread const *operator->() const{
return & operator*();
}
auto get_id() const{
return thread_.get_id();
}
auto join(){
if (thread_.joinable())
thread_.join();
}
~ScopedThread(){
join();
}
private:
std::thread thread_;
};
类作用域线程{
公众:
模板
显式作用域线程(Args&&…Args):线程(std::forward(Args)…{}
ScopedThread(ScopedThread&&other){
线程=标准::移动(其他线程);
}
ScopedThread&operator=(ScopedThread&other){
线程=标准::移动(其他线程);
归还*这个;
}
标准::线程和运算符*(){
返回线程;
}
std::线程常量和运算符*()常量{
返回线程;
}
标准::线程*运算符->(){
返回&运算符*();
}
std::线程常量*运算符->()常量{
返回&运算符*();
}
自动获取id()常量{
返回线程。获取线程id();
}
自动联接(){
if(线程可接合())
螺纹连接();
}
~ScopedThread(){
join();
}
私人:
标准:螺纹螺纹;
};
是否使用-pthread构建?是的,我想如果不使用-pthread,错误将非常详细。例如,启用多线程以使用std::thread:Operation not permitteddwell,您确定您的运行方式与粘贴在此处的完全相同吗?因为这对我来说在gcc 4.8.4Ya上也适用,在我的情况下,它在gcc中也适用,而不是在clangedited the question中实际上,似乎是使用std::forward(f)而不是std::ref。你能解释一下为什么这会导致崩溃吗?@MK.刚刚添加了一个解释。我认为问题在于std::ref(f)
正在创建一个reference\u包装器
,然后将它传递给std::thread::thread
进行调用。if(m_thread.joinable())m_thread.join()
:在这种情况下线程什么时候可以被销毁?成员不是在离开析构函数时被销毁的吗?@AndyT:我假设移动操作最终会为ScopedThread
实现。在这种情况下,从std::thread
实例移动可能会使其不可连接。@AndyT:我将其视为“所有权转移”-想想独特的\u ptr
。
~ScopedThread() { if(m_thread.joinable()) m_thread.join(); }
class ScopedThread{
public:
template<class ...Args>
explicit ScopedThread(Args &&...args) : thread_(std::forward<Args>(args)...){}
ScopedThread(ScopedThread &&other){
thread_ = std::move(other.thread_);
}
ScopedThread &operator=(ScopedThread &&other){
thread_ = std::move(other.thread_);
return *this;
}
std::thread &operator*(){
return thread_;
}
std::thread const &operator*() const{
return thread_;
}
std::thread *operator->(){
return & operator*();
}
std::thread const *operator->() const{
return & operator*();
}
auto get_id() const{
return thread_.get_id();
}
auto join(){
if (thread_.joinable())
thread_.join();
}
~ScopedThread(){
join();
}
private:
std::thread thread_;
};