开源 IOCP封装类

G_8519 2011-07-13 02:46:33

IOCP.hpp

#pragma once

#include <Windows.h>
#include <vector>
#include <assert.h>


using namespace std;





#define IO完成端口_退出线程 -1


class IO完成端口
{

// 声明友元函数
friend IO完成端口* 创建IO完成端口实例( DWORD 工作线程数 = 0 );
friend VOID 销毁IO完成端口实例( IO完成端口 *IO完成端口实例 );

private:


protected:

IO完成端口();
~IO完成端口();

static DWORD 工作线程( IO完成端口 *IO完成端口实例 );


HANDLE 私有_IO完成端口对象句柄;
vector<HANDLE> 私有_工作线程句柄表;

public:

typedef VOID (*回调函数)(
DWORD 错误号,
DWORD IO完成字节数,
LPOVERLAPPED 重叠IO结构
);

BOOL 绑定IO对象(
HANDLE IO对象句柄,
回调函数 完成事件处理函数,
DWORD 并发线程数 = 0
);

};




// 创建类实例
IO完成端口* 创建IO完成端口实例( DWORD 工作线程数 )
{

// 创建类实例
IO完成端口 *IO完成端口实例 = new IO完成端口;
if ( IO完成端口实例 == NULL )
return NULL;



// 创建 IO完成端口对象
IO完成端口实例->私有_IO完成端口对象句柄 = CreateIoCompletionPort( (HANDLE)-1, NULL, NULL, 0 );
if ( IO完成端口实例->私有_IO完成端口对象句柄 == NULL )
{
delete IO完成端口实例;
return NULL;
}



// 确定工作线程数
if ( 工作线程数 == 0 )
{
SYSTEM_INFO SysInf;
GetSystemInfo( &SysInf );

工作线程数 = SysInf.dwNumberOfProcessors * 2;
if ( 工作线程数 == 0 )
工作线程数 = 2;
}



// 创建工作线程
for ( DWORD i = 0; i < 工作线程数; i++ )
{
HANDLE 线程句柄 = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)IO完成端口实例->工作线程, IO完成端口实例, 0, NULL );
if ( 线程句柄 != NULL )
IO完成端口实例->私有_工作线程句柄表.push_back( 线程句柄 );
}



// 创建工作线程失败
if ( IO完成端口实例->私有_工作线程句柄表.size() == 0 )
{
CloseHandle( IO完成端口实例->私有_IO完成端口对象句柄 );

delete IO完成端口实例;
return NULL;
}


return IO完成端口实例;
}


// 销毁类实例
VOID 销毁IO完成端口实例( IO完成端口 *IO完成端口实例 )
{
assert( IO完成端口实例 );

DWORD 线程数 = IO完成端口实例->私有_工作线程句柄表.size();



// 向所有工作线程投递退出通知
for ( DWORD i = 0; i < 线程数; i++ )
PostQueuedCompletionStatus( IO完成端口实例->私有_IO完成端口对象句柄, 0, IO完成端口_退出线程, NULL );



// 等待所有工作线程退出
for ( DWORD i = 0; i < 线程数; i++ )
{
HANDLE 线程句柄 = IO完成端口实例->私有_工作线程句柄表[i];

// 等待退出, 如果超时则强制关闭
if ( WaitForSingleObject( 线程句柄 , 5000 ) == WAIT_TIMEOUT )
TerminateThread( 线程句柄, IO完成端口_退出线程 );

CloseHandle( 线程句柄 );
}

// 清空句柄表
IO完成端口实例->私有_工作线程句柄表.clear();



// 关闭IO完成端口对象句柄
CloseHandle( IO完成端口实例->私有_IO完成端口对象句柄 );



// 删除IO完成端口实例
delete IO完成端口实例;
}


// 构造函数
IO完成端口::IO完成端口()
:私有_IO完成端口对象句柄( NULL )
{
}

// 析构函数
IO完成端口::~IO完成端口()
{
}



// IO对象与IO完成端口绑定
BOOL IO完成端口::绑定IO对象(
HANDLE IO对象句柄,
回调函数 完成事件处理函数,
DWORD 并发线程数
)
{
assert( 完成事件处理函数 );

return ( NULL != CreateIoCompletionPort(IO对象句柄, 私有_IO完成端口对象句柄, (ULONG_PTR)完成事件处理函数, 并发线程数) );
}



