-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpool.c
137 lines (111 loc) · 2.72 KB
/
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "pool.h"
#include "stack.h"
#include "cell.h"
def_stack_container(cells, cell);
static inline void cells_add(cells* list, cell* nd)
{
sc_add(list, nd)
}
static inline cell* cells_pop(cells* list)
{
cell* save = NULL;
sc_get_pop(list, save);
return save;
}
struct pool_t
{
owned_block;
arena_t* chunk;
size_t segsize;
cells free_list;
};
size_t pool_sizeof(void)
{
return sizeof(pool_t) + arena_sizeof();
}
size_t cell_overhead_sizeof(void)
{
return cell_overhead_size;
}
size_t pool_available(pool_t* pool)
{
return get_len(&pool->free_list)+arena_capacity(pool->chunk)/pool->segsize;
}
unsigned pool_freeable(pool_t* pool)
{
return pool_available(pool) == arena_size(pool->chunk)/pool->segsize;
}
size_t pool_segsize(pool_t* pool)
{
return pool->segsize - cell_overhead_size;
}
pool_t* pool_new(malloc_impl* mallochook, size_t mem_size, size_t segsize, void* owner)
{
if(isnull(mallochook))
mallochook = malloc;
void* mem = mallochook(mem_size);
return pool_init(mem, mem_size, segsize, owner);
}
pool_t* pool_init(void* mem, size_t mem_size, size_t segsize, void* owner)
{
pool_t* pool = NULL;
arena_t* arena = NULL;
if(!isnull(mem))
{
pool = mem;
size_t used_memory = sizeof *pool;
used_memory += to_nearest_multiple(used_memory, granule_bytes);
arena = arena_init
((byteptr(mem)+used_memory), mem_size-used_memory, granule_bytes);
if(isnull(arena))
return NULL;
if(segsize <= granule_bytes)
segsize = sizeof(cell);
else
segsize = segsize + cell_overhead_size,
segsize += to_nearest_multiple(segsize, granule_bytes);
*pool = (pool_t){
owner, arena, segsize, sc_compound(cells, &pool->free_list, ),
};
}
return pool;
}
void* pool_pull(pool_t* pool)
{
void* payload = NULL;
cell* new_cell = NULL;
// printf("capacity: %zu, need: %zu\n",
// arena_capacity(pool->chunk), pool->segsize);
if(pool->segsize <= arena_capacity(pool->chunk))
new_cell = arena_malloc_quick(pool->chunk, pool->segsize),
cell_set_owner(new_cell, pool),
payload = new_cell->granules;
else if(get_len(&pool->free_list))
new_cell = cells_pop(&pool->free_list),
cell_set_owner(new_cell, pool),
payload = new_cell->granules;
return payload;
}
void* pool_pop_check(pool_t* pool, size_t n)
{
return n <= pool_segsize(pool)? pool_pull(pool): NULL;
}
void pool_push(pool_t* pool, void* payload)
{
cell* free_cell = canonic_ptr(payload);
cells_add(&pool->free_list, free_cell);
}
extern inline size_t payload_pool_segsize(void* payload)
{
cell* c = canonic_ptr(payload);
return pool_segsize((pool_t*)c->owner);
}
pool_t* payload_owner_pool(void* payload)
{
cell* c = canonic_ptr(payload);
return c->owner;
}
void payload_pushto_pool(void* payload)
{
pool_push(canonic_ptr(payload)->owner, payload);
}