* Fix #5128, #5184. Removed flush() procedure from ioselectors.nim Changed methods of work with application-driven data * Make cache switch for kqueue, update test for it. * Fix registerProcess bug returns wrong id. Fix tupcoming_async test to compile with upcoming again. Change socket() as unique identifier to dup(socket) as unique identifier.
This commit is contained in:
parent
f8736dcfb7
commit
108f5e688e
8 changed files with 674 additions and 479 deletions
|
|
@ -12,7 +12,7 @@
|
|||
import posix, times
|
||||
|
||||
# Maximum number of events that can be returned
|
||||
const MAX_POLL_RESULT_EVENTS = 64
|
||||
const MAX_POLL_EVENTS = 64
|
||||
|
||||
when hasThreadSupport:
|
||||
type
|
||||
|
|
@ -65,7 +65,7 @@ else:
|
|||
proc newSelector*[T](): Selector[T] =
|
||||
var a = rlimit()
|
||||
if getrlimit(RLIMIT_NOFILE, a) != 0:
|
||||
raiseOsError(osLastError())
|
||||
raiseIOSelectorsError(osLastError())
|
||||
var maxFD = int(a.rlim_max)
|
||||
|
||||
when hasThreadSupport:
|
||||
|
|
@ -87,6 +87,12 @@ proc close*[T](s: Selector[T]) =
|
|||
deallocSharedArray(s.pollfds)
|
||||
deallocShared(cast[pointer](s))
|
||||
|
||||
template clearKey[T](key: ptr SelectorKey[T]) =
|
||||
var empty: T
|
||||
key.ident = 0
|
||||
key.events = {}
|
||||
key.data = empty
|
||||
|
||||
template pollAdd[T](s: Selector[T], sock: cint, events: set[Event]) =
|
||||
withPollLock(s):
|
||||
var pollev: cshort = 0
|
||||
|
|
@ -111,7 +117,7 @@ template pollUpdate[T](s: Selector[T], sock: cint, events: set[Event]) =
|
|||
inc(i)
|
||||
|
||||
if i == s.pollcnt:
|
||||
raise newException(ValueError, "Descriptor is not registered in queue")
|
||||
raiseIOSelectorsError("Descriptor is not registered in queue")
|
||||
|
||||
template pollRemove[T](s: Selector[T], sock: cint) =
|
||||
withPollLock(s):
|
||||
|
|
@ -134,14 +140,14 @@ template pollRemove[T](s: Selector[T], sock: cint) =
|
|||
|
||||
template checkFd(s, f) =
|
||||
if f >= s.maxFD:
|
||||
raise newException(ValueError, "Maximum file descriptors exceeded")
|
||||
raiseIOSelectorsError("Descriptor is not registered in queue")
|
||||
|
||||
proc registerHandle*[T](s: Selector[T], fd: SocketHandle,
|
||||
events: set[Event], data: T) =
|
||||
var fdi = int(fd)
|
||||
s.checkFd(fdi)
|
||||
doAssert(s.fds[fdi].ident == 0)
|
||||
s.setKey(fdi, fdi, events, 0, data)
|
||||
setKey(s, fdi, events, 0, data)
|
||||
if events != {}: s.pollAdd(fdi.cint, events)
|
||||
|
||||
proc updateHandle*[T](s: Selector[T], fd: SocketHandle,
|
||||
|
|
@ -168,12 +174,10 @@ proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) =
|
|||
var fdi = int(ev.rfd)
|
||||
doAssert(s.fds[fdi].ident == 0)
|
||||
var events = {Event.User}
|
||||
setKey(s, fdi, fdi, events, 0, data)
|
||||
setKey(s, fdi, events, 0, data)
|
||||
events.incl(Event.Read)
|
||||
s.pollAdd(fdi.cint, events)
|
||||
|
||||
proc flush*[T](s: Selector[T]) = discard
|
||||
|
||||
proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
|
||||
let fdi = int(fd)
|
||||
s.checkFd(fdi)
|
||||
|
|
@ -196,7 +200,7 @@ proc unregister*[T](s: Selector[T], ev: SelectEvent) =
|
|||
proc newSelectEvent*(): SelectEvent =
|
||||
var fds: array[2, cint]
|
||||
if posix.pipe(fds) == -1:
|
||||
raiseOSError(osLastError())
|
||||
raiseIOSelectorsError(osLastError())
|
||||
setNonBlocking(fds[0])
|
||||
setNonBlocking(fds[1])
|
||||
result = cast[SelectEvent](allocShared0(sizeof(SelectEventImpl)))
|
||||
|
|
@ -206,16 +210,18 @@ proc newSelectEvent*(): SelectEvent =
|
|||
proc setEvent*(ev: SelectEvent) =
|
||||
var data: uint64 = 1
|
||||
if posix.write(ev.wfd, addr data, sizeof(uint64)) != sizeof(uint64):
|
||||
raiseOSError(osLastError())
|
||||
raiseIOSelectorsError(osLastError())
|
||||
|
||||
proc close*(ev: SelectEvent) =
|
||||
discard posix.close(cint(ev.rfd))
|
||||
discard posix.close(cint(ev.wfd))
|
||||
if posix.close(cint(ev.rfd)) == -1:
|
||||
raiseIOSelectorsError(osLastError())
|
||||
if posix.close(cint(ev.wfd)) == -1:
|
||||
raiseIOSelectorsError(osLastError())
|
||||
deallocShared(cast[pointer](ev))
|
||||
|
||||
proc selectInto*[T](s: Selector[T], timeout: int,
|
||||
results: var openarray[ReadyKey[T]]): int =
|
||||
var maxres = MAX_POLL_RESULT_EVENTS
|
||||
results: var openarray[ReadyKey]): int =
|
||||
var maxres = MAX_POLL_EVENTS
|
||||
if maxres > len(results):
|
||||
maxres = len(results)
|
||||
|
||||
|
|
@ -224,10 +230,8 @@ proc selectInto*[T](s: Selector[T], timeout: int,
|
|||
if count < 0:
|
||||
result = 0
|
||||
let err = osLastError()
|
||||
if err.cint == EINTR:
|
||||
discard
|
||||
else:
|
||||
raiseOSError(osLastError())
|
||||
if cint(err) != EINTR:
|
||||
raiseIOSelectorsError(err)
|
||||
elif count == 0:
|
||||
result = 0
|
||||
else:
|
||||
|
|
@ -238,58 +242,71 @@ proc selectInto*[T](s: Selector[T], timeout: int,
|
|||
let revents = s.pollfds[i].revents
|
||||
if revents != 0:
|
||||
let fd = s.pollfds[i].fd
|
||||
var skey = addr(s.fds[fd])
|
||||
skey.key.events = {}
|
||||
var pkey = addr(s.fds[fd])
|
||||
var rkey = ReadyKey(fd: int(fd), events: {})
|
||||
|
||||
if (revents and POLLIN) != 0:
|
||||
skey.key.events.incl(Event.Read)
|
||||
if Event.User in skey.events:
|
||||
rkey.events.incl(Event.Read)
|
||||
if Event.User in pkey.events:
|
||||
var data: uint64 = 0
|
||||
if posix.read(fd, addr data, sizeof(uint64)) != sizeof(uint64):
|
||||
let err = osLastError()
|
||||
if err != OSErrorCode(EAGAIN):
|
||||
raiseOSError(osLastError())
|
||||
raiseIOSelectorsError(err)
|
||||
else:
|
||||
# someone already consumed event data
|
||||
inc(i)
|
||||
continue
|
||||
skey.key.events = {Event.User}
|
||||
rkey.events = {Event.User}
|
||||
if (revents and POLLOUT) != 0:
|
||||
skey.key.events.incl(Event.Write)
|
||||
rkey.events.incl(Event.Write)
|
||||
if (revents and POLLERR) != 0 or (revents and POLLHUP) != 0 or
|
||||
(revents and POLLNVAL) != 0:
|
||||
skey.key.events.incl(Event.Error)
|
||||
results[rindex] = skey.key
|
||||
rkey.events.incl(Event.Error)
|
||||
results[rindex] = rkey
|
||||
s.pollfds[i].revents = 0
|
||||
inc(rindex)
|
||||
inc(k)
|
||||
inc(i)
|
||||
result = k
|
||||
|
||||
proc select*[T](s: Selector[T], timeout: int): seq[ReadyKey[T]] =
|
||||
result = newSeq[ReadyKey[T]](MAX_POLL_RESULT_EVENTS)
|
||||
proc select*[T](s: Selector[T], timeout: int): seq[ReadyKey] =
|
||||
result = newSeq[ReadyKey](MAX_POLL_EVENTS)
|
||||
let count = selectInto(s, timeout, result)
|
||||
result.setLen(count)
|
||||
|
||||
template isEmpty*[T](s: Selector[T]): bool =
|
||||
(s.count == 0)
|
||||
|
||||
template withData*[T](s: Selector[T], fd: SocketHandle, value,
|
||||
proc getData*[T](s: Selector[T], fd: SocketHandle|int): T =
|
||||
let fdi = int(fd)
|
||||
s.checkFd(fdi)
|
||||
if s.fds[fdi].ident != 0:
|
||||
result = s.fds[fdi].data
|
||||
|
||||
proc setData*[T](s: Selector[T], fd: SocketHandle|int, data: T): bool =
|
||||
let fdi = int(fd)
|
||||
s.checkFd(fdi)
|
||||
if s.fds[fdi].ident != 0:
|
||||
s.fds[fdi].data = data
|
||||
result = true
|
||||
|
||||
template withData*[T](s: Selector[T], fd: SocketHandle|int, value,
|
||||
body: untyped) =
|
||||
mixin checkFd
|
||||
let fdi = int(fd)
|
||||
s.checkFd(fdi)
|
||||
if s.fds[fdi].ident != 0:
|
||||
var value = addr(s.fds[fdi].key.data)
|
||||
var value = addr(s.fds[fdi].data)
|
||||
body
|
||||
|
||||
template withData*[T](s: Selector[T], fd: SocketHandle, value, body1,
|
||||
template withData*[T](s: Selector[T], fd: SocketHandle|int, value, body1,
|
||||
body2: untyped) =
|
||||
mixin checkFd
|
||||
let fdi = int(fd)
|
||||
s.checkFd(fdi)
|
||||
if s.fds[fdi].ident != 0:
|
||||
var value = addr(s.fds[fdi].key.data)
|
||||
var value = addr(s.fds[fdi].data)
|
||||
body1
|
||||
else:
|
||||
body2
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue