mirror of
https://github.com/logos-storage/nim-datastore.git
synced 2026-01-03 14:13:09 +00:00
94 lines
3.0 KiB
Nim
94 lines
3.0 KiB
Nim
# 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
|
|
val*: ptr T
|
|
|
|
proc incr*[T](a: SharedPtr[T]) =
|
|
if a.val != nil and a.cnt != nil:
|
|
let res = atomicAddFetch(a.cnt, 1, ATOMIC_RELAXED)
|
|
echo "SharedPtr: manual incr: ", res
|
|
|
|
proc decr*[T](x: SharedPtr[T]) =
|
|
if x.val != nil and x.cnt != nil:
|
|
let res = atomicSubFetch(x.cnt, 1, ATOMIC_ACQUIRE)
|
|
if res == 0:
|
|
echo "SharedPtr: FREE: ", repr x.val.pointer, " ", x.cnt[], " tp: ", $(typeof(T))
|
|
deallocShared(x.val)
|
|
deallocShared(x.cnt)
|
|
else:
|
|
echo "SharedPtr: decr: ", repr x.val.pointer, " ", x.cnt[], " tp: ", $(typeof(T))
|
|
|
|
proc `=destroy`*[T](x: var SharedPtr[T]) =
|
|
echo "SharedPtr: destroy: ", repr x.val.pointer, " ", x.cnt.repr, " tp: ", $(typeof(T))
|
|
# echo "SharedPtr: destroy:st: ", ($getStackTrace()).split("\n").join(";")
|
|
decr(x)
|
|
|
|
proc `=dup`*[T](src: SharedPtr[T]): SharedPtr[T] =
|
|
if src.val != nil and src.cnt != nil:
|
|
discard atomicAddFetch(src.cnt, 1, ATOMIC_RELAXED)
|
|
result.val = src.val
|
|
|
|
proc `=copy`*[T](dest: var SharedPtr[T], src: SharedPtr[T]) =
|
|
if src.val != nil and src.cnt != nil:
|
|
# echo "SharedPtr: copy: ", src.val.pointer.repr
|
|
discard atomicAddFetch(src.cnt, 1, ATOMIC_RELAXED)
|
|
`=destroy`(dest)
|
|
dest.val = src.val
|
|
|
|
proc newSharedPtr*[T](val: sink Isolated[T]): SharedPtr[T] {.nodestroy.} =
|
|
## Returns a shared pointer which shares,
|
|
## ownership of the object by reference counting.
|
|
result.cnt = cast[ptr int](allocShared0(sizeof(result.cnt)))
|
|
result.val = cast[typeof(result.val)](allocShared(sizeof(result.val[])))
|
|
result.cnt[] = 1
|
|
result.val.value = extract val
|
|
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,
|
|
## so reading from it before writing to it is undefined behaviour!
|
|
result.cnt = cast[ptr int](allocShared0(sizeof(result.cnt)))
|
|
result.val = cast[typeof(result.val)](allocShared0(sizeof(result.val[])))
|
|
result.cnt[] = 1
|
|
echo "SharedPtr: allocT: ", result.val.pointer.repr, " tp: ", $(typeof(T))
|
|
|
|
proc isNil*[T](p: SharedPtr[T]): bool {.inline.} =
|
|
p.val == nil
|
|
|
|
proc `[]`*[T](p: SharedPtr[T]): var T {.inline.} =
|
|
checkNotNil(p)
|
|
p.val[]
|
|
|
|
proc `[]=`*[T](p: SharedPtr[T], val: sink Isolated[T]) {.inline.} =
|
|
checkNotNil(p)
|
|
p.val[] = extract val
|
|
|
|
template `[]=`*[T](p: SharedPtr[T]; val: T) =
|
|
`[]=`(p, isolate(val))
|
|
|
|
proc `$`*[T](p: SharedPtr[T]): string {.inline.} =
|
|
if p.val == nil: "nil"
|
|
else: "(val: " & $p.val.value & ")" |