Russian Qt Forum

Qt => Общие вопросы => Тема начата: alexis031182 от Июнь 20, 2012, 21:02



Название: [РЕШЕНО] Интеграция фабрики с пулом объектов
Отправлено: alexis031182 от Июнь 20, 2012, 21:02
Хочу использовать вот такой класс пула объектов

awebobjectpool.h
Код
C++ (Qt)
#include <QList>
 
template<class T>
class AWebObjectPool
{
public:
   //! Конструктор.
   AWebObjectPool() {}
 
   //! Деструктор.
   virtual ~AWebObjectPool() {}
 
   //! Функция инициализации пула.
   static void initialize(int count = 1) {
       for(int i = 0; i < count; ++i) {
           T *object = ::new T;
           objects().append(object);
       }
   }
 
   //! Функция деинициализации пула.
   static void uninitialize() {
       if(objects().isEmpty()) return;
       qDeleteAll(objects()); objects().clear();
   }
 
   //! Оператор выделения памяти под объект.
   void *operator new(size_t) {
       if(T::objects().size() <= 0) T::initialize();
       return T::objects().takeLast();
   }
 
   //! Оператор освобождения памяти.
   void operator delete(void *object) {T::objects().append((T*)object);}
 
private:
   //! Функция возврата списка объектов пула.
   static QList<T*>& objects() {static QList<T*> objects; return objects;}
 
   //! Конструктор копирования.
   AWebObjectPool(const AWebObjectPool&);
 
   //! Оператор присваивания.
   AWebObjectPool &operator=(const AWebObjectPool&);
 
};
 

... совместно с такой вот фабрикой (состоит из 3-х классов):

awebabstractobjectconstructor.h
Код
C++ (Qt)
template<class T>
class AWebAbstractObjectConstructor
{
public:
   //! Конструктор.
   AWebAbstractObjectConstructor() {}
 
   //! Деструктор.
   virtual ~AWebAbstractObjectConstructor() {}
 
   //! Функция создания объекта класса.
   virtual T *create() const = 0;
 
private:
   //! Конструктор копирования.
   AWebAbstractObjectConstructor(const AWebAbstractObjectConstructor&);
 
   //! Оператор присваивания.
   AWebAbstractObjectConstructor &operator=(
       const AWebAbstractObjectConstructor&
   );
 
};
 

awebobjectconstructor.h
Код
C++ (Qt)
#include "awebabstractobjectconstructor.h"
 
template<class Child, class Base>
class AWebObjectConstructor : public AWebAbstractObjectConstructor<Base>
{
public:
   //! Конструктор.
   AWebObjectConstructor() {}
 
   //! Деструктор.
   virtual ~AWebObjectConstructor() {}
 
   //! Функция создания объекта класса.
   Base *create() const {return new Child();}
 
};
 

awebobjectfactory.h
Код
C++ (Qt)
#include <QHash>
 
#include "awebobjectconstructor.h"
 
template<typename Key, class T>
class AWebObjectFactory
{
public:
   //! Конструктор.
   AWebObjectFactory() {}
 
   //! Деструктор.
   virtual ~AWebObjectFactory() {qDeleteAll(_classes);}
 
   //! Функция создания объекта класса.
   T *create(const Key &key) const {
       if(!_classes.contains(key)) return NULL;
       return _classes.value(key)->create();
   }
 
   //! Функция регистрации класса объектов.
   template<class C> bool registerClass(const Key &key) {
       if(_classes.contains(key)) return false;
       _classes.insert(key, new AWebObjectConstructor<C, T>());
       return true;
   }
 
   //! Функция дерегистрации класса объектов.
   bool unregisterClass(const Key &key) {
       if(!_classes.contains(key)) return false;
       delete _classes.take(key);
       return true;
   }
 
   //! Функция определения, зарегистрирован ли класс по указанному ключу.
   bool isRegisteredClass(const Key &key) const {
       return _classes.contains(key);
   }
 
private:
   typedef AWebAbstractObjectConstructor<T> AbstractObjectConstructor;
   typedef QHash<Key, AbstractObjectConstructor*> ObjectFactoryHash;
 
   ObjectFactoryHash _classes;
 
   //! Конструктор копирования.
   AWebObjectFactory(const AWebObjectFactory&);
 
   //! Оператор присваивания.
   AWebObjectFactory &operator=(const AWebObjectFactory&);
 
};
 

Вопрос в том, что у пула есть возможность указать количество объектов к предварительному созданию. Но, видимо под вечер, не могу сообразить, как мне этот параметр через фабрику в пул прокинуть - AWebObjectPool::initialize(int count = 1) ?

З.Ы. Ну и чтобы было понятно, как всё это хозяйство используется:

Код
C++ (Qt)
class A : public AWebObjectPool<A> {};
 
AWebObjectFactory<QString, A> factory;
factory.registerClass<A>("A");
A *a = static_cast<A*>(factory.create("A"));
A *b = static_cast<A*>(factory.create("A"));
A *c = static_cast<A*>(factory.create("A"));
 


Название: Re: Интеграция фабрики с пулом объектов
Отправлено: alexis031182 от Июнь 20, 2012, 21:32
На всякий случай во вложении эти классы, если в лом рассматривать мою простыню :)


Название: Re: Интеграция фабрики с пулом объектов
Отправлено: alexis031182 от Июнь 20, 2012, 23:42
Наверное вариантов других нет и надо в фабрике поддержку параметров как-то реализовывать


Название: Re: Интеграция фабрики с пулом объектов
Отправлено: Igors от Июнь 21, 2012, 11:10
Та же проблема что и у Наташи - скажем так "совсем непросто" понять что же нужно сделать? :)  Мне помогло что Вы говорили в др темах, иначе я бы просто закрыл топик не дочитав и до половины.

Ладно, если я правильно понял, "единица фабрики" - пул объектов одного типа. Тогда первое что приходит в голову - а не повыкидывать ли нафиг большинство template выносящих мозг программиста "for nothing"? напр так
Код
C++ (Qt)
struct MyPool : public QList <MyBaseObj *> {   // да-да, наследуюсь от контейнера
const char * mKey;       // и без всяких QString
 
MyBaseObj * GetObject( bool create )
{
  if (create) {
    MyBaseObj * obj = CreateByName(mKey);
    ...
  }
  ...
}
};
 
Далее надо сосредоточиться на том как используется пул. Если заряжаются 2 или более объектов, то надо определить правила, который должен быть возвращен - пока информации об этом ноль.


Название: Re: Интеграция фабрики с пулом объектов
Отправлено: alexis031182 от Июнь 21, 2012, 11:29
Та же проблема что и у Наташи - скажем так "совсем непросто" понять что же нужно сделать? :)  Мне помогло что Вы говорили в др темах, иначе я бы просто закрыл топик не дочитав и до половины.
Виноват :)

Ладно, если я правильно понял, "единица фабрики" - пул объектов одного типа.
Всё верно, просто вместо пула можно использовать и обычный класс.

Тогда первое что приходит в голову - а не повыкидывать ли нафиг большинство template выносящих мозг программиста "for nothing"? напр так
...
Эта фабрика для наследников базового класса. Мне она нравится.
Код
C++ (Qt)
class Base : public AWebObjectPool<Base> {};
 
class A : public Base {};
 
class B : public Base {};
 
//QString в прошлом примере поставил, подумав, что будет проще в понимании
AWebObjectFactory<const char*, Base> factory;
factory.registerClass<A>("A");
factory.registerClass<B>("B");
Base *a = factory.create("A");
Base *b = factory.create("B");
 

Далее надо сосредоточиться на том как используется пул. Если заряжаются 2 или более объектов, то надо определить правила, который должен быть возвращен - пока информации об этом ноль.
Вот если глянуть на приведённый только что мною пример, то мне бы хотелось сделать, скажем как-то так:
Код
C++ (Qt)
factory.registerClass<A>("A", 10);
factory.registerClass<B>("B", 100);
 
То есть предварительно создать 10 штук A и 100 штук B. Проблема в том, что регистрируемый класс может и не быть вовсе наследником класса пула. Это вообще произвольный класс, и мне хотелось бы это сохранить. Другими словами, нужно как-то определять, что для пула - могут быть параметры, а для любого другого класса - нет.


Название: Re: Интеграция фабрики с пулом объектов
Отправлено: Igors от Июнь 21, 2012, 11:44
То есть предварительно создать 10 штук A и 100 штук B. Проблема в том, что регистрируемый класс может и не быть вовсе наследником класса пула. Это вообще произвольный класс, и мне хотелось бы это сохранить. Другими словами, нужно как-то определять, что для пула - могут быть параметры, а для любого другого класса - нет.
Создайте еще один registerClass с параметром числа элементов пула - его и подадите в конструктор.


Название: Re: Интеграция фабрики с пулом объектов
Отправлено: alexis031182 от Июнь 21, 2012, 11:46
Может быть нужно унаследовать новый класс от AWebAbstractObjectConstructor по типу того, как сделан AWebObjectConstructor, и уже в этом новом классе как-то разрулить?


Название: Re: Интеграция фабрики с пулом объектов
Отправлено: alexis031182 от Июнь 21, 2012, 11:49
Создайте еще один registerClass с параметром числа элементов пула - его и подадите в конструктор.
Да, я поначалу так и думал сделать, но AWebObjectConstructor ничего не знает о том, кого он создаёт, и есть ли у конструктора этого класса вообще какие-либо параметры. Наверное как-то всё же через наследование только.


Название: Re: Интеграция фабрики с пулом объектов
Отправлено: alexis031182 от Июнь 21, 2012, 12:09
Ёлки зелёные, ступил, так и надо было сделать через наследование ;D Спасибо, Игорь :)