123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- discard """
- output: '''allocating
- allocating
- allocating
- 55
- 60
- 99
- deallocating
- deallocating
- deallocating
- allocating
- deallocating
- '''
- joinable: false
- """
- type
- SharedPtr*[T] = object
- x: ptr T
- #proc isNil[T](s: SharedPtr[T]): bool {.inline.} = s.x.isNil
- template incRef(x) =
- atomicInc(x.refcount)
- template decRef(x): untyped = atomicDec(x.refcount)
- proc makeShared*[T](x: sink T): SharedPtr[T] =
- # XXX could benefit from a macro that generates it.
- result = cast[SharedPtr[T]](allocShared0(sizeof(x)))
- result.x[] = x
- echo "allocating"
- proc `=destroy`*[T](dest: var SharedPtr[T]) =
- var s = dest.x
- if s != nil and decRef(s) == 0:
- `=destroy`(s[])
- deallocShared(s)
- echo "deallocating"
- dest.x = nil
- proc `=`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
- var s = src.x
- if s != nil: incRef(s)
- #atomicSwap(dest, s)
- # XXX use an atomic store here:
- swap(dest.x, s)
- if s != nil and decRef(s) == 0:
- `=destroy`(s[])
- deallocShared(s)
- echo "deallocating"
- proc `=sink`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
- ## XXX make this an atomic store:
- if dest.x != src.x:
- let s = dest.x
- if s != nil:
- `=destroy`(s[])
- deallocShared(s)
- echo "deallocating"
- dest.x = src.x
- proc get*[T](s: SharedPtr[T]): lent T =
- s.x[]
- template `.`*[T](s: SharedPtr[T]; field: untyped): untyped =
- s.x.field
- template `.=`*[T](s: SharedPtr[T]; field, value: untyped) =
- s.x.field = value
- from macros import unpackVarargs
- template `.()`*[T](s: SharedPtr[T]; field: untyped, args: varargs[untyped]): untyped =
- # xxx this isn't used, the test should be improved
- unpackVarargs(s.x.field, args)
- type
- Tree = SharedPtr[TreeObj]
- TreeObj = object
- refcount: int
- le, ri: Tree
- data: int
- proc takesTree(a: Tree) =
- if not a.isNil:
- takesTree(a.le)
- echo a.data
- takesTree(a.ri)
- proc createTree(data: int): Tree =
- result = makeShared(TreeObj(refcount: 1, data: data))
- proc createTree(data: int; le, ri: Tree): Tree =
- result = makeShared(TreeObj(refcount: 1, le: le, ri: ri, data: data))
- proc main =
- let le = createTree(55)
- let ri = createTree(99)
- let t = createTree(60, le, ri)
- takesTree(t)
- main()
- #-------------------------------------------------------
- #bug #9781
- type
- MySeq* [T] = object
- refcount: int
- len: int
- data: ptr UncheckedArray[T]
- proc `=destroy`*[T](m: var MySeq[T]) {.inline.} =
- if m.data != nil:
- deallocShared(m.data)
- m.data = nil
- proc `=`*[T](m: var MySeq[T], m2: MySeq[T]) =
- if m.data == m2.data: return
- if m.data != nil:
- `=destroy`(m)
- m.len = m2.len
- let bytes = m.len.int * sizeof(float)
- if bytes > 0:
- m.data = cast[ptr UncheckedArray[T]](allocShared(bytes))
- copyMem(m.data, m2.data, bytes)
- proc `=sink`*[T](m: var MySeq[T], m2: MySeq[T]) {.inline.} =
- if m.data != m2.data:
- if m.data != nil:
- `=destroy`(m)
- m.len = m2.len
- m.data = m2.data
- proc len*[T](m: MySeq[T]): int {.inline.} = m.len
- proc newMySeq*[T](size: int, initial_value: T): MySeq[T] =
- result.len = size
- if size > 0:
- result.data = cast[ptr UncheckedArray[T]](allocShared(sizeof(T) * size))
- let x = makeShared(newMySeq(10, 1.0))
- doAssert: x.get().len == 10
- #-------------------------------------------------------
- #bug #12882
- type
- ValueObject = object
- v: MySeq[int]
- name: string
- TopObject = object
- internal: seq[ValueObject]
- var zz = new(TopObject)
|