I've been toying with making a `SharedRc[T]` wrapper type for using atomic 
ref's with regular ref objects by hi-jacking the normal ref count.

I hacked together a toy demo <https://play.nim-lang.org/#pasty=GlvskysjoRsj>

The core idea is to wrap ref's in the `SharedRc[T]` and enforce all access to 
field via accessors. It needs to be recursive so all fields need to also return 
`SharedRc[FieldType]` until you get to data which can be copied directly.

Generally the scheme seems to work, but there's lot of ways for ref's to escape 
to normal ref-counts which would be hard to avoid. Also, you can't pass an 
object tree like `ref JsonObject` without grabbing the non-atomic inner object 
or a proc using generics.

Still it's something I wanted to experiment with.
    
    
    import ./sharedrc
    
    type
      Test* = object
        msg*: string
      
      Foo* = ref object
        inner*: ref Test
    
    proc `=destroy`*(obj: Test) =
      echo "destroying Test obj: ", obj.msg
      `=destroy`(obj.msg)
    
    proc `=destroy`*(obj: Bar) =
      echo "destroying Bar obj: ", obj.field
      `=destroy`(obj.field)
    
    atomicAccessors(Foo)
    
    proc testProc(aref: SharedRc[ref Test]) {.thread.} =
      var lref: SharedRc[ref Test] = aref ## atomically inc ref
      echo "\nthread: ", lref.msg ## access data
      echo "thread done"
    
    proc testThread() =
      echo "Test Thread"
      var thread: Thread[SharedRc[Foo]]
      var t1 = newSharedRc(Foo(inner: (ref Test)(msg: "hello world!")))
      var t2 = t1
      let t3: SharedRc[ref Test] = t1.inner ## uses accessor
      createThread(thread, testProc, t3)
      thread.joinThread()
      echo "\nmain continue"
      echo "t2: ", t2.inner()
    
    testThread()
    
    
    
    Run

Reply via email to