Skip to content

Instantly share code, notes, and snippets.

@cheatfate
Last active April 28, 2016 13:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cheatfate/21799cf43e3af13d275dc1863d43b68e to your computer and use it in GitHub Desktop.
Save cheatfate/21799cf43e3af13d275dc1863d43b68e to your computer and use it in GitHub Desktop.
proc waitableCallback(param: pointer,
timerOrWaitFired: WINBOOL): void {.stdcall.} =
var p = getGlobalDispatcher()
var o = cast[PCustomOverlapped](param)
discard postQueuedCompletionStatus(p.ioPort, timerOrWaitFired,
cast[CompletionKey](o.data.fd),
cast[pointer](o))
proc withTimeout*[T](fut: Future[T], timeout: int): Future[void] =
var
hWaitHandle: Handle
hEvent: Handle
winTimeout: ULONG
var retFuture = newFuture[void]("withTimeout")
hEvent = getGlobalDispatcher().hWaitEvent
if not fut.finished:
if timeout == -1:
winTimeout = cast[ULONG](winlean.INFINITE)
else:
winTimeout = cast[ULONG](timeout)
let regFlags = cast[ULONG](WT_EXECUTEINWAITTHREAD or WT_EXECUTEONLYONCE)
var ol = PCustomOverlapped()
GC_ref(ol)
ol.data = CompletionData(cb:
proc(fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
discard unregisterWait(hWaitHandle)
getGlobalDispatcher().handles.excl(cast[AsyncFD](hWaitHandle))
retFuture.complete()
)
let ret = registerWaitForSingleObject(addr hWaitHandle, hEvent,
waitableCallback, cast[pointer](ol),
winTimeout, regFlags)
if ret == 0:
raiseOSError(osLastError())
getGlobalDispatcher().handles.incl(cast[AsyncFD](hWaitHandle))
fut.callback = proc() =
if not retFuture.finished:
discard unregisterWait(hWaitHandle)
getGlobalDispatcher().handles.excl(cast[AsyncFD](hWaitHandle))
GC_unref(ol)
retFuture.complete()
else:
retFuture.complete()
return retFuture
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment