MultilingualSimpleObject
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 }