Skip to content

Commit 282f533

Browse files
Add more implementations
1 parent 6a81c8d commit 282f533

File tree

15 files changed

+1128
-18
lines changed

15 files changed

+1128
-18
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
test:
2+
gcc -g test.c pool.c -o test
3+
4+
clean:
5+
rm -rf test *.o
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
## Generic Memory Pool Implementation
2+
3+
[A generic C memory pool implementation](https://github.com/jobtalle/pool)
4+
5+
### Important Data structure
6+
7+
```c
8+
/*
9+
This is the linked list data structure that keeps track of
10+
free memory blocks in the pool.
11+
*/
12+
typedef struct poolFreed{
13+
struct poolFreed *nextFree;
14+
} poolFreed;
15+
16+
/*
17+
The memory pool data structure that contains metadata about the pool
18+
and maintain a list of free blocks to be allocated.
19+
*/
20+
typedef struct {
21+
uint32_t elementSize;
22+
uint32_t blockSize;
23+
uint32_t used;
24+
int32_t block;
25+
poolFreed *freed;
26+
uint32_t blocksUsed;
27+
uint8_t **blocks;
28+
} pool;
29+
```
30+
31+
### Pool Implementation
32+
33+
```c
34+
35+
#ifndef max
36+
#define max(a,b) ((a)<(b)?(b):(a))
37+
#endif
38+
39+
/*
40+
Pool Initialization function
41+
*/
42+
void poolInitialize(pool *p, const uint32_t elementSize, const uint32_t blockSize)
43+
{
44+
uint32_t i;
45+
46+
p->elementSize = max(elementSize, sizeof(poolFreed));
47+
p->blockSize = blockSize;
48+
49+
// Clear the pool before any usage
50+
poolFreeAll(p);
51+
52+
p->blocksUsed = POOL_BLOCKS_INITIAL; // 1
53+
p->blocks = malloc(sizeof(uint8_t*) * p->blocksUsed);
54+
55+
for(i = 0; i < p->blocksUsed; ++i)
56+
p->blocks[i] = NULL;
57+
}
58+
59+
void poolFreePool(pool *p)
60+
{
61+
uint32_t i;
62+
for(i = 0; i < p->blocksUsed; ++i) {
63+
if(p->blocks[i] == NULL)
64+
break;
65+
else
66+
free(p->blocks[i]);
67+
}
68+
69+
free(p->blocks);
70+
}
71+
72+
#ifndef DISABLE_MEMORY_POOLING
73+
void *poolMalloc(pool *p)
74+
{
75+
if(p->freed != NULL) {
76+
void *recycle = p->freed;
77+
p->freed = p->freed->nextFree;
78+
return recycle;
79+
}
80+
81+
if(++p->used == p->blockSize) {
82+
p->used = 0;
83+
if(++p->block == (int32_t)p->blocksUsed) {
84+
uint32_t i;
85+
86+
p->blocksUsed <<= 1;
87+
p->blocks = realloc(p->blocks, sizeof(uint8_t*)* p->blocksUsed);
88+
89+
for(i = p->blocksUsed >> 1; i < p->blocksUsed; ++i)
90+
p->blocks[i] = NULL;
91+
}
92+
93+
if(p->blocks[p->block] == NULL)
94+
p->blocks[p->block] = malloc(p->elementSize * p->blockSize);
95+
}
96+
97+
return p->blocks[p->block] + p->used * p->elementSize;
98+
}
99+
100+
void poolFree(pool *p, void *ptr)
101+
{
102+
poolFreed *pFreed = p->freed;
103+
104+
// Insert the free block to the head of the free list
105+
p->freed = ptr;
106+
p->freed->nextFree = pFreed;
107+
}
108+
#endif
109+
110+
void poolFreeAll(pool *p)
111+
{
112+
p->used = p->blockSize - 1;
113+
p->block = -1;
114+
p->freed = NULL;
115+
}
116+
```
117+
118+
### Advance Reading
119+
120+
[Writing a Pool Allocator I](http://dmitrysoshnikov.com/compilers/writing-a-memory-allocator/)
121+
122+
[Writing a Pool Allocator II](http://dmitrysoshnikov.com/compilers/writing-a-pool-allocator/)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#include <string.h>
2+
#include <stdlib.h>
3+
4+
#include "pool.h"
5+
6+
#ifndef max
7+
#define max(a,b) ((a)<(b)?(b):(a))
8+
#endif
9+
10+
void poolInitialize(pool *p, const uint32_t elementSize, const uint32_t blockSize)
11+
{
12+
uint32_t i;
13+
14+
p->elementSize = max(elementSize, sizeof(poolFreed));
15+
p->blockSize = blockSize;
16+
17+
poolFreeAll(p);
18+
19+
p->blocksUsed = POOL_BLOCKS_INITIAL;
20+
p->blocks = malloc(sizeof(uint8_t*)* p->blocksUsed);
21+
22+
for(i = 0; i < p->blocksUsed; ++i)
23+
p->blocks[i] = NULL;
24+
}
25+
26+
void poolFreePool(pool *p)
27+
{
28+
uint32_t i;
29+
for(i = 0; i < p->blocksUsed; ++i) {
30+
if(p->blocks[i] == NULL)
31+
break;
32+
else
33+
free(p->blocks[i]);
34+
}
35+
36+
free(p->blocks);
37+
}
38+
39+
#ifndef DISABLE_MEMORY_POOLING
40+
void *poolMalloc(pool *p)
41+
{
42+
if(p->freed != NULL) {
43+
void *recycle = p->freed;
44+
p->freed = p->freed->nextFree;
45+
return recycle;
46+
}
47+
48+
if(++p->used == p->blockSize) {
49+
p->used = 0;
50+
if(++p->block == (int32_t)p->blocksUsed) {
51+
uint32_t i;
52+
53+
p->blocksUsed <<= 1;
54+
p->blocks = realloc(p->blocks, sizeof(uint8_t*)* p->blocksUsed);
55+
56+
for(i = p->blocksUsed >> 1; i < p->blocksUsed; ++i)
57+
p->blocks[i] = NULL;
58+
}
59+
60+
if(p->blocks[p->block] == NULL)
61+
p->blocks[p->block] = malloc(p->elementSize * p->blockSize);
62+
}
63+
64+
return p->blocks[p->block] + p->used * p->elementSize;
65+
}
66+
67+
void poolFree(pool *p, void *ptr)
68+
{
69+
poolFreed *pFreed = p->freed;
70+
71+
p->freed = ptr;
72+
p->freed->nextFree = pFreed;
73+
}
74+
#endif
75+
76+
void poolFreeAll(pool *p)
77+
{
78+
p->used = p->blockSize - 1;
79+
p->block = -1;
80+
p->freed = NULL;
81+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
5+
#define POOL_BLOCKS_INITIAL 1
6+
7+
typedef struct poolFreed{
8+
struct poolFreed *nextFree;
9+
} poolFreed;
10+
11+
typedef struct {
12+
uint32_t elementSize;
13+
uint32_t blockSize;
14+
uint32_t used;
15+
int32_t block;
16+
poolFreed *freed;
17+
uint32_t blocksUsed;
18+
uint8_t **blocks;
19+
} pool;
20+
21+
void poolInitialize(pool *p, const uint32_t elementSize, const uint32_t blockSize);
22+
void poolFreePool(pool *p);
23+
24+
#ifndef DISABLE_MEMORY_POOLING
25+
void *poolMalloc(pool *p);
26+
void poolFree(pool *p, void *ptr);
27+
#else
28+
#include <stdlib.h>
29+
#define poolMalloc(p) malloc((p)->blockSize)
30+
#define poolFree(p, d) free(d)
31+
#endif
32+
void poolFreeAll(pool *p);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include "pool.h"
4+
5+
#define SUCCESS 0
6+
#define FAILURE -1
7+
8+
int test_pool(int element_size, int block_size)
9+
{
10+
pool pool_ptr;
11+
int *test_ptr1 = NULL;
12+
int *test_ptr2 = NULL;
13+
14+
/* init memory pool with given parameters */
15+
poolInitialize(&pool_ptr, element_size, block_size);
16+
17+
/* allocate memory from memory pool */
18+
test_ptr1 = poolMalloc(&pool_ptr);
19+
test_ptr2 = poolMalloc(&pool_ptr);
20+
21+
/* test allocated memory validity */
22+
if(!(test_ptr1 && test_ptr2))
23+
{
24+
printf("memory allocation failure \n");
25+
26+
return FAILURE;
27+
}
28+
29+
/* free memory allocated from memory pool */
30+
poolFree(&pool_ptr, test_ptr1);
31+
32+
/* free all memory used by this pool */
33+
poolFreePool(&pool_ptr);
34+
35+
return SUCCESS;
36+
}
37+
38+
int main()
39+
{
40+
if(test_pool(4, 8) == FAILURE)
41+
printf("test_pool failure %s %d \n", __FILE__, __LINE__);
42+
43+
if(test_pool(8, 8) == FAILURE)
44+
printf("test_pool failure %s %d \n", __FILE__, __LINE__);
45+
46+
if(test_pool(16, 8) == FAILURE)
47+
printf("test_pool failure %s %d \n", __FILE__, __LINE__);
48+
49+
if(test_pool(32, 8) == FAILURE)
50+
printf("test_pool failure %s %d \n", __FILE__, __LINE__);
51+
52+
53+
return SUCCESS;
54+
}

0 commit comments

Comments
 (0)