add some functions in class dbuf_guard for convinence and safty

This commit is contained in:
ubuntu14 2015-11-14 06:15:22 -08:00
parent 9aad31fade
commit 4edafbda32
4 changed files with 316 additions and 51 deletions

View File

@ -1,6 +1,11 @@
修改历史列表:
------------------------------------------------------------------------
376) 2015.11.14
376.1) feature: dbuf_guard 类增加了更多方便操作的方法,同时使数组对象也在
内存池对象上创建
376.2) safety: dbuf_guard 类中增加了对 dbuf_obj 对象的安全保护
375) 2015.11.13
375.1) feature: 连接池模块简化接口设计,允许连接集群管理器在添加新的连接池时设置超时时间,
从而使连接池集群管理器针对不同的服务器地址采用不同的超时时间,这样可以使连接池

View File

@ -170,11 +170,36 @@ public:
virtual ~dbuf_obj() {}
/**
* dbuf_guard
* @return {int} dbuf_guard
* dbuf_guard -1
*/
int pos() const
{
return pos_;
}
/**
* dbuf_guard
* @return {dbuf_guard*}
*/
dbuf_guard* get_guard() const
{
return guard_;
}
private:
friend class dbuf_guard;
// 记录本对象所属的 dbuf_guard 对象
dbuf_guard* guard_;
// 该变量便于 dbuf_guard 对象使用,以增加安全性
int nrefer_;
// 该对象在 dbuf_guard 对象中记录的数组的位置
int pos_;
};
/**
@ -188,10 +213,17 @@ public:
*
* @param dbuf {dbuf_pool*} dbuf dbuf_guard
* dbuf_pool
* @param nblock {size_t} dbuf NULL
* dbuf_pool (4096)
* @param capacity {size_t} objs_
*/
dbuf_guard(dbuf_pool* dbuf = NULL, size_t nblock = 2);
dbuf_guard(dbuf_pool* dbuf, size_t capacity = 100);
/**
*
* @param nblock {size_t} dbuf_pool
* (4096)
* @param capacity {size_t} objs_
*/
dbuf_guard(size_t nblock = 2, size_t capacity = 100);
/**
* dbuf_pool
@ -301,10 +333,12 @@ public:
/**
* dbuf_pool dbuf_obj
* dbuf_guard
* dbuf_guard dbuf_obj
* dbuf_guard
* @param obj {dbuf_obj*}
* @return {int} obj dbuf_obj
* < 0 dbuf_guard
* dbuf_guard dbuf_obj
* dbuf_obj dbuf_guard
*/
int push_back(dbuf_obj* obj);
@ -314,14 +348,16 @@ public:
*/
size_t size() const
{
return objs_.size();
return size_;
}
/**
*
* @return {std::vector<dbuf_obj*>&}
* size() 使
*
* @return {dbuf_obj**} dbuf_obj NULL
* size()
*/
const std::vector<dbuf_obj*>& get_objs() const
dbuf_obj** get_objs() const
{
return objs_;
}
@ -333,9 +369,34 @@ public:
*/
dbuf_obj* operator[](size_t pos) const;
/**
*
* @param pos {size_t}
* @return {dbuf_obj*} NULL
*/
dbuf_obj* get(size_t pos) const;
/**
* objs_ 100
* @param incr {size_t}
*/
void set_increment(size_t incr);
private:
dbuf_pool* dbuf_;
std::vector<dbuf_obj*> objs_;
size_t nblock_; // 内部自建 dbuf_pool 内存块的单位个数
dbuf_pool* dbuf_; // 内存池对象
// 此处之所以使用自实现的 dbuf_obj 数组对象,而没有使用 std::vector
// 一方面使数组对象也在 dbuf_pool 内存池上创建,另一方面可以避免
// std::vector 内部在扩容时的内存不可控性
dbuf_obj** objs_; // 存储 dbuf_obj 对象的数组对象
size_t size_; // 存储于 objs_ 中的对象个数
size_t capacity_; // objs_ 数组的大小
size_t incr_; // objs_ 数组扩充时的增量个数
// 扩充 objs_ 数组对象的空间
void extend_objs();
};
/**

View File

@ -3,6 +3,9 @@
#include "stdafx.h"
#include <sys/time.h>
/**
* dbuf_obj dbuf_pool dbuf_guard
*/
class myobj : public acl::dbuf_obj
{
public:
@ -13,46 +16,192 @@ public:
void run()
{
printf("----> hello world <-----\r\n");
printf("----> run->hello world <-----\r\n");
}
private:
char* ptr_;
// 将析构声明为私人,以强制要求该对象被动态分配,该析构函数将由
// dbuf_guard 统一调用,以释放本类对象中产生的动态内存(ptr_)
~myobj()
{
free(ptr_);
printf("----> myobj destroied <-----\r\n");
}
};
static void test_dbuf(acl::dbuf_guard& dbuf)
{
for (int i = 0; i < 102400; i++)
{
// 动态分配内存
char* ptr = (char*) dbuf.dbuf_alloc(10);
(void) ptr;
}
for (int i = 0; i < 102400; i++)
{
// 动态分配字符串
char* str = dbuf.dbuf_strdup("hello world");
if (i < 5)
printf(">>str->%s\r\n", str);
}
// 动态分配内存
(void) dbuf.dbuf_alloc(1024);
(void) dbuf.dbuf_alloc(1024);
(void) dbuf.dbuf_alloc(2048);
(void) dbuf.dbuf_alloc(1024);
(void) dbuf.dbuf_alloc(1024);
(void) dbuf.dbuf_alloc(1024);
(void) dbuf.dbuf_alloc(1024);
(void) dbuf.dbuf_alloc(1024);
(void) dbuf.dbuf_alloc(1024);
(void) dbuf.dbuf_alloc(1024);
(void) dbuf.dbuf_alloc(1024);
(void) dbuf.dbuf_alloc(10240);
for (int i = 0; i < 10000; i++)
{
// 动态分配 dbuf_obj 子类对象,并通过将 dbuf_guard 对象传入
// dbuf_obj 的构造函数,从而将之由 dbuf_guard 统一管理,
myobj* obj = new (dbuf.dbuf_alloc(sizeof(myobj))) myobj(&dbuf);
// 验证 dbuf_obj 对象在 dbuf_guard 中的在在一致性
assert(obj == dbuf[obj->pos()]);
// 调用 dbuf_obj 子类对象 myobj 的函数 run
if (i < 10)
obj->run();
}
for (int i = 0; i < 10000; i++)
{
myobj* obj = new (dbuf.dbuf_alloc(sizeof(myobj))) myobj(NULL);
int pos = dbuf.push_back(obj);
assert(dbuf[pos] == obj);
if (i < 10)
obj->run();
}
for (int i = 0; i < 10000; i++)
{
myobj* obj = new (dbuf.dbuf_alloc(sizeof(myobj))) myobj(&dbuf);
// 虽然多次将 dbuf_obj 对象置入 dbuf_guard 中,因为 dbuf_obj
// 内部的引用计数,所以可以防止被重复添加
(void) dbuf.push_back(obj);
(void) dbuf.push_back(obj);
(void) dbuf.push_back(obj);
assert(obj == dbuf[obj->pos()]);
if (i < 10)
obj->run();
}
for (int i = 0; i < 10000; i++)
{
myobj* obj = new (dbuf.dbuf_alloc(sizeof(myobj))) myobj(NULL);
(void) dbuf.push_back(obj);
(void) dbuf.push_back(obj);
(void) dbuf.push_back(obj);
(void) dbuf.push_back(obj);
(void) dbuf.push_back(obj);
(void) dbuf.push_back(obj);
int pos = dbuf.push_back(obj);
assert(dbuf[pos] == obj);
if (i < 10)
obj->run();
}
}
static void wait_pause()
{
printf("Enter any key to continue ...");
fflush(stdout);
getchar();
}
static void test1()
{
// dbuf_gaurd 对象创建在栈上,函数返回前该对象自动销毁
acl::dbuf_guard dbuf;
test_dbuf(dbuf);
}
static void test2()
{
// 动态创建 dbuf_guard 对象,需要手动销毁该对象
acl::dbuf_guard* dbuf = new acl::dbuf_guard;
test_dbuf(*dbuf);
// 手工销毁该对象
delete dbuf;
}
static void test3()
{
// 将内存池对象 dbuf_pool 做为 dbuf_guard 构造函数参数传入,当
// dbuf_guard 对象销毁时dbuf_pool 对象一同被销毁
acl::dbuf_guard dbuf(new acl::dbuf_pool);
test_dbuf(dbuf);
}
static void test4()
{
// 动态创建 dbuf_guard 对象,同时指定内存池中内存块的分配倍数为 10
// 即指定内部每个内存块大小为 4096 * 10 = 40 KB同时
// 指定内部动态数组的初始容量大小
acl::dbuf_guard dbuf(10, 100);
test_dbuf(dbuf);
}
static void test5()
{
acl::dbuf_pool* dp = new acl::dbuf_pool;
// 在内存池对象上动态创建 dbuf_guard 对象,这样可以将内存分配的次数
// 进一步减少一次
acl::dbuf_guard* dbuf = new (dp->dbuf_alloc(sizeof(acl::dbuf_guard)))
acl::dbuf_guard(dp);
test_dbuf(*dbuf);
// 因为 dbuf_gaurd 对象也是在 dbuf_pool 内存池对象上动态创建的,所以
// 只能通过直接调用 dbuf_guard 的析构函数来释放所有的内存对象;
// 既不能直接 dbuf_pool->desotry(),也不能直接 delete dbuf_guard 来
// 销毁 dbuf_guard 对象
dbuf->~dbuf_guard();
}
int main(void)
{
acl::log::stdout_open(true);
acl::dbuf_guard dbuf;
test1();
wait_pause();
for (int i = 0; i < 102400; i++)
dbuf.dbuf_alloc(10);
test2();
wait_pause();
dbuf.dbuf_alloc(1024);
dbuf.dbuf_alloc(1024);
dbuf.dbuf_alloc(2048);
dbuf.dbuf_alloc(1024);
dbuf.dbuf_alloc(1024);
dbuf.dbuf_alloc(1024);
dbuf.dbuf_alloc(1024);
dbuf.dbuf_alloc(1024);
dbuf.dbuf_alloc(1024);
dbuf.dbuf_alloc(1024);
dbuf.dbuf_alloc(1024);
dbuf.dbuf_alloc(10240);
test3();
wait_pause();
for (int i = 0; i < 10; i++)
{
myobj* obj = new (dbuf.dbuf_alloc(sizeof(myobj))) myobj(&dbuf);
obj->run();
}
test4();
wait_pause();
test5();
return 0;
}

