**@wiffel, @Araq:**

Thanks a lot! I really missed that it's impossible to use spawn with closures. 
:(

So the sample should look like below one. It's much more verbose, but it works 
properly.
    
    
    import unicode, locks, os
    
    proc lenU*(s: string): int =
      result = s.runeLen
    
    proc charAtPosU*(s: string, pos: int): string =
      assert(pos >= 0 and pos < s.runeLen)
      result = s.runeAtPos(pos).toUTF8()
    
    type
      Container = ref ContainerObj
      ContainerObj = object of RootObj
        Flk: Lock
        FnLen: int
        FnCallsTotal: int
        FnCallsCur: int
        FnCallIndex: int
      
      WorkerThread = Thread[tuple[cont: Container, c: string, value: int]]
    
    proc newContainer(nLen, nCount: int): Container =
      result.new()
      result.Flk.initLock()
      result.FnLen = nLen
      result.FnCallsTotal = nLen*nCount
      result.FnCallsCur = 0
      result.FnCallIndex = 0
    
    proc isTimeToFinish(self: Container): bool =
      result = self.FnCallsCur == self.FnCallsTotal
    
    proc isOurCallIndex(self: Container, nCallIndex: int): bool =
      result = self.FnCallIndex == nCallIndex
    
    proc goToNextCallIndex(self: Container) =
      inc self.FnCallIndex
      self.FnCallIndex = self.FnCallIndex mod self.FnLen
      inc self.FnCallsCur
    
    proc destroyContainer(cont: var Container) =
      cont.Flk.deinitLock()
      cont = nil
    
    proc worker(param: tuple[cont: Container, c: string, value: int]) 
{.thread.} =
      while true:
        var bWorkDone = true
        param.cont.Flk.acquire()
        try:
          if param.cont.isTimeToFinish:
            return
          if param.cont.isOurCallIndex(param.value):
            param.cont.goToNextCallIndex()
            stdout.write param.c
          else:
            bWorkDone = false
        finally:
          param.cont.Flk.release()
        if not bWorkDone:
          sleep(1)
    
    proc multithreadedPrint(sMsg: string, nCount: int) =
      var
        cont = newContainer(sMsg.len, nCount)
        threads: seq[WorkerThread] = newSeq[WorkerThread](sMsg.len)
      for i in 0..<sMsg.len:
        threads[i].createThread(worker, (cont, sMsg.charAtPosU(i), i))
      joinThreads(threads)
      destroyContainer(cont)
    
    multithreadedPrint("01234567890123456789", 3)
    echo ""
    

Reply via email to