一个IOCP的小例子

#include <stdio.h>
#include <windows.h>

#define MAX_THREADS	16
#define BUFFER_SIZE (32*1024) // 32KB

#define KEY_FILE    0x00000001
#define KEY_START   0x00000002
#define KEY_EXIT    0x00000003

typedef struct _CHUNK
{
    OVERLAPPED overlapped;
    LPVOID buffer;
}
CHUNK, *PCHUNK;

HANDLE g_hSourceFile = NULL;
HANDLE g_hIOCompletionPort = NULL;
ULARGE_INTEGER g_uiReadPointer = {0};

int g_iResult = 0;

DWORD WINAPI IOCP_WorkThread(LPVOID lpParam);

int main(int argc, char** argv)
{
    HANDLE hThread[MAX_THREADS] = {NULL};
    SYSTEM_INFO systemInfo = {0};
    ULARGE_INTEGER fileSize = {0};
    OVERLAPPED StartOverlapped = {0};
    OVERLAPPED ExitOverlapped = {0};
    DWORD dwExitStatus = ERROR_SUCCESS;
    DWORD dwStatus = 0;
    DWORD dwNumProcessors = 2;
    UINT i = 0;

    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s <source file>\n", argv[0]);
        dwExitStatus = ERROR_INVALID_PARAMETER;
        goto EXIT;
    }

    GetSystemInfo(&systemInfo);
    dwNumProcessors = systemInfo.dwNumberOfProcessors;

    g_hSourceFile = CreateFile(
                        argv[1],
                        GENERIC_READ,
                        FILE_SHARE_READ,
                        NULL,
                        OPEN_EXISTING,
                        FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED,
                        NULL
                    );
    if (g_hSourceFile == INVALID_HANDLE_VALUE)
    {
        fprintf(stderr, "%s: Failed to open %s, error %d\n",
                argv[0],
                argv[1],
                dwExitStatus = GetLastError());

        goto EXIT;
    }

    fileSize.LowPart = GetFileSize(g_hSourceFile, &fileSize.HighPart);
    if ((fileSize.LowPart == 0xffffffff) && (GetLastError() != NO_ERROR))
    {
        fprintf(stderr, "%s: GetFileSize failed, error %d\n",
                argv[0],
                dwExitStatus = GetLastError());

        goto EXIT;
    }

    g_hIOCompletionPort = CreateIoCompletionPort(
                              g_hSourceFile,
                              NULL,
                              KEY_FILE,
                              dwNumProcessors
                          );
    if (g_hIOCompletionPort == NULL)
    {
        fprintf(stderr,
                "%s: Failed to create IO completion port (error %d)\n",
                argv[0],
                dwExitStatus = GetLastError());

        goto EXIT;
    }

    for ( i = 0; i < 2*dwNumProcessors; ++i )
    {
        hThread[i] = CreateThread(
                         NULL, 0,
                         (LPTHREAD_START_ROUTINE)IOCP_WorkThread,
                         (LPVOID)&fileSize,
                         0, NULL
                     );
        if (hThread[i] == NULL)
        {
            fprintf(stderr, "%s: Failed to create thread #%d (error %d)\n",
                    argv[0], i, dwExitStatus = GetLastError());

            goto EXIT;
        }
    }

    PostQueuedCompletionStatus(
        g_hIOCompletionPort,
        0,
        KEY_START,
        &StartOverlapped
    );
    dwStatus = WaitForMultipleObjects(
                   2*dwNumProcessors,
                   hThread,
                   FALSE,
                   INFINITE
               );
    if (dwStatus == WAIT_FAILED)
    {
        fprintf(stderr, "%s: Wait failed (error %d)\n",
                argv[0], dwExitStatus = GetLastError());

        goto EXIT;
    }

    for ( i = 0; i < 2*dwNumProcessors - 1; ++i )
    {
        PostQueuedCompletionStatus(
            g_hIOCompletionPort,
            0,
            KEY_EXIT,
            &ExitOverlapped
        );
    }
    dwStatus = WaitForMultipleObjects(
                   2*dwNumProcessors,
                   hThread,
                   TRUE,
                   INFINITE
               );
    if (dwStatus == WAIT_FAILED)
    {
        fprintf(stderr, "%s: Wait failed (error %d)\n",
                argv[0], dwExitStatus = GetLastError());

        goto EXIT;
    }

    fprintf(stderr, "result = [%d].\n", g_iResult);

