Хочу предложить вашему внимание паттерн проектирования InstanceManager;
Данный класс позволяет использовать только один экземпляр любого класса в программе не прибегая к помощи синглтонов:
//////////////////////////////////////////////////////////////////////////
// Therading model class examplestruct SingleThread
{
void Lock() {}
void Unlock() {}
};
template <class T>
struct MutexLocker
{
MutexLocker(T& m) : MyMutex(&m) { MyMutex->Lock(); };
~MutexLocker() { MyMutex->Unlock(); }
private:
T* MyMutex;
};
//////////////////////////////////////////////////////////////////////////
/// class Instance pooltemplate<class ThreadingModel = SingleThread>
class InstanceManager
{
class InstanceBase
{
public:
virtual ~InstanceBase() {}
};
template <class T>
class Instance : public T, public InstanceBase
{
};
public:
~InstanceManager()
{
while (!ObjectPool.empty())
{
delete ObjectPool.begin()->second;
ObjectPool.erase(ObjectPool.begin());
}
}
template <class T>
T* GetInstance(const T* t = 0)
{
const Loki::TypeInfo id(typeid(t));
ObjectPoolMap::iterator o = ObjectPool.find(id);
if (o == ObjectPool.end())
{
MutexLocker<ThreadingModel> locker(InsertMutex);
o = ObjectPool.find(id);
if (o == ObjectPool.end())
{
o = ObjectPool.insert(ObjectPoolMap::value_type(id, new Instance<T>())).first;
}
}
return static_cast<T*>(static_cast<Instance<T>* >(o->second));
}
private:
ThreadingModel InsertMutex;
typedef std::map<Loki::TypeInfo, InstanceBase*> ObjectPoolMap;
ObjectPoolMap ObjectPool;
};
Здравствуйте, BULAT GAIFULLIN, Вы писали:
BG>Хочу предложить вашему внимание паттерн проектирования InstanceManager; BG>Данный класс позволяет использовать только один экземпляр любого класса в программе не прибегая к помощи синглтонов:
Я думал, паттерн — это вроде как картинка, ну, или там, описание..? А тут код какой-то
Здравствуйте, BULAT GAIFULLIN, Вы писали:
BG>Хочу предложить вашему внимание паттерн проектирования InstanceManager;
бред какой-то, для получения доступа к обьекту происходит синхронизация, а ещё и поиск по мапе, тоесть ужасная писсимизация на пустом месте,
если не нравятся синглетоны майерса с неопределённым временем жизни- создайте обьект-синглетон на стеке, проинициализируйте глобальный указатель, а потом используйте где угодно, это и проще и понятнее и намного быстрее.
Здравствуйте, BULAT GAIFULLIN, Вы писали:
BG>Хочу предложить вашему внимание паттерн проектирования InstanceManager; BG>Данный класс позволяет использовать только один экземпляр любого класса в программе не прибегая к помощи синглтонов:
BG> const Loki::TypeInfo id(typeid(t));
BG> ObjectPoolMap::iterator o = ObjectPool.find(id);
интересно о чём нам расскажет этот find если ему по серединке пару инсертов сделать ...
BG> if (o == ObjectPool.end())
BG> {
BG> MutexLocker<ThreadingModel> locker(InsertMutex);
BG> o = ObjectPool.find(id);
BG> if (o == ObjectPool.end())
BG> {
BG> o = ObjectPool.insert(ObjectPoolMap::value_type(id, new Instance<T>())).first;
BG> }
BG> }
BG> return static_cast<T*>(static_cast<Instance<T>* >(o->second));
Здравствуйте, Caracrist, Вы писали:
C>Здравствуйте, BULAT GAIFULLIN, Вы писали:
BG>>Хочу предложить вашему внимание паттерн проектирования InstanceManager; BG>>Данный класс позволяет использовать только один экземпляр любого класса в программе не прибегая к помощи синглтонов:
C>
BG>> const Loki::TypeInfo id(typeid(t));
BG>> ObjectPoolMap::iterator o = ObjectPool.find(id);
C>интересно о чём нам расскажет этот find если ему по серединке пару инсертов сделать ... C>
BG>> if (o == ObjectPool.end())
BG>> {
BG>> MutexLocker<ThreadingModel> locker(InsertMutex);
BG>> o = ObjectPool.find(id);
BG>> if (o == ObjectPool.end())
BG>> {
BG>> o = ObjectPool.insert(ObjectPoolMap::value_type(id, new Instance<T>())).first;
BG>> }
BG>> }
BG>> return static_cast<T*>(static_cast<Instance<T>* >(o->second));
C>
здесь нужно лочить еще перед первым вызовом find. моя ошибка.
C>а сам класс будет статиком или синглтоном?
я собирался сделать сам класс является синглтоном.
C>п.с. try again later
Какое прекрасное слово!
Почти пессимизация, только гораздо экспрессивнее.
S>если не нравятся синглетоны майерса с неопределённым временем жизни- создайте обьект-синглетон на стеке, проинициализируйте глобальный указатель, а потом используйте где угодно, это и проще и понятнее и намного быстрее.
У Александреску (раз уж Локи было упомянуто) разных синглетонов с разными стратегиями жизни было — вагон и тележка.
"Паттерном" это вообще вряд ли можно было бы назвать, так как паттерн здесь уже есть — это синглтон.
Решение обладает следующими недостатками:
1. Дикая неэффективность: каждое обращение к экземпляру — поиск в std::map. Это делает данное решение практически непригодным.
2. Неудобная длинная запись при получении экземпляра.
3. Модель многопоточности задается для всех синглтонов сразу, а не для каждого в отдельности.
Да и вообще, непонятно для каких целей это нужно. Для тех, у кого в программе очень много синглтонов? В нормальной программе будет от силы несколько синглтонов, причем приоритетом часто является скорость доступа к экземпляру.
Кстати, такую же функциональность, как в вашем примере, можно получить таким элементарным кодом (только он гораздо эффективнее):
Здравствуйте, MrVoid, Вы писали: MV>Кстати, такую же функциональность, как в вашем примере, можно получить таким элементарным кодом (только он гораздо эффективнее):
MV>
Здравствуйте, BULAT GAIFULLIN, Вы писали:
BG>и безопасность при многопоточности в данном примере тоже не совсем понятно как реализовывать?
Между прочим, кроме внешней синхронизации существует и внутренняя. В данном случае вполне нормально сделать тип Т потокобезопасным.
(Только статиком тут лучше делать указатель и инициализировать его явно)
Это не перегрузка.
Разумеется, если написать x=GetInstance(), то компилятор не сможет победить неоднозначность.
А вот если x=GetInstance<Foo>() — всё будет хорошо.
BG>и безопасность при многопоточности в данном примере тоже не совсем понятно как реализовывать?
О, это давняя тема — как сделать синглетон Мейерса потокобезопасным.