These were tested on 1.6.0, unsure if the same will work on later versions.

The global context makes it so the destruction of `myStr` is delayed until 
program exit and `var theStr = ..` makes a copy instead. Wrapping it in a proc 
gives the result you expect.
    
    
    import locks
    type
      MyString = object
        val: string
    
    
    proc `=destroy`(myStr: var MyString) =
      echo "Destroy '", myStr, "' ", getThreadId()
      `=destroy`(myStr.val)
    
    
    var L: Lock
    var data {.guard: L.}: seq[MyString]
    proc main =
      var myThread: Thread[void]
      
      
      initLock(L)
      
      
      proc printer() {.nimcall.} =
        {.cast(gcsafe).}:
          withLock L:
            var theStr = data.pop()
            echo "Printer: '", theStr.val, "' ", getThreadId()
      
      
      echo "Main start: ", getThreadId()
      
      var myStr = MyString(val: "Hello, World!")
      withLock L:
        data.add(myStr)
      
      createThread(myThread, printer)
      joinThread(myThread)
      
      deinitLock(L)
      echo "Main finish: ", getThreadId()
    
    main()
    
    
    Run

You can make it gcsafe by passing a context object to the thread. This gives 
the same output somehow.
    
    
    import locks
    type
      MyString = object
        val: string
      
      Context = ref object
        L: Lock
        data {.guard: L.}: seq[MyString]
    
    
    proc `=destroy`(myStr: var MyString) =
      echo "Destroy '", myStr, "' ", getThreadId()
      `=destroy`(myStr.val)
    
    proc main =
      var myThread: Thread[Context]
      
      var ctx = Context()
      initLock(ctx.L)
      
      proc printer(ctx: Context) {.nimcall.} =
        withLock ctx.L:
          var theStr = ctx.data.pop()
          echo "Printer: '", theStr.val, "' ", getThreadId()
      
      echo "Main start: ", getThreadId()
      
      var myStr = MyString(val: "Hello, World!")
      withLock ctx.L:
        ctx.data.add(myStr)
      
      createThread(myThread, printer, ctx)
      joinThread(myThread)
      
      deinitLock(ctx.L)
      echo "Main finish: ", getThreadId()
    
    main()
    
    
    Run

Reply via email to