繁体   English   中英

具有boost :: thread封装的insde的对象的std :: vector

[英]std::vector of objects with a boost::thread encapsulated insde

如何创建对象的std :: vector,每个对象内部都有一个boost :: thread。

class INSTRUMENT {
public:
    INSTRUMENT() : m_thread(new boost::thread(&INSTRUMENT::Start, this)) {  
        x = "abc";
    } 
    ~INSTRUMENT() {}
    void Start();
public:
    std::string x;
    boost::shared_ptr<boost::thread> m_thread;
};

void INSTRUMENT::Start() {
    try {
        while (1) {
            boost::this_thread::interruption_point();
            std::cout << "here " << x << std::endl;
        }
    } catch (boost::thread_interrupted &thread_e) {
        std::cout << "exit " << x << std::endl;
    } catch (std::exception &e) {
    }
}

std::vector<INSTRUMENT> m_inst_vector;

for (int i = 0; i < 5; i++) {
    m_inst_vector.push_back(INSTRUMENT());
}

代码可以正常编译,但是输出只是一些垃圾,不是预期的“ abc”。 在调试中,我注意到每次调用.push_back()时都会调用〜INSTRUMENT()。

由于当前设计的限制,我尝试不使用boost :: group_thread。 只是想知道是否可能有一个内部带有线程的对象的std :: vector,或者对类似设计的任何建议都会很有帮助。

我在SO上找到类似的线程。 它提到了编译器支持的移动语义,但没有解释它是什么。 如何向矢量添加增强线程

谢谢。

此代码有两个问题。

首先,线程将立即开始运行boost::thread对象的构造,因此您需要确保对其访问的所有数据进行预先初始化---即在构造线程之前在成员初始化列表中初始化x

其次,线程使用INSTRUMENT对象的this指针,因此您的对象绑定到特定地址。 std::vector复制到周围:当您调用push_back它将对象复制到向量中,并且如果必须分配新的内存块来腾出空间,则添加其他元素可能会将其他对象复制到周围。 这是您看到的析构函数调用的原因:构造了临时函数, push_back复制到向量中,然后破坏了该临时函数。

要解决此问题,您需要确保INSTRUMENT对象一旦构建,就不能移动或复制,因为副本具有错误的语义。 为此,可以将复制构造函数和赋值运算符设为私有且未实现(或者,如果您拥有支持此新C ++ 11构造的最新编译器,则将它们标记为删除),或者从boost::noncopyable派生。 完成此操作后,您将不再需要该线程的shared_ptr ,因为它无法共享,因此您可以直接构造它。

如果INSTRUMENT是不可复制的,则不能将其直接存储在向量中,因此请在向量中使用boost::shared_ptr<INSTRUMENT>类的东西。 这将允许向量自由复制和重排其元素,而不会影响INSTRUMENT对象的地址,并确保最后将其正确销毁。

class INSTRUMENT: boost::noncopyable {
public:
    INSTRUMENT() : x("abc"),m_thread(&INSTRUMENT::Start, this) {  
    } 
    ~INSTRUMENT() {}
    void Start();
public:
    std::string x;
    boost::thread m_thread;
};

void INSTRUMENT::Start() {
    try {
        while (1) {
            boost::this_thread::interruption_point();
            std::cout << "here " << x << std::endl;
        }
    } catch (boost::thread_interrupted &thread_e) {
        std::cout << "exit " << x << std::endl;
    } catch (std::exception &e) {
    }
}

std::vector<boost::shared_ptr<INSTRUMENT> > m_inst_vector;

for (int i = 0; i < 5; i++) {
    m_inst_vector.push_back(boost::shared_ptr<INSTRUMENT>(new INSTRUMENT));
}

编辑 :您的代码中有一个竞争条件。 线程在x初始化之前开始。

您应该将向量更改为vector<boost::shared_ptr<INSTRUMENT> > ,然后从INSTRUMENT内部删除boost::shared_ptr

class INSTRUMENT {
public:
    INSTRUMENT() {  
        x = "abc";
        m_thread = boost::thread(&INSTRUMENT::Start, this) 
    } 
    ~INSTRUMENT() {}
    void Start();
public:
    std::string x;
    boost::thread m_thread;
};

for (int i = 0; i < 5; i++) {
    m_inst_vector.push_back(boost::shared_ptr<INSTRUMENT>(new INSTRUMENT()));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM