大坡3D软件开发

关注3D软件技术

用户操作
[即时聊天] [发私信] [加为好友]
蔡军生ID:caimouse
1237739次访问,排名17好友253人,关注者413
C++,3D,VC++软件开发,写技术文章,操作系统开发
caimouse的文章
原创 603 篇
翻译 0 篇
转载 41 篇
评论 940 篇
蔡军生的公告

点击这里给我发消息

MSN: caimouse1976 at sina.com

最近评论
maray:这个做量的生意还是不错哈~
雇几个C++比较好的大学生做兼职,负责回答问题,哈哈~very nice~
xavierye:发现另外一个源码分析blog:
http://www.cnblogs.com/duguguiyu/archive/2008/10/02/1303095.html
shada:前面两个混帐,没资格评论开源。
用着盗版的Word写文章批评开源的人真不少。
shada:前面两个混帐,没资格评论开源。
用着盗版的Word写文章批评开源的人大有人在。
andylrj:Google的浏览器真差劲!!!体验一把真心说出,要做的事还很多,终于明白微软的IE为什么要做这么庞大了,做小确实不行!
文章分类
收藏
相册
3D引擎
第二人生
谷歌浏览器
开发板
历史回忆
常用连接
人生历程
存档
软件项目交易
订阅我的博客
XML聚合  FeedSky

原创 Windows API一日一练(60)CreateIoCompletionPort和GetQueuedCompletionStatus函数收藏

新一篇: Windows API一日一练(61)GetDriveType函数 | 旧一篇: Windows API一日一练(59)CreateFileMapping和MapViewOfFile函数

Windows系统里,使用完成端口是高性能的方法之一,比如把完成端口使用到线程池和网络服务器里。现在就通过线程池的方法来介绍怎么样使用完成端口,高性能的服务器以后再仔细地介绍怎么样构造它。其实完成端口是一个队列,所有的线程都在等消息出现,如果队列里有消息,就每个线程去获取一个消息执行它。先用函数CreateIoCompletionPort来创建一个消息队列,然后使用GetQueuedCompletionStatus函数来从队列获取消息,使用函数PostQueuedCompletionStatus来向队列里发送消息。通过这三个函数就实现完成端口的消息循环处理。
 
函数CreateIoCompletionPortGetQueuedCompletionStatusPostQueuedCompletionStatus声明如下:
 
WINBASEAPI
__out
HANDLE
WINAPI
CreateIoCompletionPort(
    __in     HANDLE FileHandle,
    __in_opt HANDLE ExistingCompletionPort,
    __in     ULONG_PTR CompletionKey,
    __in     DWORD NumberOfConcurrentThreads
    );
WINBASEAPI
BOOL
WINAPI
GetQueuedCompletionStatus(
    __in HANDLE CompletionPort,
    __out LPDWORD lpNumberOfBytesTransferred,
    __out PULONG_PTR lpCompletionKey,
    __out LPOVERLAPPED *lpOverlapped,
    __in DWORD dwMilliseconds
    );
 
WINBASEAPI
BOOL
WINAPI
PostQueuedCompletionStatus(
    __in     HANDLE CompletionPort,
    __in     DWORD dwNumberOfBytesTransferred,
    __in     ULONG_PTR dwCompletionKey,
    __in_opt LPOVERLAPPED lpOverlapped
    );
FileHandle是关联的文件句柄。
ExistingCompletionPort是已经存在的完成端口。
CompletionKey是传送给处理函数的参数。
NumberOfConcurrentThreads是有多少个线程在访问这个消息队列。
CompletionPort是已经存在的完成端口。
lpCompletionKey是传送给处理函数的参数。
lpOverlapped是传送给处理函数的参数。
dwMilliseconds是等待时间。
dwNumberOfBytesTransferred是传送了多少个字节。
 
