tatomicptrs.nim 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. joinable: false
  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]](allocShared0(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. # xxx this isn't used, the test should be improved
  63. unpackVarargs(s.x.field, args)
  64. type
  65. Tree = SharedPtr[TreeObj]
  66. TreeObj = object
  67. refcount: int
  68. le, ri: Tree
  69. data: int
  70. proc takesTree(a: Tree) =
  71. if not a.isNil:
  72. takesTree(a.le)
  73. echo a.data
  74. takesTree(a.ri)
  75. proc createTree(data: int): Tree =
  76. result = makeShared(TreeObj(refcount: 1, data: data))
  77. proc createTree(data: int; le, ri: Tree): Tree =
  78. result = makeShared(TreeObj(refcount: 1, le: le, ri: ri, data: data))
  79. proc main =
  80. let le = createTree(55)
  81. let ri = createTree(99)
  82. let t = createTree(60, le, ri)
  83. takesTree(t)
  84. main()
  85. #-------------------------------------------------------
  86. #bug #9781
  87. type
  88. MySeq* [T] = object
  89. refcount: int
  90. len: int
  91. data: ptr UncheckedArray[T]
  92. proc `=destroy`*[T](m: var MySeq[T]) {.inline.} =
  93. if m.data != nil:
  94. deallocShared(m.data)
  95. m.data = nil
  96. proc `=`*[T](m: var MySeq[T], m2: MySeq[T]) =
  97. if m.data == m2.data: return
  98. if m.data != nil:
  99. `=destroy`(m)
  100. m.len = m2.len
  101. let bytes = m.len.int * sizeof(float)
  102. if bytes > 0:
  103. m.data = cast[ptr UncheckedArray[T]](allocShared(bytes))
  104. copyMem(m.data, m2.data, bytes)
  105. proc `=sink`*[T](m: var MySeq[T], m2: MySeq[T]) {.inline.} =
  106. if m.data != m2.data:
  107. if m.data != nil:
  108. `=destroy`(m)
  109. m.len = m2.len
  110. m.data = m2.data
  111. proc len*[T](m: MySeq[T]): int {.inline.} = m.len
  112. proc newMySeq*[T](size: int, initial_value: T): MySeq[T] =
  113. result.len = size
  114. if size > 0:
  115. result.data = cast[ptr UncheckedArray[T]](allocShared(sizeof(T) * size))
  116. let x = makeShared(newMySeq(10, 1.0))
  117. doAssert: x.get().len == 10
  118. #-------------------------------------------------------
  119. #bug #12882
  120. type
  121. ValueObject = object
  122. v: MySeq[int]
  123. name: string
  124. TopObject = object
  125. internal: seq[ValueObject]
  126. var zz = new(TopObject)