Added Windows asyncfile implementation.

This commit is contained in:
Dominik Picheta 2014-09-05 17:36:16 +01:00
commit 0f3025e320
3 changed files with 38 additions and 17 deletions

View file

@ -226,8 +226,8 @@ when defined(windows) or defined(nimdoc):
TCompletionKey = Dword TCompletionKey = Dword
TCompletionData* = object TCompletionData* = object
sock: TAsyncFD sock*: TAsyncFD # TODO: Rename this.
cb: proc (sock: TAsyncFD, bytesTransferred: Dword, cb*: proc (sock: TAsyncFD, bytesTransferred: Dword,
errcode: OSErrorCode) {.closure,gcsafe.} errcode: OSErrorCode) {.closure,gcsafe.}
PDispatcher* = ref object of PDispatcherBase PDispatcher* = ref object of PDispatcherBase
@ -237,7 +237,7 @@ when defined(windows) or defined(nimdoc):
TCustomOverlapped = object of TOVERLAPPED TCustomOverlapped = object of TOVERLAPPED
data*: TCompletionData data*: TCompletionData
PCustomOverlapped = ref TCustomOverlapped PCustomOverlapped* = ref TCustomOverlapped
TAsyncFD* = distinct int TAsyncFD* = distinct int
@ -247,7 +247,7 @@ when defined(windows) or defined(nimdoc):
proc newDispatcher*(): PDispatcher = proc newDispatcher*(): PDispatcher =
## Creates a new Dispatcher instance. ## Creates a new Dispatcher instance.
new result new result
result.ioPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1) result.ioPort = createIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1)
result.handles = initSet[TAsyncFD]() result.handles = initSet[TAsyncFD]()
result.timers = @[] result.timers = @[]
@ -260,7 +260,7 @@ when defined(windows) or defined(nimdoc):
proc register*(sock: TAsyncFD) = proc register*(sock: TAsyncFD) =
## Registers ``sock`` with the dispatcher. ## Registers ``sock`` with the dispatcher.
let p = getGlobalDispatcher() let p = getGlobalDispatcher()
if CreateIoCompletionPort(sock.THandle, p.ioPort, if createIoCompletionPort(sock.THandle, p.ioPort,
cast[TCompletionKey](sock), 1) == 0: cast[TCompletionKey](sock), 1) == 0:
raiseOSError(osLastError()) raiseOSError(osLastError())
p.handles.incl(sock) p.handles.incl(sock)
@ -286,7 +286,7 @@ when defined(windows) or defined(nimdoc):
var lpNumberOfBytesTransferred: Dword var lpNumberOfBytesTransferred: Dword
var lpCompletionKey: ULONG var lpCompletionKey: ULONG
var customOverlapped: PCustomOverlapped var customOverlapped: PCustomOverlapped
let res = GetQueuedCompletionStatus(p.ioPort, let res = getQueuedCompletionStatus(p.ioPort,
addr lpNumberOfBytesTransferred, addr lpCompletionKey, addr lpNumberOfBytesTransferred, addr lpCompletionKey,
cast[ptr POVERLAPPED](addr customOverlapped), llTimeout).bool cast[ptr POVERLAPPED](addr customOverlapped), llTimeout).bool
@ -1231,10 +1231,9 @@ proc runForever*() =
while true: while true:
poll() poll()
proc waitFor*[T](fut: PFuture[T]) = proc waitFor*[T](fut: PFuture[T]): T =
## **Blocks** the current thread until the specified future completes. ## **Blocks** the current thread until the specified future completes.
while not fut.finished: while not fut.finished:
poll() poll()
if fut.failed: fut.read
raise fut.error

View file

