SWFCDB的研究与探索 第8页
据就从刚才提交的缓冲区中直接被发送出去,与其他I/O模型的“程序数据缓冲区 socket 底层缓冲区网络”相比节省了一次复制操作。
对于WSARecv()操作,正常接收数据时,直接将socket 底层缓冲区数据复制到程序数据缓冲区,但是如果接收缓冲区中暂时没有数据,那WSARecv()中指定的缓冲区就会被锁定到系统非分页内存池以等待数据到来,当数据到来时直接将数据从网络复制到刚才指定的程序数据缓冲区,因而又节约了一次内存复制。
5.2.1 回调机制
为使完成端口I/O模型对数据的处理具有伸缩性及可扩张性,对接收数据的处理采用回调机制[6]或多态(即重写CIocp类虚函数IOCPRecv())。对于回调机制,只需在启动服务器器函数(IOCPStart())中,将数据处理函数名作为参数就可实现回调机制。回调函数原型声明为:
typedef void (*LPIOCP_RECV_CALLBACK)(TASK_QUEUE_ITEM tqi, CIocp* pIocp);
5.2.2 线程池设计
线程池线程由管理者线程和工作者线程组成。管理者线程如何分配工作者线程任务以及协调多线程程序设计中的同步与异步问题,是设计线程池的一个难点。
本线程池采用Event对象[9],通过程序控制Event对象的激发和非激发状态,来实现管理者线程对工作者线程的控制。SetEvent()函数设置Event对象为激发状态,ResetEvent()函数设置Event 对象为非激发状态。
在工作者线程创建时,管理者线程传给工作者的参数中包含hEvent和hEventWorkFinished两个Event对象,这两个Event对象就是实现线程池的关键。
函数:
DWORD WaitForSingleObject (
HANDLE hHandle,
DWORD dwMilliseconds
);
的作用是当hHandle 指向的对象处于激活状态时,函数返回,否则函数一直阻塞。将该函数用在循环中,通过控制hHandle指向的对象的状态就可以控制线程的阻塞和非阻塞状态。
函数:
DWORD WaitForMultipleObjects(
DWORD nCount,
const HANDLE* lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds
);
是上面WaitForSingleObject()函数的扩展版本,同时可以检测多个HANDLE对象的状态,管理者线程将用该函数实现对多个Event 对象进行检测(hRecvEvent激活为接收数据队列中有未处理数据)。
创建工作者线程时,hEvent和hEventWorkFinished处于非激活状态,工作者线程和管理者线程处于阻塞状态,当接收数据队列中存在未处理数据时,设置hRecvEvent为激活状态,则管理者线程激活(处于非阻塞状态),从接收数据队列中取出队头未处理任务(设置hRecvEvent为非激活状态),然后设置hEvent对象为激活状态(此时管理者线程可能又处于阻塞状态),工作者线程被激活,然后工作者线程设置hEvent为非激活状态,工作者线程处理任务,当处理完任务后,工作者线程设置hEventWorkFinished对象为激活状态(此时工作者线程处于阻塞状态,等待hEvent对象再次被激发),管理者线程知道该工作者线程已完成任务,检查任务队列中是否有未处理任务,如果有,则取出任务,设置hEvent为激活状态,工作者线程处理任务;如果没有,则管理者线程结束此次循环进入下次循环。如此循环,则实现了管理者线程对工作者线程的任务分配。
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] 下一页
SWFCDB的研究与探索 第8页下载如图片无法显示或论文不完整,请联系qq752018766