Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I've borrowed the idea from the internet and I would like to know if my implementation is all right and what could be improved.

It uses the free memory to store links to each node, so there's no extra memory being used.

memory_pool.h

#ifndef MEMORY_POOL_H
#define MEMORY_POOL_H

#include <stdlib.h>

#define MEMORY_POOL_SUCCESS 1
#define MEMORY_POOL_ERROR 0
#define MEMORY_POOL_MINIMUM_SIZE sizeof(void *)

typedef struct {
    void **head;
    void *memory;
} Memory_Pool;

//size must be greater than or equal to MEMORY_POOL_MINIMUM_SIZE
int mp_init(Memory_Pool *mp, size_t size, size_t slots);
void mp_destroy(Memory_Pool *mp);

void *mp_get(Memory_Pool *mp);
void mp_release(Memory_Pool *mp, void *mem);

#endif

memory_pool.c

#include "memory_pool.h"

int mp_init(Memory_Pool *mp, size_t size, size_t slots)
{
    //allocate memory
    if((mp->memory = malloc(size * slots)) == NULL)
        return MEMORY_POOL_ERROR;

    //initialize
    mp->head = NULL;

    //add every slot to the list
    char *end = (char *)mp->memory + size * slots;
    for(char *ite = mp->memory; ite < end; ite += size)
        mp_release(mp, ite);

    return MEMORY_POOL_SUCCESS;
}

void mp_destroy(Memory_Pool *mp)
{
    free(mp->memory);
}

void *mp_get(Memory_Pool *mp)
{
    if(mp->head == NULL)
        return NULL;

    //store first address
    void *temp = mp->head;

    //link one past it
    mp->head = *mp->head;

    //return the first address
    return temp;
}

void mp_release(Memory_Pool *mp, void *mem)
{
    //store first address
    void *temp = mp->head;

    //link new node
    mp->head = mem;

    //link to the list from new node
    *mp->head = temp;
}
share|improve this question

2 Answers 2

up vote 4 down vote accepted

I see a few things that might be changed.

mp_init

First, consider checking the passed *mp variable to see if it's NULL at least within the mp_init call. Alternatively, you could also allocate that structure within the mp_init routine and return a pointer to it or NULL on error.

The initialization is more complex than it needs to be. Rather than make repeated calls to mp_release and do all of that pointer manipulation, you could use this:

char *ptr;
for (ptr = mp->memory; --slots; ptr+=size) 
    *(void **)ptr = ptr+size;
*(void **)ptr = NULL;
mp->head = mp->memory;

mp_release

Within mp_release, there is no error checking. This might be OK if we're looking for extreme performance, but it might be nice to have at least a debug version that checks that mem actually points to a slot. For that to work, of course, you'll have to add at least one more variable to the structure to contain the size parameter.

mp_destroy

In mp_destroy it might be prudent to set mp->head = NULL so that any subsequent mp_get attempts will fail.

share|improve this answer
    
Wouldn't setting mp->head = NULL potentially hide a programmer's error? –  2013Asker May 4 '14 at 13:28
1  
@2013Asker: Rather than hiding the error, it seems to me that the proposed change would make such an error easier to find and it costs nearly nothing. –  Edward May 4 '14 at 13:40

The only addition I would make is:

int mp_init(Memory_Pool *mp, size_t size, size_t slots)
{
    if (size < MEMORY_POOL_MINIMUM_SIZE)
    {   return MEMORY_POOL_ERROR;
    }

But note: There is extra memoey being used.

typedef struct {
    void **head;
    void *memory;
} Memory_Pool;

You need space to store the above structure.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.