线程池之I/O项 (存在疑问???)

//EnsureCleanup.h
//EnsureCleanup.h
/******************************************************************************
Module:  EnsureCleanup.h
Notices: Copyright (c) 2007 Jeffrey Richter & Christophe Nasarre
Purpose: These classes ensure object cleanup when an object goes out of scope.
         See Appendix A.
******************************************************************************/


#pragma once   // Include this header file once per compilation unit


///


#include <Windows.h>


///


// Data type representing the address of the object's cleanup function.
// I used UINT_PTR so that this class works properly in 64-bit Windows.
typedef VOID (WINAPI* PFNENSURECLEANUP)(UINT_PTR);


///


// Each template instantiation requires a data type, address of cleanup 
// function, and a value that indicates an invalid value.
template<class TYPE, PFNENSURECLEANUP pfn, UINT_PTR tInvalid = NULL> 
class CEnsureCleanup {
public:
   // Default constructor assumes an invalid value (nothing to cleanup)
   CEnsureCleanup() { m_t = tInvalid; }

   // This constructor sets the value to the specified value
   CEnsureCleanup(TYPE t) : m_t((UINT_PTR) t) { }

   // The destructor performs the cleanup.
   ~CEnsureCleanup() { Cleanup(); }

   // Helper methods to tell if the value represents a valid object or not..
   BOOL IsValid() { return(m_t != tInvalid); }
   BOOL IsInvalid() { return(!IsValid()); }

   // Re-assigning the object forces the current object to be cleaned-up.
   TYPE operator=(TYPE t) { 
      Cleanup(); 
      m_t = (UINT_PTR) t;
      return(*this);  
   }

   // Returns the value (supports both 32-bit and 64-bit Windows).
   operator TYPE() { 
      return (TYPE) m_t;
   }

   // Cleanup the object if the value represents a valid object
   void Cleanup() { 
      if (IsValid()) {
         // In 64-bit Windows, all parameters are 64-bits, 
         // so no casting is required
         pfn(m_t);         // Close the object.
         m_t = tInvalid;   // We no longer represent a valid object.
      }
   }
   
private:
   UINT_PTR m_t;           // The member representing the object
};


///


// Macros to make it easier to declare instances of the template 
// class for specific data types.

#define MakeCleanupClass(className, tData, pfnCleanup) \
   typedef CEnsureCleanup<tData, (PFNENSURECLEANUP) pfnCleanup> className;

#define MakeCleanupClassX(className, tData, pfnCleanup, tInvalid) \
   typedef CEnsureCleanup<tData, (PFNENSURECLEANUP) pfnCleanup, \
   (INT_PTR) tInvalid> className;


///


// Instances of the template C++ class for common data types.
MakeCleanupClass(CEnsureCloseHandle,        HANDLE,    CloseHandle);
MakeCleanupClassX(CEnsureCloseFile,         HANDLE,    CloseHandle, 
   INVALID_HANDLE_VALUE);
MakeCleanupClass(CEnsureLocalFree,          HLOCAL,    LocalFree);
MakeCleanupClass(CEnsureGlobalFree,         HGLOBAL,   GlobalFree);
MakeCleanupClass(CEnsureRegCloseKey,        HKEY,      RegCloseKey);
MakeCleanupClass(CEnsureCloseServiceHandle, SC_HANDLE, CloseServiceHandle);
MakeCleanupClass(CEnsureCloseWindowStation, HWINSTA,   CloseWindowStation);
MakeCleanupClass(CEnsureCloseDesktop,       HDESK,     CloseDesktop);
MakeCleanupClass(CEnsureUnmapViewOfFile,    PVOID,     UnmapViewOfFile);
MakeCleanupClass(CEnsureFreeLibrary,        HMODULE,   FreeLibrary);


///


// Special class for releasing a reserved region.
// Special class is required because VirtualFree requires 3 parameters
class CEnsureReleaseRegion {
public:
   CEnsureReleaseRegion(PVOID pv = NULL) : m_pv(pv) { }
   ~CEnsureReleaseRegion() { Cleanup(); }

   PVOID operator=(PVOID pv) { 
      Cleanup(); 
      m_pv = pv; 
      return(m_pv); 
   }
   operator PVOID() { return(m_pv); }
   void Cleanup() { 
      if (m_pv != NULL) { 
         VirtualFree(m_pv, 0, MEM_RELEASE); 
         m_pv = NULL; 
      } 
   }
   
private:
   PVOID m_pv;
};


///


// Special class for freeing a block from a heap
// Special class is required because HeapFree requires 3 parameters
class CEnsureHeapFree {
public:
   CEnsureHeapFree(PVOID pv = NULL, HANDLE hHeap = GetProcessHeap()) 
      : m_pv(pv), m_hHeap(hHeap) { }
   ~CEnsureHeapFree() { Cleanup(); }

   PVOID operator=(PVOID pv) { 
      Cleanup(); 
      m_pv = pv; 
      return(m_pv); 
   }
   operator PVOID() { return(m_pv); }
   void Cleanup() { 
      if (m_pv != NULL) { 
         HeapFree(m_hHeap, 0, m_pv); 
         m_pv = NULL; 
      } 
   }
   
private:
   HANDLE m_hHeap;
   PVOID m_pv;
};


template <class TV, class TM>
inline TV chROUNDDOWN(TV Value, TM Multiple) {
   return((Value / Multiple) * Multiple);
}


// This inline function rounds a value down to the nearest multiple
template <class TV, class TM>
inline TV chROUNDUP(TV Value, TM Multiple) {
   return(chROUNDDOWN(Value, Multiple) + 
      (((Value % Multiple) > 0) ? Multiple : 0));
}
/ End of File /
 
<pre class="cpp" name="code">//IoCompletionPort.h
/******************************************************************************
Module:  IOCP.h
Notices: Copyright (c) 2007 Jeffrey Richter & Christophe Nasarre
Purpose: This class wraps an I/O Completion Port.
         See Appendix B.
******************************************************************************/


#pragma once   // Include this header file once per compilation unit


///


#include <Windows.h>

#define chVERIFY
#define chASSERT

///


class CIOCP {
public:
   CIOCP(int nMaxConcurrency = -1) { 
      m_hIOCP = NULL; 
      if (nMaxConcurrency != -1)
         (void) Create(nMaxConcurrency);
   }

   ~CIOCP() { 
      if (m_hIOCP != NULL) 
         chVERIFY(CloseHandle(m_hIOCP)); 
   }


   BOOL Close() {
      BOOL bResult = CloseHandle(m_hIOCP);
      m_hIOCP = NULL;
      return(bResult);
   }

   BOOL Create(int nMaxConcurrency = 0) {
      m_hIOCP = CreateIoCompletionPort(
         INVALID_HANDLE_VALUE, NULL, 0, nMaxConcurrency);
      chASSERT(m_hIOCP != NULL);
      return(m_hIOCP != NULL);
   }

   BOOL AssociateDevice(HANDLE hDevice, ULONG_PTR CompKey) {
      BOOL fOk = (CreateIoCompletionPort(hDevice, m_hIOCP, CompKey, 0) 
         == m_hIOCP);
      chASSERT(fOk);
      return(fOk);
   }

   BOOL AssociateSocket(SOCKET hSocket, ULONG_PTR CompKey) {
      return(AssociateDevice((HANDLE) hSocket, CompKey));
   }

   BOOL PostStatus(ULONG_PTR CompKey, DWORD dwNumBytes = 0, 
      OVERLAPPED* po = NULL) {

      BOOL fOk = PostQueuedCompletionStatus(m_hIOCP, dwNumBytes, CompKey, po);
      chASSERT(fOk);
      return(fOk);
   }

