@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.