Hi. I have a complex object declared in shared memory:
type
SubObj = object
idata: int
fdata: float
sdata: string
MyObj = object
title: string
data: SubObj
var lock: Lock
var shrObj {.guard: lock.}: ptr MyObj
shrObj = cast[ptr MyObj](allocShared0(sizeof(MyObj)))
shrObj.title = "abc"
shrObj.data.idata = 123
shrObj.data.fdata = 0.01
shrObj.data.sdata = "text data..."
#GCunref(shrObj.title)
#GCunref(shrObj.data.sdata)
dealloc(shrObj)
dealloc function will excepted (alloc.nim:399 c.prev.next = c.next
). What I'm doing wrong? Also, is it necessary to call a function GCunref? (I saw it in manual)If your object was allocated with allocShared0 then it must be de-allocated with deallocShared.
https://nim-lang.org/docs/system.html#allocShared0,Natural
As to your question regarding GCunref, yes, it is needed for objects managed by Nim's GC (like the string example in the manual) when an untraced object (ptr) points to a traced object (ref) as you have in your example.
You also need to be careful here. Your intention appears to be sharing this untraced object across threads (given the usage of allocShared0) and you are mixing GC'ed memory with non-GC'ed memory across threads, which is tricky at best (read: unsafe). You need to understand and control the lifecycle of the GC'ed objects in order to avoid unsafe behavior.
My general advice would be to avoid doing that.
If it helps steer you towards a better solution, I'll mention that in the past I created a string type called SharedString (named in the spirit of allocShared) which can be easily initialized from the standard string type, as well as manipulated much like a normal string (using converters) but ends up using global shared storage instead of GC'ed memory.
See this gist.