206 lines
5.6 KiB
C++
206 lines
5.6 KiB
C++
/*
|
||
* 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_ */
|