Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在c+中包含和访问线程全局变量+;_C++_Oop_Metaprogramming - Fatal编程技术网

C++ 在c+中包含和访问线程全局变量+;

C++ 在c+中包含和访问线程全局变量+;,c++,oop,metaprogramming,C++,Oop,Metaprogramming,在我去过的几个工作场所中,我发现了一个设计问题,但没有令人满意的解决方案: 假设您有一个具有动态线程数的系统 每个线程必须有一个访问一组“单例”的权限,单例每个线程只有一个实例(因此它们不是真正的单例,而是每个线程的单例) 这组单例在编译时是已知的 每个单例都有一个默认构造函数(不过,为了简化事情,一个没有这个约束的解决方案会更好) 令人满意的解决方案应包括以下内容: 每个线程都可以在o(1)时间内访问其任何单例 对单例的访问是无锁的 将单例添加到“单例集合”不需要在集合端编写新代码 “单例集”

在我去过的几个工作场所中,我发现了一个设计问题,但没有令人满意的解决方案:

假设您有一个具有动态线程数的系统

每个线程必须有一个访问一组“单例”的权限,单例每个线程只有一个实例(因此它们不是真正的单例,而是每个线程的单例)

这组单例在编译时是已知的

每个单例都有一个默认构造函数(不过,为了简化事情,一个没有这个约束的解决方案会更好)

