The rule is the same as other multithreaded languages without a 
multithreading-aware GC:

_Ensure the lifetime of whatever you 
[access](https://forum.nim-lang.org/postActivity.xml#access)

>From this you can derive a couple rules:

  * Stack objects can be accessed only if allocated in the current thread or an 
ancestor thread that survives the current thread.
  * Heap objects can only be accessed until they are collected.
    * Similar to stack: ref objects can be used if, thanks to blocking/awaiting 
there is a guarantee that the multithreaded section ends before ref object is 
collected by the ancestor thread.
    * Or manual alloc/free should be used
    * Or you use atomic refcounting: 
<https://github.com/nim-lang/threading/blob/49562fa0/threading/smartptrs.nim#L77-L132>



Now the old and the new memory management (deferred refcounting vs arc - 
automatic refcounting) does not change those **accessing** principles but 
significantly improve **sharing**.

In many cases it is significantly more efficient, maintainable and debuggable 
to have an unique owner of an object or data and dispatch all transformation 
steps of this object to several procs or services. Those may or may not be on 
separate threads. This is called a producer/consumer architecture (or actor 
model in some case or microservice if done at whole machine scale for some 
reason) The main advantages are:

  * within that proc or service, everything is single threaded and can be coded 
as usual.
  * no thread contention
  * backpressure-handling via queues at the input and output of those services
  * spinning up more threads with a copy of the proc/service can help deal with 
full queues



However, there is no more notion of ancestor thread that can wait for its child 
thread to stop processing.

What's the issue? you need to pass the data from one thread to the other. 
Actually you don't have to do this, you can be much faster by passing 
"ownership" so the pointer (handle) to the data. Still if behind there is some 
GC-ed memory, it needs to be collected once done and no ancestor thread can be 
relied on. Hence in the old memory management model:

  * either it needed to somehow be returned to the original thread as only it 
was able to collect the GC-ed data.
  * or data needed to be deep-copied in queues, possibly twice: Producer -> 
channel -> consumer



This is not the case anymore with ARC (or Boehm or if the data doesn't use 
GC-ed memory)

Reply via email to