This is a RFC on copy-on-write strings 
[https://github.com/nim-lang/RFCs/issues/221](https://github.com/nim-lang/RFCs/issues/221)
 (no code or pseudo-code though)

For your own refcounting scheme, as @snej mention, it's easy to do with 
destructors, see my atomic ref counted type here: 
[https://github.com/mratsim/weave/blob/9f0c384f/weave/cross_thread_com/flow_events.nim#L173-L201](https://github.com/mratsim/weave/blob/9f0c384f/weave/cross_thread_com/flow_events.nim#L173-L201)
    
    
    type
      FlowEvent* = object
        e: EventPtr
      
      EventPtr = ptr object
        refCount: Atomic[int32]
    
    # Refcounting is started from 0 and we avoid fetchSub with release semantics
    # in the common case of only one reference being live.
    
    proc `=destroy`*(event: var FlowEvent) =
      if event.e.isNil:
        return
      
      let count = event.e.refCount.load(moRelaxed)
      fence(moAcquire)
      if count == 0:
        # We have the last reference
        if not event.e.isNil:
          if event.e.kind == Iteration:
            wv_free(event.e.union.iter.singles)
          # Return memory to the memory pool
          recycle(event.e)
      else:
        discard fetchSub(event.e.refCount, 1, moRelease)
      event.e = nil
    
    proc `=sink`*(dst: var FlowEvent, src: FlowEvent) {.inline.} =
      # Don't pay for atomic refcounting when compiler can prove there is no 
ref change
      `=destroy`(dst)
      system.`=sink`(dst.e, src.e)
    
    proc `=`*(dst: var FlowEvent, src: FlowEvent) {.inline.} =
      `=destroy`(dst)
      discard fetchAdd(src.e.refCount, 1, moRelaxed)
      dst.e = src.e
    
    
    Run

To add Copy-On-Write on top you need to change the `=` so that it checks how 
many reference there are and if there is one `detach`/`copy`, `=sink` and 
`destroy` can stay as-is.

Reply via email to