Simple memory pool using no extra memory












3












$begingroup$


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









$endgroup$

















    3












    $begingroup$


    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









    $endgroup$















      3












      3








      3


      1



      $begingroup$


      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









      $endgroup$




      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;
      }






      c memory-management






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked May 4 '14 at 11:06









      2013Asker2013Asker

      1,06421223




      1,06421223






















          2 Answers
          2






          active

          oldest

          votes


















          5












          $begingroup$

          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









          $endgroup$













          • $begingroup$
            Wouldn't setting mp->head = NULL potentially hide a programmer's error?
            $endgroup$
            – 2013Asker
            May 4 '14 at 13:28






          • 1




            $begingroup$
            @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.
            $endgroup$
            – Edward
            May 4 '14 at 13:40





















          2












          $begingroup$

          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.



          How it is implemented:



          A call to mp_init() allocated a chunk of memory. This chunk of memory is slots count number of items each of size size.



           // Lets examine this specific call:
          Memory_Pool memory;
          if (mp_init(&memory, sizeof(void*) * 4, 5) != MEMORY_POOL_SUCCESS)
          {
          exit(1);
          }


          if((mp->memory = malloc(size * slots)) == NULL)
          return MEMORY_POOL_ERROR;

          mp->head----->Random
          mp->memory---> ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********

          mp->head = NULL;

          mp->head-----|
          mp->memory---> ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********


          char *end = (char *)mp->memory + size * slots;

          mp->head-----|
          mp->memory----------->***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->

          for(char *ite = mp->memory; ite < end; ite += size)
          mp_release(mp, ite);

          // Iteration 1:
          mp->head----------------|
          /
          mp->memory----------->**( null )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->

          // Iteration 2:
          mp->memory----------->**( null )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 3:
          mp->memory----------->**( null )*
          * / *
          * | *
          * *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 4:
          mp->memory----------->**( null )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 5:
          mp->memory----------->**( null )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          char *end----------------->


          return MEMORY_POOL_SUCCESS;
          }





          share|improve this answer











          $endgroup$













          • $begingroup$
            can you explain how the node linking works? The OP was last seen 4 years ago. Why is the head **void and not just *void? Why in the release function, void* mem is being assigned to void** head. I can't seem to understand the underlying logic, thanks.
            $endgroup$
            – susdu
            7 hours ago












          • $begingroup$
            @susdu Hope the diagram helps.
            $endgroup$
            – Martin York
            6 mins ago











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f48919%2fsimple-memory-pool-using-no-extra-memory%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          5












          $begingroup$

          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









          $endgroup$













          • $begingroup$
            Wouldn't setting mp->head = NULL potentially hide a programmer's error?
            $endgroup$
            – 2013Asker
            May 4 '14 at 13:28






          • 1




            $begingroup$
            @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.
            $endgroup$
            – Edward
            May 4 '14 at 13:40


















          5












          $begingroup$

          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









          $endgroup$













          • $begingroup$
            Wouldn't setting mp->head = NULL potentially hide a programmer's error?
            $endgroup$
            – 2013Asker
            May 4 '14 at 13:28






          • 1




            $begingroup$
            @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.
            $endgroup$
            – Edward
            May 4 '14 at 13:40
















          5












          5








          5





          $begingroup$

          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









          $endgroup$



          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












          share|improve this answer



          share|improve this answer










          answered May 4 '14 at 12:38









          EdwardEdward

          47.5k378213




          47.5k378213












          • $begingroup$
            Wouldn't setting mp->head = NULL potentially hide a programmer's error?
            $endgroup$
            – 2013Asker
            May 4 '14 at 13:28






          • 1




            $begingroup$
            @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.
            $endgroup$
            – Edward
            May 4 '14 at 13:40




















          • $begingroup$
            Wouldn't setting mp->head = NULL potentially hide a programmer's error?
            $endgroup$
            – 2013Asker
            May 4 '14 at 13:28






          • 1




            $begingroup$
            @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.
            $endgroup$
            – Edward
            May 4 '14 at 13:40


















          $begingroup$
          Wouldn't setting mp->head = NULL potentially hide a programmer's error?
          $endgroup$
          – 2013Asker
          May 4 '14 at 13:28




          $begingroup$
          Wouldn't setting mp->head = NULL potentially hide a programmer's error?
          $endgroup$
          – 2013Asker
          May 4 '14 at 13:28




          1




          1




          $begingroup$
          @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.
          $endgroup$
          – Edward
          May 4 '14 at 13:40






          $begingroup$
          @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.
          $endgroup$
          – Edward
          May 4 '14 at 13:40















          2












          $begingroup$

          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.



          How it is implemented:



          A call to mp_init() allocated a chunk of memory. This chunk of memory is slots count number of items each of size size.



           // Lets examine this specific call:
          Memory_Pool memory;
          if (mp_init(&memory, sizeof(void*) * 4, 5) != MEMORY_POOL_SUCCESS)
          {
          exit(1);
          }


          if((mp->memory = malloc(size * slots)) == NULL)
          return MEMORY_POOL_ERROR;

          mp->head----->Random
          mp->memory---> ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********

          mp->head = NULL;

          mp->head-----|
          mp->memory---> ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********


          char *end = (char *)mp->memory + size * slots;

          mp->head-----|
          mp->memory----------->***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->

          for(char *ite = mp->memory; ite < end; ite += size)
          mp_release(mp, ite);

          // Iteration 1:
          mp->head----------------|
          /
          mp->memory----------->**( null )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->

          // Iteration 2:
          mp->memory----------->**( null )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 3:
          mp->memory----------->**( null )*
          * / *
          * | *
          * *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 4:
          mp->memory----------->**( null )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 5:
          mp->memory----------->**( null )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          char *end----------------->


          return MEMORY_POOL_SUCCESS;
          }





          share|improve this answer











          $endgroup$













          • $begingroup$
            can you explain how the node linking works? The OP was last seen 4 years ago. Why is the head **void and not just *void? Why in the release function, void* mem is being assigned to void** head. I can't seem to understand the underlying logic, thanks.
            $endgroup$
            – susdu
            7 hours ago












          • $begingroup$
            @susdu Hope the diagram helps.
            $endgroup$
            – Martin York
            6 mins ago
















          2












          $begingroup$

          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.



          How it is implemented:



          A call to mp_init() allocated a chunk of memory. This chunk of memory is slots count number of items each of size size.



           // Lets examine this specific call:
          Memory_Pool memory;
          if (mp_init(&memory, sizeof(void*) * 4, 5) != MEMORY_POOL_SUCCESS)
          {
          exit(1);
          }


          if((mp->memory = malloc(size * slots)) == NULL)
          return MEMORY_POOL_ERROR;

          mp->head----->Random
          mp->memory---> ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********

          mp->head = NULL;

          mp->head-----|
          mp->memory---> ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********


          char *end = (char *)mp->memory + size * slots;

          mp->head-----|
          mp->memory----------->***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->

          for(char *ite = mp->memory; ite < end; ite += size)
          mp_release(mp, ite);

          // Iteration 1:
          mp->head----------------|
          /
          mp->memory----------->**( null )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->

          // Iteration 2:
          mp->memory----------->**( null )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 3:
          mp->memory----------->**( null )*
          * / *
          * | *
          * *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 4:
          mp->memory----------->**( null )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 5:
          mp->memory----------->**( null )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          char *end----------------->


          return MEMORY_POOL_SUCCESS;
          }





          share|improve this answer











          $endgroup$













          • $begingroup$
            can you explain how the node linking works? The OP was last seen 4 years ago. Why is the head **void and not just *void? Why in the release function, void* mem is being assigned to void** head. I can't seem to understand the underlying logic, thanks.
            $endgroup$
            – susdu
            7 hours ago












          • $begingroup$
            @susdu Hope the diagram helps.
            $endgroup$
            – Martin York
            6 mins ago














          2












          2








          2





          $begingroup$

          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.



          How it is implemented:



          A call to mp_init() allocated a chunk of memory. This chunk of memory is slots count number of items each of size size.



           // Lets examine this specific call:
          Memory_Pool memory;
          if (mp_init(&memory, sizeof(void*) * 4, 5) != MEMORY_POOL_SUCCESS)
          {
          exit(1);
          }


          if((mp->memory = malloc(size * slots)) == NULL)
          return MEMORY_POOL_ERROR;

          mp->head----->Random
          mp->memory---> ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********

          mp->head = NULL;

          mp->head-----|
          mp->memory---> ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********


          char *end = (char *)mp->memory + size * slots;

          mp->head-----|
          mp->memory----------->***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->

          for(char *ite = mp->memory; ite < end; ite += size)
          mp_release(mp, ite);

          // Iteration 1:
          mp->head----------------|
          /
          mp->memory----------->**( null )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->

          // Iteration 2:
          mp->memory----------->**( null )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 3:
          mp->memory----------->**( null )*
          * / *
          * | *
          * *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 4:
          mp->memory----------->**( null )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 5:
          mp->memory----------->**( null )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          char *end----------------->


          return MEMORY_POOL_SUCCESS;
          }





          share|improve this answer











          $endgroup$



          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.



          How it is implemented:



          A call to mp_init() allocated a chunk of memory. This chunk of memory is slots count number of items each of size size.



           // Lets examine this specific call:
          Memory_Pool memory;
          if (mp_init(&memory, sizeof(void*) * 4, 5) != MEMORY_POOL_SUCCESS)
          {
          exit(1);
          }


          if((mp->memory = malloc(size * slots)) == NULL)
          return MEMORY_POOL_ERROR;

          mp->head----->Random
          mp->memory---> ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********

          mp->head = NULL;

          mp->head-----|
          mp->memory---> ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********


          char *end = (char *)mp->memory + size * slots;

          mp->head-----|
          mp->memory----------->***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->

          for(char *ite = mp->memory; ite < end; ite += size)
          mp_release(mp, ite);

          // Iteration 1:
          mp->head----------------|
          /
          mp->memory----------->**( null )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->

          // Iteration 2:
          mp->memory----------->**( null )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 3:
          mp->memory----------->**( null )*
          * / *
          * | *
          * *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 4:
          mp->memory----------->**( null )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          * *
          * *
          * *
          * *
          ***********
          char *end----------------->
          // Iteration 5:
          mp->memory----------->**( null )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          * | *
          * | *
          **( * )*
          * / *
          * | *
          mp->head--------------*-| | *
          * / | *
          **( * )*
          char *end----------------->


          return MEMORY_POOL_SUCCESS;
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 6 mins ago

























          answered May 4 '14 at 11:38









          Martin YorkMartin York

          73.8k488271




          73.8k488271












          • $begingroup$
            can you explain how the node linking works? The OP was last seen 4 years ago. Why is the head **void and not just *void? Why in the release function, void* mem is being assigned to void** head. I can't seem to understand the underlying logic, thanks.
            $endgroup$
            – susdu
            7 hours ago












          • $begingroup$
            @susdu Hope the diagram helps.
            $endgroup$
            – Martin York
            6 mins ago


















          • $begingroup$
            can you explain how the node linking works? The OP was last seen 4 years ago. Why is the head **void and not just *void? Why in the release function, void* mem is being assigned to void** head. I can't seem to understand the underlying logic, thanks.
            $endgroup$
            – susdu
            7 hours ago












          • $begingroup$
            @susdu Hope the diagram helps.
            $endgroup$
            – Martin York
            6 mins ago
















          $begingroup$
          can you explain how the node linking works? The OP was last seen 4 years ago. Why is the head **void and not just *void? Why in the release function, void* mem is being assigned to void** head. I can't seem to understand the underlying logic, thanks.
          $endgroup$
          – susdu
          7 hours ago






          $begingroup$
          can you explain how the node linking works? The OP was last seen 4 years ago. Why is the head **void and not just *void? Why in the release function, void* mem is being assigned to void** head. I can't seem to understand the underlying logic, thanks.
          $endgroup$
          – susdu
          7 hours ago














          $begingroup$
          @susdu Hope the diagram helps.
          $endgroup$
          – Martin York
          6 mins ago




          $begingroup$
          @susdu Hope the diagram helps.
          $endgroup$
          – Martin York
          6 mins ago


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f48919%2fsimple-memory-pool-using-no-extra-memory%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Сан-Квентин

          8-я гвардейская общевойсковая армия

          Алькесар