summary refs log tree commit diff stats
path: root/tests/arc
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2021-07-13 14:17:59 +0200
committerGitHub <noreply@github.com>2021-07-13 14:17:59 +0200
commit12da32a891b08f34acbb676001f0c211ecfe1af8 (patch)
tree196758792d748076c4958319dafb637c7681f53b /tests/arc
parentb3aca78e228feb93d5dcd6f00cdd81e4178c24cc (diff)
downloadNim-12da32a891b08f34acbb676001f0c211ecfe1af8.tar.gz
fixes #17893 (#18485)
* fixes #17893
Diffstat (limited to 'tests/arc')
-rw-r--r--tests/arc/tshared_ptr_crash.nim67
1 files changed, 67 insertions, 0 deletions
diff --git a/tests/arc/tshared_ptr_crash.nim b/tests/arc/tshared_ptr_crash.nim
new file mode 100644
index 000000000..1794834db
--- /dev/null
+++ b/tests/arc/tshared_ptr_crash.nim
@@ -0,0 +1,67 @@
+discard """
+  cmd: "nim c --threads:on --gc:arc $file"
+  action: compile
+"""
+
+# bug #17893
+
+type
+  SharedPtr*[T] = object
+    val: ptr tuple[value: T, atomicCounter: int]
+
+proc `=destroy`*[T](p: var SharedPtr[T]) =
+  mixin `=destroy`
+  if p.val != nil:
+    if atomicLoadN(addr p.val[].atomicCounter, AtomicConsume) == 0:
+      `=destroy`(p.val[])
+      deallocShared(p.val)
+    else:
+      discard atomicDec(p.val[].atomicCounter)
+
+proc `=copy`*[T](dest: var SharedPtr[T], src: SharedPtr[T]) =
+  if src.val != nil:
+    discard atomicInc(src.val[].atomicCounter)
+  if dest.val != nil:
+    `=destroy`(dest)
+  dest.val = src.val
+
+proc newSharedPtr*[T](val: sink T): SharedPtr[T] {.nodestroy.} =
+  result.val = cast[typeof(result.val)](allocShared(sizeof(result.val[])))
+  result.val.atomicCounter = 0
+  result.val.value = val
+
+proc isNil*[T](p: SharedPtr[T]): bool {.inline.} =
+  p.val == nil
+
+proc `[]`*[T](p: SharedPtr[T]): var T {.inline.} =
+  when compileOption("boundChecks"):
+    doAssert(p.val != nil, "deferencing nil shared pointer")
+  result = p.val.value
+
+type
+  Sender*[T] = object
+    queue: SharedPtr[seq[T]]
+
+proc newSender*[T](queue: sink SharedPtr[seq[T]]): Sender[T] =
+  result = Sender[T](queue: queue)
+
+proc send*[T](self: Sender[T]; t: sink T) =
+  self.queue[].add t
+
+proc newChannel*(): Sender[int] =
+  let queue = newSharedPtr(newSeq[int]())
+  result = newSender(queue)
+
+
+var
+  p: Thread[Sender[int]]
+
+proc threadFn(tx: Sender[int]) =
+  send tx, 0
+
+proc multiThreadedChannel =
+  let tx = newChannel()
+  createThread(p, threadFn, tx)
+  joinThread(p)
+
+multiThreadedChannel()