   BOOL GetStatus(ULONG_PTR* pCompKey, PDWORD pdwNumBytes,
      OVERLAPPED** ppo, DWORD dwMilliseconds = INFINITE) {

      return(GetQueuedCompletionStatus(m_hIOCP, pdwNumBytes, 
         pCompKey, ppo, dwMilliseconds));
   }

private:
   HANDLE m_hIOCP;
};


/ End of File /
//main.cpp
/******************************************************************************
Module:  FileCopy.cpp
Notices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre
******************************************************************************/


#include "IOCompletionPort.h" // See Appendix A.
#include "EnsureCleanup.h"    // See Appendix A.

#include <WindowsX.h>

// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <string>


///


// Each I/O Request needs an OVERLAPPED structure and a data buffer
class CIOReq : public OVERLAPPED {
public:
   CIOReq() {
      Internal = InternalHigh = 0;   
      Offset = OffsetHigh = 0;   
      hEvent = NULL;
      m_nBuffSize = 0;
      m_pvData = NULL;
   }

   ~CIOReq() {
      if (m_pvData != NULL)
         VirtualFree(m_pvData, 0, MEM_RELEASE);
   }

   BOOL AllocBuffer(SIZE_T nBuffSize) {
      m_nBuffSize = nBuffSize;
      m_pvData = VirtualAlloc(NULL, m_nBuffSize, MEM_COMMIT, PAGE_READWRITE);
      return(m_pvData != NULL);
   }

   BOOL Read(HANDLE hDevice, PLARGE_INTEGER pliOffset = NULL) {
      if (pliOffset != NULL) {
         Offset     = pliOffset->LowPart;
         OffsetHigh = pliOffset->HighPart;
      }
      return(::ReadFile(hDevice, m_pvData, m_nBuffSize, NULL, this));
   }

   BOOL Write(HANDLE hDevice, PLARGE_INTEGER pliOffset = NULL) {
      if (pliOffset != NULL) {
         Offset     = pliOffset->LowPart;
         OffsetHigh = pliOffset->HighPart;
      }
      return(::WriteFile(hDevice, m_pvData, m_nBuffSize, NULL, this));
   }

public:
   SIZE_T m_nBuffSize;
   PVOID  m_pvData;
};


///


#define BUFFSIZE              (64 * 1024) // The size of an I/O buffer
//DWORD BUFFSIZE = 2;
#define MAX_PENDING_IO_REQS   4           // The maximum # of I/Os


// The completion key values indicate the type of completed I/O.
#define CK_READ  1
#define CK_WRITE 2

HANDLE hFileSrc;
HANDLE hFileDst;
PTP_IO piosrc = NULL;
PTP_IO piodst = NULL;
CIOReq ior[8];
LARGE_INTEGER liNextReadOffset = { 0 };

//volatile BYTE buf[2] = { 0 };

///
VOID CALLBACK OverlappedCompletionRoutineRead(PTP_CALLBACK_INSTANCE pIns,
										  PVOID pvContext,
										  PVOID pOverlapped,
										  ULONG IoResult,ULONG_PTR NumberofBytesTs,PTP_IO pio)
{
	StartThreadpoolIo(piodst);

	liNextReadOffset.LowPart = (*(CIOReq*)(pOverlapped)).Offset;
	liNextReadOffset.HighPart = (*(CIOReq*)(pOverlapped)).OffsetHigh;
	ior[1].Offset = liNextReadOffset.LowPart;
	ior[1].OffsetHigh = liNextReadOffset.HighPart;
	::WriteFile(hFileDst,(*(CIOReq*)(pOverlapped)).m_pvData,(*(CIOReq*)(pOverlapped)).InternalHigh,NULL,&ior[1]);
}
VOID CALLBACK OverlappedCompletionRoutineWrite(PTP_CALLBACK_INSTANCE pIns,
										  PVOID pvContext,
										  PVOID pOverlapped,
										  ULONG IoResult,ULONG_PTR NumberofBytesTs,PTP_IO pio)
{
	
	if((*(CIOReq*)(pOverlapped)).InternalHigh == BUFFSIZE)
	{
		StartThreadpoolIo(piosrc);
		liNextReadOffset.LowPart = (*(CIOReq*)(pOverlapped)).Offset;
		liNextReadOffset.HighPart = (*(CIOReq*)(pOverlapped)).OffsetHigh;
		liNextReadOffset.QuadPart += BUFFSIZE;
		ior[0].Offset = liNextReadOffset.LowPart;
		ior[0].OffsetHigh = liNextReadOffset.HighPart;
		::ReadFile(hFileSrc,ior[0].m_pvData,BUFFSIZE,NULL,&ior[0]);
	}
	else
	{
		CancelThreadpoolIo(piosrc);
	}	
}