令人满意的解决方案应包括以下内容:

  • 每个线程都可以在o(1)时间内访问其任何单例

  • 对单例的访问是无锁的

  • 将单例添加到“单例集合”不需要在集合端编写新代码

  • “单例集”在编译时填充

  • 我不确定这样的设计是否可行。如果是,我假设它需要一点元编程


    提前感谢您的任何见解。

    好的,通常我会在评论中发表这一点,因为我不太确定我是否正确理解了您的问题……但在父线程类的构造函数中创建单例集的实例还不够吗

    假设您有三个类A、B和C(在编译时已知) 和一个“线程”类

    您不在线程头中声明A、B和C的实例吗

    class Thread {
    private:
        A *a;
        B *b;
        C *c;
    public:
        Thread();
    }
    
    然后在线程的构造函数中实例化它们

    Thread:Thread() {
        a = new A();
        b = new B();
        c = new C();
    }
    
    这样,每个线程独占地“拥有”这些单例,这意味着它可以随时访问它们,而不必担心竞争条件或锁

    关于“添加单例”,我是否可以建议创建一个“单例父级”类,然后使用一个标准容器(如std::list),您可以将新指针推送到该容器上? 当然,对该列表的访问必须受到锁的保护,当您在运行时、编译时执行此操作时,这是不必要的。 在编译期间,最好使用指针的静态数组,这将允许您尽可能快地访问指针


    再一次,如果我理解错了你的问题,我很抱歉。

    好的,通常我会在评论中发表这篇文章,因为我不太确定我是否正确理解了你的问题……但是在父线程类的构造函数中创建单例集的实例还不够吗

    假设您有三个类A、B和C(在编译时已知) 和一个“线程”类

    您不在线程头中声明A、B和C的实例吗

    class Thread {
    private:
        A *a;
        B *b;
        C *c;
    public:
        Thread();
    }
    
    然后在线程的构造函数中实例化它们

    Thread:Thread() {
        a = new A();
        b = new B();
        c = new C();
    }
    
    这样,每个线程独占地“拥有”这些单例,这意味着它可以随时访问它们,而不必担心竞争条件或锁

    关于“添加单例”,我是否可以建议创建一个“单例父级”类,然后使用一个标准容器(如std::list),您可以将新指针推送到该容器上? 当然,对该列表的访问必须受到锁的保护,当您在运行时、编译时执行此操作时,这是不必要的。 在编译期间,最好使用指针的静态数组,这将允许您尽可能快地访问指针


    再一次,如果我理解错了您的问题,我很抱歉。

    线程局部变量很好地解决了这个问题

    // in .h
    class ThreadSingleton
    {
    private:
        static __thread ThreadSingleton* thread_specific_instance;
    
    public:
        static ThreadSingleton* get() { return thread_specific_instance; }
        ThreadSingleton();
        ~ThreadSingleton();
    };
    
    // in .cc
    __thread ThreadSingleton* ThreadSingleton::thread_specific_instance;
    
    ThreadSingleton::ThreadSingleton() {
        if(thread_specific_instance)
            std::abort(); // one instance per thread please
        thread_specific_instance = this;
    }
    
    ThreadSingleton::~ThreadSingleton() {
        thread_specific_instance = 0;
    }
    
    // usage
    int main() {
        // on thread entry
        ThreadSingleton x;
    
        // later anywhere in the thread
        ThreadSingleton* px = ThreadSingleton::get();
    }
    
    每个线程在堆栈的某个位置创建
    ThreadSingleton
    ,通常在线程函数中。稍后,
    ThreadSingleton
    可以通过返回调用线程的singleton的
    ThreadSingleton::get()
    从该线程的任何位置访问。(上面可以制作一个模板来包装任何其他类,我没有这样做是为了简单的说明)


    以性能为导向访问线程局部变量不需要任何调用(与使用创建的线程特定存储不同),有关详细信息,请参阅。

    线程局部变量很好地解决了这个问题

    // in .h
    class ThreadSingleton
    {
    private:
        static __thread ThreadSingleton* thread_specific_instance;
    
    public:
        static ThreadSingleton* get() { return thread_specific_instance; }
        ThreadSingleton();
        ~ThreadSingleton();
    };
    
    // in .cc
    __thread ThreadSingleton* ThreadSingleton::thread_specific_instance;
    
    ThreadSingleton::ThreadSingleton() {
        if(thread_specific_instance)
            std::abort(); // one instance per thread please
        thread_specific_instance = this;
    }
    
    ThreadSingleton::~ThreadSingleton() {
        thread_specific_instance = 0;
    }
    
    // usage
    int main() {
        // on thread entry
        ThreadSingleton x;
    
        // later anywhere in the thread
        ThreadSingleton* px = ThreadSingleton::get();
    }
    
    每个线程在堆栈的某个位置创建
    ThreadSingleton
    ,通常在线程函数中。稍后,
    ThreadSingleton
    可以通过返回调用线程的singleton的
    ThreadSingleton::get()
    从该线程的任何位置访问。(上面可以制作一个模板来包装任何其他类,我没有这样做是为了简单的说明)


    性能智能访问线程局部变量不需要任何调用(与使用创建的线程特定存储不同),请参阅以了解更多详细信息。

    我不确定是否正确理解了您的问题,但对我来说,单例的“集”是不相关的。您有固定数量的单例,将它们称为
    Singleton1
    SingletonX
    ,其中
    X
    在编译时已知。这对线程来说并不重要

    对于实际的单例,您可以让它们从处理每线程部分的单个模板基类继承。大概是这样的:

    template<class B>
    struct SingletonBase
    {
        static B &getInstance()
            {
                // One instance per thread
                static std::unordered_map<std::thread::id, B> intances;
    
                if (instances.find(std::this_thread::get_id()) == instances.end())
                    instances[std::this_thread::get_id()] = B{};
    
                return instances[std::this_thread::get_id()];
            }
    };
    
    class Singleton1 : public SingletonBase<Singleton1>
    {
        // ...
    };
    
    这将在编译时创建指定数量的数组
    X
    ,可以像普通数组一样访问:
    Singleton&instance=Singleton[0].getInstance()


    请注意,我的示例代码使用了“新”C++11标准库中的功能。

    我不确定我是否正确理解了您的问题,但对我来说,单例的“集合”是不相关的。您有固定数量的单例,将它们称为
    Singleton1
    SingletonX
    ,其中
    X
    在编译时已知。这对线程来说并不重要

    对于实际的单例,您可以让它们从处理每线程部分的单个模板基类继承。大概是这样的:

    template<class B>
    struct SingletonBase
    {
        static B &getInstance()
            {
                // One instance per thread
                static std::unordered_map<std::thread::id, B> intances;
    
                if (instances.find(std::this_thread::get_id()) == instances.end())
                    instances[std::this_thread::get_id()] = B{};
    
                return instances[std::this_thread::get_id()];
            }
    };
    
    class Singleton1 : public SingletonBase<Singleton1>
    {
        // ...
    };
    
    这将在编译时创建一个指定数量的数组
    X
    ,然后