Calculation of the maximum size of derived classes

We have a class My_list that has a list of pointers to Abstract_things. To optimize memory usage, all derivative things use a single memory pool, which is set using the stereotype "new and remote". To correctly allocate the pool during application initialization, the builder finds out which Thing is the largest, and on the basis of this allocates the pool.

The design dilemma is that if a new thing is added to the model (represented by red Thing_4), the developer must know in order to go to Builder to configure the logic. I noticed that it was quite difficult for our team to remember this (about half of our Things discussed in Builder). I am very concerned that future generations will miss this.

My question is how can I improve this? It would be great if all this max_size property was automatically processed during the creation of the Thing_4 class. I can’t think about it.

Note. By reviewing my photo, I understand that there is a mistake. The last line in the code field should read Abstract_thing :: set_max_pool_size (max_size, max_number).

Edit: I can't figure out how to display the image. Everything looks good in the preview window, but when it is published it is not. Any help?

Edit: To give a little more background, this is part of the design of an embedded application in a security-critical system. We are allowed to allocate memory from the heap during application initialization, but after exiting this phase of NO initialization, dynamic memory may be allocated. Attempting to do this causes the application to crash. Therefore, we program the largest sizes and the maximum number of copies that we use. Having one pool that contains enough space for all derived objects is the best approach to using the pool for each derived object.

alt text http://img262.imageshack.us/img262/4470/designproblemof1.png

+3
source share
5 answers

Updated : ok ... the requirements for the embedded system change somewhat.

, . , , , .

- :

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.

+3

, , , , , , ?

0

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

:

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

Could you use CTAGS or a similar parser to extract the names of all derived classes and use them to automatically generate an init_pool implementation?

0
source

Source: https://habr.com/ru/post/1699432/


All Articles