# # # The Nim Compiler # (c) Copyright 2015 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## This module implements threadpool's ``spawn``. import ast, types, idents, magicsys, msgs, options, modulegraphs, lowerings, liftdestructors, renderer from trees import getMagic, getRoot proc callProc(a: PNode): PNode = result = newNodeI(nkCall, a.info) result.add a result.typ = a.typ[0] # we have 4 cases to consider: # - a void proc --> nothing to do # - a proc returning GC'ed memory --> requires a flowVar # - a proc returning non GC'ed memory --> pass as hidden 'var' parameter # - not in a parallel environment --> requires a flowVar for memory safety type TSpawnResult* = enum srVoid, srFlowVar, srByVar TFlowVarKind = enum fvInvalid # invalid type T for 'FlowVar[T]' fvGC # FlowVar of a GC'ed type fvBlob # FlowVar of a blob type proc spawnResult*(t: PType; inParallel: bool): TSpawnResult = if t.isEmptyType: srVoid elif inParallel and not containsGarbageCollectedRef(t): srByVar else: srFlowVar proc flowVarKind(c: ConfigRef, t: PType): TFlowVarKind = if c.selectedGC in {gcArc, gcOrc}: fvBlob elif t.skipTypes(abstractInst).kind in {tyRef, tyString, tySequence}: fvGC elif containsGarbageCollectedRef(t): fvInvalid else: fvBlob proc typeNeedsNoDeepCopy(t: PType): bool = var t = t.skipTypes(abstractInst) # for the tconvexhull example (and others) we're a bit lax here and pretend # seqs and strings are *by value* only and 'shallow' doesn't exist! if t.kind == tyString: return true # note that seq[T] is fine, but 'var seq[T]' is not, so we need to skip 'var' # for the stricter check and likewise we can skip 'seq' for a less # strict check: if t.kind in {tyVar, tyLent, tySequence}: t = t.lastSon result = not containsGarbageCollectedRef(t) proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; idgen: IdGenerator; owner: PSym; typ: PType; v: PNode; useShallowCopy=false): PSym = result = newSym(skTemp, getIdent(g.cache, genPrefix), nextId idgen, owner, varSection.info, owner.options) result.typ = typ incl(result.flags, sfFromGeneric) var vpart = newNodeI(nkIdentDefs, varSection.info, 3) vpart[0] = newSymNode(result) vpart[1] = newNodeI(nkEmpty, varSection.info) vpart[2] = if varInit.isNil: v else: vpart[1] varSection.add vpart if varInit != nil: if g.config.selectedGC in {gcArc, gcOrc}: # inject destructors pass will do its own analysis varInit.add newFastMoveStmt(g, newSymNode(result), v) else: if useShallowCopy and typeNeedsNoDeepCopy(typ) or optTinyRtti in g.config.globalOptions: varInit.add newFastMoveStmt(g, newSymNode(result), v) else: let deepCopyCall = newNodeI(nkCall, varInit.info, 3) deepCopyCall[0] = newSymNode(getSysMagic(g, varSection.info, "deepCopy", mDeepCopy)) deepCopyCall[1] = newSymNode(result) deepCopyCall[2] = v varInit.add deepCopyCall discard """ We generate roughly this: proc f_wrapper(thread, args) = barrierEnter(args.barrier) # for parallel statement var a = args.a # thread transfer; deepCopy or shallowCopy or no copy # depending on whether we're in a 'parallel' statement var b = args.b var fv = args.fv fv.owner = thread # optional nimArgsPassingDone() # signal parent that the work is done # args.fv.blob = f(a, b, ...) nimFlowVarSignal(args.fv) # - or - f(a, b, ...) barrierLeave(args.barrier) # for parallel statement stmtList: var scratchObj scr
discard """
targets: "cpp"
output: "hello"
cmd: "nim cpp --nilseqs:on --nimblePath:tests/deps $file"
"""
# bug #3299
import jester
import asyncdispatch, asyncnet
# bug #5081
#import nre
echo "hello"