异步IO网络服务器设计(四) 会话生存期管理

全异步操作中存在一个问题,当一个client连接被断开的时候(client断开连接、server主动断开client或通讯故障),因为是异步的,我们无法知道在IO队列中是否还有该client的投递未被出列。盲目的删除client,释放内存(不管是真的释放了还是放进了对象池或内存池),可能会导致野指针错误或内存访问错误。如何避免?

一、间接访问client

      使用数据结构(数组或者map)保存指向client的二级指针,或者ID(ID与client建立一一对应的关系),通过数据结构单元来访问client。当需要释放client会话资源的时候,将数据结构中的二级指针指空,然后直接释放client资源。下一次通过ID查表或访问到该数据结构单元时,数据为空,代表该client已经失效了。

 

二、引用计数的智能指针

       我们可以自己写一个引用计数的智能指针或者直接使用boost::shared_ptr、tr1::shared_ptr,boost.asio就是这么干的。因为引用计数机制(通过原子操作),可以保证资源在正确的时间被安全释放。而且通过boost::shared_ptr,我们还可以方便的制定内存分配策略。

 

三、延迟释放

      将需要被释放的client会话指针放入一个列表中。每隔一段时间就把列表中的资源全部释放一次。个人认为这种方法不是很好,只是将出错的可能性降低了而已。

 

我用过间接访问方式和智能指针的方式。针对同一个client会话,存在多线程竞争的问题。如果是间接访问,我们可以针对每一个client会话建立一个原子锁。如果是用智能指针,其实引用计数机制的本质也一样是原子操作(相信读过shared_ptr源码或自己写过智能指针的兄弟都很明白)。自从看了boost.asio之后,我一直用智能指针了,配合内存分配策略,效率很不错。很多人说效率不高,如果我们直接把shared_ptr拿出来用当然效率不高了,特别是在频繁分配的场合。要注意shread_ptr内部会针对sp_count(其实也是一个二级指针加上引用计数)再做一次内存分配。boost.shared_ptr考虑到了这个问题,提供了自己管理内存的策略。利用该策略我们完全可以进行内存预分配并配合对象池或者内存池。具体请参考boost.shared_ptr说明文档或直接读源码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值