Fix compilation errors and enable async events on partially supported systems.
This commit is contained in:
parent
ac4ccc695f
commit
b59ce8d321
4 changed files with 71 additions and 64 deletions
|
|
@ -18,10 +18,12 @@
|
||||||
## Supported features: files, sockets, pipes, timers, processes, signals
|
## Supported features: files, sockets, pipes, timers, processes, signals
|
||||||
## and user events.
|
## and user events.
|
||||||
##
|
##
|
||||||
## Fully supported OS: MacOSX, FreeBSD, OpenBSD, NetBSD, Linux.
|
## Fully supported OS: MacOSX, FreeBSD, OpenBSD, NetBSD, Linux (except
|
||||||
|
## for Android).
|
||||||
##
|
##
|
||||||
## Partially supported OS: Windows (only sockets and user events),
|
## Partially supported OS: Windows (only sockets and user events),
|
||||||
## Solaris (files, sockets, handles and user events).
|
## Solaris (files, sockets, handles and user events).
|
||||||
|
## Android (files, sockets, handles and user events).
|
||||||
##
|
##
|
||||||
## TODO: ``/dev/poll``, ``event ports`` and filesystem events.
|
## TODO: ``/dev/poll``, ``event ports`` and filesystem events.
|
||||||
|
|
||||||
|
|
@ -29,9 +31,11 @@ import os
|
||||||
|
|
||||||
const hasThreadSupport = compileOption("threads") and defined(threadsafe)
|
const hasThreadSupport = compileOption("threads") and defined(threadsafe)
|
||||||
|
|
||||||
const supportedPlatform = defined(macosx) or defined(freebsd) or
|
const ioselSupportedPlatform* = defined(macosx) or defined(freebsd) or
|
||||||
defined(netbsd) or defined(openbsd) or
|
defined(netbsd) or defined(openbsd) or
|
||||||
(defined(linux) and not defined(android))
|
(defined(linux) and not defined(android))
|
||||||
|
## This constant is used to determine whether the destination platform is
|
||||||
|
## fully supported by ``ioselectors`` module.
|
||||||
|
|
||||||
const bsdPlatform = defined(macosx) or defined(freebsd) or
|
const bsdPlatform = defined(macosx) or defined(freebsd) or
|
||||||
defined(netbsd) or defined(openbsd)
|
defined(netbsd) or defined(openbsd)
|
||||||
|
|
@ -244,7 +248,7 @@ else:
|
||||||
skey.key.fd = pkeyfd
|
skey.key.fd = pkeyfd
|
||||||
skey.key.data = pdata
|
skey.key.data = pdata
|
||||||
|
|
||||||
when supportedPlatform:
|
when ioselSupportedPlatform:
|
||||||
template blockSignals(newmask: var Sigset, oldmask: var Sigset) =
|
template blockSignals(newmask: var Sigset, oldmask: var Sigset) =
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
if posix.pthread_sigmask(SIG_BLOCK, newmask, oldmask) == -1:
|
if posix.pthread_sigmask(SIG_BLOCK, newmask, oldmask) == -1:
|
||||||
|
|
|
||||||
|
|
@ -1092,11 +1092,6 @@ else:
|
||||||
import ioselectors
|
import ioselectors
|
||||||
from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK,
|
from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK,
|
||||||
MSG_NOSIGNAL
|
MSG_NOSIGNAL
|
||||||
|
|
||||||
const supportedPlatform = defined(linux) or defined(freebsd) or
|
|
||||||
defined(netbsd) or defined(openbsd) or
|
|
||||||
defined(macosx)
|
|
||||||
|
|
||||||
type
|
type
|
||||||
AsyncFD* = distinct cint
|
AsyncFD* = distinct cint
|
||||||
Callback = proc (fd: AsyncFD): bool {.closure,gcsafe.}
|
Callback = proc (fd: AsyncFD): bool {.closure,gcsafe.}
|
||||||
|
|
@ -1191,7 +1186,7 @@ else:
|
||||||
var keys: array[64, ReadyKey[AsyncData]]
|
var keys: array[64, ReadyKey[AsyncData]]
|
||||||
|
|
||||||
let p = getGlobalDispatcher()
|
let p = getGlobalDispatcher()
|
||||||
when supportedPlatform:
|
when ioselSupportedPlatform:
|
||||||
let customSet = {Event.Timer, Event.Signal, Event.Process,
|
let customSet = {Event.Timer, Event.Signal, Event.Process,
|
||||||
Event.Vnode, Event.User}
|
Event.Vnode, Event.User}
|
||||||
|
|
||||||
|
|
@ -1225,7 +1220,7 @@ else:
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
when supportedPlatform:
|
when ioselSupportedPlatform:
|
||||||
if (customSet * events) != {}:
|
if (customSet * events) != {}:
|
||||||
for node in keys[i].data.readCBs[].nodes():
|
for node in keys[i].data.readCBs[].nodes():
|
||||||
let cb = node.value
|
let cb = node.value
|
||||||
|
|
@ -1234,6 +1229,15 @@ else:
|
||||||
if cb(fd.AsyncFD):
|
if cb(fd.AsyncFD):
|
||||||
keys[i].data.readCBs[].remove(node)
|
keys[i].data.readCBs[].remove(node)
|
||||||
p.selector.unregister(fd)
|
p.selector.unregister(fd)
|
||||||
|
else:
|
||||||
|
if Event.User in events or events == {Event.Error}:
|
||||||
|
for node in keys[i].data.readCBs[].nodes():
|
||||||
|
let cb = node.value
|
||||||
|
custom = true
|
||||||
|
if cb != nil:
|
||||||
|
if cb(fd.AsyncFD):
|
||||||
|
keys[i].data.readCBs[].remove(node)
|
||||||
|
p.selector.unregister(fd)
|
||||||
|
|
||||||
# because state `data` can be modified in callback we need to update
|
# because state `data` can be modified in callback we need to update
|
||||||
# descriptor events with currently registered callbacks.
|
# descriptor events with currently registered callbacks.
|
||||||
|
|
@ -1496,7 +1500,7 @@ else:
|
||||||
addRead(socket, cb)
|
addRead(socket, cb)
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
when supportedPlatform:
|
when ioselSupportedPlatform:
|
||||||
|
|
||||||
proc addTimer*(timeout: int, oneshot: bool, cb: Callback) =
|
proc addTimer*(timeout: int, oneshot: bool, cb: Callback) =
|
||||||
## Start watching for timeout expiration, and then call the
|
## Start watching for timeout expiration, and then call the
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,10 @@ template processTest(t, x: untyped) =
|
||||||
if not x: echo(t & " FAILED\r\n")
|
if not x: echo(t & " FAILED\r\n")
|
||||||
|
|
||||||
when not defined(windows):
|
when not defined(windows):
|
||||||
import os, posix, osproc, nativesockets, times
|
import os, posix, nativesockets, times
|
||||||
|
|
||||||
const supportedPlatform = defined(macosx) or defined(freebsd) or
|
when ioselSupportedPlatform:
|
||||||
defined(netbsd) or defined(openbsd) or
|
import osproc
|
||||||
defined(linux)
|
|
||||||
|
|
||||||
proc socket_notification_test(): bool =
|
proc socket_notification_test(): bool =
|
||||||
proc create_test_socket(): SocketHandle =
|
proc create_test_socket(): SocketHandle =
|
||||||
|
|
@ -143,7 +142,7 @@ when not defined(windows):
|
||||||
selector.close()
|
selector.close()
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
when supportedPlatform:
|
when ioselSupportedPlatform:
|
||||||
proc timer_notification_test(): bool =
|
proc timer_notification_test(): bool =
|
||||||
var selector = newSelector[int]()
|
var selector = newSelector[int]()
|
||||||
var timer = selector.registerTimer(100, false, 0)
|
var timer = selector.registerTimer(100, false, 0)
|
||||||
|
|
@ -462,7 +461,7 @@ when not defined(windows):
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
processTest("Multithreaded user event notification test...",
|
processTest("Multithreaded user event notification test...",
|
||||||
mt_event_test())
|
mt_event_test())
|
||||||
when supportedPlatform:
|
when ioselSupportedPlatform:
|
||||||
processTest("Timer notification test...", timer_notification_test())
|
processTest("Timer notification test...", timer_notification_test())
|
||||||
processTest("Process notification test...", process_notification_test())
|
processTest("Process notification test...", process_notification_test())
|
||||||
processTest("Signal notification test...", signal_notification_test())
|
processTest("Signal notification test...", signal_notification_test())
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,12 @@ OK
|
||||||
"""
|
"""
|
||||||
|
|
||||||
when defined(upcoming):
|
when defined(upcoming):
|
||||||
import asyncdispatch, times, osproc, streams
|
import asyncdispatch, times, streams, posix
|
||||||
|
from ioselectors import ioselSupportedPlatform
|
||||||
|
|
||||||
const supportedPlatform = defined(linux) or defined(freebsd) or
|
proc delayedSet(ev: AsyncEvent, timeout: int): Future[void] {.async.} =
|
||||||
defined(netbsd) or defined(openbsd) or
|
await sleepAsync(timeout)
|
||||||
defined(macosx)
|
ev.setEvent()
|
||||||
|
|
||||||
proc waitEvent(ev: AsyncEvent, closeEvent = false): Future[void] =
|
proc waitEvent(ev: AsyncEvent, closeEvent = false): Future[void] =
|
||||||
var retFuture = newFuture[void]("waitEvent")
|
var retFuture = newFuture[void]("waitEvent")
|
||||||
|
|
@ -25,56 +26,55 @@ when defined(upcoming):
|
||||||
addEvent(ev, cb)
|
addEvent(ev, cb)
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc waitTimer(timeout: int): Future[void] =
|
|
||||||
var retFuture = newFuture[void]("waitTimer")
|
|
||||||
proc cb(fd: AsyncFD): bool =
|
|
||||||
retFuture.complete()
|
|
||||||
addTimer(timeout, true, cb)
|
|
||||||
return retFuture
|
|
||||||
|
|
||||||
proc waitProcess(p: Process): Future[void] =
|
|
||||||
var retFuture = newFuture[void]("waitProcess")
|
|
||||||
proc cb(fd: AsyncFD): bool =
|
|
||||||
retFuture.complete()
|
|
||||||
addProcess(p.processID(), cb)
|
|
||||||
return retFuture
|
|
||||||
|
|
||||||
proc delayedSet(ev: AsyncEvent, timeout: int): Future[void] {.async.} =
|
|
||||||
await waitTimer(timeout)
|
|
||||||
ev.setEvent()
|
|
||||||
|
|
||||||
proc timerTest() =
|
|
||||||
waitFor(waitTimer(200))
|
|
||||||
echo "OK"
|
|
||||||
|
|
||||||
proc eventTest() =
|
proc eventTest() =
|
||||||
var event = newAsyncEvent()
|
var event = newAsyncEvent()
|
||||||
var fut = waitEvent(event)
|
var fut = waitEvent(event)
|
||||||
asyncCheck(delayedSet(event, 500))
|
asyncCheck(delayedSet(event, 500))
|
||||||
waitFor(fut or waitTimer(1000))
|
waitFor(fut or sleepAsync(1000))
|
||||||
if fut.finished:
|
if fut.finished:
|
||||||
echo "OK"
|
echo "OK"
|
||||||
else:
|
else:
|
||||||
echo "eventTest: Timeout expired before event received!"
|
echo "eventTest: Timeout expired before event received!"
|
||||||
|
|
||||||
proc processTest() =
|
when ioselSupportedPlatform or defined(windows):
|
||||||
when defined(windows):
|
|
||||||
var process = startProcess("ping.exe", "",
|
|
||||||
["127.0.0.1", "-n", "2", "-w", "100"], nil,
|
|
||||||
{poStdErrToStdOut, poUsePath, poInteractive,
|
|
||||||
poDemon})
|
|
||||||
else:
|
|
||||||
var process = startProcess("/bin/sleep", "", ["1"], nil,
|
|
||||||
{poStdErrToStdOut, poUsePath})
|
|
||||||
var fut = waitProcess(process)
|
|
||||||
waitFor(fut or waitTimer(2000))
|
|
||||||
if fut.finished and process.peekExitCode() == 0:
|
|
||||||
echo "OK"
|
|
||||||
else:
|
|
||||||
echo "processTest: Timeout expired before process exited!"
|
|
||||||
|
|
||||||
when supportedPlatform:
|
import osproc
|
||||||
import posix
|
|
||||||
|
proc waitTimer(timeout: int): Future[void] =
|
||||||
|
var retFuture = newFuture[void]("waitTimer")
|
||||||
|
proc cb(fd: AsyncFD): bool =
|
||||||
|
retFuture.complete()
|
||||||
|
addTimer(timeout, true, cb)
|
||||||
|
return retFuture
|
||||||
|
|
||||||
|
proc waitProcess(p: Process): Future[void] =
|
||||||
|
var retFuture = newFuture[void]("waitProcess")
|
||||||
|
proc cb(fd: AsyncFD): bool =
|
||||||
|
retFuture.complete()
|
||||||
|
addProcess(p.processID(), cb)
|
||||||
|
return retFuture
|
||||||
|
|
||||||
|
proc timerTest() =
|
||||||
|
waitFor(waitTimer(200))
|
||||||
|
echo "OK"
|
||||||
|
|
||||||
|
proc processTest() =
|
||||||
|
when defined(windows):
|
||||||
|
var process = startProcess("ping.exe", "",
|
||||||
|
["127.0.0.1", "-n", "2", "-w", "100"], nil,
|
||||||
|
{poStdErrToStdOut, poUsePath, poInteractive,
|
||||||
|
poDemon})
|
||||||
|
else:
|
||||||
|
var process = startProcess("/bin/sleep", "", ["1"], nil,
|
||||||
|
{poStdErrToStdOut, poUsePath})
|
||||||
|
var fut = waitProcess(process)
|
||||||
|
waitFor(fut or waitTimer(2000))
|
||||||
|
if fut.finished and process.peekExitCode() == 0:
|
||||||
|
echo "OK"
|
||||||
|
else:
|
||||||
|
echo "processTest: Timeout expired before process exited!"
|
||||||
|
|
||||||
|
when ioselSupportedPlatform:
|
||||||
|
|
||||||
proc waitSignal(signal: int): Future[void] =
|
proc waitSignal(signal: int): Future[void] =
|
||||||
var retFuture = newFuture[void]("waitSignal")
|
var retFuture = newFuture[void]("waitSignal")
|
||||||
|
|
@ -97,7 +97,7 @@ when defined(upcoming):
|
||||||
else:
|
else:
|
||||||
echo "signalTest: Timeout expired before signal received!"
|
echo "signalTest: Timeout expired before signal received!"
|
||||||
|
|
||||||
when supportedPlatform:
|
when ioselSupportedPlatform:
|
||||||
timerTest()
|
timerTest()
|
||||||
eventTest()
|
eventTest()
|
||||||
processTest()
|
processTest()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue