mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-12 22:33:49 +00:00
committed by
Andreas Rumpf
parent
8b107972c5
commit
bdf6f59c6d
@@ -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)
|
||||
|
||||
36
tests/async/tasync_gcsafe.nim
Normal file
36
tests/async/tasync_gcsafe.nim
Normal 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()
|
||||
30
tests/async/tasync_gcunsafe.nim
Normal file
30
tests/async/tasync_gcunsafe.nim
Normal 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()
|
||||
Reference in New Issue
Block a user