1 #ifndef DResourcePool_h
2 #define DResourcePool_h
94 template <
typename DType>
class DResourcePool :
public std::enable_shared_from_this<DResourcePool<DType>>
98 static_assert(!std::is_pointer<DType>::value,
"The template type for DResourcePool must not be a pointer (the stored type IS a pointer though).");
99 static_assert(!std::is_const<DType>::value,
"The template type for DResourcePool must not be const.");
100 static_assert(!std::is_volatile<DType>::value,
"The template type for DResourcePool must not be volatile.");
104 DResourcePool(
size_t locGetBatchSize,
size_t locNumToAllocateAtOnce,
size_t locMaxLocalPoolSize);
105 DResourcePool(
size_t locGetBatchSize,
size_t locNumToAllocateAtOnce,
size_t locMaxLocalPoolSize,
size_t locMaxSharedPoolSize,
size_t locDebugLevel);
108 void Set_ControlParams(
size_t locGetBatchSize,
size_t locNumToAllocateAtOnce,
size_t locMaxLocalPoolSize);
109 void Set_ControlParams(
size_t locGetBatchSize,
size_t locNumToAllocateAtOnce,
size_t locMaxLocalPoolSize,
size_t locMaxSharedPoolSize,
size_t locDebugLevel);
110 DType* Get_Resource(
void);
111 shared_ptr<DType> Get_SharedResource(
void);
114 void Recycle(
const DType* locResource){
Recycle(const_cast<DType*>(locResource));}
115 void Recycle(vector<const DType*>& locResources);
118 void Recycle(DType* locResource);
119 void Recycle(vector<DType*>& locResources);
121 size_t Get_SharedPoolSize(
void)
const;
142 template <
typename RType>
typename std::enable_if<std::is_base_of<DResettable, RType>::value,
void>::type
Reset(
DResettable* locResource){locResource->
Reset();}
145 template <
typename RType>
typename std::enable_if<!std::is_base_of<DResettable, RType>::value,
void>::type
Release_Resources(RType* locResource){};
146 template <
typename RType>
typename std::enable_if<!std::is_base_of<DResettable, RType>::value,
void>::type
Reset(RType* locResource){};
149 void Get_Resources_StaticPool(
void);
150 void Recycle_Resources_StaticPool(vector<DType*>& locResources);
152 alignas(Get_CacheLineSize())
size_t dDebugLevel = 0;
153 alignas(Get_CacheLineSize())
size_t dGetBatchSize = 100;
154 alignas(Get_CacheLineSize())
size_t dNumToAllocateAtOnce = 20;
155 alignas(Get_CacheLineSize())
size_t dMaxLocalPoolSize = 2000;
156 alignas(Get_CacheLineSize()) vector<DType*> dResourcePool_Local;
159 alignas(Get_CacheLineSize())
static mutex dSharedPoolMutex;
160 alignas(Get_CacheLineSize())
static vector<DType*> dResourcePool_Shared;
161 alignas(Get_CacheLineSize())
static size_t dMaxSharedPoolSize;
162 alignas(Get_CacheLineSize())
static size_t dPoolCounter;
163 alignas(Get_CacheLineSize())
static atomic<size_t> dObjectCounter;
173 void operator()(
const DType* locResource)
const{(*this)(
const_cast<DType*
>(locResource));}
174 void operator()(DType* locResource)
const;
182 auto locSharedPtr = dResourcePool.lock();
183 if(locSharedPtr ==
nullptr)
186 locSharedPtr->Recycle(locResource);
202 Set_ControlParams(locGetBatchSize, locNumToAllocateAtOnce, locMaxLocalPoolSize, locMaxSharedPoolSize, locDebugLevel);
212 dResourcePool_Local.reserve(dMaxLocalPoolSize);
214 std::lock_guard<std::mutex> locLock(dSharedPoolMutex);
217 cout <<
"CONSTRUCTOR THREAD COUNTER " <<
typeid(DType).name() <<
": " << dPoolCounter << endl;
218 if(dPoolCounter == 1)
219 dResourcePool_Shared.reserve(dMaxSharedPoolSize);
227 Recycle_Resources_StaticPool(dResourcePool_Local);
231 vector<DType*> locResources;
233 std::lock_guard<std::mutex> locLock(dSharedPoolMutex);
236 cout <<
"DESTRUCTOR THREAD COUNTER " <<
typeid(DType).name() <<
": " << dPoolCounter << endl;
242 cout <<
"DESTRUCTOR MOVING FROM SHARED POOL " <<
typeid(DType).name() <<
": " << std::distance(dResourcePool_Shared.begin(), dResourcePool_Shared.end()) << endl;
243 std::move(dResourcePool_Shared.begin(), dResourcePool_Shared.end(), std::back_inserter(locResources));
244 dResourcePool_Shared.clear();
249 cout <<
"DESTRUCTOR DELETING " <<
typeid(DType).name() <<
": " << locResources.size() << endl;
250 for(
auto locResource : locResources)
252 dObjectCounter -= locResources.size();
254 cout <<
"All objects (ought) to be destroyed, theoretical # remaining: " << dObjectCounter;
261 if(dDebugLevel >= 10)
262 cout <<
"GET RESOURCE " <<
typeid(DType).name() << endl;
263 if(dResourcePool_Local.empty())
264 Get_Resources_StaticPool();
265 if(dResourcePool_Local.empty())
268 auto locPotentialNewSize = dResourcePool_Local.size() + dNumToAllocateAtOnce - 1;
269 auto locNumToAllocate = (locPotentialNewSize <= dMaxLocalPoolSize) ? dNumToAllocateAtOnce : (dMaxLocalPoolSize - dResourcePool_Local.size() + 1);
270 for(
size_t loc_i = 0; loc_i < locNumToAllocate - 1; ++loc_i)
271 dResourcePool_Local.push_back(
new DType);
272 dObjectCounter += locNumToAllocate;
276 auto locResource = dResourcePool_Local.back();
277 dResourcePool_Local.pop_back();
278 Reset<DType>(locResource);
284 dDebugLevel = locDebugLevel;
285 dGetBatchSize = locGetBatchSize;
286 dNumToAllocateAtOnce = (locNumToAllocateAtOnce > 0) ? locNumToAllocateAtOnce : 1;
287 dMaxLocalPoolSize = locMaxLocalPoolSize;
289 std::lock_guard<std::mutex> locLock(dSharedPoolMutex);
290 dMaxSharedPoolSize = locMaxSharedPoolSize;
291 dResourcePool_Shared.reserve(dMaxSharedPoolSize);
297 dGetBatchSize = locGetBatchSize;
298 dNumToAllocateAtOnce = (locNumToAllocateAtOnce > 0) ? locNumToAllocateAtOnce : 1;
299 dMaxLocalPoolSize = locMaxLocalPoolSize;
309 vector<DType*> locNonConstResources;
310 locNonConstResources.reserve(locResources.size());
312 auto Deconstifier = [](
const DType* locConstPointer) -> DType* {
return const_cast<DType*
>(locConstPointer);};
313 std::transform(locResources.begin(), locResources.end(), std::back_inserter(locNonConstResources), Deconstifier);
314 locResources.clear();
316 Recycle(locNonConstResources);
321 for(
auto& locResource : locResources)
322 Release_Resources<DType>(locResource);
324 size_t locFirstToMoveIndex = 0;
325 auto locPotentialNewPoolSize = dResourcePool_Local.size() + locResources.size();
326 if(locPotentialNewPoolSize > dMaxLocalPoolSize)
327 locFirstToMoveIndex = locResources.size() - (dMaxLocalPoolSize - dResourcePool_Local.size());
329 std::move(locResources.begin() + locFirstToMoveIndex, locResources.end(), std::back_inserter(dResourcePool_Local));
330 locResources.resize(locFirstToMoveIndex);
331 if(!locResources.empty())
332 Recycle_Resources_StaticPool(locResources);
337 if(locResource ==
nullptr)
339 vector<DType*> locResourceVector{locResource};
340 Recycle(locResourceVector);
347 auto locPotentialNewLocalSize = dResourcePool_Local.size() + dGetBatchSize;
348 auto locGetBatchSize = (locPotentialNewLocalSize <= dMaxLocalPoolSize) ? dGetBatchSize : dMaxLocalPoolSize - dResourcePool_Local.size();
350 std::lock_guard<std::mutex> locLock(dSharedPoolMutex);
351 if(dResourcePool_Shared.empty())
353 auto locFirstToMoveIndex = (locGetBatchSize >= dResourcePool_Shared.size()) ? 0 : dResourcePool_Shared.size() - locGetBatchSize;
355 cout <<
"MOVING FROM SHARED POOL " <<
typeid(DType).name() <<
": " << dResourcePool_Shared.size() - locFirstToMoveIndex << endl;
356 std::move(dResourcePool_Shared.begin() + locFirstToMoveIndex, dResourcePool_Shared.end(), std::back_inserter(dResourcePool_Local));
357 dResourcePool_Shared.resize(locFirstToMoveIndex);
363 size_t locFirstToMoveIndex = 0;
365 std::lock_guard<std::mutex> locLock(dSharedPoolMutex);
367 auto locPotentialNewPoolSize = dResourcePool_Shared.size() + locResources.size();
368 if(locPotentialNewPoolSize > dMaxSharedPoolSize)
369 locFirstToMoveIndex = locResources.size() - (dMaxSharedPoolSize - dResourcePool_Shared.size());
372 cout <<
"MOVING TO SHARED POOL " <<
typeid(DType).name() <<
": " << dResourcePool_Local.size() - locFirstToMoveIndex << endl;
374 std::move(locResources.begin() + locFirstToMoveIndex, locResources.end(), std::back_inserter(dResourcePool_Shared));
378 cout <<
"DELETING " <<
typeid(DType).name() <<
": " << locFirstToMoveIndex << endl;
381 auto Deleter = [](DType* locResource) ->
void {
delete locResource;};
382 std::for_each(locResources.begin(), locResources.begin() + locFirstToMoveIndex, Deleter);
384 dObjectCounter -= locFirstToMoveIndex;
385 locResources.clear();
390 std::lock_guard<std::mutex> locLock(dSharedPoolMutex);
391 return dResourcePool_Shared.size();
394 #endif // DResourcePool_h
static constexpr unsigned int Get_CacheLineSize(void)
void operator()(const DType *locResource) const
DSharedPtrRecycler(const std::shared_ptr< DResourcePool< DType >> &locResourcePool)
std::enable_if< std::is_base_of< DResettable, RType >::value, void >::type Reset(DResettable *locResource)
void Get_Resources_StaticPool(void)
DType * Get_Resource(void)
std::enable_if<!std::is_base_of< DResettable, RType >::value, void >::type Reset(RType *locResource)
size_t Get_PoolSize(void) const
std::weak_ptr< DResourcePool< DType > > dResourcePool
size_t Get_NumObjectsAllThreads(void) const
void Recycle_Resources_StaticPool(vector< DType * > &locResources)
void Set_ControlParams(size_t locGetBatchSize, size_t locNumToAllocateAtOnce, size_t locMaxLocalPoolSize)
std::enable_if<!std::is_base_of< DResettable, RType >::value, void >::type Release_Resources(RType *locResource)
virtual void Release(void)=0
virtual void Reset(void)=0
std::enable_if< std::is_base_of< DResettable, RType >::value, void >::type Release_Resources(DResettable *locResource)
size_t Get_SharedPoolSize(void) const
shared_ptr< DType > Get_SharedResource(void)
void Recycle(const DType *locResource)