oceanbase

Форк
0
/
easy_pool.c 
250 строк · 5.7 Кб
1
#include "util/easy_pool.h"
2
#include "io/easy_log.h"
3
#include "util/easy_mod_stat.h"
4
#include <assert.h>
5
#include <stdio.h>
6

7
/**
8
 * 简单的内存池
9
 */
10

11
static void *easy_pool_alloc_block(easy_pool_t *pool, uint32_t size);
12
static void *easy_pool_alloc_large(easy_pool_t *pool, easy_pool_large_t *large, uint32_t size);
13
easy_pool_realloc_pt    easy_pool_realloc = easy_pool_default_realloc;
14
#define EASY_POOL_LOCK(pool) int kcolt = pool->flags; if (unlikely(kcolt)) easy_spin_lock(&pool->tlock);
15
#define EASY_POOL_UNLOCK(pool) if (unlikely(kcolt)) easy_spin_unlock(&pool->tlock);
16

17
easy_pool_t *easy_pool_create(uint32_t size)
18
{
19
    easy_pool_t             *p;
20

21
    // 对齐
22
    size = easy_align(size + sizeof(easy_pool_t), EASY_POOL_ALIGNMENT);
23

24
    if ((p = (easy_pool_t *)easy_pool_realloc(NULL, size)) == NULL)
25
        return NULL;
26

27
    memset(p, 0, sizeof(easy_pool_t));
28
    p->last = (uint8_t *) p + sizeof(easy_pool_t);
29
    p->end = (uint8_t *) p + size;
30
    p->max = size - sizeof(easy_pool_t);
31
    p->current = p;
32
    p->mod_stat = easy_cur_mod_stat;
33
#ifdef EASY_DEBUG_MAGIC
34
    p->magic = EASY_DEBUG_MAGIC_POOL;
35
#endif
36

37
    return p;
38
}
39

40
// clear
41
void easy_pool_clear(easy_pool_t *pool)
42
{
43
    easy_pool_t             *p, *n;
44
    easy_pool_large_t       *l;
45
    easy_pool_cleanup_t     *cl;
46

47
    // cleanup
48
    for (cl = pool->cleanup; cl; cl = cl->next) {
49
        if (cl->handler)(*cl->handler)(cl->data);
50
    }
51

52
    // large
53
    for (l = pool->large; l; l = l->next) {
54
        easy_pool_realloc(l->data, 0);
55
    }
56

57
    // other page
58
    for (p = pool->next; p; p = n) {
59
        n = p->next;
60
        easy_pool_realloc(p, 0);
61
    }
62

63
    pool->cleanup = NULL;
64
    pool->large = NULL;
65
    pool->next = NULL;
66
    pool->current = pool;
67
    pool->failed = 0;
68
    pool->last = (uint8_t *) pool + sizeof(easy_pool_t);
69
}
70

71
void easy_pool_destroy(easy_pool_t *pool)
72
{
73
    EASY_STAT_TIME_GUARD(ev_malloc_count, ev_malloc_time);
74
    easy_pool_clear(pool);
75
    assert(pool->ref == 0);
76
#ifdef EASY_DEBUG_MAGIC
77
    pool->magic ++;
78
#endif
79
    easy_pool_realloc(pool, 0);
80
}
81

82
void *easy_pool_alloc_ex(easy_pool_t *pool, uint32_t size, int align)
83
{
84
    EASY_STAT_TIME_GUARD_WITH_SIZE(ev_malloc_count, ev_malloc_time, size);
85
    uint8_t                 *m;
86
    easy_pool_t             *p;
87
    int                     dsize;
88

89
    // init
90
    dsize = 0;
91

92
    if (size > pool->max) {
93
        dsize = size;
94
        size = sizeof(easy_pool_large_t);
95
    }
96

97
    EASY_POOL_LOCK(pool);
98

99
    p = pool->current;
100

101
    do {
102
        m = easy_align_ptr(p->last, align);
103

104
        if (m + size <= p->end) {
105
            p->last = m + size;
106
            break;
107
        }
108

109
        p = p->next;
110
    } while (p);
111

112
    easy_cur_mod_stat = pool->mod_stat;
113
    // 重新分配一块出来
114
    if (p == NULL) {
115
        m = (uint8_t *)easy_pool_alloc_block(pool, size);
116
    }
117

118
    if (m && dsize) {
119
        m = (uint8_t *)easy_pool_alloc_large(pool, (easy_pool_large_t *)m, dsize);
120
    }
121
    easy_cur_mod_stat = NULL;
122

123
    EASY_POOL_UNLOCK(pool);
124

125
    return m;
126
}
127

