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
|
#include "memory.hpp"
struct MemBucket {
int64_t size;
int64_t head;
int64_t free;
int64_t allocs;
bool transient;
char * ptr;
};
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(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_New(std::size_t sz, MemBucket *bkt) {
void *ptr = bkt->ptr + bkt->head;
bkt->head += sz;
bkt->allocs++;
return ptr;
}
void *Pke_New(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 Pke_New(sz, bkt);
}
void Pke_Delete(const void *ptr, std::size_t sz, 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_Delete(const void *ptr, std::size_t sz) {
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";
}
Pke_Delete(ptr, sz, bkt);
}
MemBucket *BeginTransientBucket(int64_t sz) {
return &buckets[InitNewBucket(sz, true)];
}
void EndTransientBucket(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 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]);
}
}
uint64_t Buckets_NewHandle(std::size_t bucketBytes, uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, void*& buckets) {
uint64_t newHandle{itemCounter | bucketCounter};
itemCounter += uint64_t{1ULL << 32};
if (itemCounter > uint64_t{(bucketItemCount - 1) << 32}) {
itemCounter = 0ULL;
bucketCounter += 1;
}
if (bucketCounter > bucketIncrementer) {
int64_t newIncrement = bucketIncrementer * 1.5;
char * newBuckets = reinterpret_cast<char *>(Pke_New(bucketBytes * newIncrement));
std::memcpy(newBuckets, buckets, bucketBytes * bucketIncrementer);
Pke_Delete(buckets, bucketBytes * bucketIncrementer);
buckets = newBuckets;
bucketIncrementer = newIncrement;
}
return newHandle;
}
|