Skip to content

A macro-only memory pool manager for C/C++ programs.

License

Notifications You must be signed in to change notification settings

notweerdmonk/memblock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

memblock

A memory pool manager.

Let us consider a contiguous block of memory which is either statically allocated on the stack of dynamically allocated on the heap. You need to use equal sized chunks from this memory block and memory locations can be reused.

struct foo {
  int n;
  double f;
};

int array[4 * sizeof(struct foo)];

Initialize the memory pool:

struct memblock mempool;
init_mem(mempool, struct foo, array, 4);

Now you can use chunks of memory:

struct foo *p = use_mem(struct foo, mempool);
struct foo *q = use_mem(struct foo, mempool);
struct foo *r = use_mem(struct foo, mempool);
struct foo *s = use_mem(struct foo, mempool);
struct foo *t = use_mem(struct foo, mempool);
if (t != NULL) {
  // never reached as t will be NULL because the memory pool is exhausted
}

And free any chunk so that it can be reused without bookkeeping:

free_mem(p, mempool);
free_mem(q, mempool);
free_mem(s, mempool);

Consider checking memblock.h for documentation on the arguments and test.c for examples of usage.

Here is an insight of how memblock works internally:

 On initialization of memblock start and avail point to the first memory element
  and end points the last element. Every element contains the offset to next
  element which is the size of one element.

       start                                        end
       avail                                         |
         |                                           |
        \|/                                         \|/
  ___________________________________________________________
 |              |              |              |              |
 | sizeof(type) | sizeof(type) | sizeof(type) | guard value  |
 |______________|______________|______________|______________|

 After using first memory element avail points to the next element.
 avail = avail + *avail

       start                                        end
         |            avail                          |
         |              |                            |
        \|/            \|/                          \|/
  ___________________________________________________________
 |              |              |              |              |
 |     data     | sizeof(type) | sizeof(type) | guard value  |
 |______________|______________|______________|______________|

 The last element contains a guard value instead of an offset value.
 
       start                                        end
         |                                         avail
         |                                           |
        \|/                                         \|/
  ___________________________________________________________
 |              |              |              |              |
 |     data     |     data     |     data     | guard value  |
 |______________|______________|______________|______________|

 After last element has been used avail will point to 0.

       start                                        end
         |                                           |             avail
         |                                           |               |
        \|/                                         \|/             \|/
  ___________________________________________________________
 |              |              |              |              |
 |     data     |     data     |     data     |     data     |       0
 |______________|______________|______________|______________|

 When the first location is freed its contents are set to a guard value.

       start                                        end
         |                           avail           |
         |                             |             |
        \|/                           \|/           \|/
  ___________________________________________________________
 |              |              |              |              |
 |     data     |     data     | guard value  |     data     |
 |______________|______________|______________|______________|

 The next element that is freed will contain the offset from avail and avail
  will now point to the freed element.
 *pobj = avail - pobj
 avail = pobj

       start                                        end
       avail                                         |
         |                                           |
        \|/                                         \|/
  ___________________________________________________________
 |     -2 *     |              |              |              |
 | sizeof(type) |     data     | guard value  |     data     |
 |______________|______________|______________|______________|

 Now after the first available element is used, avail will point to the next
  free element.
 avail = avail + *avail

       start                                        end
         |                           avail           |
         |                             |             |
        \|/                           \|/           \|/
  ___________________________________________________________
 |              |              |              |              |
 |   new data   |     data     | guard value  |     data     |
 |______________|______________|______________|______________|

The macro MEMBLOCK_MIN_ELEMENT_SIZE determines the minimum size of memory used to store the offset values, therefore decides the maximum size of the memory pool. The size of chunks to be used should not be smaller than MEMBLOCK_MIN_ELEMENT_SIZE. It defaults to 1 but can be defined before including the header memblock.h. Accepted values are 1, 2, 4 and 8.

#define MEMBLOCK_MIN_ELEMENT_SIZE 2
#include <memblock.h>
Footnotes
  • The macros use statement expressions which is a non-standard extension provided by GNU GCC.
  • Pointers are cast to different types for arithmetic and use_mem casts memory to pointer type requested by user. Suggestion is to add -fno-strict-aliasing option if the compiler gives warnings or there is any undefined behaviour in the program.

About

A macro-only memory pool manager for C/C++ programs.

Resources

License

Stars

Watchers

Forks

Packages