Thanks Araq for the link, it is very intersting. It is also not too difficult 
to create oneself a linkedlist that should work with ARC. For example :
    
    
    ## Source chatgpt for 30%
    import threading/smartptrs
    import std/atomics
    
    proc newAtomic*[T](val: sink T): Atomic[T] =
        result.store(val)
    
    type
        Node[T] = object
            val: T
            next: Atomic[ptr Node[T]]
        
        ThreadQueueObj[T] = object
            head: Atomic[ptr Node[T]]
            tail: Atomic[ptr Node[T]]
        
        ThreadQueue*[T] = SharedPtr[ThreadQueueObj[T]]
    
    
    proc `=destroy`*[T](q: ThreadQueueObj[T]) {.nodestroy.} =
        let qAddr = addr q
        var currentNode = qAddr[].head.load()
        while currentNode != nil:
            let nextNode = currentNode.next.load()
            `=destroy`(currentNode.val)
            deallocShared(currentNode)
            currentNode = nextNode
    
    proc newThreadQueue*[T](): ThreadQueue[T] =
        let node = cast[ptr Node[T]](alloc0(sizeof Node[T]))
        var atomicNode = newAtomic(node)
        return newSharedPtr(ThreadQueueObj[T](
            head: atomicNode,
            tail: atomicNode
        ))
    
    proc addLast*[T](q: ThreadQueue[T], val: sink T) =
        var newNode = cast[ptr Node[T]](alloc(sizeof Node[T]))
        newNode[] = Node[T](
            val: val,
            next: newAtomic[ptr Node[T]](nil),
        )
        let prevTail = q[].tail.exchange(newNode)
        prevTail[].next.store(newNode)
    
    proc popFirst*[T](q: ThreadQueue[T], outVal: out T): bool =
        var oldHead = q[].head.load()
        let newHead = oldHead[].next.load()
        if newHead == nil:
            return false
        if q[].head.compareExchange(oldHead, newHead):
            outVal = newHead[].val
            deallocShared(oldHead)
            return true
    
    proc empty*[T](q: ThreadQueue[T]): bool =
        ## The atomicity cannot be guaranted
        return q[].head.load() == q[].tail.load()
    
    
    var l = newThreadQueue[int]()
    
    for i in 1..1_000_000:
      l.addLast(i)
    
    
    Run

However, std/channels is faster, provides non busy sleep, and is surely more 
memory efficient

Reply via email to