I didn't use ARC because when I started evaluating multithreading options (July 2019) and implementing Weave (November 2019) it was not ready at all.
Now at the moment, I'm ready to run my batteries of tests on arc: [https://github.com/mratsim/weave/blob/33a446ca/weave.nimble#L99-L167](https://github.com/mratsim/weave/blob/33a446ca/weave.nimble#L99-L167) But I need to be able to at least have custom channels working: [https://github.com/nim-lang/Nim/issues/13936](https://github.com/nim-lang/Nim/issues/13936) I do provide already the primitives necessary to have `awaitable` (in the async sens) Weave jobs via `isReady`, you only need to replace the `sleep()` by `poll()` here in my own [waitFor](https://github.com/mratsim/weave/blob/33a446ca4ac6294e664d26693702e3eb1d9af326/weave/datatypes/flowvars.nim#L234-L249): proc waitFor*[T](p: Pending[T]): T {.inline.} = ## Wait for a pending value ## This blocks the thread until the value is ready ## and then returns it. preCondition: onSubmitterThread var backoff = 1 while not p.isReady: sleep(backoff) backoff *= 2 if backoff > 16: backoff = 16 let ok = p.fv.tryComplete(result) ascertain: ok cleanup(p.fv) Run See writeup/RFC: [https://github.com/mratsim/weave/issues/132](https://github.com/mratsim/weave/issues/132) The main issue right now that the GC cannot solve is if we ever want to implement an `executor` API/concept or at least common `Task` abstraction to could be dispatch on either: * Async executors (async dispatch/chronos/libuv) * Parallel executors (Nim threadpool / Weave) * An simple executor for blocking tasks like `readline()` because just as you shouldn't block asyncdispatch, you shouldn't block Weave with non-computational tasks. The simple reason why is that tasks in a parallel runtime are threadsafe closures + metadata, and the GC being thread-local prevents closures from being sent across threads. This brings us to why we would want a common Task abstraction To be honest I'm not sure, but I'm sure we would want a threadsafe async executor, potentially with task stealing as well, it's not even hard to write (at least the task stealing side, ~2k lines): * [https://github.com/stjepang/async-task](https://github.com/stjepang/async-task) * [https://github.com/stjepang/smol](https://github.com/stjepang/smol) but this would require threadsafe closures. i.e. threadsafe /sendable closures are the core primitive that ARC brings us. It also gives us `owned` and destructors give use sink which we can use to enforce ownership when we send tasks across threads. This significantly reduce the need of Atomic Refcounting schemes as we can just deep-copy the pointers instead. For example, we need to enforce ownership of futures. (Hence why I hope that when a proc is tagged with `sink` parameters it also prevents the caller from ever reusing that variable again)
