This commit is contained in:
Yuriy Glukhov
2017-07-15 09:50:41 +03:00
committed by Andreas Rumpf
parent 8b107972c5
commit bdf6f59c6d
3 changed files with 73 additions and 3 deletions

View File

@@ -28,7 +28,7 @@ template createCb(retFutureSym, iteratorNameSym,
name, futureVarCompletions: untyped) =
var nameIterVar = iteratorNameSym
#{.push stackTrace: off.}
proc cb {.closure,gcsafe.} =
proc cb {.closure.} =
try:
if not nameIterVar.finished:
var next = nameIterVar()
@@ -38,7 +38,8 @@ template createCb(retFutureSym, iteratorNameSym,
"`nil` Future?"
raise newException(AssertionError, msg % name)
else:
next.callback = cb
{.gcsafe.}:
next.callback = (proc() {.closure, gcsafe.})(cb)
except:
futureVarCompletions
@@ -379,7 +380,10 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
procBody, nnkIteratorDef)
closureIterator.pragma = newNimNode(nnkPragma, lineInfoFrom=prc.body)
closureIterator.addPragma(newIdentNode("closure"))
closureIterator.addPragma(newIdentNode("gcsafe"))
# If proc has an explicit gcsafe pragma, we add it to iterator as well.
if prc.pragma.findChild(it.kind in {nnkSym, nnkIdent} and $it == "gcsafe") != nil:
closureIterator.addPragma(newIdentNode("gcsafe"))
outerProcBody.add(closureIterator)
# -> createCb(retFuture)

View File

@@ -0,0 +1,36 @@
discard """
cmd: "nim c --threads:on $file"
output: '''
1
2
3
'''
"""
assert compileOption("threads"), "this test will not do anything useful without --threads:on"
import asyncdispatch
var globalDummy: ref int
proc gcUnsafeProc() =
if not globalDummy.isNil:
echo globalDummy[]
echo "1"
proc gcSafeAsyncProcWithNoAnnotation() {.async.} =
echo "2"
proc gcSafeAsyncProcWithAnnotation() {.gcsafe, async.} =
echo "3"
proc gcUnsafeAsyncProc() {.async.} =
# We should be able to call gcUnsafe
gcUnsafeProc()
# We should be able to call async implicitly gcsafe
await gcSafeAsyncProcWithNoAnnotation()
# We should be able to call async explicitly gcsafe
await gcSafeAsyncProcWithAnnotation()
waitFor gcUnsafeAsyncProc()

View File

@@ -0,0 +1,30 @@
discard """
cmd: "nim c --threads:on $file"
file: "asyncmacro.nim"
errormsg: "'anotherGCSafeAsyncProcIter' is not GC-safe as it calls 'asyncGCUnsafeProc'"
"""
assert compileOption("threads"), "this test will not do anything useful without --threads:on"
import asyncdispatch
var globalDummy: ref int
proc gcUnsafeProc() =
if not globalDummy.isNil:
echo globalDummy[]
proc asyncExplicitlyGCSafeProc() {.gcsafe, async.} =
echo "hi"
proc asyncImplicitlyGCSafeProc() {.async.} =
echo "hi"
proc asyncGCUnsafeProc() {.async.} =
gcUnsafeProc()
proc anotherGCSafeAsyncProc() {.async, gcsafe.} =
# We should be able to call other gcsafe procs
await asyncExplicitlyGCSafeProc()
await asyncImplicitlyGCSafeProc()
# But we can't call gcunsafe procs
await asyncGCUnsafeProc()