分享
 
 
 

狗尾续貂:利用引用计数在多线程中安全释放资源

王朝other·作者佚名  2007-01-19
窄屏简体版  字體: |||超大  

原文标题:IOCP中的socket错误和资源释放处理方法

原文作者:sodme

原文地址:http://blog.csdn.net/sodme/archive/2006/04/17/666062.aspx

原作者声明:本文可以不经作者同意任意转载、复制、传播,但任何对本文的引用均须保留本文的作者、出处及本行声明信息!谢谢!

本文是观大宝SODME的BLOG中文章有感,原文中提到了两种方法(对数据缓冲区使用引用计数机制、在clientsock的对象设计机制上使释放操作线性化),但只讨论了第2种方法的实现。其实在多线程程序里,要让一个释放操作线性化,并不是一件容易的事情,这不仅仅是多个IOCP工作线程的问题(一般来说,我们会为每个CPU设立两个IOCP工作线程),还涉及到其他业务逻辑线程的问题。

比方说,我们通常(就象文中也提到的)会将ClientSocket与接收缓冲区绑定到一个会话对象中(为简化起见,发送数据往往没有用overlapped机制,而是直接用一个异步send,也就不需要发送缓冲区),而这个对象可能被除IOCP工作线程以外的其他线程也用到,比方说一个事件队列的处理线程(我们会在收到数据的时候生成事件对象置入队例中,以类似于Command模式的方法来处理,而这些事件对象会引用到会话对象),或者,也许有某个容器会存放这些会话对象的一个引用,用于定时发送心跳包、会话计数、检索等等,这个时候,会话对象的销毁就不是那么简单的了,换句话说,仅靠“将销毁工作统一到执行GetQueuedCompletionStatus的函数里“是不够的。

在这种情况下,文中提到的第1种“采用引用计数”的方法就比较优雅了,在我的很多实际应用中,都是将会话对象设计为“可引用计数”的,不暴露它的析构函数,而是当引用计数减到0的时候,自动销毁,这样就保证“仅当没有任何人使用它的时候才会释放它”。

利用C++的模板,可以十分方便地模拟出自动引用计数的安全指针:

001: /************************************************************************

002: 引用计数基类、及引用计数指针模板类

003: ----NoSound QQ2591570 可随意复制、改动、使用、拍砖,概不追究!

004: ************************************************************************/

005: #ifndef _REFCOUNTED_INCLUDED_

006: #define _REFCOUNTED_INCLUDED_

007:

008: #include <cassert>

009: #ifdef _MT

010: #include <Windows.h>

011: #endif

012:

013: class RefCountable {

014: public:

015: int addRef(void) {

016: #ifdef _MT

017: return ::InterlockedIncrement(&refCount_);

018: #else

019: return ++refCount_;

020: #endif

021: }

022:

023: int decRef(void) {

024: int r =

025: #ifdef _MT

026: ::InterlockedDecrement(&refCount_);

027: #else

028: --refCount_;

029: #endif

030: assert(r>=0);

031: if (0==r)

032: delete this;

033: return r;

034: }

035:

036: int getRefCount(void) const { return refCount_; }

037:

038: protected:

039: RefCountable(void) : refCount_(0) {}

040: virtual ~RefCountable(void) { assert(0==refCount_); }

041:

042: private:

043: #ifdef _MT

044: long

045: #else

046: int

047: #endif

048: refCount_;

049: RefCountable(const RefCountable &);

050: RefCountable & operator = (const RefCountable &);

051: };

052:

053: template<class T>

054: class RefCountedPtr {

055: public:

056: RefCountedPtr(void) : ptr_(0) {}

057: RefCountedPtr(T *ptr) : ptr_(ptr) {

058: if (ptr_)

059: ptr_->addRef();

060: }

061: RefCountedPtr(const RefCountedPtr<T> &sour) : ptr_(sour.ptr_) {

062: if (ptr_)

063: ptr_->addRef();

064: }

065: RefCountedPtr & operator = (const RefCountedPtr<T> &right) {

066: if (this!=&right) {

067: if (0!=ptr_)

068: ptr_->decRef();

069: ptr_ = right.ptr_;

070: if (ptr_)

071: ptr_->addRef();

072: }

073: return *this;

074: }

075: ~RefCountedPtr(void) {

076: if (0!=ptr_)

077: ptr_->decRef();

078: }

079:

080: T & operator*() const { return *ptr_; }

081: T * operator->() const { return (&**this); }

082:

083: friend bool operator == (const RefCountedPtr<T> &left, const RefCountedPtr<T> &right) {

084: return (left.ptr_ == right.ptr_);

085: }

086: friend bool operator != (const RefCountedPtr<T> &left, const RefCountedPtr<T> &right) {

087: return (left.ptr_ != right.ptr_);

088: }

089: friend bool operator < (const RefCountedPtr<T> &left, const RefCountedPtr<T> &right) {

090: return (left.ptr_ < right.ptr_);

091: }

092: friend bool operator > (const RefCountedPtr<T> &left, const RefCountedPtr<T> &right) {

093: return (left.ptr_ > right.ptr_);

094: }

095: friend bool operator <= (const RefCountedPtr<T> &left, const RefCountedPtr<T> &right) {

096: return (left.ptr_ <= right.ptr_);

097: }

098: friend bool operator >= (const RefCountedPtr<T> &left, const RefCountedPtr<T> &right) {

099: return (left.ptr_ >= right.ptr_);

100: }

101:

102: bool isNull() const { return 0==ptr_; }

103: bool isValid() const { return 0!=ptr_; }

104:

105: // 返回所控制的对象指针

106: T * get(void) const { return ptr_; }

107:

108: //取得对另一指针的控制权

109: void reset(T * ptr=0) {

110: if (0!=ptr)

111: ptr->addRef();

112: if (0!=ptr_)

113: ptr_->decRef();

114: ptr_ = ptr;

115: }

116:

117: private:

118: T *ptr_;

119: };

120:

121: #endif // ifndef _REFCOUNTED_INCLUDED_

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有