Skip to content

Instantly share code, notes, and snippets.

@ofdouglas
Created August 6, 2017 19:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ofdouglas/2f1effa44f48b68c896c1a42f1ced223 to your computer and use it in GitHub Desktop.
Save ofdouglas/2f1effa44f48b68c896c1a42f1ced223 to your computer and use it in GitHub Desktop.
Dynamic allocation from a statically allocated pool
#include <stdio.h>
#include <stddef.h>
#include "public.h"
#include "assert.h"
#define NUM_FOOS 4
int main (void)
{
foo_module_init(NUM_FOOS);
struct foo * foo_handles[NUM_FOOS + 1];
/* Show that we can succesfully allocate NUM_FOOS objects, and that additional
* allocation attempts will fail safely.
*/
for (int i = 0; i < NUM_FOOS + 1; i++) {
foo_handles[i] = foo_allocate();
printf("foo_handles[%d] allocate %s\n",
i, foo_handles[i] ? "OK" : "FAILED");
}
/* Show that we can succesfully free an object and re-use that memory.
*/
foo_free(foo_handles[0]);
foo_handles[NUM_FOOS] = foo_allocate();
assert(foo_handles[NUM_FOOS]);
foo_configure(foo_handles[0], 1, 2);
printf("foo result = %d\n", foo_do_stuff(foo_handles[0]));
}
#include "public.h"
#include <stdlib.h>
#include <assert.h>
// Private implementation of foo
struct foo {
int x;
int y;
/* Used to maintain the free list. If you won't ever free foo objects, you
* could remove this item and allocate by incrementing an index into the
* free list...
*/
struct foo * next;
};
// Pointer to statically allocated pool of foo objects
static struct foo * free_list;
/* Make the foo module ready for use. This must be called exactly once, before
* any functions in the foo module are used.
*/
void foo_module_init(size_t num_foos)
{
free_list = malloc(num_foos * sizeof(struct foo));
assert(free_list);
for (int i = 0; i < num_foos - 1; i++)
free_list[i].next = &free_list[i+1];
}
/* Allocate and return a foo if possible; else return NULL.
*/
struct foo * foo_allocate(void)
{
struct foo * f = free_list;
if (f != NULL)
free_list = f->next;
return f;
}
/* Deallocate a foo.
*/
void foo_free(struct foo * f)
{
if (f == NULL)
return;
f->next = free_list;
free_list = f;
}
void foo_configure(struct foo * f, int x, int y)
{
if (f == NULL)
return;
f->x = x;
f->y = y;
}
/* In a real application this would do something interesting.
*/
int foo_do_stuff(struct foo * f)
{
return f->x + f->y;
}
#ifndef __PUBLIC_H
#define __PUBLIC_H
#include <stddef.h>
// Opaque type
struct foo;
void foo_module_init(size_t num_foos);
struct foo * foo_allocate(void);
void foo_free(struct foo * f);
void foo_configure(struct foo * f, int x, int y);
int foo_do_stuff(struct foo * f);
#endif // __PUBLIC_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment