tatomicptrs.nim 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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 `=copy`*[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 `=dup`*[T](src: SharedPtr[T]): SharedPtr[T] =
  46. `=copy`(result, src)
  47. proc `=sink`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
  48. ## XXX make this an atomic store:
  49. if dest.x != src.x:
  50. let s = dest.x
  51. if s != nil:
  52. `=destroy`(s[])
  53. deallocShared(s)
  54. echo "deallocating"
  55. dest.x = src.x
  56. proc get*[T](s: SharedPtr[T]): lent T =
  57. s.x[]
  58. template `.`*[T](s: SharedPtr[T]; field: untyped): untyped =
  59. s.x.field
  60. template `.=`*[T](s: SharedPtr[T]; field, value: untyped) =
  61. s.x.field = value
  62. from macros import unpackVarargs
  63. template `.()`*[T](s: SharedPtr[T]; field: untyped, args: varargs[untyped]): untyped =
  64. # xxx this isn't used, the test should be improved
  65. unpackVarargs(s.x.field, args)
  66. type
  67. Tree = SharedPtr[TreeObj]
  68. TreeObj = object
  69. refcount: int
  70. le, ri: Tree
  71. data: int
  72. proc takesTree(a: Tree) =
  73. if not a.isNil:
  74. takesTree(a.le)
  75. echo a.data
  76. takesTree(a.ri)
  77. proc createTree(data: int): Tree =
  78. result = makeShared(TreeObj(refcount: 1, data: data))
  79. proc createTree(data: int; le, ri: Tree): Tree =
  80. result = makeShared(TreeObj(refcount: 1, le: le, ri: ri, data: data))
  81. proc main =
  82. let le = createTree(55)
  83. let ri = createTree(99)
  84. let t = createTree(60, le, ri)
  85. takesTree(t)
  86. main()
  87. #-------------------------------------------------------
  88. #bug #9781
  89. type
  90. MySeq* [T] = object
  91. refcount: int
  92. len: int
  93. data: ptr UncheckedArray[T]
  94. proc `=destroy`*[T](m: var MySeq[T]) {.inline.} =
  95. if m.data != nil:
  96. deallocShared(m.data)
  97. m.data = nil
  98. proc `=copy`*[T](m: var MySeq[T], m2: MySeq[T]) =
  99. if m.data == m2.data: return
  100. if m.data != nil:
  101. `=destroy`(m)
  102. m.len = m2.len
  103. let bytes = m.len.int * sizeof(float)
  104. if bytes > 0:
  105. m.data = cast[ptr UncheckedArray[T]](allocShared(bytes))
  106. copyMem(m.data, m2.data, bytes)
  107. proc `=dup`*[T](m: MySeq[T]): MySeq[T] =
  108. `=copy`[T](result, m)
  109. proc `=sink`*[T](m: var MySeq[T], m2: MySeq[T]) {.inline.} =
  110. if m.data != m2.data:
  111. if m.data != nil:
  112. `=destroy`(m)
  113. m.len = m2.len
  114. m.data = m2.data
  115. m.refcount = m2.refcount
  116. proc len*[T](m: MySeq[T]): int {.inline.} = m.len
  117. proc newMySeq*[T](size: int, initial_value: T): MySeq[T] =
  118. result.len = size
  119. result.refcount = 1
  120. if size > 0:
  121. result.data = cast[ptr UncheckedArray[T]](allocShared(sizeof(T) * size))
  122. let x = makeShared(newMySeq(10, 1.0))
  123. doAssert: x.get().len == 10
  124. #-------------------------------------------------------
  125. #bug #12882
  126. type
  127. ValueObject = object
  128. v: MySeq[int]
  129. name: string
  130. TopObject = object
  131. internal: seq[ValueObject]
  132. var zz = new(TopObject)