Hello,
I am using a
var closeProgram : Atomic[bool]
to know between my threads and the main thread to know if if it time to exit properly.
By if I try to extend a string atomic variable I've got the error:
var atomicStr: Atomic[string]
Error: 'foo' is not GC-safe as it accesses 'atomicStr' which is a global using GC'ed memory
Whereas there is no error when foo accesses closeProgram
Did I miss something? Are atomics the good way to share variable between threads or is there something better?
You seem to be confused about the usage of atomics. An Atomic variable is simply a variable that has special CPU instructions that ensures that the instruction happens without the possibility to be interleaved by other threads. The reason this is useful can be seen by a simple example: myVar += 1, this is a single line and it would be easy to think that nothing could mess it up, it will always add 1 to the variable. But myVar += 1 is actually expanded to something like:
let oldVal = myVar
myVar = oldVal + 1
This means that in between the read of the value and the writing of the result some other thread could edit myVar. This can be solved by using a lock, or by using atomics (in this case atomicInc) both ensure that no other thread can interleave with the operation. But in general atomics are faster for simple things like this (even though it requires quite a bit of cache unfriendly behaviour).
Since atomics require special CPU instruction the size of the variable is pretty limited, which is often worked around by having it be a pointer to some data and swapping out the pointer (of course this means we might need further atomics in the data structure that we're pointed to).
Now, back to the error you're getting. Nims default garbage collector is thread-local, and strings are a garbage collected data structure. This means that if you set a global variable to a string from one thread it is only that threads access to the string which will be counted when it is considering if it is garbage or not. So if another thread reads the string the originating thread doesn't see this and can decide that the string is garbage and free it while the second thread is still trying to use it. This would obviously be an issue, hence the error. What you can do is to have an Atomic[ptr string] store the pointer, and then make absolutely sure that the string isn't going to be garbage collected before you're done using it across all threads. Another option is to use ARC or another of the garbage collection schemes that has a shared heap.