asyncio.h

00001 //------------------------------------------------------------------------------
00002 // File: AsyncIo.h
00003 //
00004 // Desc: DirectShow sample code - base library for I/O functionality.
00005 //
00006 // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
00007 //------------------------------------------------------------------------------
00008 
00009 #pragma once
00010 
00011 //
00012 // definition of CAsyncFile object that performs file access. It provides
00013 // asynchronous, unbuffered, aligned reads from a file, using a worker thread
00014 // on win95 and potentially overlapped i/o if available.
00015 
00016 // !!! Need to use real overlapped i/o if available
00017 // currently only uses worker thread, not overlapped i/o
00018 
00019 class CAsyncIo;
00020 class CAsyncStream;
00021 
00022 //
00023 //  Model the stream we read from based on a file-like interface
00024 //
00025 class CAsyncStream
00026 {
00027 public:
00028     virtual ~CAsyncStream() {};
00029     virtual HRESULT SetPointer(LONGLONG llPos) = 0;
00030     virtual HRESULT Read(PBYTE pbBuffer,
00031                          DWORD dwBytesToRead,
00032                          BOOL bAlign,
00033                          LPDWORD pdwBytesRead) = 0;
00034     virtual LONGLONG Size(LONGLONG *pSizeAvailable = NULL) = 0;
00035     virtual DWORD Alignment() = 0;
00036     virtual void Lock() = 0;
00037     virtual void Unlock() = 0;
00038     //virtual void SetStopHandle(HANDLE hevStop) {}
00039 };
00040 
00041 // represents a single request and performs the i/o. Can be called on either
00042 // worker thread or app thread, but must hold pcsFile across file accesses.
00043 // (ie across SetFilePointer/ReadFile pairs)
00044 class CAsyncRequest
00045 {
00046     CAsyncIo *m_pIo;
00047     CAsyncStream *m_pStream;
00048     LONGLONG      m_llPos;
00049     BOOL        m_bAligned;
00050     LONG        m_lLength;
00051     BYTE*       m_pBuffer;
00052     LPVOID      m_pContext;
00053     DWORD       m_dwUser;
00054     HRESULT     m_hr;
00055 
00056 public:
00057     // init the params for this request. Issue the i/o
00058     // if overlapped i/o is possible.
00059     HRESULT Request(
00060         CAsyncIo *pIo,
00061         CAsyncStream *pStream,
00062         LONGLONG llPos,
00063         LONG lLength,
00064         BOOL bAligned,
00065         BYTE* pBuffer,
00066         LPVOID pContext,        // filter's context
00067         DWORD dwUser);          // downstream filter's context
00068 
00069     // issue the i/o if not overlapped, and block until i/o complete.
00070     // returns error code of file i/o
00071     HRESULT Complete();
00072 
00073     // cancels the i/o. blocks until i/o is no longer pending
00074     HRESULT Cancel()
00075     {
00076         return S_OK;
00077     };
00078 
00079     // accessor functions
00080     LPVOID GetContext()
00081     {
00082         return m_pContext;
00083     };
00084 
00085     DWORD GetUser()
00086     {
00087         return m_dwUser;
00088     };
00089 
00090     HRESULT GetHResult() {
00091         return m_hr;
00092     };
00093 
00094     // we set m_lLength to the actual length
00095     LONG GetActualLength() {
00096         return m_lLength;
00097     };
00098 
00099     LONGLONG GetStart() {
00100         return m_llPos;
00101     };
00102 };
00103 
00104 
00105 typedef CGenericList<CAsyncRequest> CRequestList;
00106 
00107 // this class needs a worker thread, but the ones defined in classes\base
00108 // are not suitable (they assume you have one message sent or posted per
00109 // request, whereas here for efficiency we want just to set an event when
00110 // there is work on the queue).
00111 //
00112 // we create CAsyncRequest objects and queue them on m_listWork. The worker
00113 // thread pulls them off, completes them and puts them on m_listDone.
00114 // The events m_evWork and m_evDone are set when the corresponding lists are
00115 // not empty.
00116 //
00117 // Synchronous requests are done on the caller thread. These should be
00118 // synchronised by the caller, but to make sure we hold m_csFile across
00119 // the SetFilePointer/ReadFile code.
00120 //
00121 // Flush by calling BeginFlush. This rejects all further requests (by
00122 // setting m_bFlushing within m_csLists), cancels all requests and moves them
00123 // to the done list, and sets m_evDone to ensure that no WaitForNext operations
00124 // will block. Call EndFlush to cancel this state.
00125 //
00126 // we support unaligned calls to SyncRead. This is done by opening the file
00127 // twice if we are using unbuffered i/o (m_dwAlign > 1).
00128 // !!!fix this to buffer on top of existing file handle?
00129 class CAsyncIo
00130 {
00131 
00132     CCritSec m_csReader;
00133     CAsyncStream *m_pStream;
00134 
00135     CCritSec m_csLists;      // locks access to the list and events
00136     BOOL m_bFlushing;        // true if between BeginFlush/EndFlush
00137     CRequestList m_listWork;
00138     CRequestList m_listDone;
00139     CAMEvent m_evWork;         // set when list is not empty
00140     CAMEvent m_evDone;
00141 
00142     // for correct flush behaviour: all protected by m_csLists
00143     LONG    m_cItemsOut;    // nr of items not on listDone or listWork
00144     BOOL    m_bWaiting;     // TRUE if someone waiting for m_evAllDone
00145     CAMEvent m_evAllDone;   // signal when m_cItemsOut goes to 0 if m_cWaiting
00146 
00147 
00148     CAMEvent m_evStop;         // set when thread should exit
00149     HANDLE m_hThread;
00150 
00151     LONGLONG Size() {
00152         ASSERT(m_pStream != NULL);
00153         return m_pStream->Size();
00154     };
00155 
00156     // start the thread
00157     HRESULT StartThread(void);
00158 
00159     // stop the thread and close the handle
00160     HRESULT CloseThread(void);
00161 
00162     // manage the list of requests. hold m_csLists and ensure
00163     // that the (manual reset) event hevList is set when things on
00164     // the list but reset when the list is empty.
00165     // returns null if list empty
00166     CAsyncRequest* GetWorkItem();
00167 
00168     // get an item from the done list
00169     CAsyncRequest* GetDoneItem();
00170 
00171     // put an item on the work list
00172     HRESULT PutWorkItem(CAsyncRequest* pRequest);
00173 
00174     // put an item on the done list
00175     HRESULT PutDoneItem(CAsyncRequest* pRequest);
00176 
00177     // called on thread to process any active requests
00178     void ProcessRequests(void);
00179 
00180     // initial static thread proc calls ThreadProc with DWORD
00181     // param as this
00182     static DWORD WINAPI InitialThreadProc(LPVOID pv) {
00183         CAsyncIo * pThis = (CAsyncIo*) pv;
00184         return pThis->ThreadProc();
00185     };
00186 
00187     DWORD ThreadProc(void);
00188 
00189 public:
00190 
00191     CAsyncIo(CAsyncStream *pStream);
00192     ~CAsyncIo();
00193 
00194     // open the file
00195     HRESULT Open(LPCTSTR pName);
00196 
00197     // ready for async activity - call this before
00198     // calling Request
00199     HRESULT AsyncActive(void);
00200 
00201     // call this when no more async activity will happen before
00202     // the next AsyncActive call
00203     HRESULT AsyncInactive(void);
00204 
00205     // queue a requested read. must be aligned.
00206     HRESULT Request(
00207                 LONGLONG llPos,
00208                 LONG lLength,
00209                 BOOL bAligned,
00210                 BYTE* pBuffer,
00211                 LPVOID pContext,
00212                 DWORD dwUser);
00213 
00214     // wait for the next read to complete
00215     HRESULT WaitForNext(
00216                 DWORD dwTimeout,
00217                 LPVOID *ppContext,
00218                 DWORD * pdwUser,
00219                 LONG * pcbActual
00220                 );
00221 
00222     // perform a read of an already aligned buffer
00223     HRESULT SyncReadAligned(
00224                 LONGLONG llPos,
00225                 LONG lLength,
00226                 BYTE* pBuffer,
00227                 LONG* pcbActual,
00228                 PVOID pvContext
00229                 );
00230 
00231     // perform a synchronous read. will be buffered
00232     // if not aligned.
00233     HRESULT SyncRead(
00234                 LONGLONG llPos,
00235                 LONG lLength,
00236                 BYTE* pBuffer);
00237 
00238     // return length
00239     HRESULT Length(LONGLONG *pllTotal, LONGLONG* pllAvailable);
00240 
00241     // all Reader positions, read lengths and memory locations must
00242     // be aligned to this.
00243     HRESULT Alignment(LONG* pl);
00244 
00245     HRESULT BeginFlush();
00246     HRESULT EndFlush();
00247 
00248     LONG Alignment()
00249     {
00250         return m_pStream->Alignment();
00251     };
00252 
00253     BOOL IsAligned(LONG l) {
00254         if ((l & (Alignment() -1)) == 0) {
00255             return TRUE;
00256         } else {
00257             return FALSE;
00258         }
00259     };
00260 
00261     BOOL IsAligned(LONGLONG ll) {
00262         return IsAligned( (LONG) (ll & 0xffffffff));
00263     };
00264 
00265     //  Accessor
00266     HANDLE StopEvent() const { return m_evDone; }
00267 };

Generated on Tue Dec 13 14:47:23 2005 for guliverkli by  doxygen 1.4.5