summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorflywind <xzsflywind@gmail.com>2022-03-24 04:07:05 +0800
committerGitHub <noreply@github.com>2022-03-23 21:07:05 +0100
commita262a87bbebdaf41ea248f7caa780f8ea27e20e1 (patch)
tree14481a08064c6ebb77b376ddea82b0898c0f2c07
parent2c01c9c4c8a20772ebbb91f3333feb5dbcc94e9e (diff)
downloadNim-a262a87bbebdaf41ea248f7caa780f8ea27e20e1.tar.gz
[add testcase] arc problems with recursive types (#19456)
* [add testcase] arc problems with recursive types

close #9650

* do test

* expand

* Update tests/arc/t9650.nim
-rw-r--r--tests/arc/t9650.nim87
1 files changed, 87 insertions, 0 deletions
diff --git a/tests/arc/t9650.nim b/tests/arc/t9650.nim
new file mode 100644
index 000000000..a8182db68
--- /dev/null
+++ b/tests/arc/t9650.nim
@@ -0,0 +1,87 @@
+discard """
+  matrix: "--gc:arc"
+"""
+
+import typetraits
+
+# bug #9650
+type
+  SharedPtr*[T] = object
+    val: ptr tuple[atomicCounter: int, value: T]
+
+  Node*[T] = object
+    value: T
+    next: SharedPtr[Node[T]]
+
+  ForwardList*[T] = object
+    first: SharedPtr[Node[T]]
+
+proc `=destroy`*[T](p: var SharedPtr[T]) =
+  if p.val != nil:
+    let c = atomicDec(p.val[].atomicCounter)
+    if c == 0:
+      when not supportsCopyMem(T):
+         `=destroy`(p.val[])
+      dealloc(p.val)
+    p.val = nil
+
+proc `=`*[T](dest: var SharedPtr[T], src: SharedPtr[T]) =
+  if dest.val != src.val:
+    if dest.val != nil:
+      `=destroy`(dest)
+    if src.val != nil:
+      discard atomicInc(src.val[].atomicCounter)
+      dest.val = src.val
+
+proc `=sink`*[T](dest: var SharedPtr[T], src: SharedPtr[T]) =
+  if dest.val != nil and dest.val != src.val:
+    `=destroy`(dest)
+  dest.val = src.val
+
+ 
+proc newSharedPtr*[T](val: sink T): SharedPtr[T] =
+  result.val = cast[type(result.val)](alloc(sizeof(result.val[])))
+  reset(result.val[])
+  result.val.atomicCounter = 1
+  result.val.value = val
+
+proc isNil*[T](p: SharedPtr[T]): bool =
+  p.val == nil
+
+template `->`*[T](p: SharedPtr[T], name: untyped): untyped =
+  p.val.value.name
+
+proc createNode[T](val: T): SharedPtr[ Node[T] ]=
+  result = newSharedPtr(Node[T](value: val))
+
+proc push_front*[T](list: var ForwardList[T], val: T) =
+  var newElem = createNode(val)
+  newElem->next = list.first
+  list.first = newElem
+
+proc pop_front*[T](list: var ForwardList[T]) =
+  let head = list.first
+  list.first = head->next
+
+proc toString*[T](list: ForwardList[T]): string =
+  result = "["
+  var head = list.first
+  while not head.isNil:
+    result &= $(head->value) & ", "
+    head = head->next
+  result &= ']'
+
+block:
+  var x: ForwardList[int]
+  x.push_front(1)
+  x.push_front(2)
+  x.push_front(3)
+
+  doAssert toString(x) == "[3, 2, 1, ]"
+
+  x.pop_front()
+  x.pop_front()
+  doAssert toString(x) == "[1, ]"
+
+  x.pop_front()
+  doAssert toString(x) == "[]"