ningshuxia
7 天以前 e372b432b52bedf58b7d3bd80bd679ae9c3cecb3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
 ******************************************************************************
 Project:      OWA EPANET
 Version:      2.2
 Module:       mempool.c
 Description:  a simple fast poooled memory allocation package
 Authors:      see AUTHORS
 Copyright:    see AUTHORS
 License:      see LICENSE
 Last Updated: 05/15/2019
 
 This module is based code by Steve Hill in Graphics Gems III,
 David Kirk (ed.), Academic Press, Boston, MA, 1992
 ******************************************************************************
*/
 
#include <stdlib.h>
 
#include "mempool.h"
 
/*
**  ALLOC_BLOCK_SIZE - adjust this size to suit your installation - it
**  should be reasonably large otherwise you will be mallocing a lot.
*/
 
#define ALLOC_BLOCK_SIZE   64000       /*(62*1024)*/
 
struct MemBlock
{
    struct MemBlock *next;   // Next block
    char            *block,  // Start of block
                    *free,   // Next free position in block
                    *end;    // block + block size
};
 
struct Mempool
{
    struct MemBlock *first;
    struct MemBlock *current;
};
 
static struct MemBlock* createMemBlock()
{
    struct MemBlock* memBlock = malloc(sizeof(struct MemBlock));
    if (memBlock)
    {
        memBlock->block = malloc(ALLOC_BLOCK_SIZE * sizeof(char));
        if (memBlock->block == NULL)
        {
            free(memBlock);
            return NULL;
        }
        memBlock->free = memBlock->block;
        memBlock->next = NULL;
        memBlock->end = memBlock->block + ALLOC_BLOCK_SIZE;
    }
    return memBlock;
}
 
 
static void deleteMemBlock(struct MemBlock* memBlock)
{
    free(memBlock->block);
    free(memBlock);
}
 
 
struct Mempool * mempool_create()
{
    struct Mempool *mempool;
    mempool = (struct Mempool *)malloc(sizeof(struct Mempool));
    if (mempool == NULL) return NULL;
    mempool->first = createMemBlock();
    mempool->current = mempool->first;
    if (mempool->first == NULL) return NULL;
    return mempool;
}
 
void mempool_delete(struct Mempool *mempool)
{
    if (mempool == NULL) return;
    while (mempool->first)
    {
        mempool->current = mempool->first->next;
        deleteMemBlock(mempool->first);
        mempool->first = mempool->current;
    }
    free(mempool);
    mempool = NULL;
}
 
void mempool_reset(struct Mempool *mempool)
{
    mempool->current = mempool->first;
    mempool->current->free = mempool->current->block;
}
 
 
char * mempool_alloc(struct Mempool *mempool, size_t size)
{
    char* ptr;
 
    /*
    **  Align to 4 byte boundary - should be ok for most machines.
    **  Change this if your machine has weird alignment requirements.
    */
    size = (size + 3) & 0xfffffffc;
 
    if (!mempool->current) return NULL;
    ptr = mempool->current->free;
    mempool->current->free += size;
 
    // Check if the current block is exhausted
 
    if (mempool->current->free >= mempool->current->end)
    {
        // Is the next block already allocated?
 
        if (mempool->current->next)
        {
            // re-use block
            mempool->current->next->free = mempool->current->next->block;
            mempool->current = mempool->current->next;
        }
        else
        {
            // extend the pool with a new block
            mempool->current->next = createMemBlock();
            if (!mempool->current->next) return NULL;
            mempool->current = mempool->current->next;
        }
 
        // set ptr to the first location in the next block
 
        ptr = mempool->current->free;
        mempool->current->free += size;
    }
 
    // Return pointer to allocated memory
 
    return ptr;
}