104 lines
3.1 KiB
Nim
Raw Normal View History

2023-09-12 18:33:38 -07:00
# Nim's Runtime Library
# (c) Copyright 2021 Nim contributors
import std/atomics
import std/isolation
import std/typetraits
import std/strutils
export isolation
proc raiseNilAccess() {.noinline.} =
raise newException(NilAccessDefect, "dereferencing nil smart pointer")
template checkNotNil(p: typed) =
when compileOption("boundChecks"):
{.line.}:
if p.isNil:
raiseNilAccess()
type
SharedPtr*[T] = object
## Shared ownership reference counting pointer.
cnt: ptr int
2023-09-12 18:50:38 -07:00
val*: ptr T
2023-09-12 18:33:38 -07:00
2023-09-12 20:09:55 -07:00
proc incr*[T](a: var SharedPtr[T]) =
2023-09-12 19:15:22 -07:00
if a.val != nil and a.cnt != nil:
let res = atomicAddFetch(a.cnt, 1, ATOMIC_RELAXED)
echo "SharedPtr: manual incr: ", res
2023-09-12 18:33:38 -07:00
2023-09-12 20:09:55 -07:00
proc decr*[T](x: var SharedPtr[T]) =
2023-09-12 18:50:38 -07:00
if x.val != nil and x.cnt != nil:
2023-09-12 18:33:38 -07:00
let res = atomicSubFetch(x.cnt, 1, ATOMIC_ACQUIRE)
if res == 0:
2023-09-13 11:18:22 -07:00
echo "SharedPtr: FREE: ", repr x.val.pointer, " ", x.cnt[], " tp: ", $(typeof(T))
2023-09-13 11:50:48 -07:00
when compiles(`=destroy`(x[])):
echo "DECR FREE: ", $(typeof(x[]))
`=destroy`(x[])
2023-09-12 18:50:38 -07:00
deallocShared(x.val)
2023-09-12 18:33:38 -07:00
deallocShared(x.cnt)
2023-09-12 20:09:55 -07:00
x.val = nil
x.cnt = nil
2023-09-12 18:33:38 -07:00
else:
2023-09-12 19:15:22 -07:00
echo "SharedPtr: decr: ", repr x.val.pointer, " ", x.cnt[], " tp: ", $(typeof(T))
2023-09-12 18:33:38 -07:00
2023-09-12 20:19:57 -07:00
proc release*[T](x: var SharedPtr[T]) =
x.decr()
x.val = nil
x.cnt = nil
2023-09-12 18:33:38 -07:00
proc `=destroy`*[T](x: var SharedPtr[T]) =
2023-09-12 20:09:55 -07:00
if x.val != nil:
2023-09-12 20:43:59 -07:00
echo "SharedPtr: destroy: ", repr x.val.pointer.repr, " cnt: ", x.cnt.pointer.repr, " tp: ", $(typeof(T))
2023-09-12 18:33:38 -07:00
decr(x)
proc `=dup`*[T](src: SharedPtr[T]): SharedPtr[T] =
2023-09-12 19:15:22 -07:00
if src.val != nil and src.cnt != nil:
2023-09-12 18:50:38 -07:00
discard atomicAddFetch(src.cnt, 1, ATOMIC_RELAXED)
2023-09-12 18:33:38 -07:00
result.val = src.val
proc `=copy`*[T](dest: var SharedPtr[T], src: SharedPtr[T]) =
2023-09-12 19:15:22 -07:00
if src.val != nil and src.cnt != nil:
2023-09-12 18:33:38 -07:00
# echo "SharedPtr: copy: ", src.val.pointer.repr
2023-09-12 18:50:38 -07:00
discard atomicAddFetch(src.cnt, 1, ATOMIC_RELAXED)
2023-09-12 18:33:38 -07:00
`=destroy`(dest)
dest.val = src.val
proc newSharedPtr*[T](val: sink Isolated[T]): SharedPtr[T] {.nodestroy.} =
2023-09-12 18:50:38 -07:00
## Returns a shared pointer which shares,
2023-09-12 18:33:38 -07:00
## ownership of the object by reference counting.
2023-09-12 18:50:38 -07:00
result.cnt = cast[ptr int](allocShared0(sizeof(result.cnt)))
2023-09-12 18:33:38 -07:00
result.val = cast[typeof(result.val)](allocShared(sizeof(result.val[])))
2023-09-13 11:50:48 -07:00
result.cnt[] = 1
2023-09-12 20:09:55 -07:00
result.val[] = extract val
2023-09-12 18:33:38 -07:00
echo "SharedPtr: alloc: ", result.val.pointer.repr, " tp: ", $(typeof(T))
template newSharedPtr*[T](val: T): SharedPtr[T] =
newSharedPtr(isolate(val))
proc newSharedPtr*[T](t: typedesc[T]): SharedPtr[T] =
## Returns a shared pointer. It is not initialized,
2023-09-12 18:50:38 -07:00
result.cnt = cast[ptr int](allocShared0(sizeof(result.cnt)))
2023-09-12 18:33:38 -07:00
result.val = cast[typeof(result.val)](allocShared0(sizeof(result.val[])))
2023-09-13 11:50:48 -07:00
result.cnt[] = 1
2023-09-12 20:09:55 -07:00
echo "SharedPtr: alloc: ", result.val.pointer.repr, " tp: ", $(typeof(T))
2023-09-12 18:33:38 -07:00
proc isNil*[T](p: SharedPtr[T]): bool {.inline.} =
p.val == nil
proc `[]`*[T](p: SharedPtr[T]): var T {.inline.} =
checkNotNil(p)
2023-09-12 18:50:38 -07:00
p.val[]
2023-09-12 18:33:38 -07:00
proc `[]=`*[T](p: SharedPtr[T], val: sink Isolated[T]) {.inline.} =
checkNotNil(p)
2023-09-12 18:50:38 -07:00
p.val[] = extract val
2023-09-12 18:33:38 -07:00
template `[]=`*[T](p: SharedPtr[T]; val: T) =
`[]=`(p, isolate(val))
proc `$`*[T](p: SharedPtr[T]): string {.inline.} =
if p.val == nil: "nil"
2023-09-13 11:18:22 -07:00
else: "(val: " & $p.val[] & ")"