Create your Gitee Account
Explore and code with more than 12 million developers,Free private repositories !:)
Sign up
文件
This repository doesn't specify license. Please pay attention to the specific project description and its upstream code dependency when using it.
Clone or Download
dynamicpool.h 6.87 KB
Copy Edit Raw Blame History
#pragma once
#include <list>
#include <time.h>
#include <algorithm>
#include <assert.h>
#include "gnmutex.h"
#include <string>
#include <typeinfo>
#include <string.h>
using namespace std;
namespace KCP {
#ifndef Macro
#define Macro(T) #T
#endif
// global flag for alloc and free flag.
#define AllocFlag 0xA110C
#define FreeFlag 0xDEA110C
#define max_satisfy_count 3
//
// malloc just for c compiler, not only for c++
//
template <typename T, typename Locker = CNonMutex>
class CDynamicPoolEx {
typedef T value_type;
typedef Locker locker_type;
// shell struct derived from value_type
struct SShellT : value_type {
int ref; // reference magic.
SShellT() : ref(FreeFlag) {}
template <typename ...Paras>
SShellT(Paras&&... para) : ref(0), value_type(std::forward<Paras>(para)...) {}
virtual ~SShellT() {}
};
// resource info.
struct SResourceT {
SShellT* array;
int size;
SResourceT() :array(nullptr), size(0) {
}
SResourceT(SShellT* a, int s) :array(a), size(s) {
}
};
typedef std::list<SShellT*> CObjectList;
typedef std::list<SResourceT> CResourceList;
struct Skiller {
void operator() (SResourceT& Reource) {
if (Reource.array) {
::free(Reource.array);
Reource.array = nullptr;
}
}
};
public:
explicit CDynamicPoolEx() : m_init_size(1), m_grow_size(1), m_satisfy_count(0) {
m_all.clear();
m_free.clear();
}
virtual ~CDynamicPoolEx() {
m_locker.Lock();
m_free.clear();
m_locker.Unlock();
// release all resources.
std::for_each(m_all.begin(), m_all.end(), Skiller());
}
public:
// all alloc size
virtual int GetAllAllocSize() const {
return m_init_size + (m_all.size() - 1) * m_grow_size;
}
// left alloc size
virtual int GetLeftAllocSize() const {
return m_free.size();
}
// object name
virtual const char* GetObjectName() const {
#if defined(_WIN32)
static bool g_HasGet = false;
static std::string strClassName;
if (!g_HasGet) {
const char* pszClassName = typeid(*this).name();
const char* pszStart = strstr(pszClassName, "<");
const char* pszNext = strstr(pszStart, ",");
strClassName.assign(pszStart + 1, pszNext);
g_HasGet = true;
}
return strClassName.c_str();
#else
return typeid(*this).name();
#endif
}
// get used size
virtual int GetUsedSize() const {
return GetAllAllocSize() - GetLeftAllocSize();
}
virtual int GetInitSize() const {
return m_init_size;
}
virtual int GetGrowSize() const {
return m_grow_size;
}
virtual int GetAllocMemorySize() const {
return GetAllAllocSize() * sizeof(T);
}
public:
bool Init(int initSize, int growSize) {
m_init_size = initSize;
m_grow_size = growSize;
if (!m_init_size && !m_grow_size) {
return false;
}
if (m_init_size == 0) m_init_size = growSize;
if (m_grow_size == 0) m_grow_size = initSize;
if (_Allocate(m_init_size)) {
return true;
}
return false;
}
// Get Object.
template <typename... Args>
value_type* FetchObj(Args&&... args) {
SShellT* poShellT = _Fetch();
if (!poShellT) {
return nullptr;
}
// parameter constructor.
new (poShellT) SShellT(std::forward<Args>(args)...);
poShellT->ref = AllocFlag;
return poShellT;
}
// release Object.
void ReleaseObj(value_type* poT) {
if (!poT) return;
SShellT* poShellT = static_cast<SShellT*>(poT);
if (!poShellT) return;
assert(poShellT->ref == AllocFlag && "reference is not right flag");
poShellT->ref = FreeFlag;
// address check
SResourceT t;
if (!_address_check(poShellT, &t)) {
return;
}
// call deallocate to c++ object.
poShellT->~SShellT();
// reallocate pShellT
m_locker.Lock();
m_free.push_back(poShellT);
// only for window's debug.
#if defined(WIN32) && defined(_DEBUG)
_memory_array_check(&t);
#endif
m_locker.Unlock();
}
// gc check. can call outside as possible.
void GCCheck() {
for (auto it = m_all.begin(); it != m_all.end(); it++) {
_memory_array_check(&*it);
}
}
protected:
void _memory_array_check(const SResourceT* t) {
int all_size = 0; {// calculate all size.
for (auto it = m_all.begin(); it != m_all.end(); it++) {
all_size += it->size;
}
}
all_size -= m_init_size;
all_size -= t->size;
int real_size = int(m_free.size()) - int(t->size);
if (all_size <= 0 || real_size <= 0) { // not enough now?
return;
}
const int min_size = 10;
float percent = float(real_size) / float(all_size);
if (all_size > min_size && percent > 0.5f) { // over then 50, then release it.
if (m_satisfy_count++ >= max_satisfy_count) {
_dealloc(t);
m_satisfy_count = 0;
}
}
}
void _dealloc(const SResourceT* t) {
if (!t) return;
using CObjListIter = typename CObjectList::iterator;
auto* it_array = new CObjListIter[t->size];
// save should remove iterator.
int index = 0;
const SShellT* array = t->array;
for (int i = 0; i < t->size; i++) {
auto it = std::find(m_free.begin(), m_free.end(), &(array[i]));
if (it == m_free.end()) {
delete[] it_array;
return;
}
else {
it_array[index++] = it;
}
}
// == now remove related resource. ==
// remove from free list.
for (int i = 0; i < index; i++) {
m_free.erase(it_array[i]);
}
// remove from resource list.
for (auto it = m_all.begin(); it != m_all.end(); it++) {
if (it->array == t->array && it->size == t->size) {
m_all.erase(it);
break;
}
}
::free(t->array);
delete[] it_array;
}
// check poShellT address, and return it's array and array size.
bool _address_check(SShellT* poShellT, SResourceT* t) const {
auto it = m_all.begin();
for (; it != m_all.end(); it++) {
const SShellT* pArr = it->array;
if (poShellT >= pArr && poShellT <= &pArr[it->size - 1]) {
if (t) *t = (*it);
break;
}
}
return it != m_all.end();
}
// allocate size object.
bool _Allocate(int nSize) {
assert(nSize > 0 && "size <= 0");
// new resource and push back
SShellT* pstArray = (SShellT*)::malloc(sizeof(SShellT) * nSize);
for (int i = 0; i < nSize; i++) {
m_free.push_back(&pstArray[i]);
}
// push to all list objects
m_all.emplace_back(pstArray, nSize);
return true;
}
SShellT* _Fetch() {
// lock it
m_locker.Lock();
if (m_free.empty()) { // realloc it.
if (!_Allocate(m_grow_size)) {
m_locker.Unlock();
return nullptr;
}
}
// get front resource.
SShellT* poShellT = m_free.front();
m_free.pop_front();
// unlock
m_locker.Unlock();
return poShellT;
}
protected:
CResourceList m_all; // all resources
CObjectList m_free; // allocated resource list
locker_type m_locker; // allocated resource locker
int m_init_size; // init size
int m_grow_size; // grow size
int m_satisfy_count;// satisfy count.
};
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化