Some cosmetic changes, and comments

This commit is contained in:
cheatfate 2016-06-26 12:05:44 +03:00
commit fb0ef44864

View file

@ -50,7 +50,7 @@ when defined(nimdoc):
Selector*[T] = ref object Selector*[T] = ref object
## An object which holds descriptors to be checked for read/write status ## An object which holds descriptors to be checked for read/write status
Event* {.pure.} = enum Event* {.pure.} = enum
## An enum which hold event types ## An enum which hold event types
Read, ## Descriptor is available for read Read, ## Descriptor is available for read
Write, ## Descriptor is available for write Write, ## Descriptor is available for write
@ -249,7 +249,7 @@ else:
import locks import locks
type type
Event* {.pure.} = enum Event* {.pure.} = enum
Read, Write, Timer, Signal, Process, Vnode, User, Error, Read, Write, Timer, Signal, Process, Vnode, User, Error,
flagHandle, flagTimer, flagSignal, flagProcess, flagVnode, flagUser, flagHandle, flagTimer, flagSignal, flagProcess, flagVnode, flagUser,
flagOneshot flagOneshot
@ -299,6 +299,10 @@ else:
s.fds[f].ident = 0 s.fds[f].ident = 0
s.fds[f].flags = {} s.fds[f].flags = {}
template checkMaxFd(s, fd) =
if fd.uint >= s.maxFD:
raise newException(ValueError, "Maximum file descriptors exceeded")
when supportedPlatform: when supportedPlatform:
template blockSignals(newmask: var Sigset, oldmask: var Sigset) = template blockSignals(newmask: var Sigset, oldmask: var Sigset) =
when hasThreadSupport: when hasThreadSupport:
@ -326,7 +330,9 @@ else:
# #
when bsdPlatform: when bsdPlatform:
const const
# Maximum number of cached changes
MAX_KQUEUE_CHANGE_EVENTS = 64 MAX_KQUEUE_CHANGE_EVENTS = 64
# Maximum number of events that can be returned
MAX_KQUEUE_RESULT_EVENTS = 64 MAX_KQUEUE_RESULT_EVENTS = 64
type type
@ -401,43 +407,39 @@ else:
proc registerHandle*[T](s: Selector[T], fd: SocketHandle, proc registerHandle*[T](s: Selector[T], fd: SocketHandle,
events: set[Event], data: T) = events: set[Event], data: T) =
var fdi = int(fd) var fdi = int(fd)
if fdi.uint < s.maxFD: s.checkMaxFd(fdi)
doAssert(s.fds[fdi].ident == 0) doAssert(s.fds[fdi].ident == 0)
setKey(s, fdi, fdi, {Event.flagHandle} + events, 0, data) setKey(s, fdi, fdi, {Event.flagHandle} + events, 0, data)
if events != {}: if events != {}:
if Event.Read in events: if Event.Read in events:
modifyKQueue(s, fdi.uint, EVFILT_READ, EV_ADD, 0, 0, nil) modifyKQueue(s, fdi.uint, EVFILT_READ, EV_ADD, 0, 0, nil)
inc(s.count) inc(s.count)
if Event.Write in events: if Event.Write in events:
modifyKQueue(s, fdi.uint, EVFILT_WRITE, EV_ADD, 0, 0, nil) modifyKQueue(s, fdi.uint, EVFILT_WRITE, EV_ADD, 0, 0, nil)
inc(s.count) inc(s.count)
else:
raise newException(ValueError, "Maximum file descriptors exceeded")
proc updateHandle*[T](s: Selector[T], fd: SocketHandle, proc updateHandle*[T](s: Selector[T], fd: SocketHandle,
events: set[Event]) = events: set[Event]) =
var fdi = int(fd) var fdi = int(fd)
if fdi.uint < s.maxFD: s.checkMaxFd(fdi)
doAssert(s.fds[fdi].ident != 0) doAssert(s.fds[fdi].ident != 0)
doAssert(Event.flagHandle in s.fds[fdi].flags) doAssert(Event.flagHandle in s.fds[fdi].flags)
var ne = events + {Event.flagHandle} var ne = events + {Event.flagHandle}
var oe = s.fds[fdi].flags var oe = s.fds[fdi].flags
if oe != ne: if oe != ne:
if (Event.Read in oe) and (Event.Read notin ne): if (Event.Read in oe) and (Event.Read notin ne):
modifyKQueue(s, fdi.uint, EVFILT_READ, EV_DELETE, 0, 0, nil) modifyKQueue(s, fdi.uint, EVFILT_READ, EV_DELETE, 0, 0, nil)
dec(s.count) dec(s.count)
if (Event.Write in oe) and (Event.Write notin ne): if (Event.Write in oe) and (Event.Write notin ne):
modifyKQueue(s, fdi.uint, EVFILT_WRITE, EV_DELETE, 0, 0, nil) modifyKQueue(s, fdi.uint, EVFILT_WRITE, EV_DELETE, 0, 0, nil)
dec(s.count) dec(s.count)
if (Event.Read notin oe) and (Event.Read in ne): if (Event.Read notin oe) and (Event.Read in ne):
modifyKQueue(s, fdi.uint, EVFILT_READ, EV_ADD, 0, 0, nil) modifyKQueue(s, fdi.uint, EVFILT_READ, EV_ADD, 0, 0, nil)
inc(s.count) inc(s.count)
if (Event.Write notin oe) and (Event.Write in ne): if (Event.Write notin oe) and (Event.Write in ne):
modifyKQueue(s, fdi.uint, EVFILT_WRITE, EV_ADD, 0, 0, nil) modifyKQueue(s, fdi.uint, EVFILT_WRITE, EV_ADD, 0, 0, nil)
inc(s.count) inc(s.count)
s.fds[fdi].flags = ne s.fds[fdi].flags = ne
else:
raise newException(ValueError, "Maximum file descriptors exceeded")
proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool, proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool,
data: T): int {.discardable.} = data: T): int {.discardable.} =
@ -445,21 +447,19 @@ else:
posix.IPPROTO_TCP).int posix.IPPROTO_TCP).int
if fdi == -1: if fdi == -1:
raiseOsError(osLastError()) raiseOsError(osLastError())
if fdi.uint < s.maxFD: s.checkMaxFd(fdi)
doAssert(s.fds[fdi].ident == 0) doAssert(s.fds[fdi].ident == 0)
var mflags = if oneshot: {Event.flagTimer, Event.flagOneshot} var mflags = if oneshot: {Event.flagTimer, Event.flagOneshot}
else: {Event.flagTimer} else: {Event.flagTimer}
var kflags: cushort = if oneshot: EV_ONESHOT or EV_ADD var kflags: cushort = if oneshot: EV_ONESHOT or EV_ADD
else: EV_ADD else: EV_ADD
setKey(s, fdi, fdi, mflags, 0, data) setKey(s, fdi, fdi, mflags, 0, data)
# EVFILT_TIMER on Open/Net(BSD) has granularity of only milliseconds, # EVFILT_TIMER on Open/Net(BSD) has granularity of only milliseconds,
# but MacOS and FreeBSD allow use `0` as `fflags` to use milliseconds # but MacOS and FreeBSD allow use `0` as `fflags` to use milliseconds
# too # too
modifyKQueue(s, fdi.uint, EVFILT_TIMER, kflags, 0, cint(timeout), nil) modifyKQueue(s, fdi.uint, EVFILT_TIMER, kflags, 0, cint(timeout), nil)
inc(s.count) inc(s.count)
result = fdi result = fdi
else:
raise newException(ValueError, "Maximum file descriptors exceeded")
proc registerSignal*[T](s: Selector[T], signal: int, proc registerSignal*[T](s: Selector[T], signal: int,
data: T): int {.discardable.} = data: T): int {.discardable.} =
@ -468,24 +468,22 @@ else:
if fdi == -1: if fdi == -1:
raiseOsError(osLastError()) raiseOsError(osLastError())
if fdi.uint < s.maxFD: s.checkMaxFd(fdi)
doAssert(s.fds[fdi].ident == 0) doAssert(s.fds[fdi].ident == 0)
setKey(s, fdi, signal, {Event.flagSignal}, signal, data) setKey(s, fdi, signal, {Event.flagSignal}, signal, data)
# block signal `signal` # block signal `signal`
var nmask: Sigset var nmask: Sigset
var omask: Sigset var omask: Sigset
discard sigemptyset(nmask) discard sigemptyset(nmask)
discard sigemptyset(omask) discard sigemptyset(omask)
discard sigaddset(nmask, cint(signal)) discard sigaddset(nmask, cint(signal))
blockSignals(nmask, omask) blockSignals(nmask, omask)
# to be compatible with linux semantic we need to "eat" signals # to be compatible with linux semantic we need to "eat" signals
posix.signal(cint(signal), SIG_IGN) posix.signal(cint(signal), SIG_IGN)
modifyKQueue(s, signal.uint, EVFILT_SIGNAL, EV_ADD, 0, 0, modifyKQueue(s, signal.uint, EVFILT_SIGNAL, EV_ADD, 0, 0,
cast[pointer](fdi)) cast[pointer](fdi))
inc(s.count) inc(s.count)
result = fdi result = fdi
else:
raise newException(ValueError, "Maximum file descriptors exceeded")
proc registerProcess*[T](s: Selector[T], pid: int, proc registerProcess*[T](s: Selector[T], pid: int,
data: T): int {.discardable.} = data: T): int {.discardable.} =
@ -494,16 +492,14 @@ else:
if fdi == -1: if fdi == -1:
raiseOsError(osLastError()) raiseOsError(osLastError())
if fdi.uint < s.maxFD: s.checkMaxFd(fdi)
doAssert(s.fds[fdi].ident == 0) doAssert(s.fds[fdi].ident == 0)
var kflags: cushort = EV_ONESHOT or EV_ADD var kflags: cushort = EV_ONESHOT or EV_ADD
setKey(s, fdi, pid, {Event.flagProcess, Event.flagOneshot}, pid, data) setKey(s, fdi, pid, {Event.flagProcess, Event.flagOneshot}, pid, data)
modifyKQueue(s, pid.uint, EVFILT_PROC, kflags, NOTE_EXIT, 0, modifyKQueue(s, pid.uint, EVFILT_PROC, kflags, NOTE_EXIT, 0,
cast[pointer](fdi)) cast[pointer](fdi))
inc(s.count) inc(s.count)
result = fdi result = fdi
else:
raise newException(ValueError, "Maximum file descriptors exceeded")
proc unregister*[T](s: Selector[T], fd: int|SocketHandle|cint) = proc unregister*[T](s: Selector[T], fd: int|SocketHandle|cint) =
var fdi = int(fd) var fdi = int(fd)
@ -592,12 +588,11 @@ else:
proc unregister*[T](s: Selector[T], ev: SelectEvent) = proc unregister*[T](s: Selector[T], ev: SelectEvent) =
let fdi = ev.rfd.int let fdi = ev.rfd.int
if fdi.uint < s.maxFD: var flags = s.fds[fdi].flags
var flags = s.fds[fdi].flags if s.fds[fdi].ident != 0 and flags != {}:
if s.fds[fdi].ident != 0 and flags != {}: modifyKQueue(s, fdi.uint, EVFILT_READ, EV_DELETE, 0, 0, nil)
modifyKQueue(s, fdi.uint, EVFILT_READ, EV_DELETE, 0, 0, nil) dec(s.count)
dec(s.count) clearKey(s, fdi)
clearKey(s, fdi)
proc selectInto*[T](s: Selector[T], timeout: int, proc selectInto*[T](s: Selector[T], timeout: int,
results: var openarray[ReadyKey[T]]): int = results: var openarray[ReadyKey[T]]): int =
@ -710,6 +705,7 @@ else:
elif defined(linux): elif defined(linux):
const const
# Maximum number of events that can be returned
MAX_EPOLL_RESULT_EVENTS = 64 MAX_EPOLL_RESULT_EVENTS = 64
type type
SignalFdInfo* {.importc: "struct signalfd_siginfo", SignalFdInfo* {.importc: "struct signalfd_siginfo",
@ -772,7 +768,6 @@ else:
proc eventfd(count: cuint, flags: cint): cint proc eventfd(count: cuint, flags: cint): cint
{.cdecl, importc: "eventfd", header: "<sys/eventfd.h>".} {.cdecl, importc: "eventfd", header: "<sys/eventfd.h>".}
type type
SelectorImpl[T] = object SelectorImpl[T] = object
epollFD : cint epollFD : cint
@ -807,60 +802,56 @@ else:
proc registerHandle*[T](s: Selector[T], fd: SocketHandle, proc registerHandle*[T](s: Selector[T], fd: SocketHandle,
events: set[Event], data: T) = events: set[Event], data: T) =
var fdi = int(fd) var fdi = int(fd)
if fdi.uint < s.maxFD: s.checkMaxFd(fdi)
doAssert(s.fds[fdi].ident == 0) doAssert(s.fds[fdi].ident == 0)
setKey(s, fdi, fdi, events + {Event.flagHandle}, 0, data) setKey(s, fdi, fdi, events + {Event.flagHandle}, 0, data)
if events != {}: if events != {}:
var epv: epoll_event var epv: epoll_event
epv.events = EPOLLRDHUP epv.events = EPOLLRDHUP
epv.data.u64 = fdi.uint epv.data.u64 = fdi.uint
if Event.Read in events: if Event.Read in events:
epv.events = epv.events or EPOLLIN epv.events = epv.events or EPOLLIN
if Event.Write in events: if Event.Write in events:
epv.events = epv.events or EPOLLOUT epv.events = epv.events or EPOLLOUT
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1: if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
raiseOSError(osLastError()) raiseOSError(osLastError())
inc(s.count) inc(s.count)
else:
raise newException(ValueError, "Maximum file descriptors exceeded")
proc updateHandle*[T](s: Selector[T], fd: SocketHandle, proc updateHandle*[T](s: Selector[T], fd: SocketHandle,
events: set[Event]) = events: set[Event]) =
var fdi = int(fd) var fdi = int(fd)
if fdi.uint < s.maxFD: s.checkMaxFd(fdi)
var oe = s.fds[fdi].flags var oe = s.fds[fdi].flags
doAssert(s.fds[fdi].ident != 0) doAssert(s.fds[fdi].ident != 0)
doAssert(Event.flagHandle in oe) doAssert(Event.flagHandle in oe)
var ne = events + {Event.flagHandle} var ne = events + {Event.flagHandle}
if oe != ne: if oe != ne:
var epv: epoll_event var epv: epoll_event
epv.data.u64 = fdi.uint epv.data.u64 = fdi.uint
epv.events = EPOLLRDHUP epv.events = EPOLLRDHUP
if Event.Read in events: if Event.Read in events:
epv.events = epv.events or EPOLLIN epv.events = epv.events or EPOLLIN
if Event.Write in events: if Event.Write in events:
epv.events = epv.events or EPOLLOUT epv.events = epv.events or EPOLLOUT
if oe == {Event.flagHandle}: if oe == {Event.flagHandle}:
if ne != {Event.flagHandle}: if ne != {Event.flagHandle}:
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint,
addr epv) == -1: addr epv) == -1:
raiseOSError(osLastError()) raiseOSError(osLastError())
inc(s.count) inc(s.count)
else:
if ne != {Event.flagHandle}:
if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fdi.cint,
addr epv) == -1:
raiseOSError(osLastError())
else: else:
if events != {}: if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint,
if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fdi.cint, addr epv) == -1:
addr epv) == -1: raiseOSError(osLastError())
raiseOSError(osLastError()) dec(s.count)
else: s.fds[fdi].flags = ne
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint,
addr epv) == -1:
raiseOSError(osLastError())
dec(s.count)
s.fds[fdi].flags = ne
else:
raise newException(ValueError, "Maximum file descriptors exceeded")
proc unregister*[T](s: Selector[T], fd: int|SocketHandle|cint) = proc unregister*[T](s: Selector[T], fd: int|SocketHandle|cint) =
var epv: epoll_event var epv: epoll_event
@ -924,88 +915,88 @@ else:
var fdi = timerfd_create(CLOCK_MONOTONIC, 0) var fdi = timerfd_create(CLOCK_MONOTONIC, 0)
if fdi == -1: if fdi == -1:
raiseOSError(osLastError()) raiseOSError(osLastError())
if fdi.uint < s.maxFD: s.checkMaxFd(fdi)
doAssert(s.fds[fdi].ident == 0) doAssert(s.fds[fdi].ident == 0)
var flags = {Event.flagTimer} var flags = {Event.flagTimer}
var epv: epoll_event var epv: epoll_event
epv.data.u64 = fdi.uint epv.data.u64 = fdi.uint
epv.events = EPOLLIN or EPOLLRDHUP epv.events = EPOLLIN or EPOLLRDHUP
setNonBlocking(fdi.cint) setNonBlocking(fdi.cint)
if oneshot: if oneshot:
new_ts.it_interval.tv_sec = 0.Time new_ts.it_interval.tv_sec = 0.Time
new_ts.it_interval.tv_nsec = 0 new_ts.it_interval.tv_nsec = 0
new_ts.it_value.tv_sec = (timeout div 1_000).Time new_ts.it_value.tv_sec = (timeout div 1_000).Time
new_ts.it_value.tv_nsec = (timeout %% 1_000) * 1_000_000 new_ts.it_value.tv_nsec = (timeout %% 1_000) * 1_000_000
flags = flags + {Event.flagOneshot} flags = flags + {Event.flagOneshot}
epv.events = epv.events or EPOLLONESHOT epv.events = epv.events or EPOLLONESHOT
else:
new_ts.it_interval.tv_sec = (timeout div 1000).Time
new_ts.it_interval.tv_nsec = (timeout %% 1_000) * 1_000_000
new_ts.it_value.tv_sec = new_ts.it_interval.tv_sec
new_ts.it_value.tv_nsec = new_ts.it_interval.tv_nsec
if timerfd_settime(fdi.cint, cint(0), new_ts, old_ts) == -1:
raiseOSError(osLastError())
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
raiseOSError(osLastError())
setKey(s, fdi, fdi, flags, 0, data)
inc(s.count)
result = fdi
else: else:
raise newException(ValueError, "Maximum file descriptors exceeded") new_ts.it_interval.tv_sec = (timeout div 1000).Time
new_ts.it_interval.tv_nsec = (timeout %% 1_000) * 1_000_000
new_ts.it_value.tv_sec = new_ts.it_interval.tv_sec
new_ts.it_value.tv_nsec = new_ts.it_interval.tv_nsec
if timerfd_settime(fdi.cint, cint(0), new_ts, old_ts) == -1:
raiseOSError(osLastError())
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
raiseOSError(osLastError())
setKey(s, fdi, fdi, flags, 0, data)
inc(s.count)
result = fdi
proc registerSignal*[T](s: Selector[T], signal: int, proc registerSignal*[T](s: Selector[T], signal: int,
data: T): int {.discardable.} = data: T): int {.discardable.} =
var var
nmask: Sigset nmask: Sigset
omask: Sigset omask: Sigset
fdi: cint
discard sigemptyset(nmask) discard sigemptyset(nmask)
discard sigemptyset(omask) discard sigemptyset(omask)
discard sigaddset(nmask, signal.cint) discard sigaddset(nmask, cint(signal))
blockSignals(nmask, omask) blockSignals(nmask, omask)
fdi = signalfd(-1, nmask, 0)
var fdi = signalfd(-1, nmask, 0).int
if fdi == -1: if fdi == -1:
raiseOSError(osLastError()) raiseOSError(osLastError())
if fdi.uint < s.maxFD:
doAssert(s.fds[fdi].ident == 0) s.checkMaxFd(fdi)
setNonBlocking(fdi.cint) doAssert(s.fds[fdi].ident == 0)
var epv: epoll_event setNonBlocking(fdi.cint)
epv.data.u64 = fdi.uint
epv.events = EPOLLIN or EPOLLRDHUP var epv: epoll_event
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1: epv.data.u64 = fdi.uint
raiseOSError(osLastError()) epv.events = EPOLLIN or EPOLLRDHUP
setKey(s, fdi, signal, {Event.flagSignal}, signal, data) if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
inc(s.count) raiseOSError(osLastError())
result = fdi setKey(s, fdi, signal, {Event.flagSignal}, signal, data)
else: inc(s.count)
raise newException(ValueError, "Maximum file descriptors exceeded") result = fdi
proc registerProcess*[T](s: Selector, pid: int, proc registerProcess*[T](s: Selector, pid: int,
data: T): int {.discardable.} = data: T): int {.discardable.} =
var var
nmask: Sigset nmask: Sigset
omask: Sigset omask: Sigset
fd: int
discard sigemptyset(nmask) discard sigemptyset(nmask)
discard sigemptyset(omask) discard sigemptyset(omask)
discard sigaddset(nmask, posix.SIGCHLD) discard sigaddset(nmask, posix.SIGCHLD)
blockSignals(nmask, omask) blockSignals(nmask, omask)
var fdi = signalfd(-1, nmask, 0)
if fd == -1: var fdi = signalfd(-1, nmask, 0).int
if fdi == -1:
raiseOSError(osLastError()) raiseOSError(osLastError())
if fdi.uint < s.maxFD:
doAssert(s.fds[fdi].ident == 0) s.checkMaxFd(fdi)
setNonBlocking(fdi.cint) doAssert(s.fds[fdi].ident == 0)
var epv: epoll_event setNonBlocking(fdi.cint)
epv.data.u64 = fdi.uint
epv.events = EPOLLIN or EPOLLRDHUP var epv: epoll_event
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1: epv.data.u64 = fdi.uint
raiseOSError(osLastError()) epv.events = EPOLLIN or EPOLLRDHUP
setKey(s, fdi, pid, {Event.flagProcess}, pid, data) if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
inc(s.count) raiseOSError(osLastError())
result = fdi setKey(s, fdi, pid, {Event.flagProcess}, pid, data)
else: inc(s.count)
raise newException(ValueError, "Maximum file descriptors exceeded") result = fdi
proc flush*[T](s: Selector[T]) = proc flush*[T](s: Selector[T]) =
discard discard
@ -1502,6 +1493,7 @@ else:
# #
else: else:
# Maximum number of events that can be returned
const MAX_POLL_RESULT_EVENTS = 64 const MAX_POLL_RESULT_EVENTS = 64
type type
@ -1600,29 +1592,25 @@ else:
proc registerHandle*[T](s: Selector[T], fd: SocketHandle, proc registerHandle*[T](s: Selector[T], fd: SocketHandle,
events: set[Event], data: T) = events: set[Event], data: T) =
var fdi = int(fd) var fdi = int(fd)
if fdi.uint < s.maxFD: s.checkMaxFd(fdi)
doAssert(s.fds[fdi].ident == 0) doAssert(s.fds[fdi].ident == 0)
setKey(s, fdi, fdi, {Event.flagHandle} + events, 0, data) setKey(s, fdi, fdi, {Event.flagHandle} + events, 0, data)
s.pollAdd(fdi.cint, events) s.pollAdd(fdi.cint, events)
else:
raise newException(ValueError, "Maximum file descriptors exceeded")
proc updateHandle*[T](s: Selector[T], fd: SocketHandle, proc updateHandle*[T](s: Selector[T], fd: SocketHandle,
events: set[Event]) = events: set[Event]) =
var fdi = int(fd) var fdi = int(fd)
if fdi.uint < s.maxFD: s.checkMaxFd(fdi)
var oe = s.fds[fdi].flags var oe = s.fds[fdi].flags
doAssert(s.fds[fdi].ident != 0) doAssert(s.fds[fdi].ident != 0)
doAssert(Event.flagHandle in oe) doAssert(Event.flagHandle in oe)
var ne = events + {Event.flagHandle} var ne = events + {Event.flagHandle}
if ne != oe: if ne != oe:
if events != {}: if events != {}:
s.pollUpdate(fd.cint, events) s.pollUpdate(fd.cint, events)
else: else:
s.pollRemove(fd.cint) s.pollRemove(fd.cint)
s.fds[fdi].flags = ne s.fds[fdi].flags = ne
else:
raise newException(ValueError, "Maximum file descriptors exceeded")
proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool, proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool,
data: T): int {.discardable.} = data: T): int {.discardable.} =