Расчет максимального размера производных классов - PullRequest
3 голосов
/ 12 ноября 2008

У нас есть класс My_list, в котором есть список указателей на Abstract_things. Чтобы оптимизировать использование памяти, все производные вещи используют один пул памяти, созданный со стереотипом «new and delete». Чтобы правильно определить размер пула во время инициализации приложения, разработчик выясняет, какая вещь является самой большой, и определяет размер пула на основе этого.

Дилемма дизайна заключается в том, что если в модель добавляется новая вещь (обозначена красным Thing_4), дизайнер должен знать, что нужно перейти к Builder для настройки логики. Я заметил, что нашей команде было достаточно сложно запомнить это (около половины наших вещей не было учтено в Builder). Я очень обеспокоен тем, что будущие поколения не заметят этого.

Мой вопрос, как я могу улучшить это? Было бы замечательно, если бы в процессе создания класса Thing_4 все эти вещи max_size автоматически обрабатывались. Хотя я не могу придумать способ.

Примечание: просматривая мою фотографию, я понимаю, что произошла ошибка. Последняя строка в блоке кода должна выглядеть как Abstract_thing :: set_max_pool_size (max_size, max_number).

Редактировать: я не могу понять, как отобразить картинку. В окне предварительного просмотра все выглядит хорошо, но после публикации его там нет. Любая помощь?

Редактировать: Чтобы дать немного больше фона, это часть дизайна для встроенного приложения в системе, критически важной для безопасности. Нам разрешается выделять память из кучи при инициализации приложения, но после выхода из этой фазы инициализации НИКАКАЯ динамическая память не может быть выделена. Попытка сделать это приводит к сбою приложения. Поэтому мы программируем до самых больших размеров и максимального количества используемых нами экземпляров. Наличие одного пула, который содержит достаточно места для всех производных объектов, является лучшим подходом, чем наличие пула для каждого производного объекта.

альтернативный текст http://img262.imageshack.us/img262/4470/designproblemof1.png

Ответы [ 5 ]

3 голосов
/ 12 ноября 2008

Обновлено : хорошо ... требования к встроенной системе несколько меняют ситуацию.

Вы можете использовать класс для автоматической регистрации производных классов, а затем добавить статический экземпляр этого класса в каждый производный класс. Вы все еще должны помнить, чтобы сделать это, хотя, но, по крайней мере, это самодостаточно в одном месте.

Что-то вроде:

template<class T>
class RegisterPoolClass
{
public:
    RegisterPoolClass() { init_pool.Register(sizeof(T)); }
};

class Thing_1 : public Abstract_Thing
{
   static RegisterPoolClass<Thing_1> sInitializer;
    ...
};

RegisterPoolClass<Thing_1> Thing_1::sInitializer;

Вы можете использовать макрос для инкапсуляции кода, необходимого в каждом производном классе, точно так же, как это делает ATL.

0 голосов
/ 12 ноября 2008

Не могли бы вы использовать CTAGS или подобный парсер для извлечения имен всех производных классов и использовать его для автоматической генерации вашей реализации init_pool?

0 голосов
/ 12 ноября 2008

Как насчет этого:

AbstractThing.h
#ifndef ABSTRACT_THING
#define ABSTRACT_THING
class AbstractThing
{
private:
    static  size_t                  maxChildSize;
    static  bool                    maxChildLock;
    static  std::vector<type_info>  validChildren;

    static size_t   getMaxChildSize()
    {
        maxChildLock    = true;
        return maxChildSize;
    }
public:
    template<typename T>
    static  void setChildSize()
    {
        // This is to stop registering things after getMaxChildSize()
        // has been called. This check is only needed during testing
        if (maxChildLocked)
        {
            exit(1);
        }
        maxChildSize    = std::max(maxChildSize,sizeof(T));
        validChildren.push_back(typeid T);
    }
    template<typename T>
    static bool testValidType()
    {
        // While testing call this method.
        // Don't call in production to speed things up.

        // Only registered children will be allowed to get memory.
        // Or maybe generate a warning in the log if it fails.
        return validChildren.find(typeid T) != validChildren.end();
    }
};
template<typename T>
class RegisterAbsoluteThing
{
public:
    RegisterAbsoluteThing()
    {
        AbstractThing::setChildSize<T>();
    }
};
#endif
Thing1.h
#ifndef THING_1
#define THING_1

#include "AbstractThing.h"
class Thing1: public AbstractThing
{
};

namespace
{
    // Because this is in an anonymous namespace
    // It does not matter how many times different files it is included
    // This will then all be registered at startup before main.
    RegisterAbsoluteThing<Thing1>   RegisterAsValidThing1;

    // All class that derive from AbstractThing should have this block.
    // Any that do not that try and use the pool will cause the tests to fail.
}
#endif
0 голосов
/ 12 ноября 2008

grep для классов, создайте приложение, которое проверяет все размеры и дает сбой, если они испортились.

echo '#include"head"' > out.cpp
grep "class \w+ : TheClass" *.cpp | sed  "s/.*class \(\w\)+ : TheClass.*/assert(sizeof($1) <= MAX_SIZE); >> out.cpp
echo '#include"tail"' >> out.cpp
gcc out.cpp
./a.out
0 голосов
/ 12 ноября 2008

Я не уверен, правильно ли я это понимаю, но что мешает вам выполнить шаг сборки, который перечисляет все производные классы, оценивает их размеры любым способом, который вы используете сейчас, чтобы рассчитать размер ваших вещей и найти самый большой один

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...