syndicate-nim/src/syndicate/actors.nim

198 lines
5.2 KiB
Nim
Raw Normal View History

2023-05-06 19:09:45 +00:00
# SPDX-FileCopyrightText: ☭ Emery Hemingway
2021-09-24 19:25:47 +00:00
# SPDX-License-Identifier: Unlicense
2024-02-15 10:52:12 +00:00
import std/[deques, hashes, options, times]
import pkg/cps
2022-03-19 00:09:19 +00:00
import preserves
2021-09-24 19:25:47 +00:00
import ../syndicate/protocols/[protocol, sturdy]
2024-02-15 10:52:12 +00:00
# const traceSyndicate {.booldefine.}: bool = true
const traceSyndicate* = true
2023-07-13 13:15:13 +00:00
2024-02-15 10:52:12 +00:00
when traceSyndicate:
2023-07-13 13:15:13 +00:00
import std/streams
from std/os import getEnv
import ./protocols/trace
2024-02-15 10:52:12 +00:00
export protocol.Handle
2021-09-24 19:25:47 +00:00
type
Actor* = ref object
2024-02-15 10:52:12 +00:00
## https://synit.org/book/glossary.html#actor
2021-09-24 19:25:47 +00:00
root: Facet
2024-02-15 10:52:12 +00:00
handleAllocator: Handle
2023-07-13 13:15:13 +00:00
id: ActorId
2024-02-15 10:52:12 +00:00
when traceSyndicate:
2023-07-13 13:15:13 +00:00
traceStream: FileStream
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
Facet* = ref object
## https://synit.org/book/glossary.html#facet
actor: Actor
parent: Facet
stopHandlers: Work
state: FacetState
when traceSyndicate:
id: FacetId
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
FacetState = enum fIdle, fRunning, fStopped
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
Entity* = ref object of RootObj
## https://synit.org/book/glossary.html#entity
facet*: Facet
oid*: sturdy.Oid # oid is how Entities are identified over the wire
when traceSyndicate:
id: FacetId
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
Cap* {.final, preservesEmbedded.} = ref object of EmbeddedObj
relay*: Facet
target*: Entity
attenuation*: seq[sturdy.Caveat]
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
Turn* = ref object
## https://synit.org/book/glossary.html#turn
facet: Facet
entity: Entity
event: Option[protocol.Event]
work: Work
when traceSyndicate:
desc: TurnDescription
2023-07-13 13:15:13 +00:00
2024-02-15 10:52:12 +00:00
Work = Deque[Cont]
2023-07-13 13:15:13 +00:00
2024-02-15 10:52:12 +00:00
Cont* = ref object of Continuation
facet: Facet
turn: Turn
2021-09-24 19:25:47 +00:00
using
actor: Actor
facet: Facet
2024-02-15 10:52:12 +00:00
entity: Entity
cap: Cap
turn: Turn
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
proc hash*(facet): Hash = facet.unsafeAddr.hash
proc hash*(cap): Hash = cap.unsafeAddr.hash
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
proc newFacet(actor: Actor; parent: Facet): Facet =
result = Facet(
actor: actor,
parent: parent,
)
when traceSyndicate:
if not parent.isNil:
result.id = parent.id
inc(result.id.register)
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
proc newActor(name: string): Actor =
result = Actor(id: name.toPreserves)
result.root = newFacet(result, nil)
when traceSyndicate:
let path = getEnv("SYNDICATE_TRACE_FILE", "")
case path
of "": discard
of "-": result.traceStream = newFileStream(stderr)
else: result.traceStream = openFileStream(path, fmWrite)
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
when traceSyndicate:
proc trace(actor: Actor; act: ActorActivation) =
if not actor.traceStream.isNil:
var entry = TraceEntry(
timestamp: getTime().toUnixFloat(),
actor: actor.id,
item: act,
)
actor.traceStream.writeLine($entry.toPreserves)
proc traceTarget(cap): trace.Target =
Target(
actor: cap.relay.actor.id,
facet: cap.relay.id,
oid: cap.target.oid.toPreserves,
)
proc startActor(actor: Actor) =
when traceSyndicate:
var act = ActorActivation(orkind: ActorActivationKind.start)
trace(actor, act)
proc stopActor(actor: Actor) =
when traceSyndicate:
var act = ActorActivation(orkind: ActorActivationKind.stop)
trace(actor, act)
proc bootActor*(name: string, c: Cont) =
let actor = newActor(name)
startActor(actor)
proc queue*(t: Turn; c: Cont) =
assert not c.facet.isNil
t.work.addLast(c)
template syndicate*(prc: typed): untyped =
cps(Cont, prc)
proc activeFacet*(c: Cont): Facet {.cpsVoodoo.} =
## Return the active `Facet` within a `{.syndicate.}` context.
assert not c.facet.isNil
c.facet
proc activeTurn*(c: Cont): Turn {.cpsVoodoo.} =
## Return the active `Turn` within a `{.syndicate.}` context.
assert not c.turn.isNil
c.turn
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
type
AssertionRef* = ref object
value*: Value
# if the Enity methods take a Value object then the generated
# C code has "redefinition of struct" problems when orc is enabled
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
method publish*(e: Entity; turn: Turn; v: AssertionRef; h: Handle) {.base.} = discard
method retract*(e: Entity; turn: Turn; h: Handle) {.base.} = discard
method message*(e: Entity; turn: Turn; v: AssertionRef) {.base.} = discard
method sync*(e: Entity; turn: Turn; peer: Cap) {.base.} = discard
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
proc newCap*(f: Facet; e: Entity): Cap =
Cap(relay: f, target: e)
2021-09-24 19:25:47 +00:00
proc nextHandle(facet: Facet): Handle =
2024-02-15 10:52:12 +00:00
inc(facet.actor.handleAllocator)
facet.actor.handleAllocator
proc publish*(turn: Turn; cap: Cap; val: Value): Handle =
result = turn.facet.nextHandle()
when traceSyndicate:
2023-12-31 17:15:06 +00:00
var act = ActionDescription(orKind: ActionDescriptionKind.enqueue)
2024-02-15 10:52:12 +00:00
act.enqueue.event = TargetedTurnEvent(
target: cap.traceTarget,
detail: trace.TurnEvent(orKind: trace.TurnEventKind.assert)
)
2023-12-31 17:15:06 +00:00
act.enqueue.event.detail = trace.TurnEvent(orKind: TurnEventKind.assert)
2024-02-15 10:52:12 +00:00
act.enqueue.event.detail.assert = TurnEventAssert(
assertion: AssertionDescription(orKind: AssertionDescriptionKind.value),
handle: result,
)
act.enqueue.event.detail.assert.assertion.value.value = val
2023-07-13 13:15:13 +00:00
turn.desc.actions.add act
2024-02-15 10:52:12 +00:00
proc retract*(t: Turn; h: Handle) =
discard
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
proc message*(t: Turn; cap: Cap; val: Value) =
discard
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
proc sync*(t: Turn) =
discard
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
proc publish*(cap: Cap; val: Value): Handle {.syndicate.} =
publish(activeTurn(), cap, val)
2022-05-21 18:21:02 +00:00
2024-02-15 10:52:12 +00:00
proc retract*(h: Handle) {.syndicate.} =
activeTurn().retract(h)
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
proc message*(cap: Cap; val: Value) {.syndicate.} =
activeTurn().message(cap, val)
2021-09-24 19:25:47 +00:00
2024-02-15 10:52:12 +00:00
proc sync*() {.syndicate.} =
activeTurn().sync()