Older/ToolKit/Util/ResourcePool.h
amass 9de3af15eb
All checks were successful
Deploy / PullDocker (push) Successful in 12s
Deploy / Build (push) Successful in 1m51s
add ZLMediaKit code for learning.
2024-09-28 23:55:00 +08:00

206 lines
5.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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_ */