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