asyncio.h
上传用户:hxb_1234
上传日期:2010-03-30
资源大小:8328k
文件大小:8k
源码类别:

VC书籍

开发平台:

Visual C++

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1992 - 1997  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. #ifndef __ASYNCIO_H__
  12. #define __ASYNCIO_H__
  13. //
  14. // definition of CAsyncFile object that performs file access. It provides
  15. // asynchronous, unbuffered, aligned reads from a file, using a worker thread
  16. // on win95 and potentially overlapped i/o if available.
  17. // !!! Need to use real overlapped i/o if available
  18. // currently only uses worker thread, not overlapped i/o
  19. class CAsyncIo;
  20. class CAsyncStream;
  21. //
  22. //  Model the stream we read from based on a file-like interface
  23. //
  24. class CAsyncStream
  25. {
  26. public:
  27.     virtual ~CAsyncStream() {};
  28.     virtual HRESULT SetPointer(LONGLONG llPos) = 0;
  29.     virtual HRESULT Read(PBYTE pbBuffer,
  30.                          DWORD dwBytesToRead,
  31.                          BOOL bAlign,
  32.                          LPDWORD pdwBytesRead) = 0;
  33.     virtual LONGLONG Size(LONGLONG *pSizeAvailable = NULL) = 0;
  34.     virtual DWORD Alignment() = 0;
  35.     virtual void Lock() = 0;
  36.     virtual void Unlock() = 0;
  37. };
  38. // represents a single request and performs the i/o. Can be called on either
  39. // worker thread or app thread, but must hold pcsFile across file accesses.
  40. // (ie across SetFilePointer/ReadFile pairs)
  41. class CAsyncRequest
  42. {
  43.     CAsyncIo *m_pIo;
  44.     CAsyncStream *m_pStream;
  45.     LONGLONG      m_llPos;
  46.     BOOL        m_bAligned;
  47.     LONG  m_lLength;
  48.     BYTE*  m_pBuffer;
  49.     LPVOID  m_pContext;
  50.     DWORD m_dwUser;
  51.     HRESULT     m_hr;
  52. public:
  53.     // init the params for this request. Issue the i/o
  54.     // if overlapped i/o is possible.
  55.     HRESULT Request(
  56.      CAsyncIo *pIo,
  57.         CAsyncStream *pStream,
  58.      LONGLONG llPos,
  59. LONG lLength,
  60.         BOOL bAligned,
  61. BYTE* pBuffer,
  62. LPVOID pContext, // filter's context
  63. DWORD dwUser); // downstream filter's context
  64.     // issue the i/o if not overlapped, and block until i/o complete.
  65.     // returns error code of file i/o
  66.     HRESULT Complete();
  67.     // cancels the i/o. blocks until i/o is no longer pending
  68.     HRESULT Cancel()
  69.     {
  70. return S_OK;
  71.     };
  72.     // accessor functions
  73.     LPVOID GetContext()
  74.     {
  75.      return m_pContext;
  76.     };
  77.     DWORD GetUser()
  78.     {
  79. return m_dwUser;
  80.     };
  81.     HRESULT GetHResult() {
  82.         return m_hr;
  83.     };
  84.     // we set m_lLength to the actual length
  85.     LONG GetActualLength() {
  86.         return m_lLength;
  87.     };
  88.     LONGLONG GetStart() {
  89.         return m_llPos;
  90.     };
  91. };
  92. typedef CGenericList<CAsyncRequest> CRequestList;
  93. // this class needs a worker thread, but the ones defined in classesbase
  94. // are not suitable (they assume you have one message sent or posted per
  95. // request, whereas here for efficiency we want just to set an event when
  96. // there is work on the queue).
  97. //
  98. // we create CAsyncRequest objects and queue them on m_listWork. The worker
  99. // thread pulls them off, completes them and puts them on m_listDone.
  100. // The events m_evWork and m_evDone are set when the corresponding lists are
  101. // not empty.
  102. //
  103. // Synchronous requests are done on the caller thread. These should be
  104. // synchronised by the caller, but to make sure we hold m_csFile across
  105. // the SetFilePointer/ReadFile code.
  106. //
  107. // Flush by calling BeginFlush. This rejects all further requests (by
  108. // setting m_bFlushing within m_csLists), cancels all requests and moves them
  109. // to the done list, and sets m_evDone to ensure that no WaitForNext operations
  110. // will block. Call EndFlush to cancel this state.
  111. //
  112. // we support unaligned calls to SyncRead. This is done by opening the file
  113. // twice if we are using unbuffered i/o (m_dwAlign > 1).
  114. // !!!fix this to buffer on top of existing file handle?
  115. class CAsyncIo
  116. {
  117.     CCritSec m_csReader;
  118.     CAsyncStream *m_pStream;
  119.     CCritSec m_csLists;      // locks access to the list and events
  120.     BOOL m_bFlushing;        // true if between BeginFlush/EndFlush
  121.     CRequestList m_listWork;
  122.     CRequestList m_listDone;
  123.     CAMEvent m_evWork;         // set when list is not empty
  124.     CAMEvent m_evDone;
  125.     // for correct flush behaviour: all protected by m_csLists
  126.     LONG    m_cItemsOut;    // nr of items not on listDone or listWork
  127.     BOOL    m_bWaiting;     // TRUE if someone waiting for m_evAllDone
  128.     CAMEvent m_evAllDone;   // signal when m_cItemsOut goes to 0 if m_cWaiting
  129.     CAMEvent m_evStop;         // set when thread should exit
  130.     HANDLE m_hThread;
  131.     LONGLONG Size() {
  132.         ASSERT(m_pStream != NULL);
  133.         return m_pStream->Size();
  134.     };
  135.     // start the thread
  136.     HRESULT StartThread(void);
  137.     // stop the thread and close the handle
  138.     HRESULT CloseThread(void);
  139.     // manage the list of requests. hold m_csLists and ensure
  140.     // that the (manual reset) event hevList is set when things on
  141.     // the list but reset when the list is empty.
  142.     // returns null if list empty
  143.     CAsyncRequest* GetWorkItem();
  144.     // get an item from the done list
  145.     CAsyncRequest* GetDoneItem();
  146.     // put an item on the work list
  147.     HRESULT PutWorkItem(CAsyncRequest* pRequest);
  148.     // put an item on the done list
  149.     HRESULT PutDoneItem(CAsyncRequest* pRequest);
  150.     // called on thread to process any active requests
  151.     void ProcessRequests(void);
  152.     // initial static thread proc calls ThreadProc with DWORD
  153.     // param as this
  154.     static DWORD InitialThreadProc(LPVOID pv) {
  155. CAsyncIo * pThis = (CAsyncIo*) pv;
  156. return pThis->ThreadProc();
  157.     };
  158.     DWORD ThreadProc(void);
  159. public:
  160.     CAsyncIo(CAsyncStream *pStream);
  161.     ~CAsyncIo();
  162.     // open the file
  163.     HRESULT Open(LPCTSTR pName);
  164.     // ready for async activity - call this before
  165.     // calling Request
  166.     HRESULT AsyncActive(void);
  167.     // call this when no more async activity will happen before
  168.     // the next AsyncActive call
  169.     HRESULT AsyncInactive(void);
  170.     // queue a requested read. must be aligned.
  171.     HRESULT Request(
  172.      LONGLONG llPos,
  173. LONG lLength,
  174.                 BOOL bAligned,
  175. BYTE* pBuffer,
  176. LPVOID pContext,
  177. DWORD dwUser);
  178.     // wait for the next read to complete
  179.     HRESULT WaitForNext(
  180.      DWORD dwTimeout,
  181. LPVOID *ppContext,
  182. DWORD * pdwUser,
  183.                 LONG * pcbActual
  184.                 );
  185.     // perform a read of an already aligned buffer
  186.     HRESULT SyncReadAligned(
  187.      LONGLONG llPos,
  188. LONG lLength,
  189. BYTE* pBuffer,
  190.                 LONG* pcbActual
  191.                 );
  192.     // perform a synchronous read. will be buffered
  193.     // if not aligned.
  194.     HRESULT SyncRead(
  195.                 LONGLONG llPos,
  196.                 LONG lLength,
  197.                 BYTE* pBuffer);
  198.     // return length
  199.     HRESULT Length(LONGLONG *pllTotal, LONGLONG* pllAvailable);
  200.     // all Reader positions, read lengths and memory locations must
  201.     // be aligned to this.
  202.     HRESULT Alignment(LONG* pl);
  203.     HRESULT BeginFlush();
  204.     HRESULT EndFlush();
  205.     LONG Alignment()
  206.     {
  207.         return m_pStream->Alignment();
  208.     };
  209.     BOOL IsAligned(LONG l) {
  210. if ((l & (Alignment() -1)) == 0) {
  211.     return TRUE;
  212. } else {
  213.     return FALSE;
  214. }
  215.     };
  216.     BOOL IsAligned(LONGLONG ll) {
  217. return IsAligned( (LONG) (ll & 0xffffffff));
  218.     };
  219. };
  220. #endif // __ASYNCIO_H__