在运行循环外声明,分配和释放线程局部指针变量

时间:2016-10-06 18:44:01

标签: c++ multithreading c++11

我有一个线程管道和过滤器实现,我想在我的一个过滤器中使用线程局部副本。我自己没有实现运行循环。相反,只要获得要处理的数据,基类Filter类就会在每个过滤器上调用process()方法。

在这种情况下,我有两个使用thread_locals的问题: 1)我不能在process()方法中声明thread_locals,因为无论何时调用process()方法都要重用线程本地。

以下示例代码:

<keyword>

所以上面我初始化了SomeClass的thread_local实例。但是我没有释放它,因为每当新数据到达时,process()将由同一个线程的运行循环调用。显然,它永远不会被释放。坏。

2)我已经将一个threadCleanup()方法添加到过滤器实现中,只要过滤器停止(并且它的线程停止),现在就会调用它。虽然这需要声明thread_local成员变量,如:

void process(SomeInput in) {
    thread_local SomeClass* someClass = nullptr;
    if (someClass == nullptr) someClass = new SomeClass(params);

    // do stuff here...
}

但这不适用于类和抛出: “thread_local仅允许在变量声明”

在这种情况下声明,分配和取消分配线程局部的正确方法是什么?

2 个答案:

答案 0 :(得分:3)

回答原始问题的修复,而不是您为自己创建的新问题:

只需使用原始代码std::unique_ptr即可。您甚至可以对其进行单行since thread_local implies static,因此只需初始化一次,而无需执行nullptr的每次通话测试:

void process(SomeInput in) {
    thread_local std::unique_ptr<SomeClass> someClass(new SomeClass(params));

    // do stuff here...
}

任何给定线程第一次调用process时,为该线程初始化unique_ptr;当该线程退出时,unique_ptr被销毁并收集该线程的SomeClass实例because thread_local destructors are called on thread exit

请注意,如果someClass很小,您可以将其直接存储在thread_local存储中,而不是将unique_ptr存储在指向堆的位置,这样可以避免{{1}完全,因为如上所述,unique_ptr暗示thread_local并在线程退出时调用析构函数:

static

使用void process(SomeInput in) { thread_local SomeClass someClass(params); // do stuff here, // using someClass. instead of someClass-> for member/method access, // and &someClass where you used to use someClass if something needs a raw // pointer (the raw pointer is definitely sticking around until thread // exit after all) } 方法可能仍然有利(线程本地存储可能有限/慢,因此将其余类存储在普通堆内存中可能是值得的。)

答案 1 :(得分:2)

您要查找的成员变量static thread_local的语法是:

class SomeFilter : public Filter <...> {
// ...
private:
    static thread_local SomeClass* _someClass;
}

而不是执行手动清理,最好将_someClass封装在unique_ptr中,因为线程本地在线程退出时被销毁:

    static thread_local std::unique_ptr<SomeClass> _someClass;