128
void *easy_pool_calloc(easy_pool_t *pool, uint32_t size)
129
{
130
    void                    *p;
131

132
    if ((p = easy_pool_alloc_ex(pool, size, sizeof(long))) != NULL)
133
        memset(p, 0, size);
134

135
    return p;
136
}
137

138
// set lock
139
void easy_pool_set_lock(easy_pool_t *pool)
140
{
141
    pool->flags = 1;
142
}
143

144
// set realloc
145
void easy_pool_set_allocator(easy_pool_realloc_pt alloc)
146
{
147
    easy_pool_realloc = (alloc ? alloc : easy_pool_default_realloc);
148
    realloc_lowlevel = easy_pool_realloc;
149
    easy_pool_realloc = realloc_with_mod_stat;
150
}
151

152
void *easy_pool_default_realloc(void *ptr, size_t size)
153
{
154
    if (size) {
155
        return realloc(ptr, size);
156
    } else if (ptr) {
157
        free(ptr);
158
    }
159

160
    return 0;
161
}
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163
// default realloc
164

165
static void *easy_pool_alloc_block(easy_pool_t *pool, uint32_t size)
166
{
167
    uint8_t                 *m;
168
    uint32_t                psize;
169
    easy_pool_t             *p, *newpool, *current;
170

171
    psize = (uint32_t)(pool->end - (uint8_t *) pool);
172

173
    if ((m = (uint8_t *)easy_pool_realloc(NULL, psize)) == NULL)
174
        return NULL;
175

176
    newpool = (easy_pool_t *) m;
177
    newpool->end = m + psize;
178
    newpool->next = NULL;
179
    newpool->failed = 0;
180

181
    m += offsetof(easy_pool_t, current);
182
    m = easy_align_ptr(m, sizeof(unsigned long));
183
    newpool->last = m + size;
184
    current = pool->current;
185

186
    if (NULL != current) {
187
        for (p = current; p->next; p = p->next) {
188
            if (p->failed++ > 4) {
189
                current = p->next;
190
            }
191
        }
192
        p->next = newpool;
193
    }
194

195
    pool->current = current ? current : newpool;
196

197
    return m;
198
}
199

200
static void *easy_pool_alloc_large(easy_pool_t *pool, easy_pool_large_t *large, uint32_t size)
201
{
202
    if ((large->data = (uint8_t *)easy_pool_realloc(NULL, size)) == NULL)
203
        return NULL;
204

205
    large->next = pool->large;
206
    large->size = size;
207
    pool->large = large;
208
    return large->data;
209
}
210

211
/**
212
 * strdup
213
 */
214
char *easy_pool_strdup(easy_pool_t *pool, const char *str)
215
{
216
    int                     sz;
217
    char                    *ptr;
218

219
    if (str == NULL)
220
        return NULL;
221

222
    sz = strlen(str) + 1;
223

224
    if ((ptr = (char *)easy_pool_alloc(pool, sz)) == NULL)
225
        return NULL;
226

227
    memcpy(ptr, str, sz);
228
    return ptr;
229
}
230

231
easy_pool_cleanup_t *easy_pool_cleanup_new(easy_pool_t *pool, const void *data, easy_pool_cleanup_pt *handler)
232
{
233
    easy_pool_cleanup_t *cl;
234
    cl = easy_pool_alloc(pool, sizeof(easy_pool_cleanup_t));
235

236
    if (cl) {
237
        cl->handler = handler;
238
        cl->data = data;
239
    }
240

241
    return cl;
242
}
243

244
void easy_pool_cleanup_reg(easy_pool_t *pool, easy_pool_cleanup_t *cl)
245
{
246
    EASY_POOL_LOCK(pool);
247
    cl->next = pool->cleanup;
248
    pool->cleanup = cl;
249
    EASY_POOL_UNLOCK(pool);
250
}
251

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.