Original article title: Socket errors and resource release methods in iocp
Author: sodimethyl
Address: http://blog.csdn.net/sodme/archive/2006/04/17/666062.aspx
Original Author's statement: This article can be reproduced, reproduced, or disseminated without the author's consent. However, any reference to this article must retain the author, source, and statement information of this article! Thank you! This article is an article in Guan dabao sodimethyl's blog. The original Article mentions two methods (using the reference counting mechanism for the data buffer and linear the release operation on the clientsock Object Design Mechanism ), however, we only discuss the implementation of the 2nd methods. In fact, in a multi-threaded program, it is not easy to make a release operation linear. This is not just a problem with multiple iocp working threads (generally, we will set up two iocp working threads for each CPU), and also involve other business logic threads. For example, we usually (as mentioned in this Article) bind the clientsocket and the receiving buffer to a session object. (To simplify the process, the overlapped mechanism is often not used to send data, instead, it directly uses an asynchronous send, so it does not need to send the buffer), and this object may be used by other threads except the iocp working thread, for example, the processing thread of an event queue (We will generate an event object when we receive the data and place it in the team instance for processing in a way similar to the command mode, and these event objects will reference session objects), or, a container may store a reference of these session objects for sending heartbeat packets, session counts, and retrieval at regular intervals, at this time, the destruction of session objects is not that simple. In other words, it is not enough to simply "unify the destruction work into the function for executing getqueuedcompletionstatus. In this case, the 1st "reference counting" methods mentioned in this article are more elegant. In many of my practical applications, the Session object is designed to be a "reference count" without exposing its destructor. Instead, it is automatically destroyed when the reference count is reduced to 0, this ensures that "it will be released only when no one uses it ". Using the C ++ template, you can easily simulate the Security pointer for automatic reference counting:
001:/****************************************** ******************************
002:Reference counting base class and reference counting pointer template class
003:---- Nosound qq2591570 can be copied, modified, used, or made on demand!
004:**************************************** ********************************/
005:# Ifndef_ Refcounted_included _
006:# Define_ Refcounted_included _
007:
008:# Include<Cassert>
009:# Ifdef_ Mt
010:# Include<Windows. h>
011:# Endif
012:
013:ClassRefcountable {
014:Public:
015: intAddref(Void ){
016:# Ifdef_ Mt
017:Return::Interlockedincrement(& Refcount _);
018:# Else
019:Return++ Refcount _;
020:# Endif
021 :}
022:
023: intDecref(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:ReturnR;
034 :}
035:
036: intGetrefcount(Void)Const{ReturnRefcount _;}
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(ConstRefcountable &);
050: refcountable &Operator= (ConstRefcountable &);
051 :};
052:
053:Template<ClassT>
054:ClassRefcountedptr {
055:Public:
056:Refcountedptr(Void ):PTR _(0 ){}
057:Refcountedptr(T * PTR ):PTR _(PTR ){
058:If(PTR _)
059: PTR _->Addref();
060 :}
061:Refcountedptr(ConstRefcountedptr <t> & sour ):PTR _(Sour. PTR _){
062:If(PTR _)
063: PTR _->Addref();
064 :}
065: refcountedptr &Operator= (ConstRefcountedptr <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:FriendBoolOperator= (ConstRefcountedptr <t> & left,ConstRefcountedptr <t> & right ){
084:Return(Left. PTR _ = right. PTR _);
085 :}
086:FriendBoolOperator! = (ConstRefcountedptr <t> & left,ConstRefcountedptr <t> & right ){
087:Return(Left. PTR _! = Right. PTR _);
088 :}
089:FriendBoolOperator<(ConstRefcountedptr <t> & left,ConstRefcountedptr <t> & right ){
090:Return(Left. PTR _ <right. PTR _);
091 :}
092:FriendBoolOperator> (ConstRefcountedptr <t> & left,ConstRefcountedptr <t> & right ){
093:Return(Left. PTR _> right. PTR _);
094 :}
095:FriendBoolOperator<= (ConstRefcountedptr <t> & left,ConstRefcountedptr <t> & right ){
096:Return(Left. PTR _ <= right. PTR _);
097 :}
098:FriendBoolOperator> = (ConstRefcountedptr <t> & left,ConstRefcountedptr <t> & right ){
099:Return(Left. PTR _> = right. PTR _);
100 :}
101:
102: boolIsnull()Const{Return0 = PTR _;}
103: boolIsvalid()Const{Return0! = PTR _;}
104:
105://Returns the controlled object pointer.
106: T *Get(Void)Const{ReturnPTR _;}
107:
108://Get control of another pointer
109: voidReset(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 _