J
jacob navia
Until now, I hadn't started the problem of memory allocation. Each
container allocated with malloc each new piece of memory as needed and
freed it when deleting an element.
The first abstraction is an object with 3 function pointers:
malloc
free
realloc.
This abstract a memory allocator system. Two memory allocators are
recognized: the normal C system of memory allocation (plain malloc,
free, realloc) and the GC, with GC_malloc,GC_free, and GC_realoc.
A further abstraction is a "heap manager" object. This object will
manage memory allocations, allocating several objects at once to
minimize malloc overhead. When doing a great number of allocations, the
memory needed to manage each piece of memory increases *considerably*
memory consumption, so that for any container where the number of
objects allocateds goes beyond 10 000 this is almost a requirement.
This heap manager looks like this:
struct tagHeapObject {
AllocatorInterface *VTable;
unsigned BlockCount;
unsigned CurrentBlock;
unsigned BlockIndex;
void **Heap;
size_t ElementSize;
void *FreeList;
ContainerMemoryManager *Allocator;
size_t MemoryUsed;
};
Memory is managed in an array of arrays to allocated objects. The index
"CurrentBlock" points to the block that is currently being used. Arrays
with index smaller than "CurrentBlock" are full, arrays with index
greater than CurrentBlock aren't allocated yet.
BlockIndex points to the position within the current block that is going
to be allocated next. The "Heap" field points to the actual data.
Problems arise when initializing this stuff. When a "new" function is
called for some container, I need to
(1) Allocate memory for the header
(2) Allocate memory for the heap manager object
Which allocator should be used to allocate memory?
There is a global variable containing the default memory allocator that
is initialized by the container library either to the normal C library
or to the GC one. I could decide that this default memory allocator is
always used to create objects. This would complicate matters when
changing the allocator since some memory would be allocated with a
default allocator, and some with the custm memory allocator. This is
confusing and can lead to bugs.
I could decide that the allocator should be passed as an argument to the
creation function. If NULL is passed, it means that the default
allocator should be used. But that means another argument to all
creation functions that in 95% of the cases will be just NULL.
Another possibility is that AFTER object creation but before adding
*any* objects you change the heap object with some API like
ContainerAllocator *ChangeAllocator(container, newAllocator);
that would allocate memory for the container object using the new
allocator, copy the contents, and free the memory allocated with the
default allocator during obhect creation. This option looks quite
inefficient but allows for simple syntax for MOST cases when the
allocator used is the default one.
Maybe there are other solutions. If anyne here has any idea, do not
hesitate to answer.
jacob
container allocated with malloc each new piece of memory as needed and
freed it when deleting an element.
The first abstraction is an object with 3 function pointers:
malloc
free
realloc.
This abstract a memory allocator system. Two memory allocators are
recognized: the normal C system of memory allocation (plain malloc,
free, realloc) and the GC, with GC_malloc,GC_free, and GC_realoc.
A further abstraction is a "heap manager" object. This object will
manage memory allocations, allocating several objects at once to
minimize malloc overhead. When doing a great number of allocations, the
memory needed to manage each piece of memory increases *considerably*
memory consumption, so that for any container where the number of
objects allocateds goes beyond 10 000 this is almost a requirement.
This heap manager looks like this:
struct tagHeapObject {
AllocatorInterface *VTable;
unsigned BlockCount;
unsigned CurrentBlock;
unsigned BlockIndex;
void **Heap;
size_t ElementSize;
void *FreeList;
ContainerMemoryManager *Allocator;
size_t MemoryUsed;
};
Memory is managed in an array of arrays to allocated objects. The index
"CurrentBlock" points to the block that is currently being used. Arrays
with index smaller than "CurrentBlock" are full, arrays with index
greater than CurrentBlock aren't allocated yet.
BlockIndex points to the position within the current block that is going
to be allocated next. The "Heap" field points to the actual data.
Problems arise when initializing this stuff. When a "new" function is
called for some container, I need to
(1) Allocate memory for the header
(2) Allocate memory for the heap manager object
Which allocator should be used to allocate memory?
There is a global variable containing the default memory allocator that
is initialized by the container library either to the normal C library
or to the GC one. I could decide that this default memory allocator is
always used to create objects. This would complicate matters when
changing the allocator since some memory would be allocated with a
default allocator, and some with the custm memory allocator. This is
confusing and can lead to bugs.
I could decide that the allocator should be passed as an argument to the
creation function. If NULL is passed, it means that the default
allocator should be used. But that means another argument to all
creation functions that in 95% of the cases will be just NULL.
Another possibility is that AFTER object creation but before adding
*any* objects you change the heap object with some API like
ContainerAllocator *ChangeAllocator(container, newAllocator);
that would allocate memory for the container object using the new
allocator, copy the contents, and free the memory allocated with the
default allocator during obhect creation. This option looks quite
inefficient but allows for simple syntax for MOST cases when the
allocator used is the default one.
Maybe there are other solutions. If anyne here has any idea, do not
hesitate to answer.
jacob