Asynchronous File I/O in C++
I can't find information about asynchronous reading and writing in C++. So I write code, function read() works correctly, but synchronization doesn't. Sync() function doesn't wait for the end of reading. For my opinion variable state_read in thread has incorrect value. Please, understand me why.
struct IOParams{
char* buf;
unsigned int nBytesForRead;
FILE* fp;
};
struct AsyncFile {
FILE* fp;
bool state_read;
HANDLE hThreadRead;
IOParams read_params;
void 开发者_如何学运维AsyncFile::read(char* buf, unsigned int nBytesForRead){
sync();
read_params.buf = buf;
read_params.fp = fp;
read_params.nBytesForRead = nBytesForRead;
hThreadRead = CreateThread(0,0,ThreadFileRead,this,0);
}
void AsyncFile::sync() {
if (state_read) {
WaitForSingleObject(hThreadRead,INFINITE);
CloseHandle(hThreadRead);
}
state_read = false;
}
};
DWORD WINAPI ThreadFileRead(void* lpParameter) {
AsyncFile* asf = (AsyncFile*)lpParameter;
asf->setReadState(true);
IOParams & read_params = *asf->getReadParams();
fread(read_params.buf, 1, read_params.nBytesForRead, read_params.fp);
asf->setReadState(false);
return 0;
}
Maybe you know how to write the asynchronous reading in more reasonable way.
Maybe you know how to write the asynchronous reading in more reasonable way.
Since your question is tagged "Windows", you might look into FILE_FLAG_OVERLAPPED
and ReadFileEx
, which do asynchronous reading without extra threads (synchronisation via an event, a callback, or a completion port).
If you insist on using a separate loader thread (there may be valid reasons for that, though few), you do not want to read and write a flag repeatedly from two threads and use that for synchronisation. Although your code looks correct, the mere fact that does not work as intended shows that it's a bad idea.
Always use a proper synchronisation primitive (event or semaphore) for synchronisation, do not tamper with some flag that's (possibly inconsistently) written and read from different threads.
Alternatively, if you don't want an extra event object, you could always wait on the thread to die, unconditionally (but, read the next paragraph).
Generally, spawning a thread and letting it die for every read is not a good design. Not only is spawning a thread considerable overhead (both for CPU and memory), it can also introduce hard to predict "funny effects" and turn out to be a total anti-optimization. Imagine for example having 50 threads thrashing the harddrive on seeks, all of them trying to get a bit of it. This will be asynchronous for sure, but it will be a hundred times slower, too.
Using a small pool of workers (emphasis on small) will probably be a much superior design, if you do not want to use the operating system's native asynchronous mechanisms.
精彩评论