P
pinkfloydhomer
Please read the example below. I'm sorry I couldn't make it smaller,
but it is pretty simple.
When client code is calling newThingy(), it is similar to malloc: the
client gets a pointer to a chunk of memory that it can use for it's own
purposes.
But on the "library" side, I want to be able to do some book-keeping
for each memory block that I hand out. I want some "hidden" meta-data
(that I keep in struct Container) to be associated with each memory
block that I return from newThingy().
The _problem_ lies in findContainer(). It runs in linear time. I would
like constant time. I would like not having to search for the Container
containing the allocated memory. What do I do?
#include <stdio.h>
#include <stddef.h>
#include <malloc.h>
#include <assert.h>
/* "library" code */
typedef struct Container_
{
int foo;
int bar;
void* thingy;
struct Container_* next;
} Container;
Container* list = NULL;
void* newThingy(size_t size)
{
void* thingy;
Container* container;
thingy = malloc(size);
assert(thingy);
container = (Container*) malloc(sizeof(Container));
assert(container);
container->foo = 42;
container->bar = 3;
container->thingy = thingy;
container->next = list;
list = container;
return thingy;
}
Container* findContainer(void* thingy)
{
Container* container;
for (container = list; container; container = container->next)
{
if (container->thingy == thingy)
return container;
}
return NULL;
}
void doSomething(void* thingy)
{
Container* container = findContainer(thingy);
assert(container);
/* do something */
printf("%d\n", container->foo);
}
/* "client" code */
typedef struct
{
int whatever;
float something;
} ClientThingy1;
typedef struct
{
char dontask;
int* whocares;
} ClientThingy2;
int main(void)
{
ClientThingy1* thingy1 = newThingy(sizeof(ClientThingy1));
ClientThingy2* thingy2 = newThingy(sizeof(ClientThingy2));
doSomething(thingy1);
doSomething(thingy2);
return 0;
}
I was considering something along the lines of allocating the memory
for Container and thingy in one go, like:
Container* container = malloc(sizeof(Container) + size);
and then return something like
return (container + sizeof(Container));
and then findContainer() would become constant time, something like:
Container* findContainer(void* thingy)
{
return thingy - sizeof(Container);
}
But is that portable and well-defined? Or are there other solutions?
/David
but it is pretty simple.
When client code is calling newThingy(), it is similar to malloc: the
client gets a pointer to a chunk of memory that it can use for it's own
purposes.
But on the "library" side, I want to be able to do some book-keeping
for each memory block that I hand out. I want some "hidden" meta-data
(that I keep in struct Container) to be associated with each memory
block that I return from newThingy().
The _problem_ lies in findContainer(). It runs in linear time. I would
like constant time. I would like not having to search for the Container
containing the allocated memory. What do I do?
#include <stdio.h>
#include <stddef.h>
#include <malloc.h>
#include <assert.h>
/* "library" code */
typedef struct Container_
{
int foo;
int bar;
void* thingy;
struct Container_* next;
} Container;
Container* list = NULL;
void* newThingy(size_t size)
{
void* thingy;
Container* container;
thingy = malloc(size);
assert(thingy);
container = (Container*) malloc(sizeof(Container));
assert(container);
container->foo = 42;
container->bar = 3;
container->thingy = thingy;
container->next = list;
list = container;
return thingy;
}
Container* findContainer(void* thingy)
{
Container* container;
for (container = list; container; container = container->next)
{
if (container->thingy == thingy)
return container;
}
return NULL;
}
void doSomething(void* thingy)
{
Container* container = findContainer(thingy);
assert(container);
/* do something */
printf("%d\n", container->foo);
}
/* "client" code */
typedef struct
{
int whatever;
float something;
} ClientThingy1;
typedef struct
{
char dontask;
int* whocares;
} ClientThingy2;
int main(void)
{
ClientThingy1* thingy1 = newThingy(sizeof(ClientThingy1));
ClientThingy2* thingy2 = newThingy(sizeof(ClientThingy2));
doSomething(thingy1);
doSomething(thingy2);
return 0;
}
I was considering something along the lines of allocating the memory
for Container and thingy in one go, like:
Container* container = malloc(sizeof(Container) + size);
and then return something like
return (container + sizeof(Container));
and then findContainer() would become constant time, something like:
Container* findContainer(void* thingy)
{
return thingy - sizeof(Container);
}
But is that portable and well-defined? Or are there other solutions?
/David