Just for fun, I went and parallelized creation of each branch of the tree. 
There's a race condition between "preferSpawn" and "spawn" so it occasionally 
locks up, since you can't stop another thread from spawning new workers between 
preferSpawn and spawn. You can't wrap that code in a lock either, since that 
lock has to release after the spawn will not block, but before the recursive 
call tries to acquire it again.

But it's sort of neat. I wanted to use "parallel:" but you can't use spawn 
twice in that, so it can only parallelize loops.
    
    
    import threadpool
    from strutils import repeat
    
    type Tree = ref object
      d: int
      left, right: Tree
    
    proc toString(root: int, o: Tree): string;
    
    proc `$`(o: Tree): string =
      toString(o.d,o)
    
    proc toString(root: int, o: Tree): string =
      if o.isNil:
        return "nil"
      let tab: string = ' '.repeat(2*(root - o.d))
      result = "Tree " & $o.d & "\n"
      result.add(tab & "- left\n")
      result.add(tab & "  ")
      result.add(toString(root,o.left))
      result.add("\n")
      result.add(tab & "- right\n")
      result.add(tab & "  ")
      result.add(toString(root,o.right))
    
    proc tree(depth: int): Tree =
      if depth == 0:
        return Tree(d: 0)
      else:
        result = Tree(d: depth)
        if not preferSpawn():
          result.left = tree(depth-1)
          result.right = tree(depth-1)
        else:
          let left = spawn tree(depth-1)
          let right = spawn tree(depth-1)
          discard awaitAny([left.FlowVarBase,right.FlowVarBase])
          result.left = ^left
          result.right = ^right
    
    proc main() =
      let t = tree(3)
      echo(t)
    
    main()
    

Reply via email to