代码拉取完成,页面将自动刷新
同步操作将从 gavingqf/kcp 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
#pragma once
// single object pool with listh.h
// Copyright (c) 2019 - 2020 gavingqf (gavingqf@126.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <stdlib.h>
#include <cassert>
#include "gnmutex.h"
#include "list.h"
#include <memory>
using namespace KCP;
namespace SObjPoolSpace {
typedef struct list_head list_head;
// alloc and free macro.
#define ObjMalloc ::malloc
#define ObjFree ::free
// function for alloc and free.
inline void* obj_alloc(size_t size) {
return ObjMalloc(size);
}
inline void obj_free(void *data) {
ObjFree(data);
}
// construct is whether construct when get object.
template <typename T, bool construct = true, typename locker = CNonMutex>
class object_pool {
public:
typedef T value_type;
private:
// value wrap.
struct value_info {
// value must in the front of value_info.
value_type value;
// reference num.
int magic_num;
// double link node.
list_head link;
};
// resource info.
struct resource_info {
list_head link;
value_info *array;
int size;
};
public:
explicit object_pool() : m_init_size(0), m_grow_size(0) {
INIT_LIST_HEAD(&m_list_free);
INIT_LIST_HEAD(&m_list_all);
}
virtual ~object_pool() {
m_free_locker.Lock();
INIT_LIST_HEAD(&m_list_free);
m_free_locker.Unlock();
// release all resource.
list_head *pos, *n;
resource_info *pvalue;
list_for_each_safe(pos, n, &m_list_all) {
if ((pvalue = list_entry(pos, resource_info, link))) {
obj_free(pvalue->array);
obj_free(pvalue);
} else {
assert(false && "pointer is nil");
}
}
}
public:
// init.
bool init(int init_size, int grow_size) {
m_init_size = init_size;
m_grow_size = grow_size;
if (!m_init_size && !m_grow_size) return false;
if (!m_init_size) m_init_size = m_grow_size;
if (!m_grow_size) m_grow_size = m_init_size;
return this->allocate(m_init_size);
}
// fetch object.
// compatible with all construction.
template <typename ...Args>
value_type* fetch_obj(Args&& ...args) {
value_type* obj = _fetch();
if (!obj) return nullptr;
new (obj) value_type(std::forward<Args>(args)...);
return obj;
}
// release object.
bool release_obj(value_type* value) {
if (!value) return false;
// transfer to wrap_info.
value_info *shell = (value_info*)value;
if (!shell) return false;
assert(shell && "shell is null");
assert(shell->magic_num == m_reference && "reference info is error");
if (shell->magic_num != m_reference)
return false;
// pointer check
list_head *pos, *n;
resource_info *pvalue;
list_for_each_safe(pos, n, &m_list_all) {
if ((pvalue = list_entry(pos, resource_info, link))) {
if (shell >= pvalue->array && shell < pvalue->array + pvalue->size)
goto succ; // find it is valid pointer, then goto succ to put back.
} else {
assert(false && "get value pointer error");
}
}
assert(false && "can not find user pointer");
return false;
succ:
// set unreferenced.
shell->magic_num = m_unreference;
// de construct as possible.
if (construct) {
shell->value.~value_type();
}
m_free_locker.Lock();
list_add_tail(&shell->link, &m_list_free);
m_free_locker.Unlock();
return true;
}
protected:
// allocate memory.
bool allocate(int size) {
assert(size > 0 && "size <= 0");
if (size <= 0) return false;
// new resource and push back
value_info* array = (value_info*)obj_alloc(sizeof(value_info) * size);
if (!array) return false;
for (int i = 0; i < size; i++) {
list_add_tail(&array[i].link, &m_list_free);
}
// push to all list objects
resource_info *t = (resource_info *)obj_alloc(sizeof(resource_info));
assert(t && "alloc resource info error");
if (!t) return false;
t->array = array;
t->size = size;
list_add_tail(&t->link, &m_list_all);
return true;
}
// fetch pointer.
value_type* _fetch() {
// lock it
m_free_locker.Lock();
if (list_empty(&m_list_free)) { // realloc it.
if (!allocate(m_grow_size)) {
m_free_locker.Unlock();
return nullptr;
}
}
// get first object.
value_info *object = list_first_entry(&m_list_free, value_info, link);
assert(object && "object is null");
list_del(&object->link);
m_free_locker.Unlock();
object->magic_num = m_reference;
return &object->value;
}
protected:
list_head m_list_all; // all resources
list_head m_list_free; // allocated resource list
locker m_free_locker; // allocated resource locker
int m_init_size; // init size
int m_grow_size; // grow size
static const int m_reference = 0xA110CAED; // reference num.
static const int m_unreference= 0xDEA110CA;// unreferenced num.
};
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。