在C 中,可以从第三个共享对象访问其他两个不同共享对象

In C++, can two other different shared objects access a Singleton from a third shared object?

本文关键字:共享 对象 其他 访问 两个 三个      更新时间:2023-10-16

i在C 中有一个应用程序,该应用程序通过共享对象从两个或多个插件(每个插件)加载大部分代码(每个插件)。我使用以下代码加载插件:

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的地步。由于该应用程序不允许在两个插件之间进行通信,而无需更改应用程序本身中的代码(我们要避免的一点),所以我想我找到了一种解决方法:第三个插件,其中包括带有一个带有一个带有a的singleton类线程安全Queue

然后,我将重新编译并将两个插件链接到库,然后使用getInstance()来获取单例并开始将任务添加到队列中。

这是安全的实施吗?Singleton Queue可以工作吗?

动态库(共享对象),其中包括一个带有线程安全队列的单例类。

当您只想限制一个类仅实例化一次时,使用单身人士。那是不是您想要的:您希望所有插件都可以在类的特定实例上工作。这里没有"只有一个人可以活"的要求。

使用Meyer的模式在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;
    }
};

默认构造函数是私人声明的,并且删除了复制/分配操作以避免多个实例。

您需要更简单的内容:一个函数总是返回同一实例。这样的东西:

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;
    }
};

请注意,最后两个实现需要围绕非静态代码的静音才能进行线程安全。