Fetch the repository succeeded.
This action will force synchronization from gavingqf/kcp, which will overwrite any changes that you have made since you forked the repository, and can not be recovered!!!
Synchronous operation will process in the background and will refresh the page when finishing processing. Please be patient.
#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.
};
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。