This is a mirror of official site: http://jasper-net.blogspot.com/

A simple wrapper for asynchronous file I/O (ReadFileEx,WriteFileEx)

| Friday, April 8, 2011
Introduction

Hi all, here Iam dealing with a subject which is comparatively less discussed. The people new to programming world will start with samples which create, read or write files. In Windows all file related calls finally reach in CreateFile, ReadFile or WriteFile. We are all familiar with these APIs. Technically, ReadFile and WriteFile APIs are  synchronous APIs. That is these APIs return only after the requested data is read or written. Now, coming to today’s topic. There are asynchronous versions of these APIs. The ReadFileEx and WriteFileEx. Actually ReadFile and WriteFile can also behave asynchronous. But our discussion is on the explicitly asynchronous APIs, ReadFilEx and WriteFilEx.

Background

Normally, when we need asynchronous behaviour or parallelism we create threads. The asynchronous file I/O APIs allows us to leverage the asynchronous behaviour without introducing threads. So we can issue ReadFileEx or WriteFileEx and perform other operations. Then finally when the application needs the result of I/O, it can check the status of asynchronous operation with the help of some APIs which we will discuss shortly. The file should be opened with FILE_FLAG_OVERLAPPED for using the asynchronous APIs.

See the prototype for ReadFileEx below. It is the same for WriteFileEx.

BOOL WINAPI ReadFileEx(
__in HANDLE hFile,
__out_opt LPVOID lpBuffer,
__in DWORD nNumberOfBytesToRead,
__inout LPOVERLAPPED lpOverlapped,
__in_opt LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

Here we are interested in the last two parameters lpOverlapped and lpCompletionRoutine. We need to specify OVERLAPPED structure filled with offset from where data is to be read or written. There is a hEvent member in this structure. The MSDN documentation says that we are free to use this for our purpose. But there is asynchronous behaviour exhibited by ReadFile and WriteFile when its last parameter OVERLAPPED pointer is provided. In this case some MSDN documentation says that we need to supply separate event handles for each instance of OVERLAPPED structure. So there is a confusion that we need to specify the hEvent or not. Also it mentions that this event object will be signalled when the specified overlapped operation completes. The lpCompletionRoutine is the callback function to be called by the system when the specified asynchronous operation completes. It will be invoked per ReadFileEx/WriteFileEx call. There is a side track for this. This callback routine is invoked only when the thread enters in an “alertable” wait state. This state can be set with the help of SleepEx, WaitForSingleObjectEx, WaitForMultipleObjectsEx, MsgWaitForMultipleObjectsEx etc. A thread can issue asynchronous I/O operations and freely do other jobs. Then, once all its other tasks are completed, it can enter the alertable wait state. The callback routines are then called in the context of such APIs. The status of an overlapped operation can be checked with the help of GetOverlappedResult API.

Using the code

I have wrapped all these knowledge in to a small class AsyncFile.

class IAsyncOperationCompletionNotifier {
public:
    virtual void OnAsyncOperationComplete(BOOL bRead,DWORD dwErrorCode)=0;
};

class AsyncFile{
public:
     AsyncFile(LPCTSTR lpctszFileName,BOOL bCreate,DWORD dwDesiredAccess,
                   DWORD dwShareMode, IAsyncOperationCompletionNotifier* pINotifier,
                   BOOL bSequentialMode=FALSE, __int64 nStartOffset=0,
                   BOOL bInUIThread=FALSE);
     BOOL IsOpen();
     BOOL Write(LPVOID pvBuffer,DWORD dwBufLen,DWORD dwOffsetLow=0,DWORD dwOffsetHigh=0);
     BOOL Read(LPVOID pvBuffer,DWORD dwBufLen,DWORD dwOffsetLow=0,DWORD dwOffsetHigh=0);
     BOOL IsAsyncIOComplete(BOOL bFlushBuffers=TRUE);
     BOOL AbortIO();
     DWORD GetFileLength(DWORD* pdwOffsetHigh);
     __int64 GetLargeFileLength();
     VOID Reset(BOOL bSequentialMode=FALSE,__int64 nStartOffset=0);
     operator HANDLE()
     {
        return m_hAsyncFile;
     }
     BOOL SeekFile(__int64 nBytesToSeek,__int64& nNewOffset,DWORD dwSeekOption);
     ~AsyncFile(void);
private:
....
};

Read more: Codeproject

Posted via email from Jasper-net

0 comments: