-
Notifications
You must be signed in to change notification settings - Fork 1
/
memory_utils.hpp
149 lines (120 loc) · 3.84 KB
/
memory_utils.hpp
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
138
139
140
141
142
143
144
145
146
147
148
149
// [genius_naming][nolint]
//#pragma once
#include <cstdio>
#include <tuple>
#include <memory>
#include <cstdlib>
struct MemoryManager {
static size_t type_new_allocated;
static size_t type_new_deleted;
static size_t allocator_allocated;
static size_t allocator_deallocated;
static size_t allocator_constructed;
static size_t allocator_destroyed;
static void TypeNewAllocate(size_t n) {
type_new_allocated += n;
}
static void TypeNewDelete(size_t n) {
type_new_deleted += n;
}
static void AllocatorAllocate(size_t n) {
allocator_allocated += n;
}
static void AllocatorDeallocate(size_t n) {
allocator_deallocated += n;
}
static void AllocatorConstruct(size_t n) {
allocator_constructed += n;
}
static void AllocatorDestroy(size_t n) {
allocator_destroyed += n;
}
};
void* operator new(size_t n, bool from_my_allocator ) {
(void)from_my_allocator;
return malloc(n);
}
void operator delete(void* ptr, size_t n, bool from_my_allocator) noexcept {
(void)n;
(void)from_my_allocator;
free(ptr);
}
template <typename T>
struct AllocatorWithCount {
using value_type = T;
AllocatorWithCount() = default;
template <typename U>
AllocatorWithCount(const AllocatorWithCount<U>& other) {
std::ignore = other;
}
T* allocate(size_t n) {
MemoryManager::AllocatorAllocate(n * sizeof(T));
allocator_allocated += n * sizeof(T);
return reinterpret_cast<T*>(operator new(n * sizeof(T), true));
}
void deallocate(T* ptr, size_t n) {
MemoryManager::AllocatorDeallocate(n * sizeof(T));
allocator_deallocated += n * sizeof(T);
operator delete(ptr, n, true);
}
template <typename U, typename... Args>
void construct(U* ptr, Args&&... args) {
MemoryManager::AllocatorConstruct(1);
allocator_constructed += 1;
::new(ptr) U(std::forward<Args>(args)...);
}
template <typename U>
void destroy(U* ptr) noexcept {
MemoryManager::AllocatorDestroy(1);
allocator_destroyed += 1;
ptr->~U();
}
size_t allocator_allocated = 0;
size_t allocator_deallocated = 0;
size_t allocator_constructed = 0;
size_t allocator_destroyed = 0;
};
template <typename T>
bool operator==(const AllocatorWithCount<T>& lhs, const AllocatorWithCount<T>& rhs) {
return lhs.allocator_allocated == rhs.allocator_allocated &&
lhs.allocator_deallocated == rhs.allocator_deallocated &&
lhs.allocator_constructed == rhs.allocator_constructed &&
lhs.allocator_destroyed == rhs.allocator_destroyed;
}
template <typename T, bool PropagateOnConstruct, bool PropagateOnAssign>
struct WhimsicalAllocator : public std::allocator<T> {
std::shared_ptr<int> number;
auto select_on_container_copy_construction() const {
return PropagateOnConstruct
? WhimsicalAllocator<T, PropagateOnConstruct, PropagateOnAssign>()
: *this;
}
struct propagate_on_container_copy_assignment
: std::conditional_t<PropagateOnAssign, std::true_type, std::false_type>
{};
template <typename U>
struct rebind {
using other = WhimsicalAllocator<U, PropagateOnConstruct, PropagateOnAssign>;
};
WhimsicalAllocator(): number(std::make_shared<int>(counter)) {
++counter;
}
template <typename U>
WhimsicalAllocator(const WhimsicalAllocator<U, PropagateOnConstruct, PropagateOnAssign>& another)
: number(another.number)
{}
template <typename U>
auto& operator=(const WhimsicalAllocator<U, PropagateOnConstruct, PropagateOnAssign>& another) {
number = another.number;
return *this;
}
template <typename U>
bool operator==(const WhimsicalAllocator<U, PropagateOnConstruct, PropagateOnAssign>& another) const {
return *number == *another.number;
}
template <typename U>
bool operator!=(const WhimsicalAllocator<U, PropagateOnConstruct, PropagateOnAssign>& another) const {
return *number != *another.number;
}
static size_t counter;
};