调用函数的例子如下:
#001 #pragma once
#002 
#003 #include "Thread.h"
#004 
#005 
#006 //使用IOCP实现线程池。
#007 //蔡军生 2007/10/29 QQ:9073204 深圳
#008 class CThreadPools
#009 {
#010 public:
#011 
#012  CThreadPools(void)
#013  {
#014          m_nThreadCount = 2;
#015   }
#016 
#017  ~CThreadPools(void)
#018  {
#019  }
#020 
#021  bool Init(void)
#022  {
#023         //创建一个IOCP
#024         m_hQueue = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, m_nThreadCount);
#025         if (m_hQueue == NULL)
#026         {
#027               //创建IOCP失败。
#028               return false;
#029         }
#030  }
#031 
#032  int GetThreadCount(void) const
#033  {
#034         return m_nThreadCount;
#035  }
#036 
#037  //线程池处理的内容。
#038  DWORD Run(void)
#039  {
#040         DWORD dwBytesTransfered;
#041         ULONG_PTR dwCompletionKey;
#042 
#043         OVERLAPPED* pOverlapped;
#044 
#045         //等一个IOCP的消息。
#046        while (GetQueuedCompletionStatus(m_hQueue, &dwBytesTransfered, &dwCompletionKey, &pOverlapped, INFINITE))
#047         {
#048               if (pOverlapped == ((OVERLAPPED*) ((__int64) -1)) )
#049               {
#050                    //退出。
#051                    OutputDebugString(_T("退出 \r\n"));
#052                    break;
#053               }
#054               else                                            
#055        
#056               {
#057                    WPARAM request = (WPARAM) dwCompletionKey;
#058 
#059                    //处理消息。
#060                    OutputDebugString(_T("GetQueuedCompletionStatus \r\n"));
#061               }
#062         }
#063 
#064         return 0;
#065  }
#066 
#067  //发送处理的消息。
#068  bool QueueRequest(WPARAM wParam)
#069  {        
#070         //IOCP里发送一条消息。
#071        if (!PostQueuedCompletionStatus(m_hQueue, 0, (ULONG_PTR) wParam, NULL))
#072         {
#073               return false;
#074         }
#075        
#076         return true;
#077  }
#078 
#079  //关闭所有线程。
#080  void Close(void)
#081  {
#082         for (int i = 0; i < m_nThreadCount; i++)
#083         {
#084               PostQueuedCompletionStatus(m_hQueue, 0, 0, (OVERLAPPED*) ((__int64) -1) );
#085         }
#086  }
#087 
#088 protected:
#089  //接收消息处理的队列。
#090  HANDLE m_hQueue;
#091 
#092  //线程个数。
#093  int m_nThreadCount;
#094 };
#095 
#096 //////////////////////////////////////////////////////////////////////////
#097 class CThreads :
#098  public CThread
#099 {
#100 public:
#101  CThreads(CThreadPools* pPool)
#102  {
#103          m_pPool = pPool;        
#104  }
#105  virtual ~CThreads(void)
#106  {
#107 
#108  }
#109 
#110 
#111 protected:
#112  //
#113  //线程运行函数。
#114  //在这里可以使用类里的成员,也可以让派生类实现更强大的功能。
#115  //蔡军生 2007/10/29
#116  virtual DWORD Run(void)
#117  {
#118         //
#119         if (m_pPool)
#120         {
#121               return m_pPool->Run();
#122         }
#123 
#124         return -1;
#125  }
#126 
#127 protected:
#128  CThreadPools* m_pPool;
#129 
#130 };
 

发表于 @ 2007年10月29日 21:41:00|评论(loading...)|编辑

新一篇: Windows API一日一练(61)GetDriveType函数 | 旧一篇: Windows API一日一练(59)CreateFileMapping和MapViewOfFile函数

评论

#Waiting4you 发表于2007-10-31 13:25:40  IP: 221.224.23.*
以后用机会用用, 不知道它是不是相当于一个线程安全的公共队列? 类似于线程消息队列? 从MSDN上看好像很复杂的样子
先收藏
#zhangjie830621 发表于2008-07-16 16:02:05  IP: 61.189.37.*
蔡老师,好久没有在Q上看到你,今天又从你的BLOG上,受益了!
发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © 蔡军生