tshared_ptr_crash.nim 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. discard """
  2. cmd: "nim c --threads:on --gc:arc $file"
  3. action: compile
  4. """
  5. # bug #17893
  6. type
  7. SharedPtr*[T] = object
  8. val: ptr tuple[value: T, atomicCounter: int]
  9. proc `=destroy`*[T](p: var SharedPtr[T]) =
  10. mixin `=destroy`
  11. if p.val != nil:
  12. if atomicLoadN(addr p.val[].atomicCounter, AtomicConsume) == 0:
  13. `=destroy`(p.val[])
  14. deallocShared(p.val)
  15. else:
  16. discard atomicDec(p.val[].atomicCounter)
  17. proc `=copy`*[T](dest: var SharedPtr[T], src: SharedPtr[T]) =
  18. if src.val != nil:
  19. discard atomicInc(src.val[].atomicCounter)
  20. if dest.val != nil:
  21. `=destroy`(dest)
  22. dest.val = src.val
  23. proc newSharedPtr*[T](val: sink T): SharedPtr[T] {.nodestroy.} =
  24. result = SharedPtr[T]()
  25. result.val = cast[typeof(result.val)](allocShared(sizeof(result.val[])))
  26. result.val.atomicCounter = 0
  27. result.val.value = val
  28. proc isNil*[T](p: SharedPtr[T]): bool {.inline.} =
  29. p.val == nil
  30. proc `[]`*[T](p: SharedPtr[T]): var T {.inline.} =
  31. when compileOption("boundChecks"):
  32. doAssert(p.val != nil, "deferencing nil shared pointer")
  33. result = p.val.value
  34. type
  35. Sender*[T] = object
  36. queue: SharedPtr[seq[T]]
  37. proc newSender*[T](queue: sink SharedPtr[seq[T]]): Sender[T] =
  38. result = Sender[T](queue: queue)
  39. proc send*[T](self: Sender[T]; t: sink T) =
  40. self.queue[].add t
  41. proc newChannel*(): Sender[int] =
  42. let queue = newSharedPtr(newSeq[int]())
  43. result = newSender(queue)
  44. var
  45. p: Thread[Sender[int]]
  46. proc threadFn(tx: Sender[int]) =
  47. send tx, 0
  48. proc multiThreadedChannel =
  49. let tx = newChannel()
  50. createThread(p, threadFn, tx)
  51. joinThread(p)
  52. multiThreadedChannel()