オーバーラップIOでは、ファイルハンドルを同期オブジェクトとして
取り扱うことも可能です。
CreateFile関数の第6引数にFILE_FLAG_OVERLAPPEDを指定するのは同じです。
WriteFile関数にOVERLAPPED構造体のアドレスを指定します。
この関数は、実際に失敗しても、オーバーラップIOでペンディングしていてもエラーを返します。エラーが返ってきた場合は、GetLastError関数を呼び出して戻り値を調べます。
ペンディングの場合は、ERROR_IO_PENDINGが返されます。
ペンディングになった場合は、待機関数で待機します。
待機後シグナル状態になって、オーバーラップが成功すれば、GetOverlappedResult関数がTRUEを返します。
では、WriteFileを繰り返し何回も呼び出して、ファイルに大量のデータを書き込むプログラムを作ってみましょう。
ペンディングが起るでしょうか。
また、同じプログラムを複数起動して同じファイルに書き込みをしてみてください。 複数のプログラムを起動した時、同時にファイルの書き込みが始まるように、 コンピュータの時刻の秒が20の倍数になったら、ファイル書き込みを開始するようにしてあります。
/* overlap02.c */
#define MYFILE "test.txt"
#include <stdio.h>
#include <windows.h>
#include <conio.h>
OVERLAPPED ovl;
SYSTEMTIME st;
int main()
{
HANDLE hFile;
BOOL bRet, bLError;
char szOrg[64], szBuf[64];
DWORD dwWritten;
int i;
strcpy(szOrg, "No.%dテスト書き込みです\n");
hFile = CreateFile(MYFILE, GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("ファイルのオープンに失敗しました\n");
return -1;
}
while (1) {
GetLocalTime(&st);
if (st.wSecond % 20 == 0)
break;
Sleep(50);
}
for (i = 0; i < 1000; i++) {
wsprintf(szBuf, szOrg, i);
memset(&ovl, 0, sizeof(OVERLAPPED));
ovl.Offset = ((int)strlen(szBuf)) * i;
bRet = WriteFile(hFile, szBuf, (DWORD)strlen(szBuf), &dwWritten, &ovl);
if (!bRet) {
bLError = GetLastError();
if (bLError == ERROR_IO_PENDING) {
WaitForSingleObject(hFile, INFINITE);
if (GetOverlappedResult(hFile, &ovl, &dwWritten, TRUE)) {
printf("No.%dpending...\n", i);
}
} else {
printf("エラーです");
CloseHandle(hFile);
return -2;
}
}
}
CloseHandle(hFile);
printf("何かキーを打ってください\n");
_getch();
return 0;
}
複数のプログラムを起動した時の、一つの結果です。
Update Dec/08/2004 By Y.Kumei