Older/ToolKit/Util/ResourcePool.h

206 lines
5.6 KiB
C
Raw Normal View History

2024-09-28 23:55:00 +08:00
/*
* Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
*
* This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef UTIL_RECYCLEPOOL_H_
#define UTIL_RECYCLEPOOL_H_
#include "List.h"
#include <atomic>
#include <deque>
#include <functional>
#include <memory>
#include <mutex>
#include <unordered_set>
namespace toolkit {
#if (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 9))) || defined(__clang__) \
|| !defined(__GNUC__)
#define SUPPORT_DYNAMIC_TEMPLATE
#endif
template <typename C>
class ResourcePool_l;
template <typename C>
class ResourcePool;
template <typename C>
class shared_ptr_imp : public std::shared_ptr<C> {
public:
shared_ptr_imp() {}
/**
*
* @param ptr
* @param weakPool
* @param quit 使
*/
shared_ptr_imp(
C *ptr, const std::weak_ptr<ResourcePool_l<C>> &weakPool, std::shared_ptr<std::atomic_bool> quit,
const std::function<void(C *)> &on_recycle);
/**
* 使
* @param flag
*/
void quit(bool flag = true) {
if (_quit) {
*_quit = flag;
}
}
private:
std::shared_ptr<std::atomic_bool> _quit;
};
template <typename C>
class ResourcePool_l : public std::enable_shared_from_this<ResourcePool_l<C>> {
public:
using ValuePtr = shared_ptr_imp<C>;
friend class shared_ptr_imp<C>;
friend class ResourcePool<C>;
ResourcePool_l() {
_alloc = []() -> C * { return new C(); };
}
#if defined(SUPPORT_DYNAMIC_TEMPLATE)
template <typename... ArgTypes>
ResourcePool_l(ArgTypes &&...args) {
_alloc = [args...]() -> C * { return new C(args...); };
}
#endif // defined(SUPPORT_DYNAMIC_TEMPLATE)
~ResourcePool_l() {
for (auto ptr : _objs) {
delete ptr;
}
}
void setSize(size_t size) {
_pool_size = size;
_objs.reserve(size);
}
ValuePtr obtain(const std::function<void(C *)> &on_recycle = nullptr) {
return ValuePtr(getPtr(), _weak_self, std::make_shared<std::atomic_bool>(false), on_recycle);
}
std::shared_ptr<C> obtain2() {
auto weak_self = _weak_self;
return std::shared_ptr<C>(getPtr(), [weak_self](C *ptr) {
auto strongPool = weak_self.lock();
if (strongPool) {
//放入循环池
strongPool->recycle(ptr);
} else {
delete ptr;
}
});
}
private:
void recycle(C *obj) {
auto is_busy = _busy.test_and_set();
if (!is_busy) {
//获取到锁
if (_objs.size() >= _pool_size) {
delete obj;
} else {
_objs.emplace_back(obj);
}
_busy.clear();
} else {
//未获取到锁
delete obj;
}
}
C *getPtr() {
C *ptr;
auto is_busy = _busy.test_and_set();
if (!is_busy) {
//获取到锁
if (_objs.size() == 0) {
ptr = _alloc();
} else {
ptr = _objs.back();
_objs.pop_back();
}
_busy.clear();
} else {
//未获取到锁
ptr = _alloc();
}
return ptr;
}
void setup() { _weak_self = this->shared_from_this(); }
private:
size_t _pool_size = 8;
std::vector<C *> _objs;
std::function<C *(void)> _alloc;
std::atomic_flag _busy { false };
std::weak_ptr<ResourcePool_l> _weak_self;
};
/**
* enable_shared_from_this
* @tparam C
*/
template <typename C>
class ResourcePool {
public:
using ValuePtr = shared_ptr_imp<C>;
ResourcePool() {
pool.reset(new ResourcePool_l<C>());
pool->setup();
}
#if defined(SUPPORT_DYNAMIC_TEMPLATE)
template <typename... ArgTypes>
ResourcePool(ArgTypes &&...args) {
pool = std::make_shared<ResourcePool_l<C>>(std::forward<ArgTypes>(args)...);
pool->setup();
}
#endif // defined(SUPPORT_DYNAMIC_TEMPLATE)
void setSize(size_t size) { pool->setSize(size); }
//获取一个对象,性能差些,但是功能丰富些
ValuePtr obtain(const std::function<void(C *)> &on_recycle = nullptr) { return pool->obtain(on_recycle); }
//获取一个对象,性能好些
std::shared_ptr<C> obtain2() { return pool->obtain2(); }
private:
std::shared_ptr<ResourcePool_l<C>> pool;
};
template<typename C>
shared_ptr_imp<C>::shared_ptr_imp(C *ptr,
const std::weak_ptr<ResourcePool_l<C> > &weakPool,
std::shared_ptr<std::atomic_bool> quit,
const std::function<void(C *)> &on_recycle) :
std::shared_ptr<C>(ptr, [weakPool, quit, on_recycle](C *ptr) {
if (on_recycle) {
on_recycle(ptr);
}
auto strongPool = weakPool.lock();
if (strongPool && !(*quit)) {
//循环池还在并且不放弃放入循环池
strongPool->recycle(ptr);
} else {
delete ptr;
}
}), _quit(std::move(quit)) {}
} /* namespace toolkit */
#endif /* UTIL_RECYCLEPOOL_H_ */