more progress on destructors; removed old destructor based code as it proved confusing

This commit is contained in:
Araq 2017-12-01 01:52:00 +01:00
commit fa92c519aa
9 changed files with 152 additions and 270 deletions

View file

@ -0,0 +1,101 @@
discard """
output: '''allocating
allocating
allocating
55
60
99
deallocating
deallocating
deallocating
'''
cmd: '''nim c --newruntime $file'''
"""
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: T): SharedPtr[T] =
# XXX could benefit from 'sink' parameter.
# 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
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()

View file

@ -20,10 +20,10 @@ myobj destroyed
----
myobj destroyed
'''
cmd: '''nim c --newruntime $file'''
disabled: "true"
"""
{.experimental.}
type
TMyObj = object
x, y: int
@ -61,7 +61,7 @@ proc `=destroy`(o: var TMyObj) =
if o.p != nil: dealloc o.p
echo "myobj destroyed"
proc `=destroy`(o: var TMyGeneric1) =
proc `=destroy`(o: var TMyGeneric1[int]) =
echo "mygeneric1 destroyed"
proc `=destroy`[A, B](o: var TMyGeneric2[A, B]) =

View file

@ -1,27 +0,0 @@
discard """
line: 23
nimout: " usage of a type with a destructor in a non destructible context"
"""
{.experimental.}
type
TMyObj = object
x, y: int
p: pointer
proc `=destroy`(o: var TMyObj) =
if o.p != nil: dealloc o.p
proc open: TMyObj =
result = TMyObj(x: 1, y: 2, p: alloc(3))
proc `$`(x: TMyObj): string = $x.y
proc foo =
discard open()
# XXX doesn't trigger this yet:
#echo open()

View file

@ -2,14 +2,14 @@ discard """
output: '''assign
destroy
destroy
destroy Foo: 5
5
destroy Foo: 123
123'''
123
destroy Foo: 5
destroy Foo: 123'''
cmd: '''nim c --newruntime $file'''
"""
# bug #2821
{.experimental.}
type T = object