2016-12-29 15 views
1

私は、共有オブジェクトを介して2つ以上のプラグイン(少なくとも1つのスレッドを持つ)からコードの大部分を読み込むC++のアプリケーションを持っています。C++では、2つの異なる共有オブジェクトが3番目の共有オブジェクトからシングルトンにアクセスできますか?

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へのデータの追加を開始するために、これらのプラグインのうちの2つを必要とするポイントに到着しました:私は、プラグインをロードするには、次のコードを使用します。アプリケーションは、アプリケーション自体のコードを変更することなく、両方のプラグイン間の通信を許可しないため(私たちが避けようとしているところ)、これを解決する方法が見つけられたと思います。第3のプラグインスレッドセーフQueue

次に、両方のプラグインをライブラリに対して再コンパイルしてリンクし、getInstance()を使用してシングルトンを取得し、タスクをキューに追加します。

これは安全な実装ですか?シングルトンQueueは機能しますか?

答えて

1

スレッドセーフなキューを持つシングルトンクラスを含む動的ライブラリ(共有オブジェクト)。

シングルトンは、クラスを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; 
    } 
}; 

デフォルトのコンストラクタは、プライベート宣言、および/割付操作が複数のインスタンスを避けるために削除され、コピーされます。

もっと単純なものが必要です。関数は常に同じインスタンスを返します。

複数インスタンス化を防ぐ必要はありません。同じインスタンスが必要な場合は、同じインスタンスを要求してください。

また、いくつかのIDを指定した同じインスタンスを返すリソースプールで設計を拡張することができます。この例p[id]Resourceのデフォルトコンストラクタを持つ場で作成されていることを

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

注意を。あなたは、建設中にパラメータを渡す必要があります。

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

注最後の2つの実装は、スレッドであることを非静的コードの周りにミューテックスが必要であること安全。

関連する問題