转载至: http://blog.chinaunix.net/uid-28748731-id-3540287.html
1.Handlerset类的作用
类HandlerSet:Handler集合.Handler是什么呢?它是一种专门用于执行socket操作的任务(函数),HandlerSet被TaskScheduler用来管理所有的socket任务(增删改查);可以对每一个sock描述符实现不同的操作,以实现多态;
在BasicTaskScheduler0任务管理类中,包含HandlerSet* fHandlers,以实现对套接字的任务管理;
例如:在RTSP服务器建立的时候,在RTSPServer的构造函数RTSPServer::RTSPServer中会调用env.taskScheduler().turnOnBackgroundReadHandling,然后会调用BasicTaskScheduler::setBackgroundHandlingsetBackgroundHandling();把新建立的套接字,与RTSPServer::incomingConnectionHandlerRTSP建立一个HandlerDescriptort,来实现在服务器的listen套接字上接受新建立的链接;
2.HandlerDescriptort链表节点
HandlerDescriptort类,提供了sock描述符上的操作,把一个套接字描述符与一个操作,和一个私有数据结合起来;这个类相当于Handlerset双向链表的子节点;
类的定义:
点击(此处)折叠或打开
- class HandlerDescriptor {
- HandlerDescriptor(HandlerDescriptor* nextHandler);
- virtual ~HandlerDescriptor();
- public:
- int socketNum; //
- int conditionSet;
- TaskScheduler::BackgroundHandlerProc* handlerProc;
- void* clientData;
- private:
- // Descriptors are linked together in a doubly-linked list:
- friend class HandlerSet;
- friend class HandlerIterator;
- HandlerDescriptor* fNextHandler;
- HandlerDescriptor* fPrevHandler;
- };
类的构造函数为:
nextHandler为新建结点的下一个结点的指针,一般的使用方法为:HandlerDescriptor(fHandlers.fNextHandler);fHandlers为双向链表的头指针,把新建里的节点插入到头部节点的后面;
- HandlerDescriptor::HandlerDescriptor(HandlerDescriptor* nextHandler):conditionSet(0), handlerProc(NULL)
- {
- // Link this descriptor into a doubly-linked list:
- if (nextHandler == this) { // initialization仅仅用于创建一个新的双向链表,在HandlerSet的构造函数中
- fNextHandler = fPrevHandler = this;
- } else {
- fNextHandler = nextHandler;
- fPrevHandler = nextHandler->fPrevHandler;
- nextHandler->fPrevHandler = this;
- fPrevHandler->fNextHandler = this;
- }
- }
3.Handlerset双向链表
Handlerset主要实现了一个 HandlerDescriptort的双向链表,并实现了对链表的插入,查找,删除的操作;点击(此处)折叠或打开
- class HandlerSet {
- public:
- HandlerSet();
- virtual ~HandlerSet();
- /* 把一个新的sock插入双向链表中,在HandlerDescriptor对象中建立socket和handler之间的关系;*/
- void assignHandler(int socketNum, int conditionSet, TaskScheduler::BackgroundHandlerProc* handlerProc, void* clientData);
- void clearHandler(int socketNum); //删除相应的节点
- void moveHandler(int oldSocketNum, int newSocketNum);//改变套接字描述符为新的套接字描述符
-
- private:
- HandlerDescriptor* lookupHandler(int socketNum);//根据套接字查找相应的处理函数,没有找到则返回NULL
-
- private:
- friend class HandlerIterator;
- HandlerDescriptor fHandlers; // handler双向链表的头结点
- };
点击(此处)折叠或打开
- void HandlerSet::assignHandler(int socketNum, int conditionSet, TaskScheduler::BackgroundHandlerProc* handlerProc, void* clientData) {
- // First, see if there's already a handler for this socket:
- HandlerDescriptor* handler = lookupHandler(socketNum);
- if (handler == NULL) { // No existing handler, so create a new descr:
- handler = new HandlerDescriptor(fHandlers.fNextHandler);//头结点的下一个节点
- handler->socketNum = socketNum;
- }
-
- handler->conditionSet = conditionSet;
- handler->handlerProc = handlerProc;
- handler->clientData = clientData;
- }
4.类HandlerIterator
类HandlerIterator主要实现在HandlerSet中的迭代容器,next函数返回set中的下一个HandlerDescriptor,并保存当前的查找位置;
- class HandlerIterator {
- public:
- HandlerIterator(HandlerSet& handlerSet);
- virtual ~HandlerIterator();
-
- HandlerDescriptor* next(); // returns NULL if none
- void reset();
-
- private:
- HandlerSet& fOurSet;
- HandlerDescriptor* fNextPtr;
- };
点击(此处)折叠或打开
- HandlerDescriptor* HandlerIterator::next() {
- HandlerDescriptor* result = fNextPtr;
- if (result == &fOurSet.fHandlers) // #toc, .toc, .mw-warning { border: 1px solid rgb(170, 170, 170); background-color: rgb(249, 249, 249); padding: 5px; font-size: 95%; }#toc h2, .toc h2 { display: inline; border: medium none; padding: 0px; font-size: 100%; font-weight: bold; }#toc #toctitle, .toc #toctitle, #toc .toctitle, .toc .toctitle { text-align: center; }#toc ul, .toc ul { list-style-type: none; list-style-image: none; margin-left: 0px; padding-left: 0px; text-align: left; }#toc ul ul, .toc ul ul { margin: 0px 0px 0px 2em; }#toc .toctoggle, .toc .toctoggle { font-size: 94%; }body { font-family: '宋体'; font-size: 10pt; text-align: justify; }table { }td { border-collapse: collapse; text-align: left; vertical-align: top 第一个插入链表的元素,也是最后一个元素,指向头部结点;每插入一个元素都排在头结点的后面;
- { // no more
- result = NULL;
- }
- else
- {
- fNextPtr = fNextPtr->fNextHandler;
- }
- return result;
- }