forked from stsaz/kernel-queue-the-complete-guide
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
iocp-file.c
76 lines (63 loc) · 2 KB
/
iocp-file.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/* Kernel Queue The Complete Guide: iocp-file.c: Asynchronous file reading
Usage:
echo Hello file AIO >iocp-file.txt
iocp-file
*/
#include <windows.h>
#include <assert.h>
#include <stdio.h>
HANDLE kq;
struct context {
void (*handler)(struct context *obj);
HANDLE fd;
OVERLAPPED rctx;
};
void file_io_result(struct context *obj)
{
DWORD res;
BOOL ok = GetOverlappedResult(NULL, &obj->rctx, &res, 0);
if (ok)
;
else if (GetLastError() == ERROR_HANDLE_EOF)
res = 0;
else
assert(0);
printf("Read from file with IOCP: %d\n", res);
}
void main()
{
// create KQ object
kq = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
assert(kq != NULL);
struct context obj = {};
obj.handler = file_io_result;
// create a named pipe, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED are mandatory
obj.fd = CreateFileW(L"iocp-file.txt"
, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL);
assert(obj.fd != INVALID_HANDLE_VALUE);
// attach file to KQ
assert(NULL != CreateIoCompletionPort(obj.fd, kq, (ULONG_PTR)&obj, 0));
void *buf = HeapAlloc(GetProcessHeap(), 0, 4*1024);
assert(buf != NULL);
// begin asynchronous file read operation
memset(&obj.rctx, 0, sizeof(obj.rctx));
unsigned int size = 4*1024;
unsigned long long off = 0;
obj.rctx.Offset = (unsigned int)off;
obj.rctx.OffsetHigh = (unsigned int)(off >> 32);
BOOL ok = ReadFile(obj.fd, buf, size, NULL, &obj.rctx);
assert(GetLastError() != ERROR_HANDLE_EOF);
assert(ok || GetLastError() == ERROR_IO_PENDING);
// asynchronous file reading is in progress, now wait for the signal from KQ
OVERLAPPED_ENTRY events[1];
ULONG n = 0;
int timeout_ms = -1; // wait indefinitely
ok = GetQueuedCompletionStatusEx(kq, events, 1, &n, timeout_ms, 0);
assert(ok);
struct context *o = (void*)events[0].lpCompletionKey;
o->handler(o); // handle read event
HeapFree(GetProcessHeap(), 0, buf);
CloseHandle(obj.fd);
CloseHandle(kq);
}