@ -104,11 +104,11 @@ proc closeHandle*(hObject: THandle): WINBOOL {.stdcall, dynlib: "kernel32",
importc: "CloseHandle".} importc: "CloseHandle".}
proc readFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToRead: int32, proc readFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToRead: int32,
lpNumberOfBytesRead: var int32, lpOverlapped: pointer): WINBOOL{. lpNumberOfBytesRead: ptr int32, lpOverlapped: pointer): WINBOOL{.
stdcall, dynlib: "kernel32", importc: "ReadFile".} stdcall, dynlib: "kernel32", importc: "ReadFile".}
proc writeFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToWrite: int32, proc writeFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToWrite: int32,
lpNumberOfBytesWritten: var int32, lpNumberOfBytesWritten: ptr int32,
lpOverlapped: pointer): WINBOOL{. lpOverlapped: pointer): WINBOOL{.
stdcall, dynlib: "kernel32", importc: "WriteFile".} stdcall, dynlib: "kernel32", importc: "WriteFile".}
@ -573,12 +573,14 @@ proc waitForMultipleObjects*(nCount: DWORD, lpHandles: PWOHandleArray,
const const
GENERIC_READ* = 0x80000000'i32 GENERIC_READ* = 0x80000000'i32
GENERIC_WRITE* = 0x40000000'i32
GENERIC_ALL* = 0x10000000'i32 GENERIC_ALL* = 0x10000000'i32
FILE_SHARE_READ* = 1'i32 FILE_SHARE_READ* = 1'i32
FILE_SHARE_DELETE* = 4'i32 FILE_SHARE_DELETE* = 4'i32
FILE_SHARE_WRITE* = 2'i32 FILE_SHARE_WRITE* = 2'i32
CREATE_ALWAYS* = 2'i32 CREATE_ALWAYS* = 2'i32
CREATE_NEW* = 1'i32
OPEN_EXISTING* = 3'i32 OPEN_EXISTING* = 3'i32
FILE_BEGIN* = 0'i32 FILE_BEGIN* = 0'i32
INVALID_SET_FILE_POINTER* = -1'i32 INVALID_SET_FILE_POINTER* = -1'i32
@ -595,6 +597,7 @@ const
# Error Constants # Error Constants
const const
ERROR_ACCESS_DENIED* = 5 ERROR_ACCESS_DENIED* = 5
ERROR_HANDLE_EOF* = 38
when useWinUnicode: when useWinUnicode:
proc createFileW*(lpFileName: WideCString, dwDesiredAccess, dwShareMode: DWORD, proc createFileW*(lpFileName: WideCString, dwDesiredAccess, dwShareMode: DWORD,
@ -649,10 +652,10 @@ proc unmapViewOfFile*(lpBaseAddress: pointer): WINBOOL {.stdcall,
type type
TOVERLAPPED* {.pure, inheritable.} = object TOVERLAPPED* {.pure, inheritable.} = object
Internal*: PULONG internal*: PULONG
InternalHigh*: PULONG internalHigh*: PULONG
Offset*: DWORD offset*: DWORD
OffsetHigh*: DWORD offsetHigh*: DWORD
hEvent*: THandle hEvent*: THandle
POVERLAPPED* = ptr TOVERLAPPED POVERLAPPED* = ptr TOVERLAPPED
@ -668,6 +671,7 @@ type
const const
ERROR_IO_PENDING* = 997 # a.k.a WSA_IO_PENDING ERROR_IO_PENDING* = 997 # a.k.a WSA_IO_PENDING
FILE_FLAG_OVERLAPPED* = 1073741824
WSAECONNABORTED* = 10053 WSAECONNABORTED* = 10053
WSAECONNRESET* = 10054 WSAECONNRESET* = 10054
WSAEDISCON* = 10101 WSAEDISCON* = 10101
@ -675,17 +679,21 @@ const
WSAETIMEDOUT* = 10060 WSAETIMEDOUT* = 10060
ERROR_NETNAME_DELETED* = 64 ERROR_NETNAME_DELETED* = 64
proc CreateIoCompletionPort*(FileHandle: THandle, ExistingCompletionPort: THandle, proc createIoCompletionPort*(FileHandle: THandle, ExistingCompletionPort: THandle,
CompletionKey: DWORD, CompletionKey: DWORD,
NumberOfConcurrentThreads: DWORD): THandle{.stdcall, NumberOfConcurrentThreads: DWORD): THandle{.stdcall,
dynlib: "kernel32", importc: "CreateIoCompletionPort".} dynlib: "kernel32", importc: "CreateIoCompletionPort".}
proc GetQueuedCompletionStatus*(CompletionPort: THandle, proc getQueuedCompletionStatus*(CompletionPort: THandle,
lpNumberOfBytesTransferred: PDWORD, lpCompletionKey: PULONG, lpNumberOfBytesTransferred: PDWORD, lpCompletionKey: PULONG,
lpOverlapped: ptr POVERLAPPED, lpOverlapped: ptr POVERLAPPED,
dwMilliseconds: DWORD): WINBOOL{.stdcall, dwMilliseconds: DWORD): WINBOOL{.stdcall,
dynlib: "kernel32", importc: "GetQueuedCompletionStatus".} dynlib: "kernel32", importc: "GetQueuedCompletionStatus".}
proc getOverlappedResult*(hFile: THandle, lpOverlapped: TOverlapped,
lpNumberOfBytesTransferred: var DWORD, bWait: WINBOOL): WINBOOL{.
stdcall, dynlib: "kernel32", importc: "GetOverlappedResult".}
const const
IOC_OUT* = 0x40000000 IOC_OUT* = 0x40000000
IOC_IN* = 0x80000000 IOC_IN* = 0x80000000

View file

@ -0,0 +1,14 @@
discard """
file: "tasyncexceptions.nim"
exitcode: 0
"""
import asyncfile, asyncdispatch, os
proc main() {.async.} =
var file = openAsync(getTempDir() / "foobar.txt", fmReadWrite)
await file.write("test")
file.setFilePos(0)
let data = await file.readAll()
doAssert data == "test"
waitFor main()