big rename
This commit is contained in:
parent
15a7bcc89f
commit
11b6958755
98 changed files with 2491 additions and 2341 deletions
|
|
@ -1,6 +1,6 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# Nim's Runtime Library
|
||||
# (c) Copyright 2014 Dominik Picheta
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
|
|
@ -18,57 +18,57 @@ elif defined(windows):
|
|||
else:
|
||||
import posix
|
||||
|
||||
proc hash*(x: TSocketHandle): THash {.borrow.}
|
||||
proc `$`*(x: TSocketHandle): string {.borrow.}
|
||||
proc hash*(x: SocketHandle): THash {.borrow.}
|
||||
proc `$`*(x: SocketHandle): string {.borrow.}
|
||||
|
||||
type
|
||||
TEvent* = enum
|
||||
Event* = enum
|
||||
EvRead, EvWrite
|
||||
|
||||
PSelectorKey* = ref object
|
||||
fd*: TSocketHandle
|
||||
events*: set[TEvent] ## The events which ``fd`` listens for.
|
||||
data*: PObject ## User object.
|
||||
SelectorKey* = ref object
|
||||
fd*: SocketHandle
|
||||
events*: set[Event] ## The events which ``fd`` listens for.
|
||||
data*: RootRef ## User object.
|
||||
|
||||
TReadyInfo* = tuple[key: PSelectorKey, events: set[TEvent]]
|
||||
ReadyInfo* = tuple[key: SelectorKey, events: set[Event]]
|
||||
|
||||
when defined(nimdoc):
|
||||
type
|
||||
PSelector* = ref object
|
||||
Selector* = ref object
|
||||
## An object which holds file descripters to be checked for read/write
|
||||
## status.
|
||||
fds: TTable[TSocketHandle, PSelectorKey]
|
||||
fds: Table[SocketHandle, SelectorKey]
|
||||
|
||||
proc register*(s: PSelector, fd: TSocketHandle, events: set[TEvent],
|
||||
data: PObject): PSelectorKey {.discardable.} =
|
||||
proc register*(s: Selector, fd: SocketHandle, events: set[Event],
|
||||
data: RootRef): SelectorKey {.discardable.} =
|
||||
## Registers file descriptor ``fd`` to selector ``s`` with a set of TEvent
|
||||
## ``events``.
|
||||
|
||||
proc update*(s: PSelector, fd: TSocketHandle,
|
||||
events: set[TEvent]): PSelectorKey {.discardable.} =
|
||||
proc update*(s: Selector, fd: SocketHandle,
|
||||
events: set[Event]): SelectorKey {.discardable.} =
|
||||
## Updates the events which ``fd`` wants notifications for.
|
||||
|
||||
proc select*(s: PSelector, timeout: int): seq[TReadyInfo] =
|
||||
proc select*(s: Selector, timeout: int): seq[ReadyInfo] =
|
||||
## The ``events`` field of the returned ``key`` contains the original events
|
||||
## for which the ``fd`` was bound. This is contrary to the ``events`` field
|
||||
## of the ``TReadyInfo`` tuple which determines which events are ready
|
||||
## on the ``fd``.
|
||||
|
||||
proc contains*(s: PSelector, fd: TSocketHandle): bool =
|
||||
proc contains*(s: Selector, fd: SocketHandle): bool =
|
||||
## Determines whether selector contains a file descriptor.
|
||||
|
||||
proc `[]`*(s: PSelector, fd: TSocketHandle): PSelectorKey =
|
||||
proc `[]`*(s: Selector, fd: SocketHandle): SelectorKey =
|
||||
## Retrieves the selector key for ``fd``.
|
||||
|
||||
|
||||
elif defined(linux):
|
||||
type
|
||||
PSelector* = ref object
|
||||
Selector* = ref object
|
||||
epollFD: cint
|
||||
events: array[64, epoll_event]
|
||||
fds: TTable[TSocketHandle, PSelectorKey]
|
||||
fds: Table[SocketHandle, SelectorKey]
|
||||
|
||||
proc createEventStruct(events: set[TEvent], fd: TSocketHandle): epoll_event =
|
||||
proc createEventStruct(events: set[Event], fd: SocketHandle): epoll_event =
|
||||
if EvRead in events:
|
||||
result.events = EPOLLIN
|
||||
if EvWrite in events:
|
||||
|
|
@ -76,22 +76,22 @@ elif defined(linux):
|
|||
result.events = result.events or EPOLLRDHUP
|
||||
result.data.fd = fd.cint
|
||||
|
||||
proc register*(s: PSelector, fd: TSocketHandle, events: set[TEvent],
|
||||
data: PObject): PSelectorKey {.discardable.} =
|
||||
proc register*(s: Selector, fd: SocketHandle, events: set[Event],
|
||||
data: RootRef): SelectorKey {.discardable.} =
|
||||
## Registers file descriptor ``fd`` to selector ``s`` with a set of TEvent
|
||||
## ``events``.
|
||||
var event = createEventStruct(events, fd)
|
||||
if events != {}:
|
||||
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0:
|
||||
OSError(OSLastError())
|
||||
raiseOSError(osLastError())
|
||||
|
||||
var key = PSelectorKey(fd: fd, events: events, data: data)
|
||||
var key = SelectorKey(fd: fd, events: events, data: data)
|
||||
|
||||
s.fds[fd] = key
|
||||
result = key
|
||||
|
||||
proc update*(s: PSelector, fd: TSocketHandle,
|
||||
events: set[TEvent]): PSelectorKey {.discardable.} =
|
||||
proc update*(s: Selector, fd: SocketHandle,
|
||||
events: set[Event]): SelectorKey {.discardable.} =
|
||||
## Updates the events which ``fd`` wants notifications for.
|
||||
if s.fds[fd].events != events:
|
||||
if events == {}:
|
||||
|
|
@ -101,7 +101,7 @@ elif defined(linux):
|
|||
# because its got fds which are waiting for no events and
|
||||
# are therefore constantly ready. (leading to 100% CPU usage).
|
||||
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0:
|
||||
OSError(OSLastError())
|
||||
raiseOSError(osLastError())
|
||||
s.fds[fd].events = events
|
||||
else:
|
||||
var event = createEventStruct(events, fd)
|
||||
|
|
@ -109,36 +109,36 @@ elif defined(linux):
|
|||
# This fd is idle. It's not a member of this epoll instance and must
|
||||
# be re-registered.
|
||||
if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0:
|
||||
OSError(OSLastError())
|
||||
raiseOSError(osLastError())
|
||||
else:
|
||||
if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0:
|
||||
OSError(OSLastError())
|
||||
raiseOSError(osLastError())
|
||||
s.fds[fd].events = events
|
||||
|
||||
result = s.fds[fd]
|
||||
|
||||
proc unregister*(s: PSelector, fd: TSocketHandle): PSelectorKey {.discardable.} =
|
||||
proc unregister*(s: Selector, fd: SocketHandle): SelectorKey {.discardable.} =
|
||||
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0:
|
||||
let err = OSLastError()
|
||||
let err = osLastError()
|
||||
if err.cint notin {ENOENT, EBADF}: # TODO: Why do we sometimes get an EBADF? Is this normal?
|
||||
OSError(err)
|
||||
raiseOSError(err)
|
||||
result = s.fds[fd]
|
||||
s.fds.del(fd)
|
||||
|
||||
proc close*(s: PSelector) =
|
||||
if s.epollFD.close() != 0: OSError(OSLastError())
|
||||
proc close*(s: Selector) =
|
||||
if s.epollFD.close() != 0: raiseOSError(osLastError())
|
||||
dealloc(addr s.events) # TODO: Test this
|
||||
|
||||
proc epollHasFd(s: PSelector, fd: TSocketHandle): bool =
|
||||
proc epollHasFd(s: Selector, fd: SocketHandle): bool =
|
||||
result = true
|
||||
var event = createEventStruct(s.fds[fd].events, fd)
|
||||
if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0:
|
||||
let err = osLastError()
|
||||
if err.cint in {ENOENT, EBADF}:
|
||||
return false
|
||||
OSError(OSLastError())
|
||||
raiseOSError(osLastError())
|
||||
|
||||
proc select*(s: PSelector, timeout: int): seq[TReadyInfo] =
|
||||
proc select*(s: Selector, timeout: int): seq[ReadyInfo] =
|
||||
##
|
||||
## The ``events`` field of the returned ``key`` contains the original events
|
||||
## for which the ``fd`` was bound. This is contrary to the ``events`` field
|
||||
|
|
@ -146,12 +146,12 @@ elif defined(linux):
|
|||
## on the ``fd``.
|
||||
result = @[]
|
||||
let evNum = epoll_wait(s.epollFD, addr s.events[0], 64.cint, timeout.cint)
|
||||
if evNum < 0: OSError(OSLastError())
|
||||
if evNum < 0: raiseOSError(osLastError())
|
||||
if evNum == 0: return @[]
|
||||
for i in 0 .. <evNum:
|
||||
let fd = s.events[i].data.fd.TSocketHandle
|
||||
let fd = s.events[i].data.fd.SocketHandle
|
||||
|
||||
var evSet: set[TEvent] = {}
|
||||
var evSet: set[Event] = {}
|
||||
if (s.events[i].events and EPOLLIN) != 0: evSet = evSet + {EvRead}
|
||||
if (s.events[i].events and EPOLLOUT) != 0: evSet = evSet + {EvWrite}
|
||||
let selectorKey = s.fds[fd]
|
||||
|
|
@ -160,15 +160,15 @@ elif defined(linux):
|
|||
|
||||
#echo("Epoll: ", result[i].key.fd, " ", result[i].events, " ", result[i].key.events)
|
||||
|
||||
proc newSelector*(): PSelector =
|
||||
proc newSelector*(): Selector =
|
||||
new result
|
||||
result.epollFD = epoll_create(64)
|
||||
#result.events = cast[array[64, epoll_event]](alloc0(sizeof(epoll_event)*64))
|
||||
result.fds = initTable[TSocketHandle, PSelectorKey]()
|
||||
result.fds = initTable[SocketHandle, SelectorKey]()
|
||||
if result.epollFD < 0:
|
||||
OSError(OSLastError())
|
||||
raiseOSError(osLastError())
|
||||
|
||||
proc contains*(s: PSelector, fd: TSocketHandle): bool =
|
||||
proc contains*(s: Selector, fd: SocketHandle): bool =
|
||||
## Determines whether selector contains a file descriptor.
|
||||
if s.fds.hasKey(fd):
|
||||
# Ensure the underlying epoll instance still contains this fd.
|
||||
|
|
@ -179,46 +179,46 @@ elif defined(linux):
|
|||
else:
|
||||
return false
|
||||
|
||||
proc `[]`*(s: PSelector, fd: TSocketHandle): PSelectorKey =
|
||||
proc `[]`*(s: Selector, fd: SocketHandle): SelectorKey =
|
||||
## Retrieves the selector key for ``fd``.
|
||||
return s.fds[fd]
|
||||
|
||||
elif not defined(nimdoc):
|
||||
# TODO: kqueue for bsd/mac os x.
|
||||
type
|
||||
PSelector* = ref object
|
||||
fds: TTable[TSocketHandle, PSelectorKey]
|
||||
Selector* = ref object
|
||||
fds: Table[SocketHandle, SelectorKey]
|
||||
|
||||
proc register*(s: PSelector, fd: TSocketHandle, events: set[TEvent],
|
||||
data: PObject): PSelectorKey {.discardable.} =
|
||||
proc register*(s: Selector, fd: SocketHandle, events: set[Event],
|
||||
data: RootRef): SelectorKey {.discardable.} =
|
||||
if s.fds.hasKey(fd):
|
||||
raise newException(EInvalidValue, "File descriptor already exists.")
|
||||
var sk = PSelectorKey(fd: fd, events: events, data: data)
|
||||
raise newException(ValueError, "File descriptor already exists.")
|
||||
var sk = SelectorKey(fd: fd, events: events, data: data)
|
||||
s.fds[fd] = sk
|
||||
result = sk
|
||||
|
||||
proc update*(s: PSelector, fd: TSocketHandle,
|
||||
events: set[TEvent]): PSelectorKey {.discardable.} =
|
||||
proc update*(s: Selector, fd: SocketHandle,
|
||||
events: set[Event]): SelectorKey {.discardable.} =
|
||||
## Updates the events which ``fd`` wants notifications for.
|
||||
if not s.fds.hasKey(fd):
|
||||
raise newException(EInvalidValue, "File descriptor not found.")
|
||||
raise newException(ValueError, "File descriptor not found.")
|
||||
|
||||
s.fds[fd].events = events
|
||||
result = s.fds[fd]
|
||||
|
||||
proc unregister*(s: PSelector, fd: TSocketHandle): PSelectorKey {.discardable.} =
|
||||
proc unregister*(s: Selector, fd: SocketHandle): SelectorKey {.discardable.} =
|
||||
result = s.fds[fd]
|
||||
s.fds.del(fd)
|
||||
|
||||
proc close*(s: PSelector) = nil
|
||||
proc close*(s: Selector) = discard
|
||||
|
||||
proc timeValFromMilliseconds(timeout: int): TTimeVal =
|
||||
proc timeValFromMilliseconds(timeout: int): TimeVal =
|
||||
if timeout != -1:
|
||||
var seconds = timeout div 1000
|
||||
result.tv_sec = seconds.int32
|
||||
result.tv_usec = ((timeout - seconds * 1000) * 1000).int32
|
||||
|
||||
proc createFdSet(rd, wr: var TFdSet, fds: TTable[TSocketHandle, PSelectorKey],
|
||||
proc createFdSet(rd, wr: var FdSet, fds: Table[SocketHandle, SelectorKey],
|
||||
m: var int) =
|
||||
FD_ZERO(rd); FD_ZERO(wr)
|
||||
for k, v in pairs(fds):
|
||||
|
|
@ -229,22 +229,22 @@ elif not defined(nimdoc):
|
|||
m = max(m, int(k))
|
||||
FD_SET(k, wr)
|
||||
|
||||
proc getReadyFDs(rd, wr: var TFdSet, fds: TTable[TSocketHandle, PSelectorKey]):
|
||||
seq[TReadyInfo] =
|
||||
proc getReadyFDs(rd, wr: var FdSet, fds: Table[SocketHandle, SelectorKey]):
|
||||
seq[ReadyInfo] =
|
||||
result = @[]
|
||||
for k, v in pairs(fds):
|
||||
var events: set[TEvent] = {}
|
||||
var events: set[Event] = {}
|
||||
if FD_ISSET(k, rd) != 0'i32:
|
||||
events = events + {EvRead}
|
||||
if FD_ISSET(k, wr) != 0'i32:
|
||||
events = events + {EvWrite}
|
||||
result.add((v, events))
|
||||
|
||||
proc select(fds: TTable[TSocketHandle, PSelectorKey], timeout = 500):
|
||||
seq[TReadyInfo] =
|
||||
var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout)
|
||||
proc select(fds: Table[SocketHandle, SelectorKey], timeout = 500):
|
||||
seq[ReadyInfo] =
|
||||
var tv {.noInit.}: TimeVal = timeValFromMilliseconds(timeout)
|
||||
|
||||
var rd, wr: TFdSet
|
||||
var rd, wr: FdSet
|
||||
var m = 0
|
||||
createFdSet(rd, wr, fds, m)
|
||||
|
||||
|
|
@ -255,26 +255,26 @@ elif not defined(nimdoc):
|
|||
retCode = int(select(cint(m+1), addr(rd), addr(wr), nil, nil))
|
||||
|
||||
if retCode < 0:
|
||||
OSError(OSLastError())
|
||||
raiseOSError(osLastError())
|
||||
elif retCode == 0:
|
||||
return @[]
|
||||
else:
|
||||
return getReadyFDs(rd, wr, fds)
|
||||
|
||||
proc select*(s: PSelector, timeout: int): seq[TReadyInfo] =
|
||||
proc select*(s: Selector, timeout: int): seq[ReadyInfo] =
|
||||
result = select(s.fds, timeout)
|
||||
|
||||
proc newSelector*(): PSelector =
|
||||
proc newSelector*(): Selector =
|
||||
new result
|
||||
result.fds = initTable[TSocketHandle, PSelectorKey]()
|
||||
result.fds = initTable[SocketHandle, SelectorKey]()
|
||||
|
||||
proc contains*(s: PSelector, fd: TSocketHandle): bool =
|
||||
proc contains*(s: Selector, fd: SocketHandle): bool =
|
||||
return s.fds.hasKey(fd)
|
||||
|
||||
proc `[]`*(s: PSelector, fd: TSocketHandle): PSelectorKey =
|
||||
proc `[]`*(s: Selector, fd: SocketHandle): SelectorKey =
|
||||
return s.fds[fd]
|
||||
|
||||
proc contains*(s: PSelector, key: PSelectorKey): bool =
|
||||
proc contains*(s: Selector, key: SelectorKey): bool =
|
||||
## Determines whether selector contains this selector key. More accurate
|
||||
## than checking if the file descriptor is in the selector because it
|
||||
## ensures that the keys are equal. File descriptors may not always be
|
||||
|
|
@ -282,20 +282,24 @@ proc contains*(s: PSelector, key: PSelectorKey): bool =
|
|||
## the new one may have the same value.
|
||||
return key.fd in s and s.fds[key.fd] == key
|
||||
|
||||
{.deprecated: [TEvent: Event, PSelectorKey: SelectorKey,
|
||||
TReadyInfo: ReadyInfo, PSelector: Selector].}
|
||||
|
||||
|
||||
when isMainModule and not defined(nimdoc):
|
||||
# Select()
|
||||
import sockets
|
||||
type
|
||||
PSockWrapper = ref object of PObject
|
||||
sock: TSocket
|
||||
SockWrapper = ref object of RootObj
|
||||
sock: Socket
|
||||
|
||||
var sock = socket()
|
||||
if sock == sockets.InvalidSocket: osError(osLastError())
|
||||
if sock == sockets.InvalidSocket: raiseOSError(osLastError())
|
||||
#sock.setBlocking(false)
|
||||
sock.connect("irc.freenode.net", TPort(6667))
|
||||
sock.connect("irc.freenode.net", Port(6667))
|
||||
|
||||
var selector = newSelector()
|
||||
var data = PSockWrapper(sock: sock)
|
||||
var data = SockWrapper(sock: sock)
|
||||
let key = selector.register(sock.getFD, {EvWrite}, data)
|
||||
var i = 0
|
||||
while true:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue