thread_local可以用来在dll中为每个线程提供静态全局变量吗?

问题描述 投票:0回答:2

我想在我们的开源库中使用 C++11 关键字 thread_local,它可以在静态变量的上下文中动态或静态链接到许多平台(Windows、Linux、Mac OS...) 。这个变量是一个类类型,基本上只是封装一个 std::stringstream 变量并初始化它以满足我们的 stringstream 格式要求。出于性能原因,我们希望使其静态可用(有关更多详细信息,请参阅我之前的问题),如果这是每个线程完成的,那也没关系。

全局变量应该在静态模板类方法中使用,并且必须在标头中实现。但这意味着,如果我理解正确的话,库的用户可能会在其可执行文件的代码中包含此标头,这会将模板化方法编译到可执行文件中。然后,这些方法将从可执行文件的线程内访问提到的全局变量。我需要如何声明/定义静态变量才能使其工作,即我是否需要导出变量或类类型,或者声明它“static thread_local X”就足够了吗?这是我目前的声明:

// SharedStringstream.h
#include <sstream>
// Export stands for _declspec(dllimport) or (dllexport) respectively
class EXPORT SharedStringstream
{
public:
    SharedStringstream();

    static thread_local SharedStringstream s_sharedStreamInstance;

    std::stringstream d_sharedStream;
};

和定义:

// SharedStringstream.cpp
#include "SharedStringStream.h"

SharedStringstream SharedStringstream::s_sharedStreamInstance();

SharedStringstream::SharedStringstream()
{
    d_sharedStream.imbue(std::locale("C"));
    d_sharedStream << std::skipws;
    d_sharedStream >> std::skipws;
}

如果没有导出,我会收到链接器错误,使用它,我会在 Visual Studio 2015 中收到以下错误:

错误C2492'public:static SharedStringstream SharedStringstream :: s_sharedStreamInstance':具有线程存储持续时间的数据可能没有dll接口

更多信息在 here 给出,基本上表明

thread_local
变量可能无法导出。为此,我必须将其从类中移到我的命名空间中,这是唯一的方法吗?

此外: 关于 “Thread Local Storage” 的 MSDN 页面对

thread_local
和 DLL 做了如下说明:

使用线程属性可能会干扰 DLL 导入的延迟加载。

我们确实在内部对库中包含的某些插件使用了 DLL 的延迟加载,但不会对变量进行任何调用。不过,我认为用户可以延迟加载该库,尽管我们并不正式支持这一点。假设我们不支持库的延迟加载,并且不从内部任何延迟加载的 dll 调用变量,我们是否能够确保这在任何情况下都不会成为问题?

我的问题中还有哪些问题没有考虑到吗?

c++ c++11 dll
2个回答
0
投票

您可以隐藏

thread_local
变量而不导出它,并且具有静态 getter。

正如链接文章所暗示的那样,主要限制来自于无法获取已运行线程的

DLL_THREAD_ATTACH
消息。

为了避免这两个限制:

  • 有 getter,并且实际的
    thread_local
    变量隐藏在实现中,未导出
  • 使用常量初始化的空指针进行惰性构造,并在第一次请求时进行构造

像这样:

// SharedStringstream.h
#include <sstream>
// Export stands for _declspec(dllimport) or (dllexport) respectively
class EXPORT SharedStringstream
{
public:
    SharedStringstream();

    static SharedStringstream& GetSharedStreamInstance();

    std::stringstream d_sharedStream;
}
// SharedStringstream.cpp
#include "SharedStringStream.h"

static thread_local std::unique_ptr<SharedStringstream> s_sharedStreamInstance;


/* static */ SharedStringstream& SharedStringstream::s_sharedStreamInstance() 
{
    std::unique_ptr<SharedStringstream>& inst = s_sharedStreamInstance;
    if (inst == nullptr)
    {
        inst = std::make_unique<SharedStringstream>();
    }
    return *inst;
} 

-1
投票

当 dll 加载时,它会加载自己的内存模型。因此,任何静态代码都不会在不同进程之间共享。

© www.soinside.com 2019 - 2024. All rights reserved.