View File

@ -89,51 +89,101 @@ bool dbuf_pool::dbuf_unkeep(const void* addr)
//////////////////////////////////////////////////////////////////////////////
dbuf_obj::dbuf_obj(dbuf_guard* guard /* = NULL */)
: nrefer_(0)
: guard_(guard)
, nrefer_(0)
, pos_(-1)
{
if (guard)
guard->push_back(this);
}
dbuf_guard::dbuf_guard(acl::dbuf_pool* dbuf /* = NULL */, size_t nblock /* = 2 */)
dbuf_guard::dbuf_guard(acl::dbuf_pool* dbuf, size_t capacity /* = 100 */)
: nblock_(2)
, size_(0)
, capacity_(capacity == 0 ? 100 : capacity)
, incr_(100)
{
if (dbuf == NULL)
dbuf_ = new (nblock) acl::dbuf_pool;
dbuf_ = new (nblock_) acl::dbuf_pool;
else
dbuf_ = dbuf;
objs_ = (dbuf_obj**) dbuf_->dbuf_alloc(sizeof(dbuf_obj*) * capacity_);
}
dbuf_guard::dbuf_guard(size_t nblock /* = 2 */, size_t capacity /* = 100 */)
: nblock_(nblock == 0 ? 2 : nblock)
, size_(0)
, capacity_(capacity == 0 ? 100 : capacity)
, incr_(100)
{
dbuf_ = new (nblock_) acl::dbuf_pool;
objs_ = (dbuf_obj**) dbuf_->dbuf_alloc(sizeof(dbuf_obj*) * capacity_);
}
dbuf_guard::~dbuf_guard()
{
for (std::vector<dbuf_obj*>::iterator it = objs_.begin();
it != objs_.end(); ++it)
{
(*it)->~dbuf_obj();
}
for (size_t i = 0; i < size_; i++)
objs_[i]->~dbuf_obj();
dbuf_->destroy();
}
void dbuf_guard::extend_objs()
{
dbuf_obj** old_objs = objs_;
capacity_ += incr_;
objs_ = (dbuf_obj**) dbuf_->dbuf_alloc(sizeof(dbuf_obj*) * capacity_);
for (size_t i = 0; i < size_; i++)
objs_[i] = old_objs[i];
}
void dbuf_guard::set_increment(size_t incr)
{
if (incr > 0)
incr_ = incr;
}
int dbuf_guard::push_back(dbuf_obj* obj)
{
if (obj->nrefer_ >= 1)
if (obj->nrefer_ < 1)
{
logger_error("obj->nrefer_: %d >= 1", obj->nrefer_);
return -1;
if (obj->guard_ == NULL)
obj->guard_ = this;
else if (obj->guard_ != this)
{
logger_fatal("obj->guard_(%p) != me(%p), nrefer: %d",
obj->guard_, this, obj->nrefer_);
}
if (size_ >= capacity_)
extend_objs();
objs_[size_] = obj;
obj->nrefer_++;
obj->pos_ = (int) size_;
size_++;
}
else if (obj->guard_ != this)
{
logger_fatal("obj->guard_(%p) != me(%p), nrefer: %d",
obj->guard_, this, obj->nrefer_);
}
objs_.push_back(obj);
obj->nrefer_++;
return (int) objs_.size() - 1;
return obj->pos_;
}
dbuf_obj* dbuf_guard::operator[](size_t pos) const
{
if (pos >= objs_.size())
return NULL;
return get(pos);
}
return objs_[pos];
dbuf_obj* dbuf_guard::get(size_t pos) const
{
if (pos >= size_)
return NULL;
else
return objs_[pos];
}
} // namespace acl