mempool.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /*
  2. ** © 2009-2017 by Kornel Lesiński.
  3. ** © 1989, 1991 by Jef Poskanzer.
  4. ** © 1997, 2000, 2002 by Greg Roelofs; based on an idea by Stefan Schneider.
  5. **
  6. ** See COPYRIGHT file for license.
  7. */
  8. #include "libimagequant.h"
  9. #include "mempool.h"
  10. #include <stdlib.h>
  11. #include <stdint.h>
  12. #include <assert.h>
  13. #define ALIGN_MASK 15UL
  14. #define MEMPOOL_RESERVED ((sizeof(struct mempool)+ALIGN_MASK) & ~ALIGN_MASK)
  15. struct mempool {
  16. unsigned int used, size;
  17. void* (*malloc)(size_t);
  18. void (*free)(void*);
  19. struct mempool *next;
  20. };
  21. LIQ_PRIVATE void* mempool_create(mempoolptr *mptr, const unsigned int size, unsigned int max_size, void* (*malloc)(size_t), void (*free)(void*))
  22. {
  23. if (*mptr && ((*mptr)->used+size) <= (*mptr)->size) {
  24. unsigned int prevused = (*mptr)->used;
  25. (*mptr)->used += (size+15UL) & ~0xFUL;
  26. return ((char*)(*mptr)) + prevused;
  27. }
  28. mempoolptr old = *mptr;
  29. if (!max_size) max_size = (1<<17);
  30. max_size = size+ALIGN_MASK > max_size ? size+ALIGN_MASK : max_size;
  31. *mptr = malloc(MEMPOOL_RESERVED + max_size);
  32. if (!*mptr) return NULL;
  33. **mptr = (struct mempool){
  34. .malloc = malloc,
  35. .free = free,
  36. .size = MEMPOOL_RESERVED + max_size,
  37. .used = sizeof(struct mempool),
  38. .next = old,
  39. };
  40. uintptr_t mptr_used_start = (uintptr_t)(*mptr) + (*mptr)->used;
  41. (*mptr)->used += (ALIGN_MASK + 1 - (mptr_used_start & ALIGN_MASK)) & ALIGN_MASK; // reserve bytes required to make subsequent allocations aligned
  42. assert(!(((uintptr_t)(*mptr) + (*mptr)->used) & ALIGN_MASK));
  43. return mempool_alloc(mptr, size, size);
  44. }
  45. LIQ_PRIVATE void* mempool_alloc(mempoolptr *mptr, const unsigned int size, const unsigned int max_size)
  46. {
  47. if (((*mptr)->used+size) <= (*mptr)->size) {
  48. unsigned int prevused = (*mptr)->used;
  49. (*mptr)->used += (size + ALIGN_MASK) & ~ALIGN_MASK;
  50. return ((char*)(*mptr)) + prevused;
  51. }
  52. return mempool_create(mptr, size, max_size, (*mptr)->malloc, (*mptr)->free);
  53. }
  54. LIQ_PRIVATE void mempool_destroy(mempoolptr m)
  55. {
  56. while (m) {
  57. mempoolptr next = m->next;
  58. m->free(m);
  59. m = next;
  60. }
  61. }