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()
|
|
|
|
|
|
2023-09-13 13:55:11 -07:00
|
|
|
|
2023-09-14 20:29:35 -07:00
|
|
|
when not defined(datastoreEchoedThread):
|
2023-09-14 21:35:58 -07:00
|
|
|
template echoed*(vals: varargs[untyped]) =
|
2023-09-13 13:32:23 -07:00
|
|
|
discard
|
2023-09-14 19:23:14 -07:00
|
|
|
else:
|
|
|
|
|
import std/terminal
|
2023-09-14 20:29:35 -07:00
|
|
|
proc echoed*(vals: varargs[string]) =
|
2023-09-14 19:23:14 -07:00
|
|
|
proc printThread(): ForegroundColor =
|
|
|
|
|
let tclr = [fgRed, fgGreen, fgBlue, fgMagenta, fgCyan]
|
|
|
|
|
let tid = getThreadId()
|
|
|
|
|
let color = tclr[(tid mod (tclr.len() - 1))]
|
|
|
|
|
stdout.styledWrite(styleBright, fgWhite, "(thr: ", color, $tid, fgWhite, ") ")
|
|
|
|
|
color
|
|
|
|
|
try:
|
|
|
|
|
let color = printThread()
|
|
|
|
|
var i = 0
|
|
|
|
|
if vals.len() mod 2 != 0:
|
|
|
|
|
stdout.styledWrite(color, vals[i])
|
|
|
|
|
i.inc()
|
|
|
|
|
while i + 1 < vals.len():
|
|
|
|
|
stdout.styledWrite(color, vals[i], fgDefault, vals[i+1])
|
|
|
|
|
i.inc(2)
|
|
|
|
|
stdout.styledWrite("\n")
|
|
|
|
|
except:
|
|
|
|
|
discard
|
|
|
|
|
finally:
|
|
|
|
|
discard
|
2023-09-13 13:32:23 -07:00
|
|
|
|
2023-09-12 18:33:38 -07:00
|
|
|
type
|
|
|
|
|
SharedPtr*[T] = object
|
|
|
|
|
## Shared ownership reference counting pointer.
|
2023-09-14 15:03:50 -07:00
|
|
|
container*: ptr tuple[value: T, cnt: int, manual: bool]
|
2023-09-12 18:33:38 -07:00
|
|
|
|
2023-09-14 15:21:12 -07:00
|
|
|
proc incr*[T](a: SharedPtr[T]) =
|
2023-09-13 14:42:59 -07:00
|
|
|
if a.container != nil:
|
2023-09-12 19:15:22 -07:00
|
|
|
let res = atomicAddFetch(a.cnt, 1, ATOMIC_RELAXED)
|
2023-09-13 14:42:59 -07:00
|
|
|
echoed "SharedPtr: incr: ", res
|
2023-09-12 18:33:38 -07:00
|
|
|
|
2023-09-14 15:21:12 -07:00
|
|
|
proc decr*[T](x: SharedPtr[T]) =
|
2023-09-13 12:39:26 -07:00
|
|
|
if x.container != nil:
|
2023-09-14 19:58:31 -07:00
|
|
|
let res = atomicSubFetch(addr x.container.cnt, 1, ATOMIC_RELEASE)
|
2023-09-12 18:33:38 -07:00
|
|
|
if res == 0:
|
2023-09-14 20:29:35 -07:00
|
|
|
echoed "SharedPtr: FREE: ", $x.container.pointer.repr, " cnt: ", $x.container.cnt, " tp: ", $(typeof(T))
|
2023-09-13 11:50:48 -07:00
|
|
|
when compiles(`=destroy`(x[])):
|
2023-09-13 13:32:23 -07:00
|
|
|
echoed "SharedPtr:call:child:destructor: ", $(typeof(x[]))
|
2023-09-13 11:50:48 -07:00
|
|
|
`=destroy`(x[])
|
2023-09-13 14:29:41 -07:00
|
|
|
else:
|
|
|
|
|
echoed "SharedPtr:NOT CALLED:child:destructor: ", $(typeof(x[]))
|
2023-09-13 12:39:26 -07:00
|
|
|
deallocShared(x.container)
|
2023-09-14 15:21:12 -07:00
|
|
|
# x.container = nil # alas
|
2023-09-12 18:33:38 -07:00
|
|
|
else:
|
2023-09-14 20:29:35 -07:00
|
|
|
echoed "SharedPtr: decr: ", $x.container.pointer.repr, " cnt: ", $x.container.cnt, " tp: ", $(typeof(T))
|
2023-09-12 18:33:38 -07:00
|
|
|
|
2023-09-14 13:52:35 -07:00
|
|
|
proc release*[T](x: var SharedPtr[T]) =
|
2023-09-13 13:32:23 -07:00
|
|
|
echoed "SharedPtr: release: ", $(typeof(T))
|
2023-09-12 20:19:57 -07:00
|
|
|
x.decr()
|
2023-09-13 12:39:26 -07:00
|
|
|
x.container = nil
|
2023-09-12 20:19:57 -07:00
|
|
|
|
2023-09-12 18:33:38 -07:00
|
|
|
proc `=destroy`*[T](x: var SharedPtr[T]) =
|
2023-09-14 15:03:50 -07:00
|
|
|
if x.container != nil and not x.container.manual:
|
2023-09-14 20:29:35 -07:00
|
|
|
echoed "SharedPtr: destroy: ", $x.container.pointer.repr, " cnt: ", $x.container.cnt, " tp: ", $(typeof(T))
|
2023-09-14 15:03:50 -07:00
|
|
|
decr(x)
|
2023-09-12 18:33:38 -07:00
|
|
|
|
|
|
|
|
proc `=dup`*[T](src: SharedPtr[T]): SharedPtr[T] =
|
2023-09-14 15:03:50 -07:00
|
|
|
if src.container != nil and not src.container.manual:
|
2023-09-13 15:07:13 -07:00
|
|
|
echoed "SharedPtr: dup: ", src.container.pointer.repr, " cnt: ", src.container.cnt, " tp: ", $(typeof(T))
|
2023-09-12 18:50:38 -07:00
|
|
|
discard atomicAddFetch(src.cnt, 1, ATOMIC_RELAXED)
|
2023-09-13 12:39:26 -07:00
|
|
|
result.container = src.container
|
2023-09-13 12:26:29 -07:00
|
|
|
result.cnt = src.cnt
|
2023-09-12 18:33:38 -07:00
|
|
|
|
|
|
|
|
proc `=copy`*[T](dest: var SharedPtr[T], src: SharedPtr[T]) =
|
2023-09-14 15:03:50 -07:00
|
|
|
if src.container != nil and not src.container.manual:
|
2023-09-13 12:39:26 -07:00
|
|
|
# echo "SharedPtr: copy: ", src.container.pointer.repr
|
|
|
|
|
discard atomicAddFetch(addr src.container.cnt, 1, ATOMIC_RELAXED)
|
2023-09-14 20:29:35 -07:00
|
|
|
echoed "SharedPtr: copy:src: ", $src.container.pointer.repr, " cnt: ", $src.container.cnt, " tp: ", $(typeof(T))
|
2023-09-13 14:42:59 -07:00
|
|
|
if dest.container != nil:
|
2023-09-14 20:29:35 -07:00
|
|
|
echoed "SharedPtr: copy:dest: ", $dest.container.pointer.repr, " cnt: ", $dest.container.cnt, " tp: ", $(typeof(T))
|
2023-09-12 18:33:38 -07:00
|
|
|
`=destroy`(dest)
|
2023-09-13 12:39:26 -07:00
|
|
|
dest.container = src.container
|
2023-09-12 18:33:38 -07:00
|
|
|
|
2023-09-14 15:03:50 -07:00
|
|
|
proc newSharedPtr*[T](val: sink Isolated[T], manualCount: Natural = 0): 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-13 12:39:26 -07:00
|
|
|
result.container = cast[typeof(result.container)](allocShared(sizeof(result.container[])))
|
2023-09-14 15:03:50 -07:00
|
|
|
result.container.cnt = max(1, manualCount)
|
|
|
|
|
result.container.manual = manualCount > 0
|
2023-09-13 12:39:26 -07:00
|
|
|
result.container.value = extract val
|
2023-09-14 20:29:35 -07:00
|
|
|
echoed "SharedPtr: alloc: ", $result.container.pointer.repr, " cnt: ", $result.container.cnt, " tp: ", $(typeof(T))
|
2023-09-12 18:33:38 -07:00
|
|
|
|
|
|
|
|
template newSharedPtr*[T](val: T): SharedPtr[T] =
|
|
|
|
|
newSharedPtr(isolate(val))
|
|
|
|
|
|
2023-09-14 15:03:50 -07:00
|
|
|
proc newSharedPtr*[T](t: typedesc[T], manualCount: Natural = 0): SharedPtr[T] =
|
2023-09-12 18:33:38 -07:00
|
|
|
## Returns a shared pointer. It is not initialized,
|
2023-09-14 15:03:50 -07:00
|
|
|
## ownership of the object by reference counting.
|
2023-09-13 12:39:26 -07:00
|
|
|
result.container = cast[typeof(result.container)](allocShared0(sizeof(result.container[])))
|
2023-09-14 15:03:50 -07:00
|
|
|
result.container.cnt = max(1, manualCount)
|
|
|
|
|
result.container.manual = manualCount > 0
|
2023-09-14 20:29:35 -07:00
|
|
|
echoed "SharedPtr: alloc: ", $result.container.pointer.repr, " cnt: ", $result.container.cnt, " tp: ", $(typeof(T))
|
2023-09-12 18:33:38 -07:00
|
|
|
|
|
|
|
|
proc isNil*[T](p: SharedPtr[T]): bool {.inline.} =
|
2023-09-13 12:39:26 -07:00
|
|
|
p.container == nil
|
2023-09-12 18:33:38 -07:00
|
|
|
|
|
|
|
|
proc `[]`*[T](p: SharedPtr[T]): var T {.inline.} =
|
|
|
|
|
checkNotNil(p)
|
2023-09-13 12:39:26 -07:00
|
|
|
p.container.value
|
2023-09-12 18:33:38 -07:00
|
|
|
|
|
|
|
|
proc `[]=`*[T](p: SharedPtr[T], val: sink Isolated[T]) {.inline.} =
|
|
|
|
|
checkNotNil(p)
|
2023-09-13 12:39:26 -07:00
|
|
|
p.container[] = 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.} =
|
2023-09-13 13:19:38 -07:00
|
|
|
if p.container == nil: "nil\"\""
|
|
|
|
|
else: p.container.pointer.repr & "\"" & $p.container[] & "\""
|