Added Windows asyncfile implementation.
This commit is contained in:
parent
5fb12144b3
commit
0f3025e320
3 changed files with 38 additions and 17 deletions
|
|
@ -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
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
14
tests/async/tasyncfile.nim
Normal file
14
tests/async/tasyncfile.nim
Normal 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()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue