1 //
2 // Created by whg on 2020/8/25.
3 //
4 #pragma once
5 #include <utility>
6 #include <memory>
7 #include <vector>
8 #include <chrono>
9
10 namespace typany {
11 namespace ObjectPool {
12
13 inline int64_t GetCurrentTimeStamp() {
14 std::chrono::time_point<std::chrono::system_clock> current = std::chrono::system_clock::now();
15 auto stamp = std::chrono::duration_cast<std::chrono::milliseconds>(current.time_since_epoch());
16 return stamp.count();
17 }
18
19 template <typename T, size_t ChunkMaxBlockSize = 128, std::int64_t MaxAccessIntervalMillisecond = 3*60*1000>
20 class Allocator
21 {
22 public:
23 typedef T value_type;
24 typedef T* pointer;
25 typedef const T* const_pointer;
26
27 private:
28 Allocator() {}
29 ~Allocator(){
30 Chunk* chunkPointer = chunk_;
31 while (chunkPointer != nullptr) {
32 Chunk* next = chunkPointer->Next();
33 ::delete chunkPointer;
34 chunkPointer = next;
35 }
36 }
37
38 public:
39 static Allocator<value_type>& Instance() {
40 static Allocator<value_type> allocator_;
41 return allocator_;
42 }
43 void* Allocate(size_t size) {
44 if (size > MaxSize()) {
45 throw std::runtime_error("");
46 }
47
48 if (chunk_ == nullptr) {
49 chunk_ = ::new Chunk(ChunkMaxBlockSize, minBlockSize_, align_);
50 }
51
52 Chunk* chunkPointer = chunk_;
53 while (chunkPointer != nullptr) {
54 if (!chunkPointer->Full() || chunkPointer->Next() == nullptr) {
55 break;
56 }
57 chunkPointer = chunkPointer->Next();
58 }
59 if (!chunkPointer->Full()) {
60 return chunkPointer->Acquire();
61 }
62 if (chunkPointer->Next() == nullptr) {
63 chunkPointer->Next(::new Chunk(ChunkMaxBlockSize, minBlockSize_, align_));
64 }
65 return chunkPointer->Next()->Acquire();
66 }
67
68 void Deallocate(void* ptr, size_t length) noexcept {
69 if (chunk_ == nullptr) {
70 throw std::runtime_error("Allocator<T>::allocate(size_t n) 'n' exceeds maximum supported size");
71 }
72
73 Chunk* chunkPointer = chunk_;
74 while (chunkPointer != nullptr) {
75 if (chunkPointer->InRange(ptr) || chunkPointer->Next() == nullptr) {
76 break;
77 }
78 chunkPointer = chunkPointer->Next();
79 }
80 if (chunkPointer->InRange(ptr) && chunkPointer->CheckAddressValid(ptr)) {
81 chunkPointer->Release(ptr);
82 } else {
83 throw std::runtime_error("Allocator<T>::allocate(size_t n) 'n' exceeds maximum supported size");
84 }
85
86 ++deallocateCount_;
87 ShrinkChunk();
88 }
89 inline size_t MaxSize() const noexcept {
90 return size_t(~0) / type_size_;
91 }
92
93 private:
94 // 收缩,超出MaxAccessIntervalMillisecond未访问,且Empty = true,则删掉该Chunk
95 void ShrinkChunk() {
96 if (chunk_ == nullptr || deallocateCount_ % ChunkMaxBlockSize != 0) {
97 return;
98 }
99 // 至少保留一个chunk
100 Chunk* chunkPointer = chunk_;
101 while (chunkPointer != nullptr) {
102 Chunk* next = chunkPointer->Next();
103 if (next == nullptr) {
104 break;
105 }
106 if (next->Idle()) {
107 std::int64_t chunkStamp = next->LastReleaseTimeStamp();
108 std::int64_t currentStamp = GetCurrentTimeStamp();
109 if (currentStamp - chunkStamp >= MaxAccessIntervalMillisecond) {
110 chunkPointer->Next(next->Next());
111 ::delete next;
112 } else {
113 chunkPointer = chunkPointer->Next();
114 }
115 } else {
116 chunkPointer = chunkPointer->Next();
117 }
118 }
119 }
120 private:
121 // 数据块,
122 class Chunk {
123 public:
124 Chunk(size_t maxBlockCount, size_t blockSize, size_t align) : maxBlockCount_(maxBlockCount), blockSize_(blockSize), length_(maxBlockCount_*blockSize_), align_(align) {
125 unsigned char* address = (unsigned char*)malloc(length_);
126 data_ = reinterpret_cast<pointer>(address);
127 enabled_ = (data_ != nullptr);
128 if (enabled_) {
129 idle_.reserve(maxBlockCount_);
130 for (size_t i = 0; i < maxBlockCount; ++i) {
131 idle_.push_back(i);
132 }
133 }
134 }
135 ~Chunk(){
136 Destory();
137 }
138 void* Acquire() {
139 if (!enabled_ || Full()) {
140 return nullptr;
141 }
142 size_t index = idle_.back();
143 idle_.pop_back();
144 lastReleaseTimeStamp_ = std::numeric_limits<std::int64_t>::max();
145 return IndexToAddress(index);
146 }
147 void Release(void* ptr) {
148 if (!InRange(ptr) || !CheckAddressValid(ptr)) {
149 return;
150 }
151 size_t index = AddressToIndex(ptr);
152 idle_.push_back(index);
153 if (Idle()) {
154 // 只记最后一次归还的时间
155 lastReleaseTimeStamp_ = GetCurrentTimeStamp();
156 }
157 }
158 void Destory() {
159 if (!enabled_) {
160 return;
161 }
162 free(data_);
163 idle_.clear();
164 }
165 bool Full() const {
166 return data_ == nullptr ? true : idle_.empty();
167 }
168 bool Idle() const {
169 return idle_.size() == ChunkMaxBlockSize;
170 }
171 const_pointer Begin() const {
172 return data_;
173 }
174 pointer End() const {
175 return data_ + maxBlockCount_;
176 }
177 bool InRange(void* ptr) {
178 return (data_ <= reinterpret_cast<pointer>(ptr) && reinterpret_cast<pointer>(ptr) < data_ + maxBlockCount_);
179 }
180 bool CheckAddressValid(void* ptr) {
181 return (reinterpret_cast<size_t >(ptr) % align_ == 0)
182 && ((reinterpret_cast<size_t >(ptr) - reinterpret_cast<size_t >(data_)) % blockSize_ == 0);
183 }
184 Chunk* Next() {
185 return next_;
186 }
187 void Next(Chunk* chunkPointer) {
188 next_ = chunkPointer;
189 }
190 const std::int64_t& LastReleaseTimeStamp() {
191 return lastReleaseTimeStamp_;
192 }
193 private:
194 size_t AddressToIndex (void* ptr) {
195 return reinterpret_cast<pointer>(ptr) - data_ ;
196 }
197 void* IndexToAddress(const size_t& index) {
198 if (data_ == nullptr || index >= maxBlockCount_) {
199 return nullptr;
200 }
201 return data_ + index;
202 }
203 private:
204 bool enabled_{false};
205 pointer data_{nullptr};
206 std::vector<size_t> idle_;
207 size_t maxBlockCount_{0};
208 size_t blockSize_{0};
209 size_t length_{0};
210 size_t align_{0};
211 std::int64_t lastReleaseTimeStamp_{std::numeric_limits<std::int64_t>::max()};
212 private:
213 Chunk* next_{nullptr};
214 };
215 private:
216 const size_t type_size_{sizeof(value_type)};
217 const size_t align_{alignof(value_type)};
218 const size_t minBlockSize_ {(sizeof(value_type) + alignof(value_type) - 1) / alignof(value_type) * alignof(value_type)};
219 size_t deallocateCount_{0};
220 Chunk* chunk_{nullptr};
221 };
222
223 // 简易对象
224 template<typename ClassName>
225 class MultilingualSimpleObject : public ClassName
226 {
227 // 不要使用虚函数,虚表会增加内存开销
228 // 不要定义成员变量
229 typedef MultilingualSimpleObject<ClassName> BuiltInClass;
230 public:
231 template<typename... T>
232 MultilingualSimpleObject(T&&... t) : ClassName(std::forward<T>(t)...) {}
233 // virtual ~MultilingualSimpleObject(){}
234
235 template<typename... T>
236 static std::shared_ptr<ClassName> Create(T&&... t) {
237 return std::shared_ptr<ClassName>(new BuiltInClass(t...));
238 }
239
240 static void* operator new(size_t size) {
241 return Allocator<BuiltInClass>::Instance().Allocate(1);
242 }
243
244 static void operator delete (void* ptr, size_t size) {
245 Allocator<BuiltInClass>::Instance().Deallocate(ptr, size);
246 }
247 };
248
249 }
250 }