discard """
output: '''allocating
allocating
allocating
55
60
99
deallocating
deallocating
deallocating
allocating
deallocating
'''
joinable: false
"""
type
SharedPtr*[T] = object
x: ptr T
#proc isNil[T](s: SharedPtr[T]): bool {.inline.} = s.x.isNil
template incRef(x) =
atomicInc(x.refcount)
template decRef(x): untyped = atomicDec(x.refcount)
proc makeShared*[T](x: sink T): SharedPtr[T] =
# XXX could benefit from a macro that generates it.
result = cast[SharedPtr[T]](allocShared(sizeof(x)))
result.x[] = x
echo "allocating"
proc `=destroy`*[T](dest: var SharedPtr[T]) =
var s = dest.x
if s != nil and decRef(s) == 0:
`=destroy`(s[])
deallocShared(s)
echo "deallocating"
dest.x = nil
proc `=`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
var s = src.x
if s != nil: incRef(s)
#atomicSwap(dest, s)
# XXX use an atomic store here:
swap(dest.x, s)
if s != nil and decRef(s) == 0:
`=destroy`(s[])
deallocShared(s)
echo "deallocating"
proc `=sink`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
## XXX make this an atomic store:
if dest.x != src.x:
let s = dest.x
if s != nil:
`=destroy`(s[])
deallocShared(s)
echo "deallocating"
dest.x = src.x
proc get*[T](s: SharedPtr[T]): lent T =
s.x[]
template `.`*[T](s: SharedPtr[T]; field: untyped): untyped =
s.x.field
template `.=`*[T](s: SharedPtr[T]; field, value: untyped) =
s.x.field = value
from macros import unpackVarargs
template `.()`*[T](s: SharedPtr[T]; field: untyped, args: varargs[untyped]): untyped =
unpackVarargs(s.x.field, args)
type
Tree = SharedPtr[TreeObj]
TreeObj = object
refcount: int
le, ri: Tree
data: int
proc takesTree(a: Tree) =
if not a.isNil:
takesTree(a.le)
echo a.data
takesTree(a.ri)
proc createTree(data: int): Tree =
result = makeShared(TreeObj(refcount: 1, data: data))
proc createTree(data: int; le, ri: Tree): Tree =
result = makeShared(TreeObj(refcount: 1, le: le, ri: ri, data: data))
proc main =
let le = createTree(55)
let ri = createTree(99)
let t = createTree(60, le, ri)
takesTree(t)
main()
#-------------------------------------------------------
#bug #9781
type
MySeq* [T] = object
refcount: int
len: int
data: ptr UncheckedArray[T]
proc `=destroy`*[T](m: var MySeq[T]) {.inline.} =
if m.data != nil:
deallocShared(m.data)
m.data = nil
proc `=`*[T](m: var MySeq[T], m2: MySeq[T]) =
if m.data == m2.data: return
if m.data != nil:
`=destroy`(m)
m.len = m2.len
let bytes = m.len.int * sizeof(float)
if bytes > 0:
m.data = cast[ptr UncheckedArray[T]](allocShared(bytes))
copyMem(m.data, m2.data, bytes)
proc `=sink`*[T](m: var MySeq[T], m2: MySeq[T]) {.inline.} =
if m.data != m2.data:
if m.data != nil:
`=destroy`(m)
m.len = m2.len
m.data = m2.data
proc len*[T](m: MySeq[T]): int {.inline.} = m.len
proc newMySeq*[T](size: int, initial_value: T): MySeq[T] =
result.len = size
if size > 0:
result.data = cast[ptr UncheckedArray[T]](allocShared(sizeof(T) * size))
let x = makeShared(newMySeq(10, 1.0))
doAssert: x.get().len == 10
#-------------------------------------------------------
#bug #12882
type
ValueObject = object
v: MySeq[int]
name: string
TopObject = object
internal: seq[ValueObject]
var zz = new(TopObject)