BOOL FileCopy(PCTSTR pszFileSrc, PCTSTR pszFileDst) {

   BOOL bOk = FALSE;    // Assume file copy fails
   LARGE_INTEGER liFileSizeSrc = { 0 }, liFileSizeDst;

      // Open the source file without buffering & get its size
      hFileSrc = CreateFile(pszFileSrc, GENERIC_READ, 
         FILE_SHARE_READ, NULL, OPEN_EXISTING, 
         /*FILE_FLAG_NO_BUFFERING |*/ FILE_FLAG_OVERLAPPED, NULL);
      if (hFileSrc == INVALID_HANDLE_VALUE) goto leave;

      // Get the file's size
      GetFileSizeEx(hFileSrc, &liFileSizeSrc);

      // Nonbuffered I/O requires sector-sized transfers.
      // I'll use buffer-size transfers since it's easier to calculate.
      liFileSizeDst.QuadPart = chROUNDUP(liFileSizeSrc.QuadPart, BUFFSIZE);

      // Open the destination file without buffering & set its size
      hFileDst = CreateFile(pszFileDst, GENERIC_WRITE, 
         0, NULL, CREATE_ALWAYS, 
         /*FILE_FLAG_NO_BUFFERING |*/ FILE_FLAG_OVERLAPPED, hFileSrc);
      if (hFileDst == INVALID_HANDLE_VALUE) goto leave;

      // File systems extend files synchronously. Extend the destination file 
      // now so that I/Os execute asynchronously improving performance.

	  piosrc = CreateThreadpoolIo(hFileSrc,OverlappedCompletionRoutineRead,L"src",NULL);
	  piodst = CreateThreadpoolIo(hFileDst,OverlappedCompletionRoutineWrite,L"dst",NULL);
	  ior[0].AllocBuffer(BUFFSIZE);
	  ior[1].AllocBuffer(BUFFSIZE);

	  StartThreadpoolIo(piosrc); //每次发出IO请求需要调用些函数,否则回调函数不将被调用
	  ::ReadFile(hFileSrc,ior[0].m_pvData,BUFFSIZE,NULL,&ior[0]);
	  
	  //WaitForThreadpoolIoCallbacks(piosrc,TRUE);
	  //WaitForThreadpoolIoCallbacks(piodst,TRUE); //why this is fail if replace getchar()
	  getchar();
//	  CloseThreadpoolIo(piosrc);
//	  CloseThreadpoolIo(piodst);

	  SetFilePointerEx(hFileDst, liFileSizeSrc, NULL, FILE_BEGIN);
      SetEndOfFile(hFileDst);
leave:;
	  return 0;
}

int wmain(int argc,wchar_t **argv) 
{
	//GetDiskFreeSpaceW(NULL,NULL,&BUFFSIZE,NULL,NULL); //cache bytes of per sector for support FILE_FLAG_NO_BUFFERING flag.
	if(argc < 3)	return -1;
	FileCopy(argv[1],argv[2]);
	return(0);
}


 End of File //


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值