-
Notifications
You must be signed in to change notification settings - Fork 41
/
generic_pool.c
120 lines (100 loc) · 4 KB
/
generic_pool.c
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
#include "generic_pool.h"
#include "utils/mathutils.h"
#include "ww.h"
#ifdef POOL_DEBUG
#include "loggers/network_logger.h"
#endif
#define GENERIC_POOL_DEFAULT_WIDTH ((unsigned long) ((RAM_PROFILE)))
static master_pool_item_t *poolCreateItemHandle(struct master_pool_s *pool, void *userdata)
{
(void) pool;
generic_pool_t *gpool = userdata;
if (gpool->item_size == 0)
{
return gpool->create_item_handle(gpool);
}
return globalMalloc(gpool->item_size);
}
static void poolDestroyItemHandle(struct master_pool_s *pool, master_pool_item_t *item, void *userdata)
{
(void) pool;
generic_pool_t *gpool = userdata;
if (gpool->item_size == 0)
{
gpool->destroy_item_handle(gpool, item);
}
else
{
globalFree(item);
}
}
void poolReCharge(generic_pool_t *pool)
{
const size_t increase = min((pool->cap - pool->len), (pool->cap) / 2);
popMasterPoolItems(pool->mp, (void const **) &(pool->available[pool->len]), increase,pool);
pool->len += increase;
#if defined(DEBUG) && defined(POOL_DEBUG)
hlogd("BufferPool: allocated %d new buffers, %zu are in use", increase, pool->in_use);
#endif
}
void poolShrink(generic_pool_t *pool)
{
const size_t decrease = (pool->len < (pool->cap / 2) ? pool->len : (pool->cap / 2));
reuseMasterPoolItems(pool->mp, &(pool->available[pool->len - decrease]), decrease,pool);
pool->len -= decrease;
#if defined(DEBUG) && defined(POOL_DEBUG)
hlogd("BufferPool: freed %d buffers, %zu are in use", decrease, pool->in_use);
#endif
}
static void poolFirstCharge(generic_pool_t *pool)
{
poolReCharge(pool);
}
static generic_pool_t *allocateGenericPool(struct master_pool_s *mp, unsigned int item_size, unsigned int pool_width,
PoolItemCreateHandle create_h, PoolItemDestroyHandle destroy_h)
{
pool_width = max(1, pool_width);
// half of the pool is used, other half is free at startup
pool_width = 2 * pool_width;
const unsigned long container_len = pool_width * sizeof(pool_item_t *);
generic_pool_t *pool_ptr = globalMalloc(sizeof(generic_pool_t) + container_len);
#ifdef DEBUG
memset(pool_ptr, 0xEB, sizeof(generic_pool_t) + container_len);
#endif
*pool_ptr = (generic_pool_t) {.cap = pool_width,
.free_threshold = max(pool_width / 2, (pool_width * 2) / 3),
.item_size = item_size,
.mp = mp,
.create_item_handle = create_h,
.destroy_item_handle = destroy_h};
installMasterPoolAllocCallbacks(pool_ptr->mp, poolCreateItemHandle, poolDestroyItemHandle);
// poolFirstCharge(pool_ptr);
return pool_ptr;
}
static pool_item_t *poolDefaultAllocator(struct generic_pool_s *pool)
{
return globalMalloc(pool->item_size);
}
static void poolDefaultDeallocator(struct generic_pool_s *pool, pool_item_t *item)
{
(void) pool;
globalFree(item);
}
generic_pool_t *newGenericPool(struct master_pool_s *mp, PoolItemCreateHandle create_h, PoolItemDestroyHandle destroy_h)
{
return allocateGenericPool(mp, 0, GENERIC_POOL_DEFAULT_WIDTH, create_h, destroy_h);
}
generic_pool_t *newGenericPoolWithCap(struct master_pool_s *mp, unsigned int pool_width, PoolItemCreateHandle create_h,
PoolItemDestroyHandle destroy_h)
{
return allocateGenericPool(mp, 0, pool_width, create_h, destroy_h);
}
generic_pool_t *newGenericPoolDefaultAllocator(struct master_pool_s *mp, unsigned int item_size)
{
return allocateGenericPool(mp, item_size, GENERIC_POOL_DEFAULT_WIDTH, poolDefaultAllocator, poolDefaultDeallocator);
}
generic_pool_t *newGenericPoolDefaultAllocatorWithCap(struct master_pool_s *mp, unsigned int item_size,
unsigned int pool_width)
{
return allocateGenericPool(mp, item_size, pool_width, poolDefaultAllocator, poolDefaultDeallocator);
}