From 471c0aa6349b7ad41d70b64ed370106bed9f0d01 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Thu, 31 Oct 2013 15:07:14 +0000 Subject: [PATCH] Epoll now works. --- lib/posix/epoll.nim | 13 ++++---- lib/pure/selectors.nim | 73 +++++++++++++++++++++++++++--------------- 2 files changed, 54 insertions(+), 32 deletions(-) diff --git a/lib/posix/epoll.nim b/lib/posix/epoll.nim index 098838624d..d50394f604 100644 --- a/lib/posix/epoll.nim +++ b/lib/posix/epoll.nim @@ -31,13 +31,14 @@ const EPOLL_CTL_MOD* = 3 # Change file descriptor epoll_event structure. type - epoll_data* {.pure, final.} = object - thePtr*: pointer - fd*: cint - u32*: uint32 - u64*: uint64 + epoll_data* {.importc: "union epoll_data", + header: "", pure, final.} = object # TODO: This is actually a union. + thePtr* {.importc: "ptr".}: pointer # \ + #fd*: cint + #u32*: uint32 + #u64*: uint64 - epoll_event* {.pure, final.} = object + epoll_event* {.importc: "struct epoll_event", header: "", pure, final.} = object events*: uint32 # Epoll events data*: epoll_data # User data variable diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 613f2d57b4..83c158da14 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -29,7 +29,7 @@ type PSelector* = ref object of PObject ## Selector interface. fds*: TTable[cint, TSelectorKey] registerImpl*: proc (s: PSelector, fd: cint, events: set[TEvent], - data: var PObject): TSelectorKey {.nimcall, tags: [FWriteIO].} + data: PObject): TSelectorKey {.nimcall, tags: [FWriteIO].} unregisterImpl*: proc (s: PSelector, fd: cint): TSelectorKey {.nimcall, tags: [FWriteIO].} selectImpl*: proc (s: PSelector, timeout: int): seq[TReadyInfo] {.nimcall, tags: [FReadIO].} closeImpl*: proc (s: PSelector) {.nimcall.} @@ -38,7 +38,7 @@ template initSelector(r: expr) = new r r.fds = initTable[cint, TSelectorKey]() -proc register*(s: PSelector, fd: cint, events: set[TEvent], data: var PObject): +proc register*(s: PSelector, fd: cint, events: set[TEvent], data: PObject): TSelectorKey = if not s.registerImpl.isNil: result = s.registerImpl(s, fd, events, data) @@ -51,10 +51,10 @@ proc unregister*(s: PSelector, fd: cint): TSelectorKey = proc select*(s: PSelector, timeout = 500): seq[TReadyInfo] = ## - ## **Note:** For the ``epoll`` implementation the resulting - ## ``TSelectorKey.events`` will not contain the original events. - ## TODO: This breaks what TSelectorKey means... it's not a key anymore. - ## Rename to TSelectorInfo? + ## 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``. if not s.selectImpl.isNil: result = s.selectImpl(s, timeout) @@ -67,7 +67,7 @@ type PSelectSelector* = ref object of PSelector ## Implementation of select() proc ssRegister(s: PSelector, fd: cint, events: set[TEvent], - data: var PObject): TSelectorKey = + data: PObject): TSelectorKey = if s.fds.hasKey(fd): raise newException(EInvalidValue, "FD already exists in selector.") var sk = TSelectorKey(fd: fd, events: events, data: data) @@ -144,19 +144,29 @@ proc newSelectSelector*(): PSelectSelector = when defined(linux): import epoll type - PEpollSelector = ref object of PSelector + PEpollSelector* = ref object of PSelector epollFD: cint + events: array[64, ptr epoll_event] + + TDataWrapper = object + fd: cint + boundEvents: set[TEvent] ## The events which ``fd`` listens for. + data: PObject ## User object. proc esRegister(s: PSelector, fd: cint, events: set[TEvent], - data: var PObject): TSelectorKey = + data: PObject): TSelectorKey = var es = PEpollSelector(s) var event: epoll_event if EvRead in events: event.events = EPOLLIN if EvWrite in events: event.events = event.events or EPOLLOUT - event.data.fd = fd - event.data.thePtr = addr(data) + + var dw = cast[ptr TDataWrapper](alloc0(sizeof(TDataWrapper))) # TODO: This needs to be dealloc'd + dw.fd = fd + dw.boundEvents = events + dw.data = data + event.data.thePtr = dw if epoll_ctl(es.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0: OSError(OSLastError()) @@ -176,47 +186,58 @@ when defined(linux): proc esClose(s: PSelector) = var es = PEpollSelector(s) if es.epollFD.close() != 0: OSError(OSLastError()) + dealloc(addr es.events) # TODO: Test this proc esSelect(s: PSelector, timeout: int): seq[TReadyInfo] = result = @[] var es = PEpollSelector(s) - var events: array[64, epoll_event] - let evNum = epoll_wait(es.epollFD, addr events[0], 64.cint, timeout.cint) + let evNum = epoll_wait(es.epollFD, es.events[0], 64.cint, timeout.cint) if evNum < 0: OSError(OSLastError()) - for i in 0 .. 63: + if evNum == 0: return @[] + for i in 0 .. 0: echo ready[0].repr - + if ready.len > 0: echo ready[0].events + i.inc + if i == 6: + selector.close() + break