blob: f9197703f675e09c96ab8c5242c9a318692c7837 (
plain)
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
|
#include "memory.hpp"
struct pke::MemBucket {
int64_t size;
int64_t head;
int64_t free;
int64_t allocs;
bool transient;
char * ptr;
};
pke::MemBucket buckets[128];
int64_t bucketHead = 0;
int64_t InitNewBucket(int64_t sz, bool transient = false) {
buckets[bucketHead].size = sz;
buckets[bucketHead].head = 0;
buckets[bucketHead].free = 0;
buckets[bucketHead].allocs = 0;
buckets[bucketHead].transient = transient;
buckets[bucketHead].ptr = reinterpret_cast<char *>(std::malloc(sz));
return bucketHead++;
}
void DestroyBucket(pke::MemBucket *bkt) {
std::free(bkt->ptr);
bkt->size = 0;
bkt->head = 0;
bkt->free = 0;
bkt->allocs = 0;
bkt->transient = false;
bkt->ptr = CAFE_BABE(char);
}
void *pke::PkeNew(std::size_t sz, pke::MemBucket *bkt) {
void *ptr = bkt->ptr + bkt->head;
bkt->head += sz;
bkt->allocs++;
return ptr;
}
void *pke::PkeNew(std::size_t sz) {
MemBucket *bkt = nullptr;
for (long i = 0; i < bucketHead; ++i) {
if (buckets[i].transient == false && buckets[i].size - buckets[i].head > sz) {
bkt = &buckets[i];
}
}
if (bkt == nullptr) {
bkt = &buckets[InitNewBucket(DEFAULT_BUCKET_SIZE)];
}
return PkeNew(sz, bkt);
}
void pke::PkeDelete(const void *ptr, std::size_t sz, pke::MemBucket *bkt) {
assert(ptr >= bkt->ptr && ptr < bkt->ptr + bkt->size && "pointer not in bucket range");
bkt->allocs--;
bkt->free += sz;
if (ptr == bkt->ptr + bkt->head - sz) bkt->head -= sz;
if (bkt->allocs == 0) {
bkt->head = 0;
bkt->free = 0;
}
}
void pke::PkeDelete(const void *ptr, std::size_t sz) {
pke::MemBucket *bkt = nullptr;
for (long i = 0; i < bucketHead; ++i) {
bkt = &buckets[i];
if (ptr >= bkt->ptr && ptr < bkt->ptr + bkt->size) break;
}
if (bkt == nullptr) {
std::printf("bad pointer %llu", reinterpret_cast<unsigned long long>(ptr));
throw "bad pointer";
}
PkeDelete(ptr, sz, bkt);
}
pke::MemBucket *pke::BeginTransientBucket(int64_t sz) {
return &buckets[InitNewBucket(sz, true)];
}
void pke::EndTransientBucket(pke::MemBucket *bkt) {
int64_t foundIndex = -1;
for (int64_t i = 0; i < bucketHead; ++i) {
if (&buckets[i] == bkt) {
foundIndex = i;
DestroyBucket(&buckets[i]);
break;
}
}
if (foundIndex == bucketHead) {
bucketHead--;
}
}
void pke::Flush() {
for (long i = bucketHead - 2; i > -1; --i) {
if (buckets[i].head != 0) break;
if (buckets[i+1].head != 0) break;
if (buckets[i].transient == true) break;
if (buckets[i+1].transient == true) break;
bucketHead--;
DestroyBucket(&buckets[i + 1]);
}
}
|