syndicate-nim/src/syndicate/membranes.nim

50 lines
1.4 KiB
Nim

# SPDX-FileCopyrightText: ☭ 2022 Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/[hashes, options, tables]
from ./actors import Ref, hash
from ./protocols/sturdy import Oid
proc hash(r: Ref): Hash = !$(r.relay.hash !& r.target.unsafeAddr.hash)
type
Membrane* = object
## Bidirectional mapping between `Oid` and `Ref` values.
byOid: Table[Oid, WireSymbol]
byRef: Table[Ref, WireSymbol]
WireSymbol* = ref object
oid: Oid
`ref`: Ref
count: int
when not defined(release):
mem: Membrane
proc oid*(sym: WireSymbol): Oid = sym.oid
proc `ref`*(sym: WireSymbol): Ref = sym.ref
proc grab*(mem: Membrane; key: Oid|Ref): WireSymbol =
## Grab a `WireSymbol` from a `Membrane`.
result =
when key is Oid: mem.byOid.getOrDefault(key)
elif key is Ref: mem.byRef.getOrDefault(key)
else: {.error.}
if not result.isNil: inc result.count
proc drop*(mem: var Membrane; sym: WireSymbol) =
## Drop a `WireSymbol` from a `Membrane`.
when not defined(release): assert sym.mem == mem
assert sym.count > 0
dec sym.count
if sym.count < 1:
mem.byOid.del sym.oid
mem.byRef.del sym.`ref`
proc newWireSymbol*(mem: var Membrane; o: Oid; r: Ref): WireSymbol =
## Allocate a `WireSymbol` at a `Membrane`.
result = WireSymbol(oid: o, `ref`: r)
when not defined(release): result.mem = mem
mem.byOid[result.oid] = result
mem.byRef[result.`ref`] = result