2016-12-29 85 views
1

我在C++中有一个应用程序,它通过共享对象从两个或多个插件(每个插件至少有一个线程)加载其大部分代码。我用下面的代码加载插件:在C++中,其他两个不同的共享对象可以从第三个共享对象访问Singleton吗?

pluginHandle = dlopen(fileName, RTLD_NOW|RTLD_GLOBAL); 
init_t* init = (init_t*) dlsym(pluginHandle, "init") // Create should return an instance of the class of the plugin 
plugin = init(); 

我到达的地步,我需要两个那些插件来开始将数据添加到一个共同的Queue。由于应用程序不允许在不改变应用程序本身中的代码的情况下在两个插件之间进行通信(我们试图避免的一点),所以我想我找到了解决这个问题的方法:第三个插件,其中包括一个带有线程安全的Queue

然后,我会重新编译和链接两个插件库,并使用getInstance()获取单身人士,并开始添加任务到队列。

这是一个安全的实现吗?单身人士Queue会工作吗?

回答

1

一个动态库(共享对象),它包含一个具有线程安全队列的单例类。

当你想约束一个类只被实例化一次时,使用单例。这就是而不是你想要什么:你想让你所有的插件在一个类的特定实例上工作。这里没有“只有一个人可以生活”的要求。

在C++ 11线程安全使用单迈耶的模式可能看起来像这样:

class Singleton 
{ 
private: 
    Singleton(); 

public: 
    Singleton(const &Singleton) = delete; 
    Singleton& operator=(const &Singleton) = delete; 

    static Singleton& get_instance() 
    { 
     static Singleton s; 
     return s; 
    } 
}; 

默认构造方法声明为private和复制/赋值操作都将被删除,以避免多个实例。

你需要更简单的东西:一个函数总是返回相同的实例。事情是这样的:

class Manager 
{ 
public: 
    static Resource& get_resource() 
    { 
     static Resource r; 
     return r; 
    } 
}; 

没有必要,以防止多个实例:如果你想同一个实例,只问了相同的实例。

您也可以与资源池返回给一些ID的同一实例扩展设计:

enum class ResourceId 
{ 
    ID_FOR_A_FAMILY_OF_PLUGIN, 
    ID_FOR_AN_OTHER_FAMILY_OF_PLUGIN 
}; 

class Pool 
{ 
public: 
    static Resource& get_resource(ResourceId id) 
    { 
     static std::map<ResourceId, Resource> p; 
     return p[id]; 
    } 
}; 

注意,在这个例子中p[id]是与Resource的默认构造函数动态创建。您可能需要在施工期间传递参数:

class Resource 
{ 
public: 
    Resource():ready(false){} 

    void init(some parameters) 
    { 
     // do some intialization 
     ready = true; 
    } 

    bool is_ready() const { return ready; } 

private: 
    bool ready; 
}; 

class Pool 
{ 
public: 
    static Resource& get_resource(ResourceId id) 
    { 
     static std::map<ResourceId, Resource> p; 
     auto& r = p[id]; 
     if(!r.is_ready()) 
     { 
      r.init(some parameters); 
     } 
     return r; 
    } 
}; 

或者,使用指针,允许多态性

class Pool 
{ 
public: 
    static std::unique_ptr<Resource>& get_resource(ResourceId id) 
    { 
     static std::map<ResourceId, std::unique_ptr<Resource>> p; 
     auto& r = p[id]; 
     if(!r) 
     { 
      r = std::make_unique<SomeResourceTypeForId>(some parameters); 
     } 
     return r; 
    } 
}; 

注意的是,过去两年实现需要周围的非静态代码互斥是thread-安全。