Win平台高级编程:完成端口 (IOCP) serial functions

来源:互联网 发布:上海民族乐器一厂 淘宝 编辑:程序博客网 时间:2024/05/17 01:58

Completion Port serial functions, below are the APIs and their description

 *    1  CreateIoCompletionPort              Associates an I/O completion port with one or more file handles, or creates an I/O completion port  that is not associated with a file handle.
 *    2  GetQueuedCompletionStatus           Attempts to dequeue an I/O completion packet from a specified I/O completion port.
 *    3  GetQueuedCompletionStatusEx        Retrieves multiple completion port entries simultaneously.
 *    4  PostQueuedCompletionStatus         Posts an I/O completion packet to an I/O completion port.

#include <stdio.h>#include <windows.h>// WARNING !!!  All list items must be aligned on a MEMORY_ALLOCATION_ALIGNMENT boundary;// WARNING !!!  otherwise, this function will behave unpredictably.#define MAX_THREADS 5#define ERR_MSG(m)                            \  if (!PrintMessage(GetLastError(), NULL))   \    fprintf(stderr, m);#define FATAL_ERROR(m)                        \  {                                           \    ERR_MSG(m)                                \    goto Exception;                           \  }volatile BOOL bLoop;BOOLPrintMessage(errorId, format)  long errorId;  char *format;{  LPSTR    text = NULL;  DWORD    length;  // Gets the message string by an error code.  length = FormatMessage(    FORMAT_MESSAGE_ALLOCATE_BUFFER |    FORMAT_MESSAGE_FROM_SYSTEM |    FORMAT_MESSAGE_IGNORE_INSERTS,    NULL, errorId, 0,    (LPSTR)&text,    0, NULL);  if (length == 0)  {    fprintf(stderr, "FormatMessage was failed, error:0x%08x, format:0x%08x\n", GetLastError(), errorId);    return FALSE;  }  if (format != NULL)    fprintf(stderr, format, text);  else    fprintf(stderr, text);  // Free the buffer allocate by the FormatMessage function.  LocalFree(text);  return TRUE;}DWORD WINAPIpfnProcThread(data)  LPVOID data;{  HANDLE    hIocp = (HANDLE)data;  DWORD    error,    transferred;  ULONG_PTR    iokey;  LPOVERLAPPED    pOverlap;  while (bLoop)  {    if (!GetQueuedCompletionStatus(hIocp, &transferred, &iokey, &pOverlap, 500))  //INFINITE, in milliseconds    {      error = GetLastError();      if (error == WAIT_TIMEOUT)        continue;      if (pOverlap == NULL)        break;    }    fprintf(stdout, "IOCP T %04X, D %04d, K %04d\n", GetCurrentThreadId(), transferred, iokey);    Sleep(100);  }  fprintf(stdout, "Thread %04X was exited.\n", GetCurrentThreadId(), transferred);  return 0;}BOOLWaitForUserKeyInput(key, exitkey, keydown)  LPDWORD key;  DWORD exitkey;  BOOL keydown;{  DWORD    length;  INPUT_RECORD    record;  *key = -1;  if (!ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &record, 1, &length) ||      !length)  {    ERR_MSG("Failed to get user key input.");    Sleep(100);    // 读取键盘输入失败,返回TRUE进入下一个读取动作。    return TRUE;  }  if (record.EventType != KEY_EVENT ||     !(keydown ? record.Event.KeyEvent.bKeyDown: !record.Event.KeyEvent.bKeyDown))    return TRUE;  // 返回当前KEY值。  *key = record.Event.KeyEvent.wVirtualKeyCode;  // 如果是指定的退出按键或ESC则返回FALSE。  return !(*key == exitkey || *key == VK_ESCAPE);}intmain(){  DWORD    i,    threads_num;  HANDLE    hFile = NULL,    *thread_array = NULL,    hIocp = NULL;  SYSTEM_INFO    sysinfo;  OVERLAPPED    overlap;  ULONG_PTR    iokey;  CHAR    szFilePath[MAX_PATH];  GetSystemInfo(&sysinfo);  threads_num = sysinfo.dwNumberOfProcessors * 2;  GetModuleFileName(NULL, szFilePath, MAX_PATH);  i = strlen(szFilePath);  while (szFilePath[--i] != '\\');  strcpy(&szFilePath[i], "\\data.dat");  hFile = CreateFile(szFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);  if (hFile == INVALID_HANDLE_VALUE)    FATAL_ERROR("Failed to create test file.\n");  hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);  if (hIocp == NULL)    FATAL_ERROR("Failed to call CreateIoCompletionPort.\n");  thread_array = (HANDLE*)malloc(threads_num * sizeof(HANDLE));  if (!thread_array)    FATAL_ERROR("Failed to allocate memory for thread array.\n");  bLoop = TRUE;  for (i = 0; i < threads_num; i++)  {    thread_array[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnProcThread, (LPVOID)hIocp, 0, NULL);    if (thread_array[i] == NULL)    {      ERR_MSG("Failed to create thread.");      for (; i < threads_num; i++)        thread_array[i] = NULL;      goto InitThreadsFailed;    }  }  iokey = 100;  if (CreateIoCompletionPort(hFile, hIocp, iokey, 0) == NULL)    FATAL_ERROR("Failed to bind file handle to completion port.\n");  ZeroMemory(&overlap, sizeof(OVERLAPPED));  PostQueuedCompletionStatus(hIocp, 0123, 100, NULL);  while (WaitForUserKeyInput(&i, VK_RETURN, TRUE))  {    switch (i)    {    case VK_UP:      PostQueuedCompletionStatus(hIocp, 1234, 110, NULL);      break;    case VK_DOWN:      PostQueuedCompletionStatus(hIocp, 2345, 120, NULL);      break;    case VK_LEFT:      PostQueuedCompletionStatus(hIocp, 3456, 130, NULL);      break;    case VK_RIGHT:      PostQueuedCompletionStatus(hIocp, 4567, 140, NULL);      break;    }  }  bLoop = FALSE;  WaitForMultipleObjects(threads_num, thread_array, TRUE, INFINITE);Exception:  if (hIocp)    CloseHandle(hIocp);  if (hFile && hFile != INVALID_HANDLE_VALUE)    CloseHandle(hFile);  if (thread_array)  {    for (i = 0; i < threads_num; i++)      CloseHandle(thread_array[i]);    free(thread_array);    thread_array = NULL;  }  return 0;}