@Araq:

> This "owned wrapper" becomes a memory region with all its known up- and 
> downsides...

I may be too simple to understand how a "owned" wrapper turns into a memory 
region; perhaps the following example will help and you can tell me its 
problems or give me a reference so I can learn; a proposed impementation of a 
Owned/Dangling wrapper pair as follows: 
    
    
    const hasThreadSupport = compileOption("threads") and defined(threadsafe)
    
    # can only create Owned; can not create Dangling...
    # defined in this order because we can't {.borrow `.`.} generic types yet...
    type
      Dangling[T] = object
        cntnts: T
        refcnt: int
      Owned[T] = distinct Dangling[T]
    proc `=destroy`[T](x: var Owned[T]) {.inline.} =
      if x != nil:
        let cst = cast[Dangling[T]](x) # so we can access non Dangling fields
        assert cst.refcnt == 0, "destroying owned type with dangling 
references!"
        cast[ptr T](cst.cntnts.unsafeAddr)[].deepDestroy; x.reset
    proc `=`[T](dst: var Owned[T]; src: Owned[T]) {.error: "owned types can 
only be moved".}
    proc `=sink`[T](dst: var Owned[T]; src: Owned[T]) {.inline.} =
      let cstdst = cast[Dangling[T]](dst); let cstsrc = cast[Dangling[T]](src)
      if cstdst.cntnts != cstsrc.cntnts:
        dst.`=destroy`; cast[ptr T](cstdst.cntnts.unsafeAddr)[] = cstsrc.cntnts
    # when `=move` is used instead of `=sink`
    proc `=move`[T](dst, src: var OwnedRefRC[T]) {.inline.} =
      let cstdst = cast[Dangling[T]](dst); let cstsrc = cast[Dangling[T]](src)
      if cstdst.cntnts != cstsrc.cntnts:
        dst.`=destroy`; cast[ptr T](cstdst.cntnts.unsafeAddr)[] = 
cstsrc.cntnts; src.reset
    proc `$`[T](x: Owned[T]): string =
      result = "owned:  "; result &= $cast[Dangling[T]](x).cntnts
    
    proc `=destroy`[T](x: var Dangling[T]) {.inline.} =
      when hasThreadSupport: x.refcnt.atomicDec else: x.refcnt.dec
    proc `=`[T](dst: var Dangling[T]; src: Dangiing[T]) {.inline.} =
      when hasThreadSupport: dst.refcnt.atomicInc else: dst.refcnt.inc
      when hasThreadSupport: src.refcnt.atomicInc else: src.refcnt.inc
      copyMem(dst.unsafeAddr, src.unsafeAddr, src.sizeof) # just copy the 
pointer is a byte copy
    proc `=sink`[T](dst: var Dangling[T]; src: Dangling[T]) {.inline.} =
      # moves are the same as assignments
      `=`(dst, src)
    proc `=move`[T](dst, src: var Dangling[T]) {.inline.} =
      # moves are the same as assignments
      `=`(dst, src)
    proc `$`[T](x: RefRC[T]): string =
      result = "unowned:  "; result &= $x.cntnts
    
    
    Run

> Owned vs non-owned looked intractable to compute to me...

You're "the man" regarding what you think can be done with the compiler ;-) I'm 
just envisioning a simple syntax where one doesn't have to go back and change 
every declaration of a data type that is a heap reference or contains a heap 
reference to add the "owned" designation. There is also the question of 
handling nested "owned"'s but perhaps there is no need if my understanding of 
"owned" just being a wrapper is incorrect.

Reply via email to