Home > Dynamic memory allocation, Projects, RTOS, SKC++ > SKC++: Dynamic Memory Classes

SKC++: Dynamic Memory Classes

Wednesday, September 30, 2009 Leave a comment Go to comments

Following on from previous postings, here is a UML diagram showing two classes concerned with dynamic memory handling:

Dynamic Memory Classes

Dynamic Memory Classes

Bear in mind that everything shown in this blog is work in progress; things will change as development continues.

The System Class

This class will eventually hold everything to do with system configuration and initialisation; it is not just for memory management. At the moment, though, only the management of the global “quasi-heap” is shown. As explained previously, the quasi-heap is an allocate-only area of memory; no memory taken from it is ever returned. Although most of System‘s useful member functions are static, a single System object must be created in order to configure and initialise SKC++. The constructor requires a pointer to the start of the quasi-heap and a further parameter indicating its size in bytes. Thus the user must supply the area of memory to be managed. One way of doing this is to declare a static array and pass its starting address and size to the System constructor.

What the diagram does not show is the global overrides for ::operator new and ::operator delete. The overriding ::operator delete causes a fatal error, as discussed previously. The overriding ::operator new calls System::getMem. It does so as a friend of the class, so that System::getMem can be kept private. Although it would do no harm for a user to call System::getMem directly, it is better style always to use the new keyword instead.

As there is no dynamic memory management available (because of the overrides) until the System object has been created, it is important to realise that this cannot be created dynamically. It can be created statically or it can be created as a local variable. Although a local object disappears if it goes out of scope, the destructor does nothing and the static facilities of the class , including the quasi-heap, remain available. The initial quasi-heap area itself must, of course, be statically located in some way.

The Pooled Class

Why an adjective rather than a noun for this class? Well, the idea is to qualify some other class, whose objects are to be pooled. A typical example of a class with pooled objects would be some kind of Message to be transferred from one Task to another. Messages are not Pools but they are Pooled. So a Message class allows its objects to be pooled by inheriting from the Pooled class. It might be said that the same functionality could be achieved by association (Message uses a Pool) or aggregation (Message has a Pool), but this would require the designer of Message to implement Message::operator new and Message::operator delete such that they interact with the pool. By using inheritance instead, we can provide these operators ready-made in the Pooled base class. Using the memory allocation operators of a base class has some well-documented pitfalls but the scheme proposed here works well – trust me – provided the class requiring the pool capability inherits directly from Pooled. Here is an example:

class MyClass: public Pooled<MyClass, 10> ...
{
...
};

From this example, and also from the diagram, you can see that Pooled is a template class, where the name of the inheriting class is given as the first template argument. This ensures that each inheriting class gets a pool exclusively for its own use. Of course, we require only one pool for each entire class of objects, so the pool-related attributes of Pooled are static. Pooled::operator new and Pooled::operator delete are necessarily static in any case, according to C++ rules. Pooled must have a default constructor and a virtual destructor, but they are empty.

The second template argument is the total number of blocks (each the size of the inherited object) in the pool. If non-zero, this number specifies exactly how big the pool will be. In the example, we have 10. On creation of the first MyClass object, space for all 10 objects is reserved (by taking it from the quasi-heap), though only the first object is actually created. This means that memory for all pools is reserved as soon as reasonably possible in the initialisation of the system and that any shortage of memory is likely to be discovered during development and not left to become a nasty surprise in the field.

During development, it is not always easy to know how big a pool should be. It is therefore allowed to specify 0 for the number of blocks. Doing this allows the pool to expand indefinitely: each object is created upon request, using memory from the pool, if there is any, or otherwise from the quasi-heap. Deleted objects end up in the pool anyway, and thus the pool grows to meet peak demand, then stops growing. Using such open-ended pools is not recommended for production code; once the dynamic memory requirements have been properly sorted out, each pool should be re-specified to have a definite number of blocks.

Coming Soon

I’m now leaving the vitally important but rather dry subject of dynamic memory management and I hope to make only passing reference to it in future SKC++ articles. The next subject to be covered will be the Task (known to some as the Thread, but this is a term I dislike in RTOS discussions, for reasons I will share with you next time).

Advertisements
  1. Peter Bushell
    Thursday, October 1, 2009 at 11:20

    Update…

    After further thought, I will probably include the quasi-heap as a static array within the System class. The System class will then become a template, so that the size of the quasi-heap can be specified as a template argument. This simplifies things for the user and ensures that the quasi-heap is statically allocated, as required.

  2. Peter Bushell
    Thursday, October 1, 2009 at 17:21

    Update…

    After even more thought, I’ll leave the original way of allocating the quasi-heap as an option for people who want to use the “spare” memory indicated by the linker/locator, rather than allocating a specific array.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: