First attempt, but I haven't yet run it through any sanitizers:
    
    
    import std / [os, locks, atomics]
    
    type
      MyList {.acyclic.} = ref object
        data: string
        next: MyList
    
    template withMyLock*(a: Lock, body: untyped) =
      acquire(a)
      {.gcsafe.}:
        try:
          body
        finally:
          release(a)
    
    var head: MyList
    var headL: Lock
    
    var shouldStop: Atomic[bool]
    
    initLock headL
    
    proc send(x: sink string) =
      withMyLock headL:
        head = MyList(data: x, next: head)
    
    proc worker() {.thread.} =
      var workItem = MyList(nil)
      var echoed = 0
      while true:
        withMyLock headL:
          var h = head
          if h != nil:
            workItem = h
            # workitem is now isolated:
            head = h.next
          else:
            workItem = nil
        # workItem is isolated, so we can access it outside
        # the lock:
        if workItem.isNil:
          if shouldStop.load:
            break
          else:
            # give producer time to breath:
            os.sleep 30
        else:
          if echoed < 100:
            echo workItem.data
          inc echoed
    
    var thr: Thread[void]
    createThread(thr, worker)
    
    send "abc"
    send "def"
    for i in 0 ..< 10_000:
      send "xzy"
      send "zzz"
    shouldStop.store true
    
    joinThread(thr)
    
    
    Run

Reply via email to