tatomicptrs.nim 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. discard """
  2. output: '''allocating
  3. allocating
  4. allocating
  5. 55
  6. 60
  7. 99
  8. deallocating
  9. deallocating
  10. deallocating
  11. allocating
  12. deallocating
  13. '''
  14. cmd: '''nim c --newruntime $file'''
  15. """
  16. type
  17. SharedPtr*[T] = object
  18. x: ptr T
  19. #proc isNil[T](s: SharedPtr[T]): bool {.inline.} = s.x.isNil
  20. template incRef(x) =
  21. atomicInc(x.refcount)
  22. template decRef(x): untyped = atomicDec(x.refcount)
  23. proc makeShared*[T](x: sink T): SharedPtr[T] =
  24. # XXX could benefit from a macro that generates it.
  25. result = cast[SharedPtr[T]](allocShared(sizeof(x)))
  26. result.x[] = x
  27. echo "allocating"
  28. proc `=destroy`*[T](dest: var SharedPtr[T]) =
  29. var s = dest.x
  30. if s != nil and decRef(s) == 0:
  31. `=destroy`(s[])
  32. deallocShared(s)
  33. echo "deallocating"
  34. dest.x = nil
  35. proc `=`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
  36. var s = src.x
  37. if s != nil: incRef(s)
  38. #atomicSwap(dest, s)
  39. # XXX use an atomic store here:
  40. swap(dest.x, s)
  41. if s != nil and decRef(s) == 0:
  42. `=destroy`(s[])
  43. deallocShared(s)
  44. echo "deallocating"
  45. proc `=sink`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
  46. ## XXX make this an atomic store:
  47. if dest.x != src.x:
  48. let s = dest.x
  49. if s != nil:
  50. `=destroy`(s[])
  51. deallocShared(s)
  52. echo "deallocating"
  53. dest.x = src.x
  54. proc get*[T](s: SharedPtr[T]): lent T =
  55. s.x[]
  56. template `.`*[T](s: SharedPtr[T]; field: untyped): untyped =
  57. s.x.field
  58. template `.=`*[T](s: SharedPtr[T]; field, value: untyped) =
  59. s.x.field = value
  60. from macros import unpackVarargs
  61. template `.()`*[T](s: SharedPtr[T]; field: untyped, args: varargs[untyped]): untyped =
  62. unpackVarargs(s.x.field, args)
  63. type
  64. Tree = SharedPtr[TreeObj]
  65. TreeObj = object
  66. refcount: int
  67. le, ri: Tree
  68. data: int
  69. proc takesTree(a: Tree) =
  70. if not a.isNil:
  71. takesTree(a.le)
  72. echo a.data
  73. takesTree(a.ri)
  74. proc createTree(data: int): Tree =
  75. result = makeShared(TreeObj(refcount: 1, data: data))
  76. proc createTree(data: int; le, ri: Tree): Tree =
  77. result = makeShared(TreeObj(refcount: 1, le: le, ri: ri, data: data))
  78. proc main =
  79. let le = createTree(55)
  80. let ri = createTree(99)
  81. let t = createTree(60, le, ri)
  82. takesTree(t)
  83. main()
  84. #-------------------------------------------------------
  85. #bug #9781
  86. type
  87. MySeq* [T] = object
  88. refcount: int
  89. len: int
  90. data: ptr UncheckedArray[T]
  91. proc `=destroy`*[T](m: var MySeq[T]) {.inline.} =
  92. if m.data != nil:
  93. deallocShared(m.data)
  94. m.data = nil
  95. proc `=`*[T](m: var MySeq[T], m2: MySeq[T]) =
  96. if m.data == m2.data: return
  97. if m.data != nil:
  98. `=destroy`(m)
  99. m.len = m2.len
  100. let bytes = m.len.int * sizeof(float)
  101. if bytes > 0:
  102. m.data = cast[ptr UncheckedArray[T]](allocShared(bytes))
  103. copyMem(m.data, m2.data, bytes)
  104. proc `=sink`*[T](m: var MySeq[T], m2: MySeq[T]) {.inline.} =
  105. if m.data != m2.data:
  106. if m.data != nil:
  107. `=destroy`(m)
  108. m.len = m2.len
  109. m.data = m2.data
  110. proc len*[T](m: MySeq[T]): int {.inline.} = m.len
  111. proc newMySeq*[T](size: int, initial_value: T): MySeq[T] =
  112. result.len = size
  113. if size > 0:
  114. result.data = cast[ptr UncheckedArray[T]](allocShared(sizeof(T) * size))
  115. let x = makeShared(newMySeq(10, 1.0))
  116. doAssert: x.get().len == 10