summary refs log tree commit diff stats
path: root/tests/destructor/tatomicptrs.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/destructor/tatomicptrs.nim')
-rw-r--r--tests/destructor/tatomicptrs.nim101
1 files changed, 101 insertions, 0 deletions
diff --git a/tests/destructor/tatomicptrs.nim b/tests/destructor/tatomicptrs.nim
new file mode 100644
index 000000000..d20596415
--- /dev/null
+++ b/tests/destructor/tatomicptrs.nim
@@ -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()
+