Merge branch 'devel' into sighashes
This commit is contained in:
commit
24239c2361
14 changed files with 341 additions and 216 deletions
|
|
@ -973,7 +973,11 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
|
||||||
r = mangleName(p.module, sym)
|
r = mangleName(p.module, sym)
|
||||||
sym.loc.r = r # but be consequent!
|
sym.loc.r = r # but be consequent!
|
||||||
res.add($r)
|
res.add($r)
|
||||||
else: internalError(t.sons[i].info, "genAsmOrEmitStmt()")
|
else:
|
||||||
|
var a: TLoc
|
||||||
|
initLocExpr(p, t.sons[i], a)
|
||||||
|
res.add($a.rdLoc)
|
||||||
|
#internalError(t.sons[i].info, "genAsmOrEmitStmt()")
|
||||||
|
|
||||||
if isAsmStmt and hasGnuAsm in CC[cCompiler].props:
|
if isAsmStmt and hasGnuAsm in CC[cCompiler].props:
|
||||||
for x in splitLines(res):
|
for x in splitLines(res):
|
||||||
|
|
|
||||||
|
|
@ -659,8 +659,14 @@ proc compileCFile(list: TLinkedList, script: var Rope, cmds: var TStringSeq,
|
||||||
|
|
||||||
proc getLinkCmd(projectfile, objfiles: string): string =
|
proc getLinkCmd(projectfile, objfiles: string): string =
|
||||||
if optGenStaticLib in gGlobalOptions:
|
if optGenStaticLib in gGlobalOptions:
|
||||||
let name = splitFile(gProjectName).name
|
var libname: string
|
||||||
result = CC[cCompiler].buildLib % ["libfile", (libNameTmpl() % name),
|
if options.outFile.len > 0:
|
||||||
|
libname = options.outFile.expandTilde
|
||||||
|
if not libname.isAbsolute():
|
||||||
|
libname = getCurrentDir() / libname
|
||||||
|
else:
|
||||||
|
libname = (libNameTmpl() % splitFile(gProjectName).name)
|
||||||
|
result = CC[cCompiler].buildLib % ["libfile", libname,
|
||||||
"objfiles", objfiles]
|
"objfiles", objfiles]
|
||||||
else:
|
else:
|
||||||
var linkerExe = getConfigVar(cCompiler, ".linkerexe")
|
var linkerExe = getConfigVar(cCompiler, ".linkerexe")
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ type
|
||||||
errIndexOutOfBounds, errIndexTypesDoNotMatch, errBracketsInvalidForType,
|
errIndexOutOfBounds, errIndexTypesDoNotMatch, errBracketsInvalidForType,
|
||||||
errValueOutOfSetBounds, errFieldInitTwice, errFieldNotInit,
|
errValueOutOfSetBounds, errFieldInitTwice, errFieldNotInit,
|
||||||
errExprXCannotBeCalled, errExprHasNoType, errExprXHasNoType,
|
errExprXCannotBeCalled, errExprHasNoType, errExprXHasNoType,
|
||||||
errCastNotInSafeMode, errExprCannotBeCastedToX, errCommaOrParRiExpected,
|
errCastNotInSafeMode, errExprCannotBeCastToX, errCommaOrParRiExpected,
|
||||||
errCurlyLeOrParLeExpected, errSectionExpected, errRangeExpected,
|
errCurlyLeOrParLeExpected, errSectionExpected, errRangeExpected,
|
||||||
errMagicOnlyInSystem, errPowerOfTwoExpected,
|
errMagicOnlyInSystem, errPowerOfTwoExpected,
|
||||||
errStringMayNotBeEmpty, errCallConvExpected, errProcOnlyOneCallConv,
|
errStringMayNotBeEmpty, errCallConvExpected, errProcOnlyOneCallConv,
|
||||||
|
|
@ -229,7 +229,7 @@ const
|
||||||
errExprHasNoType: "expression has no type",
|
errExprHasNoType: "expression has no type",
|
||||||
errExprXHasNoType: "expression \'$1\' has no type (or is ambiguous)",
|
errExprXHasNoType: "expression \'$1\' has no type (or is ambiguous)",
|
||||||
errCastNotInSafeMode: "\'cast\' not allowed in safe mode",
|
errCastNotInSafeMode: "\'cast\' not allowed in safe mode",
|
||||||
errExprCannotBeCastedToX: "expression cannot be casted to $1",
|
errExprCannotBeCastToX: "expression cannot be cast to $1",
|
||||||
errCommaOrParRiExpected: "',' or ')' expected",
|
errCommaOrParRiExpected: "',' or ')' expected",
|
||||||
errCurlyLeOrParLeExpected: "\'{\' or \'(\' expected",
|
errCurlyLeOrParLeExpected: "\'{\' or \'(\' expected",
|
||||||
errSectionExpected: "section (\'type\', \'proc\', etc.) expected",
|
errSectionExpected: "section (\'type\', \'proc\', etc.) expected",
|
||||||
|
|
|
||||||
|
|
@ -460,8 +460,22 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
|
||||||
result = newNode(nkAsmStmt, n.info)
|
result = newNode(nkAsmStmt, n.info)
|
||||||
|
|
||||||
proc pragmaEmit(c: PContext, n: PNode) =
|
proc pragmaEmit(c: PContext, n: PNode) =
|
||||||
discard getStrLitNode(c, n)
|
if n.kind != nkExprColonExpr:
|
||||||
|
localError(n.info, errStringLiteralExpected)
|
||||||
|
else:
|
||||||
|
let n1 = n[1]
|
||||||
|
if n1.kind == nkBracket:
|
||||||
|
var b = newNodeI(nkBracket, n1.info, n1.len)
|
||||||
|
for i in 0..<n1.len:
|
||||||
|
b.sons[i] = c.semExpr(c, n1[i])
|
||||||
|
n.sons[1] = b
|
||||||
|
else:
|
||||||
|
n.sons[1] = c.semConstExpr(c, n1)
|
||||||
|
case n.sons[1].kind
|
||||||
|
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||||
n.sons[1] = semAsmOrEmit(c, n, '`')
|
n.sons[1] = semAsmOrEmit(c, n, '`')
|
||||||
|
else:
|
||||||
|
localError(n.info, errStringLiteralExpected)
|
||||||
|
|
||||||
proc noVal(n: PNode) =
|
proc noVal(n: PNode) =
|
||||||
if n.kind == nkExprColonExpr: invalidPragma(n)
|
if n.kind == nkExprColonExpr: invalidPragma(n)
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ proc checkConvertible(c: PContext, castDest, src: PType): TConvStatus =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc isCastable(dst, src: PType): bool =
|
proc isCastable(dst, src: PType): bool =
|
||||||
## Checks whether the source type can be casted to the destination type.
|
## Checks whether the source type can be cast to the destination type.
|
||||||
## Casting is very unrestrictive; casts are allowed as long as
|
## Casting is very unrestrictive; casts are allowed as long as
|
||||||
## castDest.size >= src.size, and typeAllowed(dst, skParam)
|
## castDest.size >= src.size, and typeAllowed(dst, skParam)
|
||||||
#const
|
#const
|
||||||
|
|
@ -223,7 +223,7 @@ proc semCast(c: PContext, n: PNode): PNode =
|
||||||
addSon(result, copyTree(n.sons[0]))
|
addSon(result, copyTree(n.sons[0]))
|
||||||
addSon(result, semExprWithType(c, n.sons[1]))
|
addSon(result, semExprWithType(c, n.sons[1]))
|
||||||
if not isCastable(result.typ, result.sons[1].typ):
|
if not isCastable(result.typ, result.sons[1].typ):
|
||||||
localError(result.info, errExprCannotBeCastedToX,
|
localError(result.info, errExprCannotBeCastToX,
|
||||||
typeToString(result.typ))
|
typeToString(result.typ))
|
||||||
|
|
||||||
proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
|
|
|
||||||
|
|
@ -760,8 +760,10 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||||
internalAssert st.kind in {tyPtr, tyRef}
|
internalAssert st.kind in {tyPtr, tyRef}
|
||||||
internalAssert st.lastSon.sym == nil
|
internalAssert st.lastSon.sym == nil
|
||||||
incl st.flags, tfRefsAnonObj
|
incl st.flags, tfRefsAnonObj
|
||||||
st.lastSon.sym = newSym(skType, getIdent(s.name.s & ":ObjectType"),
|
let obj = newSym(skType, getIdent(s.name.s & ":ObjectType"),
|
||||||
getCurrOwner(), s.info)
|
getCurrOwner(), s.info)
|
||||||
|
obj.typ = st.lastSon
|
||||||
|
st.lastSon.sym = obj
|
||||||
|
|
||||||
|
|
||||||
proc checkForMetaFields(n: PNode) =
|
proc checkForMetaFields(n: PNode) =
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,6 @@ It can also be used as a statement, in that case it takes a list of *renamings*.
|
||||||
Stream = ref object
|
Stream = ref object
|
||||||
{.deprecated: [TFile: File, PStream: Stream].}
|
{.deprecated: [TFile: File, PStream: Stream].}
|
||||||
|
|
||||||
The ``nimfix`` tool can be used to, without effort, automatically update your
|
|
||||||
code and refactor it by performing these renamings.
|
|
||||||
|
|
||||||
|
|
||||||
noSideEffect pragma
|
noSideEffect pragma
|
||||||
-------------------
|
-------------------
|
||||||
|
|
@ -678,14 +675,15 @@ Example:
|
||||||
{.push stackTrace:off.}
|
{.push stackTrace:off.}
|
||||||
proc embedsC() =
|
proc embedsC() =
|
||||||
var nimVar = 89
|
var nimVar = 89
|
||||||
# use backticks to access Nim symbols within an emit section:
|
# access Nim symbols within an emit section outside of string literals:
|
||||||
{.emit: """fprintf(stdout, "%d\n", cvariable + (int)`nimVar`);""".}
|
{.emit: ["""fprintf(stdout, "%d\n", cvariable + (int)""", nimVar, ");"].}
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
embedsC()
|
embedsC()
|
||||||
|
|
||||||
As can be seen from the example, to Nim symbols can be referred via backticks.
|
For backwards compatibility, if the argument to the ``emit`` statement
|
||||||
Use two backticks to produce a single verbatim backtick.
|
is a single string literal, Nim symbols can be referred to via backticks.
|
||||||
|
This usage is however deprecated.
|
||||||
|
|
||||||
For a toplevel emit statement the section where in the generated C/C++ file
|
For a toplevel emit statement the section where in the generated C/C++ file
|
||||||
the code should be emitted can be influenced via the
|
the code should be emitted can be influenced via the
|
||||||
|
|
|
||||||
|
|
@ -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)
|
(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:
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import posix, times
|
||||||
# Maximum number of events that can be returned
|
# Maximum number of events that can be returned
|
||||||
const MAX_EPOLL_RESULT_EVENTS = 64
|
const MAX_EPOLL_RESULT_EVENTS = 64
|
||||||
|
|
||||||
|
when not defined(android):
|
||||||
type
|
type
|
||||||
SignalFdInfo* {.importc: "struct signalfd_siginfo",
|
SignalFdInfo* {.importc: "struct signalfd_siginfo",
|
||||||
header: "<sys/signalfd.h>", pure, final.} = object
|
header: "<sys/signalfd.h>", pure, final.} = object
|
||||||
|
|
@ -35,6 +36,7 @@ type
|
||||||
ssi_addr*: uint64
|
ssi_addr*: uint64
|
||||||
pad* {.importc: "__pad".}: array[0..47, uint8]
|
pad* {.importc: "__pad".}: array[0..47, uint8]
|
||||||
|
|
||||||
|
type
|
||||||
eventFdData {.importc: "eventfd_t",
|
eventFdData {.importc: "eventfd_t",
|
||||||
header: "<sys/eventfd.h>", pure, final.} = uint64
|
header: "<sys/eventfd.h>", pure, final.} = uint64
|
||||||
epoll_data {.importc: "union epoll_data", header: "<sys/epoll.h>",
|
epoll_data {.importc: "union epoll_data", header: "<sys/epoll.h>",
|
||||||
|
|
@ -68,12 +70,22 @@ proc timerfd_create(clock_id: ClockId, flags: cint): cint
|
||||||
proc timerfd_settime(ufd: cint, flags: cint,
|
proc timerfd_settime(ufd: cint, flags: cint,
|
||||||
utmr: var Itimerspec, otmr: var Itimerspec): cint
|
utmr: var Itimerspec, otmr: var Itimerspec): cint
|
||||||
{.cdecl, importc: "timerfd_settime", header: "<sys/timerfd.h>".}
|
{.cdecl, importc: "timerfd_settime", header: "<sys/timerfd.h>".}
|
||||||
proc signalfd(fd: cint, mask: var Sigset, flags: cint): cint
|
|
||||||
{.cdecl, importc: "signalfd", header: "<sys/signalfd.h>".}
|
|
||||||
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>".}
|
||||||
proc ulimit(cmd: cint): clong
|
|
||||||
{.importc: "ulimit", header: "<ulimit.h>", varargs.}
|
when not defined(android):
|
||||||
|
proc signalfd(fd: cint, mask: var Sigset, flags: cint): cint
|
||||||
|
{.cdecl, importc: "signalfd", header: "<sys/signalfd.h>".}
|
||||||
|
|
||||||
|
var RLIMIT_NOFILE {.importc: "RLIMIT_NOFILE",
|
||||||
|
header: "<sys/resource.h>".}: cint
|
||||||
|
type
|
||||||
|
rlimit {.importc: "struct rlimit",
|
||||||
|
header: "<sys/resource.h>", pure, final.} = object
|
||||||
|
rlim_cur: int
|
||||||
|
rlim_max: int
|
||||||
|
proc getrlimit(resource: cint, rlp: var rlimit): cint
|
||||||
|
{.importc: "getrlimit",header: "<sys/resource.h>".}
|
||||||
|
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
type
|
type
|
||||||
|
|
@ -97,7 +109,10 @@ type
|
||||||
SelectEvent* = ptr SelectEventImpl
|
SelectEvent* = ptr SelectEventImpl
|
||||||
|
|
||||||
proc newSelector*[T](): Selector[T] =
|
proc newSelector*[T](): Selector[T] =
|
||||||
var maxFD = int(ulimit(4, 0))
|
var a = rlimit()
|
||||||
|
if getrlimit(RLIMIT_NOFILE, a) != 0:
|
||||||
|
raiseOsError(osLastError())
|
||||||
|
var maxFD = int(a.rlim_max)
|
||||||
doAssert(maxFD > 0)
|
doAssert(maxFD > 0)
|
||||||
|
|
||||||
var epollFD = epoll_create(MAX_EPOLL_RESULT_EVENTS)
|
var epollFD = epoll_create(MAX_EPOLL_RESULT_EVENTS)
|
||||||
|
|
@ -194,6 +209,7 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
|
||||||
doAssert(pkey.ident != 0)
|
doAssert(pkey.ident != 0)
|
||||||
|
|
||||||
if pkey.events != {}:
|
if pkey.events != {}:
|
||||||
|
when not defined(android):
|
||||||
if pkey.events * {Event.Read, Event.Write} != {}:
|
if pkey.events * {Event.Read, Event.Write} != {}:
|
||||||
var epv = epoll_event()
|
var epv = epoll_event()
|
||||||
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
||||||
|
|
@ -227,6 +243,19 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
|
||||||
unblockSignals(nmask, omask)
|
unblockSignals(nmask, omask)
|
||||||
discard posix.close(fdi.cint)
|
discard posix.close(fdi.cint)
|
||||||
dec(s.count)
|
dec(s.count)
|
||||||
|
else:
|
||||||
|
if pkey.events * {Event.Read, Event.Write} != {}:
|
||||||
|
var epv = epoll_event()
|
||||||
|
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
dec(s.count)
|
||||||
|
elif Event.Timer in pkey.events:
|
||||||
|
var epv = epoll_event()
|
||||||
|
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
discard posix.close(fdi.cint)
|
||||||
|
dec(s.count)
|
||||||
|
|
||||||
pkey.ident = 0
|
pkey.ident = 0
|
||||||
pkey.events = {}
|
pkey.events = {}
|
||||||
|
|
||||||
|
|
@ -280,6 +309,7 @@ proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool,
|
||||||
inc(s.count)
|
inc(s.count)
|
||||||
result = fdi
|
result = fdi
|
||||||
|
|
||||||
|
when not defined(android):
|
||||||
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
|
||||||
|
|
@ -382,6 +412,7 @@ proc selectInto*[T](s: Selector[T], timeout: int,
|
||||||
events.incl(Event.Error)
|
events.incl(Event.Error)
|
||||||
if (pevents and EPOLLOUT) != 0:
|
if (pevents and EPOLLOUT) != 0:
|
||||||
events.incl(Event.Write)
|
events.incl(Event.Write)
|
||||||
|
when not defined(android):
|
||||||
if (pevents and EPOLLIN) != 0:
|
if (pevents and EPOLLIN) != 0:
|
||||||
if Event.Read in skey.events:
|
if Event.Read in skey.events:
|
||||||
events.incl(Event.Read)
|
events.incl(Event.Read)
|
||||||
|
|
@ -416,6 +447,25 @@ proc selectInto*[T](s: Selector[T], timeout: int,
|
||||||
else:
|
else:
|
||||||
raiseOSError(err)
|
raiseOSError(err)
|
||||||
events = {Event.User}
|
events = {Event.User}
|
||||||
|
else:
|
||||||
|
if (pevents and EPOLLIN) != 0:
|
||||||
|
if Event.Read in skey.events:
|
||||||
|
events.incl(Event.Read)
|
||||||
|
elif Event.Timer in skey.events:
|
||||||
|
var data: uint64 = 0
|
||||||
|
if posix.read(fdi.cint, addr data, sizeof(uint64)) != sizeof(uint64):
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
events = {Event.Timer}
|
||||||
|
elif Event.User in skey.events:
|
||||||
|
var data: uint64 = 0
|
||||||
|
if posix.read(fdi.cint, addr data, sizeof(uint64)) != sizeof(uint64):
|
||||||
|
let err = osLastError()
|
||||||
|
if err == OSErrorCode(EAGAIN):
|
||||||
|
inc(i)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raiseOSError(err)
|
||||||
|
events = {Event.User}
|
||||||
|
|
||||||
skey.key.events = events
|
skey.key.events = events
|
||||||
results[k] = skey.key
|
results[k] = skey.key
|
||||||
|
|
|
||||||
|
|
@ -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,6 +26,20 @@ when defined(upcoming):
|
||||||
addEvent(ev, cb)
|
addEvent(ev, cb)
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
|
proc eventTest() =
|
||||||
|
var event = newAsyncEvent()
|
||||||
|
var fut = waitEvent(event)
|
||||||
|
asyncCheck(delayedSet(event, 500))
|
||||||
|
waitFor(fut or sleepAsync(1000))
|
||||||
|
if fut.finished:
|
||||||
|
echo "OK"
|
||||||
|
else:
|
||||||
|
echo "eventTest: Timeout expired before event received!"
|
||||||
|
|
||||||
|
when ioselSupportedPlatform or defined(windows):
|
||||||
|
|
||||||
|
import osproc
|
||||||
|
|
||||||
proc waitTimer(timeout: int): Future[void] =
|
proc waitTimer(timeout: int): Future[void] =
|
||||||
var retFuture = newFuture[void]("waitTimer")
|
var retFuture = newFuture[void]("waitTimer")
|
||||||
proc cb(fd: AsyncFD): bool =
|
proc cb(fd: AsyncFD): bool =
|
||||||
|
|
@ -39,24 +54,10 @@ when defined(upcoming):
|
||||||
addProcess(p.processID(), cb)
|
addProcess(p.processID(), cb)
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc delayedSet(ev: AsyncEvent, timeout: int): Future[void] {.async.} =
|
|
||||||
await waitTimer(timeout)
|
|
||||||
ev.setEvent()
|
|
||||||
|
|
||||||
proc timerTest() =
|
proc timerTest() =
|
||||||
waitFor(waitTimer(200))
|
waitFor(waitTimer(200))
|
||||||
echo "OK"
|
echo "OK"
|
||||||
|
|
||||||
proc eventTest() =
|
|
||||||
var event = newAsyncEvent()
|
|
||||||
var fut = waitEvent(event)
|
|
||||||
asyncCheck(delayedSet(event, 500))
|
|
||||||
waitFor(fut or waitTimer(1000))
|
|
||||||
if fut.finished:
|
|
||||||
echo "OK"
|
|
||||||
else:
|
|
||||||
echo "eventTest: Timeout expired before event received!"
|
|
||||||
|
|
||||||
proc processTest() =
|
proc processTest() =
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
var process = startProcess("ping.exe", "",
|
var process = startProcess("ping.exe", "",
|
||||||
|
|
@ -73,8 +74,7 @@ when defined(upcoming):
|
||||||
else:
|
else:
|
||||||
echo "processTest: Timeout expired before process exited!"
|
echo "processTest: Timeout expired before process exited!"
|
||||||
|
|
||||||
when supportedPlatform:
|
when ioselSupportedPlatform:
|
||||||
import posix
|
|
||||||
|
|
||||||
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()
|
||||||
|
|
|
||||||
22
tests/cpp/temitlist.nim
Normal file
22
tests/cpp/temitlist.nim
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
discard """
|
||||||
|
cmd: "nim cpp $file"
|
||||||
|
output: '''6.0'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
# bug #4730
|
||||||
|
|
||||||
|
type Vector* {.importcpp: "std::vector", header: "<vector>".}[T] = object
|
||||||
|
|
||||||
|
template `[]=`*[T](v: var Vector[T], key: int, val: T) =
|
||||||
|
{.emit: [v, "[", key, "] = ", val, ";"].}
|
||||||
|
|
||||||
|
proc setLen*[T](v: var Vector[T]; size: int) {.importcpp: "resize", nodecl.}
|
||||||
|
proc `[]`*[T](v: var Vector[T], key: int): T {.importcpp: "(#[#])", nodecl.}
|
||||||
|
|
||||||
|
proc main =
|
||||||
|
var v: Vector[float]
|
||||||
|
v.setLen 1
|
||||||
|
v[0] = 6.0
|
||||||
|
echo v[0]
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
@ -55,6 +55,28 @@ Compiler Additions
|
||||||
Language Additions
|
Language Additions
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
- The ``emit`` pragma now takes a list of Nim expressions instead
|
||||||
|
of a single string literal. This list can easily contain non-strings
|
||||||
|
like template parameters. This means ``emit`` works out of the
|
||||||
|
box with templates and no new quoting rules needed to be introduced.
|
||||||
|
The old way with backtick quoting is still supported but will be
|
||||||
|
deprecated.
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
type Vector* {.importcpp: "std::vector", header: "<vector>".}[T] = object
|
||||||
|
|
||||||
|
template `[]=`*[T](v: var Vector[T], key: int, val: T) =
|
||||||
|
{.emit: [v, "[", key, "] = ", val, ";"].}
|
||||||
|
|
||||||
|
proc setLen*[T](v: var Vector[T]; size: int) {.importcpp: "resize", nodecl.}
|
||||||
|
proc `[]`*[T](v: var Vector[T], key: int): T {.importcpp: "(#[#])", nodecl.}
|
||||||
|
|
||||||
|
proc main =
|
||||||
|
var v: Vector[float]
|
||||||
|
v.setLen 1
|
||||||
|
v[0] = 6.0
|
||||||
|
echo v[0]
|
||||||
|
|
||||||
|
|
||||||
Bugfixes
|
Bugfixes
|
||||||
--------
|
--------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue