macros: add onStart and onStop
The onStart and onStop macros will be called as actors start and stop. This can be used to call `quit`, since the async dispatcher will run empty and raise an error otherwise.
This commit is contained in:
parent
300f0169bb
commit
50afa0107f
|
@ -11,6 +11,8 @@ export dataspaces.Facet
|
||||||
export dataspaces.FieldId
|
export dataspaces.FieldId
|
||||||
export dataspaces.Fields
|
export dataspaces.Fields
|
||||||
export dataspaces.addEndpoint
|
export dataspaces.addEndpoint
|
||||||
|
export dataspaces.addStartScript
|
||||||
|
export dataspaces.addStopScript
|
||||||
export dataspaces.defineObservableProperty
|
export dataspaces.defineObservableProperty
|
||||||
export dataspaces.generateId
|
export dataspaces.generateId
|
||||||
export dataspaces.hash
|
export dataspaces.hash
|
||||||
|
@ -178,4 +180,4 @@ template syndicate*(name: string; dataspaceBody: untyped): untyped =
|
||||||
proc bootProc(rootFacet: Facet) =
|
proc bootProc(rootFacet: Facet) =
|
||||||
proc getCurrentFacet(): Facet {.inject, used.} = rootFacet
|
proc getCurrentFacet(): Facet {.inject, used.} = rootFacet
|
||||||
dataspaceBody
|
dataspaceBody
|
||||||
waitFor bootModule(name, bootProc)
|
asyncCheck bootModule(name, bootProc)
|
||||||
|
|
|
@ -253,6 +253,8 @@ proc abort(facet; emitPatches: bool) =
|
||||||
for child in facet.children.values:
|
for child in facet.children.values:
|
||||||
child.abort(emitPatches)
|
child.abort(emitPatches)
|
||||||
facet.retractAssertionsAndSubscriptions(emitPatches)
|
facet.retractAssertionsAndSubscriptions(emitPatches)
|
||||||
|
for s in facet.stopScripts: s(facet)
|
||||||
|
# call stopScripts immediately
|
||||||
|
|
||||||
proc enqueueScriptAction(actor; action: Action) =
|
proc enqueueScriptAction(actor; action: Action) =
|
||||||
actor.pendingActions.add(action)
|
actor.pendingActions.add(action)
|
||||||
|
@ -342,10 +344,13 @@ proc scheduleScript*(facet; prio: Priority; script: Script[void]) =
|
||||||
proc scheduleScript*(facet; script: Script[void]) =
|
proc scheduleScript*(facet; script: Script[void]) =
|
||||||
facet.actor.scheduleTask(pNormal, facet.wrap(script))
|
facet.actor.scheduleTask(pNormal, facet.wrap(script))
|
||||||
|
|
||||||
proc addStartScript(facet; s: Script[void]) =
|
proc addStartScript*(facet; s: Script[void]) =
|
||||||
facet.ensureFacetSetup("onStart")
|
facet.ensureFacetSetup("onStart")
|
||||||
facet.scheduleScript(pNormal, s)
|
facet.scheduleScript(pNormal, s)
|
||||||
|
|
||||||
|
proc addStopScript*(facet; s: Script[void]) =
|
||||||
|
facet.stopScripts.add(s)
|
||||||
|
|
||||||
proc addFacet(actor; parentFacet: Option[Facet]; bootScript: Script[void]; checkInScript = false) =
|
proc addFacet(actor; parentFacet: Option[Facet]; bootScript: Script[void]; checkInScript = false) =
|
||||||
if checkInScript and parentFacet.isSome:
|
if checkInScript and parentFacet.isSome:
|
||||||
assert parentFacet.get.inScript
|
assert parentFacet.get.inScript
|
||||||
|
@ -530,6 +535,8 @@ proc step(g: Ground) =
|
||||||
if g.dataspace.runTasks():
|
if g.dataspace.runTasks():
|
||||||
asyncdispatch.callSoon: step(g)
|
asyncdispatch.callSoon: step(g)
|
||||||
else:
|
else:
|
||||||
|
for actor in g.dataspace.actors.values:
|
||||||
|
terminate(actor, false)
|
||||||
for sh in g.stopHandlers:
|
for sh in g.stopHandlers:
|
||||||
sh(g.dataspace)
|
sh(g.dataspace)
|
||||||
reset g.stopHandlers
|
reset g.stopHandlers
|
||||||
|
|
|
@ -7,15 +7,17 @@ import syndicate
|
||||||
const
|
const
|
||||||
BoxState = RecordClass(label: symbol"box-state", arity: 1)
|
BoxState = RecordClass(label: symbol"box-state", arity: 1)
|
||||||
SetBox = RecordClass(label: symbol"set-box", arity: 1)
|
SetBox = RecordClass(label: symbol"set-box", arity: 1)
|
||||||
|
# TODO: hide RecordClass behind Assertion and Message types
|
||||||
|
|
||||||
syndicate "test_dsl":
|
syndicate "test_dsl":
|
||||||
|
|
||||||
spawn "box":
|
spawn "box":
|
||||||
field(currentValue, int, 0)
|
field(currentValue, int, 0)
|
||||||
assert(BoxState, currentValue)
|
assert(BoxState, currentValue.get)
|
||||||
stopIf currentValue.get == 10:
|
stopIf currentValue.get == 10:
|
||||||
echo "box: terminating"
|
echo "box: terminating"
|
||||||
onMessage(SetBox) do (newValue: int):
|
onMessage(SetBox) do (newValue: int):
|
||||||
|
# The SetBox message is unpacked to `newValue: int`
|
||||||
echo "box: taking on new value ", newValue
|
echo "box: taking on new value ", newValue
|
||||||
currentValue.set(newValue)
|
currentValue.set(newValue)
|
||||||
|
|
||||||
|
@ -27,3 +29,9 @@ syndicate "test_dsl":
|
||||||
send(SetBox, v+1)
|
send(SetBox, v+1)
|
||||||
onRetracted(BoxState) do (_):
|
onRetracted(BoxState) do (_):
|
||||||
echo "client: box state disappeared"
|
echo "client: box state disappeared"
|
||||||
|
onStop:
|
||||||
|
quit(0) # Quit explicitly rather than let the dispatcher run empty.
|
||||||
|
|
||||||
|
runForever()
|
||||||
|
# The dataspace is driven by the async dispatcher.
|
||||||
|
# Without `runForever` this module would exit immediately.
|
||||||
|
|
Loading…
Reference in New Issue