# 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, "cannot drop WireSymbol at the wrong Membrane" 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, count: 1) mem.byOid[result.oid] = result mem.byRef[result.`ref`] = result when not defined(release): result.mem = mem