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