一個動態庫(共享對象),它包含一個具有線程安全隊列的單例類。
當你想約束一個類只被實例化一次時,使用單例。這就是而不是你想要什麼:你想讓你所有的插件在一個類的特定實例上工作。這裏沒有「只有一個人可以生活」的要求。
在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-安全。