EXIT:

    for ( i = 0; i < 2*dwNumProcessors; ++i )
    {
        if (hThread[i])
        {
            CloseHandle(hThread[i]);
            hThread[i] = NULL;
        }
    }

    if (g_hIOCompletionPort)
    {
        CloseHandle(g_hIOCompletionPort);
        g_hIOCompletionPort = NULL;
    }

    if (g_hSourceFile)
    {
        CloseHandle(g_hSourceFile);
        g_hSourceFile = NULL;
    }

    return dwExitStatus;
}

DWORD WINAPI IOCP_WorkThread(LPVOID lpParam)
{
    DWORD i = 0;
    DWORD dwKey = 0;
    DWORD dwNumBytes = 0;
    LPOVERLAPPED completedOverlapped = NULL;
    CHUNK chunk = {0};

    while (true)
    {
        BOOL bSuccess = GetQueuedCompletionStatus(
                            g_hIOCompletionPort,
                            &dwNumBytes,
                            &dwKey,
                            &completedOverlapped,
                            INFINITE
                        );

        if (!bSuccess)
        {
            fprintf(stderr, "GetQueuedCompletionStatus removed a bad I/O packet (error %d)\n", GetLastError());
            ExitThread(E_FAIL);
        }

        if (completedOverlapped == NULL)
        {
            fprintf(stderr, "GetQueuedCompletionStatus failed (error %d)\n", GetLastError());
            ExitThread(E_FAIL);
        }

        if (dwKey == KEY_EXIT)
        {
            ExitThread(ERROR_SUCCESS);
        }

        if (dwKey == KEY_FILE)
        {
            PCHUNK completedChunk = (PCHUNK)completedOverlapped;
            PBYTE pbData = (PBYTE)completedChunk->buffer;

            for ( i = 0; i < dwNumBytes; ++i )
            {
                if ( pbData[i] == 0xff )
                {
                    g_iResult++;
                }
            }

            VirtualFree((LPVOID)pbData, 0, MEM_RELEASE);
        }

        if (dwKey == KEY_FILE || dwKey == KEY_START)
        {
            BOOL bMoreToRead = FALSE;

            if (g_uiReadPointer.QuadPart < ((ULARGE_INTEGER*)lpParam)->QuadPart)
            {
                bMoreToRead = TRUE;
                chunk.overlapped.Offset = g_uiReadPointer.LowPart;
                chunk.overlapped.OffsetHigh = g_uiReadPointer.HighPart;
                chunk.overlapped.hEvent = NULL;

                g_uiReadPointer.QuadPart += BUFFER_SIZE;
            }

            if (bMoreToRead)
            {
                chunk.buffer = VirtualAlloc(NULL, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE);
                if (chunk.buffer == NULL)
                {
                    fprintf(stderr, "VirtualAlloc failed (error %d)\n", GetLastError());
                    ExitThread(E_OUTOFMEMORY);
                }

                DWORD dwNumBytesTmp = 0;
                DWORD dwSuccess = ReadFile(
                                g_hSourceFile,
                                chunk.buffer,
                                BUFFER_SIZE,
                                &dwNumBytesTmp,
                                &chunk.overlapped
                            );

                if (!dwSuccess && (GetLastError() == ERROR_HANDLE_EOF))
                {
                    fprintf(stderr, "End of file\n");
                    VirtualFree((LPVOID)chunk.buffer, 0, MEM_RELEASE);
                    ExitThread(E_FAIL);
                }

                if (!dwSuccess && (GetLastError() != ERROR_IO_PENDING))
                {
                    fprintf(stderr, "ReadFile at [%lx:%lx] failed (error %d)\n",
                            chunk.overlapped.OffsetHigh,    
                            chunk.overlapped.Offset,
                            GetLastError());
                    VirtualFree((LPVOID)chunk.buffer, 0, MEM_RELEASE);
                    ExitThread(E_FAIL);
                }
            }
            else
            {
                ExitThread(ERROR_SUCCESS);
            }
        }
    }

    ExitThread(E_FAIL);
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值