服务器开发之内存<二>: 带生命周期的小内存块


      需求:请思考这样的一个场景,客户端发起了一次购买流程,这个流程算是一个复杂,并且操作周期,和跨度都比较长的流程。 下面的图形是一个简单的模拟图,也有可能你们的计费并不是这个样子。



        在上面的步骤中:从(3)开始到介绍,服务器GameServer需要维护这个玩家的计费信息,这些信息有订单号,账号,交易号,购买时间,购买物品等等一系列的数据信息,而这些信息又是在用户发起购买的时候才会产生的,所有如果在GameServer里面的User数据结构里面添加一个内存块,是比较浪费的,因为90%以上的玩家是不需要这个数据信息的,会造成严重的内存浪费。最好的方法就是临时分配一个内存,购买完成后也就释放了,但是因为购买流程比较长,有时候还需要跨越物理的机器,比如赠送功能,接收物品的用户和付费的用户可能不在同一个服务器上面,这样流程会更长。并且这些操作里面,可能任何一个环节都会发生一些错误,造成我们逻辑上请求的消息没有回应这样的事情发生。这个时候,我们上面申请的内存块,会造成逻辑上释放的函数不会被调用。从而造成内存的泄漏。

        这就是我要解决的根本问题:

                     a: 满足购买逻辑所需要的内存问题。

                     b:保证内存的安全。

                     c:保证没有内存在任何逻辑错误的情况下没有泄漏。 


          这就是我要提出来的,有一定生命周期的内存块,这些内存块会被集中的组件去管理,和释放。不多说了,直接上代码了:


//下面的需要的一些结构定义

enum emTempItemypeOne
{
	emTempTypeOne_Error  = 0,
	emTempTypeOne_BufMsg,
	emTempTypeOne_Obj,
};
struct TTempItemType
{
	char			typeone;
	char			typetwo;
	short			typethree;
};

//
class  CTempObjItem
{
protected:
	CTempObjItem(){ m_calpos=0; }
public:
	virtual ~CTempObjItem(){}
public:
	unsigned int m_calpos;
};

//
struct TItemObjItem
{
public:
	const CTempObjItem *m_pObj;
	unsigned int        m_param;
};
struct TItemMsgItem
{
public:
	char          *m_pbuff;
	unsigned int   m_bufflen;
};

//
struct TTempItemHead
{
	unsigned int		begintime;
	unsigned int		keeptimelen;
	TTempItemType		type;

	union uInTData
	{
		TItemMsgItem   BufMsg;
		TItemObjItem   Obj;
	}indata;
};
typedef map<unsigned int,TTempItemHead*> MAPIDD_VOID;
typedef map<string,      TTempItemHead*> MAPKEY_VOID;

//超时回调接口
typedef boost::function< bool(unsigned int, TItemMsgItem *)> HandMsgBuf_TimeoutKeyUint;
typedef boost::function< bool(string      , TItemMsgItem *)> HandMsgBuf_TimeoutKeyStr;
typedef boost::function< bool(unsigned int, TItemObjItem *)> HandObjBuf_TimeoutKeyUint;
typedef boost::function< bool(string      , TItemObjItem *)> HandObjBuf_TimeoutKeyStr;

//下面的实现的类头文件定义:


//临时结构体,简单的结构体,可以使用memcpy来拷贝对象。类不能使用,如果是类使用下面的对象。

class CGsDllMsgTBufMg
{
public:
	static CGsDllMsgTBufMg * single(){ static CGsDllMsgTBufMg _check; return &_check; }

private:
	CGsDllMsgTBufMg(){}
public:
	~CGsDllMsgTBufMg(void){}

public:
        //添加一个对象,pdata 指向你要保存的数据结构,这个对象可以使用memcpy来复制。
        //如果你选择的是字符串key,需要注意自己定义规则,不要重复,重复会添加失败,
        TItemMsgItem        *add( string        ukey,const char *pdata, unsigned int datalen, unsigned int maxkeeptimelen/*秒*/  );
	TItemMsgItem        *add( unsigned int &ukey,const char *pdata, unsigned int datalen, unsigned int maxkeeptimelen/*秒*/  );
	bool                 del( string vkey );
	bool                 del( unsigned int vkey );
	void                 delvoid( unsigned int vkey ){del(vkey);}

	const TItemMsgItem * find( string vkey );
	const TItemMsgItem * find( unsigned int vkey );

	void                 run();
	void                 uninit();

	void                 setcbfun_msguint( HandMsgBuf_TimeoutKeyUint  msgcb_uint);
	void                 setcbfun_msgstr(  HandMsgBuf_TimeoutKeyStr   msgcb_str);
};

//临时对象
//
class CGsDllTempTObjMg
{
public:
	static CGsDllTempTObjMg * single(){ static CGsDllTempTObjMg _check; return &_check; }

private:
	CGsDllTempTObjMg(){}
public:
	~CGsDllTempTObjMg(void){}

public:
	bool 	             add( string        ukey, const  CTempObjItem *pObj,unsigned int maxkeeptimelen/*秒*/  );
	bool                 add( unsigned int &ukey, const  CTempObjItem *pObj,unsigned int maxkeeptimelen/*秒*/  );
	bool                 del( string vkey );
	bool                 del( unsigned int vkey );

	const CTempObjItem * find( string vkey );
	const CTempObjItem * find( unsigned int errorid );

	void                 setcbfun_objuint( HandObjBuf_TimeoutKeyUint  objcb_uint);
	void                 setcbfun_objstr(  HandObjBuf_TimeoutKeyStr   objcb_str );
};



   这个函数接口用来设置超时回调,通知上层逻辑,当然你也可以不设置,

    void                 setcbfun_msguint( HandMsgBuf_TimeoutKeyUint  msgcb_uint);
    void                 setcbfun_msgstr(  HandMsgBuf_TimeoutKeyStr   msgcb_str);

一个使用的例

	//保存
	WebServiceGmcmdRep  repMsg;
	repMsg.gm_gtserverid  = pmsg->gm_gtserverid;
	repMsg.gm_usertemp_id = pmsg->gm_usertemp_id;
	repMsg.webss_index    = pmsg->webss_index;
	repMsg.webss_serverid = pmsg->webss_serverid;
	unsigned int ukeybuf  = 0;
	TItemMsgItem *pItem = CTempMsgBufferMg::single()->add( ukeybuf,(char*)&repMsg,repMsg.Len,200 );
	if( !pItem )
		return;


	//得到
	const TItemMsgItem *pADD = CTempMsgBufferMg::single()->find( ukeybuf );
	if( !pADD )
		return;
	WebServiceGmcmdRep *pMsg = (WebServiceGmcmdRep*)pADD->m_pbuff;





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值