diff --git a/chronos/asyncfutures2.nim b/chronos/asyncfutures2.nim index 614be3d..bbecdfa 100644 --- a/chronos/asyncfutures2.nim +++ b/chronos/asyncfutures2.nim @@ -64,8 +64,6 @@ type ## Future to hold GC seqs gcholder*: seq[B] - FutureVar*[T] = distinct Future[T] - FutureDefect* = object of Defect cause*: FutureBase @@ -113,9 +111,6 @@ proc newFutureSeqImpl[A, B](loc: ptr SrcLoc): FutureSeq[A, B] = proc newFutureStrImpl[T](loc: ptr SrcLoc): FutureStr[T] = setupFutureBase(loc) -proc newFutureVarImpl[T](loc: ptr SrcLoc): FutureVar[T] = - FutureVar[T](newFutureImpl[T](loc)) - template newFuture*[T](fromProc: static[string] = ""): Future[T] = ## Creates a new future. ## @@ -139,28 +134,11 @@ template newFutureStr*[T](fromProc: static[string] = ""): FutureStr[T] = ## that this future belongs to, is a good habit as it helps with debugging. newFutureStrImpl[T](getSrcLocation(fromProc)) -template newFutureVar*[T](fromProc: static[string] = ""): FutureVar[T] = - ## Create a new ``FutureVar``. This Future type is ideally suited for - ## situations where you want to avoid unnecessary allocations of Futures. - ## - ## Specifying ``fromProc``, which is a string specifying the name of the proc - ## that this future belongs to, is a good habit as it helps with debugging. - newFutureVarImpl[T](getSrcLocation(fromProc)) - -proc clean*[T](future: FutureVar[T]) = - ## Resets the ``finished`` status of ``future``. - Future[T](future).state = FutureState.Pending - Future[T](future).value = default(T) - Future[T](future).error = nil - -proc finished*(future: FutureBase | FutureVar): bool {.inline.} = +proc finished*(future: FutureBase): bool {.inline.} = ## Determines whether ``future`` has completed, i.e. ``future`` state changed ## from state ``Pending`` to one of the states (``Finished``, ``Cancelled``, ## ``Failed``). - when future is FutureVar: - result = (FutureBase(future).state != FutureState.Pending) - else: - result = (future.state != FutureState.Pending) + result = (future.state != FutureState.Pending) proc cancelled*(future: FutureBase): bool {.inline.} = ## Determines whether ``future`` has cancelled. @@ -254,31 +232,6 @@ template complete*(future: Future[void]) = ## Completes a void ``future``. complete(future, getSrcLocation()) -proc complete[T](future: FutureVar[T], loc: ptr SrcLoc) = - if not(future.cancelled()): - template fut: untyped = Future[T](future) - checkFinished(FutureBase(fut), loc) - doAssert(isNil(fut.error)) - fut.finish(FutureState.Finished) - -template complete*[T](futvar: FutureVar[T]) = - ## Completes a ``FutureVar``. - complete(futvar, getSrcLocation()) - -proc complete[T](futvar: FutureVar[T], val: T, loc: ptr SrcLoc) = - if not(futvar.cancelled()): - template fut: untyped = Future[T](futvar) - checkFinished(FutureBase(fut), loc) - doAssert(isNil(fut.error)) - fut.value = val - fut.finish(FutureState.Finished) - -template complete*[T](futvar: FutureVar[T], val: T) = - ## Completes a ``FutureVar`` with value ``val``. - ## - ## Any previously stored value will be overwritten. - complete(futvar, val, getSrcLocation()) - proc fail[T](future: Future[T], error: ref CatchableError, loc: ptr SrcLoc) = if not(future.cancelled()): checkFinished(FutureBase(future), loc) @@ -503,12 +456,12 @@ proc internalCheckComplete*(fut: FutureBase) {. injectStacktrace(fut) raise fut.error -proc internalRead*[T](fut: Future[T] | FutureVar[T]): T {.inline.} = +proc internalRead*[T](fut: Future[T]): T {.inline.} = # For internal use only. Used in asyncmacro when T isnot void: return fut.value -proc read*[T](future: Future[T] | FutureVar[T]): T {. +proc read*[T](future: Future[T] ): T {. raises: [Defect, CatchableError].} = ## Retrieves the value of ``future``. Future must be finished otherwise ## this function will fail with a ``ValueError`` exception. @@ -533,13 +486,6 @@ proc readError*[T](future: Future[T]): ref CatchableError {. # TODO: Make a custom exception type for this? raise newException(ValueError, "No error in future.") -proc mget*[T](future: FutureVar[T]): var T = - ## Returns a mutable value stored in ``future``. - ## - ## Unlike ``read``, this function will not raise an exception if the - ## Future has not been finished. - result = Future[T](future).value - template taskFutureLocation(future: FutureBase): string = let loc = future.location[0] "[" & ( diff --git a/chronos/asyncmacro2.nim b/chronos/asyncmacro2.nim index a0f9fc0..c30b978 100644 --- a/chronos/asyncmacro2.nim +++ b/chronos/asyncmacro2.nim @@ -21,7 +21,7 @@ proc skipUntilStmtList(node: NimNode): NimNode {.compileTime.} = # result = node[0] when defined(chronosStrictException): template createCb(retFutureSym, iteratorNameSym, - strName, identName, futureVarCompletions: untyped) = + strName, identName: untyped) = bind finished var nameIterVar = iteratorNameSym @@ -51,14 +51,13 @@ when defined(chronosStrictException): except CancelledError: retFutureSym.cancelAndSchedule() except CatchableError as exc: - futureVarCompletions retFutureSym.fail(exc) identName(nil) {.pop.} else: template createCb(retFutureSym, iteratorNameSym, - strName, identName, futureVarCompletions: untyped) = + strName, identName: untyped) = bind finished var nameIterVar = iteratorNameSym @@ -88,40 +87,19 @@ else: except CancelledError: retFutureSym.cancelAndSchedule() except CatchableError as exc: - futureVarCompletions retFutureSym.fail(exc) except Exception as exc: # TODO remove Exception handler to turn on strict mode if exc of Defect: raise (ref Defect)(exc) - futureVarCompletions retFutureSym.fail((ref ValueError)(msg: exc.msg, parent: exc)) identName(nil) {.pop.} -proc createFutureVarCompletions(futureVarIdents: seq[NimNode], - fromNode: NimNode): NimNode {.compileTime.} = - result = newNimNode(nnkStmtList, fromNode) - # Add calls to complete each FutureVar parameter. - for ident in futureVarIdents: - # Only complete them if they have not been completed already by the user. - # TODO: Once https://github.com/nim-lang/Nim/issues/5617 is fixed. - # TODO: Add line info to the complete() call! - # In the meantime, this was really useful for debugging :) - #result.add(newCall(newIdentNode("echo"), newStrLitNode(fromNode.lineinfo))) - result.add newIfStmt( - ( - newCall(newIdentNode("not"), - newDotExpr(ident, newIdentNode("finished"))), - newCall(newIdentNode("complete"), ident) - ) - ) - proc processBody(node, retFutureSym: NimNode, - subTypeIsVoid: bool, - futureVarIdents: seq[NimNode]): NimNode {.compileTime.} = + subTypeIsVoid: bool): NimNode {.compileTime.} = #echo(node.treeRepr) result = node case node.kind @@ -129,8 +107,6 @@ proc processBody(node, retFutureSym: NimNode, result = newNimNode(nnkStmtList, node) # As I've painfully found out, the order here really DOES matter. - result.add createFutureVarCompletions(futureVarIdents, node) - if node[0].kind == nnkEmpty: if not subTypeIsVoid: result.add newCall(newIdentNode("complete"), retFutureSym, @@ -138,8 +114,7 @@ proc processBody(node, retFutureSym: NimNode, else: result.add newCall(newIdentNode("complete"), retFutureSym) else: - let x = node[0].processBody(retFutureSym, subTypeIsVoid, - futureVarIdents) + let x = node[0].processBody(retFutureSym, subTypeIsVoid) if x.kind == nnkYieldStmt: result.add x else: result.add newCall(newIdentNode("complete"), retFutureSym, x) @@ -155,8 +130,7 @@ proc processBody(node, retFutureSym: NimNode, # We must not transform nested procedures of any form, otherwise # `retFutureSym` will be used for all nested procedures as their own # `retFuture`. - result[i] = processBody(result[i], retFutureSym, subTypeIsVoid, - futureVarIdents) + result[i] = processBody(result[i], retFutureSym, subTypeIsVoid) proc getName(node: NimNode): string {.compileTime.} = case node.kind @@ -171,14 +145,6 @@ proc getName(node: NimNode): string {.compileTime.} = else: error("Unknown name.") -proc getFutureVarIdents(params: NimNode): seq[NimNode] {.compileTime.} = - result = @[] - for i in 1 ..< len(params): - expectKind(params[i], nnkIdentDefs) - if params[i][1].kind == nnkBracketExpr and - params[i][1][0].eqIdent("futurevar"): - result.add(params[i][0]) - proc isInvalidReturnType(typeName: string): bool = return typeName notin ["Future"] #, "FutureStream"] @@ -217,8 +183,6 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = let subtypeIsVoid = returnType.kind == nnkEmpty or (baseType.kind == nnkIdent and returnType[1].eqIdent("void")) - let futureVarIdents = getFutureVarIdents(prc.params) - var outerProcBody = newNimNode(nnkStmtList, prc.body) # -> var retFuture = newFuture[T]() @@ -245,8 +209,7 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = # -> # -> complete(retFuture, result) var iteratorNameSym = genSym(nskIterator, $prcName) - var procBody = prc.body.processBody(retFutureSym, subtypeIsVoid, - futureVarIdents) + var procBody = prc.body.processBody(retFutureSym, subtypeIsVoid) # don't do anything with forward bodies (empty) if procBody.kind != nnkEmpty: if subtypeIsVoid: @@ -259,8 +222,6 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = # fix #13899, `defer` should not escape its original scope procBody = newStmtList(newTree(nnkBlockStmt, newEmptyNode(), procBody)) - procBody.add(createFutureVarCompletions(futureVarIdents, nil)) - if not subtypeIsVoid: procBody.insert(0, newNimNode(nnkPragma).add(newIdentNode("push"), newNimNode(nnkExprColonExpr).add(newNimNode(nnkBracketExpr).add( @@ -329,8 +290,7 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = var cbName = genSym(nskVar, prcName & "_continue") var procCb = getAst createCb(retFutureSym, iteratorNameSym, newStrLitNode(prcName), - cbName, - createFutureVarCompletions(futureVarIdents, nil)) + cbName) outerProcBody.add procCb # -> return retFuture