// 工作者线程, 负责 等待完成事件, 回调处理函数
DWORD IO完成端口::工作线程( IO完成端口 *IO完成端口实例 )
{

HANDLE IO完成端口对象句柄 = IO完成端口实例->私有_IO完成端口对象句柄;


DWORD IO完成字节数 = 0;
ULONG_PTR 用户参数 = NULL;
LPOVERLAPPED 重叠IO结构 = NULL;

DWORD 错误号 = 0;


// GetQueuedCompletionStatus 循环
GQCS循环:
{
// 等待 IO完成事件
if ( FALSE != GetQueuedCompletionStatus(IO完成端口对象句柄, &IO完成字节数, &用户参数, &重叠IO结构, INFINITE) )
{
// 退出线程
if ( 用户参数 == IO完成端口_退出线程 )
return IO完成端口_退出线程;

错误号 = 0;
}
else
{
错误号 = GetLastError();

switch ( 错误号 )
{
case ERROR_INVALID_HANDLE:
{
return ERROR_INVALID_HANDLE;
}
case ERROR_ABANDONED_WAIT_0:
{
return ERROR_ABANDONED_WAIT_0;
}
}
}


if ( 用户参数 != NULL )
// 回调用户提供的事件处理函数
((回调函数)用户参数)( 错误号, IO完成字节数, 重叠IO结构 );


} goto GQCS循环;


}




demo

#include "stdafx.h"
#include "IO完成端口.hpp"

#include <assert.h>


struct MYOVERLAPPED
{
OVERLAPPED OverLapped;
HANDLE hFile;
DWORD dwBufLen;
BYTE *lpBuffer;
};



VOID IO完成事件处理函数(
DWORD 错误号,
DWORD IO完成字节数,
LPOVERLAPPED 重叠IO结构
)
{
printf( "IO完成事件处理函数: 错误 %d, IO完成字节数 %d, 重叠IO结构 %d .\n", 错误号, IO完成字节数, 重叠IO结构 );



// 继续读
MYOVERLAPPED *myol = (MYOVERLAPPED *)重叠IO结构;
SetFilePointer( myol->hFile, IO完成字节数, 0, FILE_CURRENT );
ReadFile( myol->hFile, myol->lpBuffer, myol->dwBufLen, NULL, 重叠IO结构 );

}


int _tmain(int argc, _TCHAR* argv[])
{

IO完成端口 *IO完成端口实例 = 创建IO完成端口实例();
assert( IO完成端口实例 );



HANDLE hFile = CreateFile( TEXT("F:\\Fraps\\Movies\\fsx 2011-07-01 13-48-21-66.avi"),
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );


// 文件对象与IO完成端口关联
IO完成端口实例->绑定IO对象( hFile, IO完成事件处理函数 );



MYOVERLAPPED *myol = new MYOVERLAPPED;
memset( myol, 0, sizeof(MYOVERLAPPED) );


myol->hFile = hFile;
myol->dwBufLen = 4096;
myol->lpBuffer = new BYTE[myol->dwBufLen];


// 异步读文件
if ( FALSE == ReadFile( hFile, myol->lpBuffer, myol->dwBufLen, NULL, (LPOVERLAPPED)myol ) )
assert( GetLastError() == ERROR_IO_PENDING );



getchar();


销毁IO完成端口实例( IO完成端口实例 );

delete[] myol->lpBuffer;
delete myol;

CloseHandle( hFile );


return 0;
}
...全文
509 24 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
牛魔皇 2013-08-20
  • 打赏
  • 举报
回复
好神奇!!!!哈哈
cjl_852006 2012-07-05
  • 打赏
  • 举报
回复
请问在IOCP中怎样加入socket用来监听呢?
__lhy 2011-07-14
  • 打赏
  • 举报
回复
G_8519 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 blukercn 的回复:]
诡异。。。
[/Quote]

  • 打赏
  • 举报
回复
诡异。。。
G_8519 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 hurryboylqs 的回复:]
看着这程序代码就觉得很搞笑
[/Quote]

有什么好笑的

谁规定的不能写中文代码了
hurryboylqs 2011-07-13
  • 打赏
  • 举报
回复
看着这程序代码就觉得很搞笑
HBack 2011-07-13
  • 打赏
  • 举报
回复
............这个太强大咧
b2b160 2011-07-13
  • 打赏
  • 举报
回复
使用了混淆器么?
b2b160 2011-07-13
  • 打赏
  • 举报
回复
我的天啊!!!
zwfgdlc 2011-07-13
  • 打赏
  • 举报
回复
差不多赶上易语言了。
不说害怕 2011-07-13
  • 打赏
  • 举报
回复
vs2005也可以呢。nnd。啥时候全部变中文呢。
不说害怕 2011-07-13
  • 打赏
  • 举报
回复

vs2010好强大。哈哈。以后直接全部中文都可以吧
hnzlk 2011-07-13
  • 打赏
  • 举报
回复
G_8519 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 shenyi0106 的回复:]
这样写看着挺别扭的
[/Quote]

shenyi0106 2011-07-13
  • 打赏
  • 举报
回复
这样写看着挺别扭的
G_8519 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 shenyi0106 的回复:]
现有的C++编译器能通过?
[/Quote]

vs 2010 编译通过
shenyi0106 2011-07-13
  • 打赏
  • 举报
回复
现有的C++编译器能通过?
  • 打赏
  • 举报
回复
学习学习
Eleven 2011-07-13
  • 打赏
  • 举报
回复
加载更多回复(4)

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