smart_ptr.nim 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. type
  2. SharedPtr*[T] = object
  3. val: ptr tuple[atomicCounter: int, value: T]
  4. proc `=destroy`*[T](p: var SharedPtr[T]) =
  5. mixin `=destroy`
  6. if p.val != nil:
  7. let c = atomicDec(p.val[].atomicCounter)
  8. if c == 0:
  9. `=destroy`(p.val.value)
  10. freeShared(p.val)
  11. p.val = nil
  12. proc `=`*[T](dest: var SharedPtr[T], src: SharedPtr[T]) {.inline.} =
  13. if dest.val != src.val:
  14. if dest.val != nil:
  15. `=destroy`(dest)
  16. if src.val != nil:
  17. discard atomicInc(src.val[].atomicCounter)
  18. dest.val = src.val
  19. proc `=sink`*[T](dest: var SharedPtr[T], src: SharedPtr[T]) {.inline.} =
  20. if dest.val != src.val:
  21. if dest.val != nil:
  22. `=destroy`(dest)
  23. dest.val = src.val
  24. proc newSharedPtr*[T](val: sink T): SharedPtr[T] =
  25. result.val = cast[type(result.val)](allocShared0(sizeof(result.val[])))
  26. result.val.atomicCounter = 1
  27. result.val.value = val
  28. func get*[T](p: SharedPtr[T]): var T {.inline.} =
  29. p.val.value
  30. func isNil*[T](p: SharedPtr[T]): bool {.inline.} =
  31. p.val == nil
  32. proc cas*[T](p, old_val: var SharedPtr[T], new_val: SharedPtr[T]): bool {.inline.} =
  33. if old_val.val == new_val.val:
  34. result = true
  35. else:
  36. result = cas(p.val.addr, old_val.val, new_val.val)
  37. if result:
  38. `=destroy`(old_val)
  39. if new_val.val != nil:
  40. discard atomicInc(new_val.val[].atomicCounter)