Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active October 20, 2017 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenwebb/834e367697da821ca2b207552f761018 to your computer and use it in GitHub Desktop.
Save kenwebb/834e367697da821ca2b207552f761018 to your computer and use it in GitHub Desktop.
Sync vs Async
<?xml version="1.0" encoding="UTF-8"?>
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Fri Oct 20 2017 09:58:26 GMT-0400 (EDT)-->
<XholonWorkbook>
<Notes><![CDATA[
Xholon
------
Title: Sync vs Async
Description:
Url: http://www.primordion.com/Xholon/gwt/
InternalName: 834e367697da821ca2b207552f761018
Keywords:
My Notes
--------
sync = synchronous interaction = a functional approach
async = asynchronous interaction = a non-functional approach
What is the accepted name for the non-functional approach?
- this is the standard approach in ROOM/ObjecTime/eTrice/Xholon
In this workbook, I will write the same app using both of these approaches.
The app will perform a number of arithmetic calculations, and will produce a single result.
The sync approach will use Xholon synchronous messaging.
The async approach will use Xholon asynchronous messaging.
(((3 + 2) * 6) - (7 + 1))
]]></Notes>
<_-.XholonClass xmlns:xi="http://www.w3.org/2001/XInclude">
<PhysicalSystem/>
<ArithFunc>
<!-- a function that adds 2 numbers -->
<AddFunc superClass="Script"/>
<!-- a function that subtracts 2 numbers -->
<SubFunc superClass="Script"/>
<!-- a function that multiplies 2 numbers -->
<MulFunc superClass="Script"/>
</ArithFunc>
<Functions/>
<!-- MathML Mechanism -->
<xi:include href="config/mech/mathml/MathMLEntity.xml"/>
<xi:include href="config/mech/mathml/MathML_ClassDetails.xml"/>
</_-.XholonClass>
<xholonClassDetails>
<AddFunc><DefaultContent>
var me, beh = {
postConfigure: function() {
me = this.cnode;
me.println(me.name());
},
processReceivedSyncMessage: function(msg) {
var data = msg.data;
me.println(data);
return data[0] + data[1];
}
}
</DefaultContent></AddFunc>
<SubFunc><DefaultContent>
var me, beh = {
postConfigure: function() {
me = this.cnode;
me.println(me.name());
},
processReceivedSyncMessage: function(msg) {
var data = msg.data;
me.println(data);
return data[0] - data[1];
}
}
</DefaultContent></SubFunc>
<MulFunc><DefaultContent>
var me, beh = {
postConfigure: function() {
me = this.cnode;
me.println(me.name());
},
processReceivedSyncMessage: function(msg) {
var data = msg.data;
me.println(data);
return data[0] * data[1];
}
}
</DefaultContent></MulFunc>
</xholonClassDetails>
<PhysicalSystem>
<TestNullApproach implName="org.primordion.xholon.base.Behavior_gwtjs">
var me, beh = {
postConfigure: function() {
me = this.cnode;
me.println(me.name());
me.println("(((3 + 2) * 6) - (7 + 1)) = " + (((3 + 2) * 6) - (7 + 1)));
}
}
</TestNullApproach>
<TestMathmlApproach>
<math>
<apply>
<minus/>
<apply>
<times/>
<apply>
<plus/>
<cn>3</cn>
<cn>2</cn>
</apply>
<cn>6</cn>
</apply>
<apply>
<plus/>
<cn>7</cn>
<cn>1</cn>
</apply>
</apply>
</math>
</TestMathmlApproach>
<TestSyncApproach implName="org.primordion.xholon.base.Behavior_gwtjs">
var me, beh = {
postConfigure: function() {
me = this.cnode;
me.println(me.name());
me.println("(((3 + 2) * 6) - (7 + 1)) = " + (((3 + 2) * 6) - (7 + 1)));
me.addF = me.next().first();
me.subF = me.addF.next();
me.mulF = me.subF.next();
},
act: function() {
// 1
var result1 = me.addF.call(101, [3,2], me);
me.println(result1.data);
$wnd.console.log(result1.data);
// 2
var result2 = me.addF.call(101, [7,1], me);
me.println(result2.data);
$wnd.console.log(result2.data);
// 3
var result3 = me.mulF.call(101, [result1.data, 6], me);
me.println(result3.data);
$wnd.console.log(result3.data);
// 4
var result4 = me.subF.call(101, [result3.data, result2.data], me);
me.println(result4.data);
$wnd.console.log(result4.data);
}
}
</TestSyncApproach>
<!-- a set of functions
TestSyncApproach requires that this subtree be immediately after it
-->
<Functions>
<AddFunc/>
<SubFunc/>
<MulFunc/>
</Functions>
<!-- TODO this will probably be similar to a Petri Net (PN)
Processing is synchronized by waiting for all required values to be ready.
It should contain three sets:
- a set of functions
- a set of values (passive objects, Petri Net places)
- a set of synchronizing nodes (these call the functions, Petri Net transitions)
-->
<TestAsyncApproach implName="org.primordion.xholon.base.Behavior_gwtjs">
var me, beh = {
postConfigure: function() {
me = this.cnode;
me.println(me.name());
}
}
</TestAsyncApproach>
<!-- structure the problem as a Petri Net, but it won't do the correct calculations
(((3 + 2) * 6) - (7 + 1))
-->
<TestPetriNetApproach>
<!-- KINETICS_CUSTOM = 6; use the PetriNetCusomProcessor node to do calculations -->
<PetriNet roleName="arithPN" kineticsType="6">
<QueueTransitions/>
<Places>
<!-- initial values -->
<PlacePN roleName="p1" token="3"/>
<PlacePN roleName="p2" token="2"/>
<PlacePN roleName="p3" token="6"/>
<PlacePN roleName="p4" token="7"/>
<PlacePN roleName="p5" token="1"/>
<!-- intermediate values -->
<PlacePN roleName="p11"/>
<PlacePN roleName="p12"/>
<PlacePN roleName="p13"/>
<!-- final result value -->
<PlacePN roleName="p101"/>
</Places>
<Transitions>
<TransitionPN roleName="t1Add">
<InputArcs>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p1']"/>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p2']"/>
</InputArcs>
<OutputArcs>
<OutputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p11']"/>
</OutputArcs>
</TransitionPN>
<TransitionPN roleName="t2Add">
<InputArcs>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p4']"/>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p5']"/>
</InputArcs>
<OutputArcs>
<OutputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p12']"/>
</OutputArcs>
</TransitionPN>
<TransitionPN roleName="t3Mul">
<InputArcs>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p11']"/>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p3']"/>
</InputArcs>
<OutputArcs>
<OutputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p13']"/>
</OutputArcs>
</TransitionPN>
<TransitionPN roleName="t4Sub">
<InputArcs>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p13']"/>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p12']"/>
</InputArcs>
<OutputArcs>
<OutputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p101']"/>
</OutputArcs>
</TransitionPN>
</Transitions>
</PetriNet>
<PetriNetCustomProcessor implName="org.primordion.xholon.base.Behavior_gwtjs">
var me, trns, funcs, beh = {
postConfigure: function() {
me = this.cnode;
me.println(me.name());
trns = me.xpath("../PetriNet/Transitions/TransitionPN");
funcs = me.xpath("../../Functions");
},
act: function() {
if (trns) {
me.println(trns.name());
var inarcs = trns.first();
var outarcs = inarcs.next();
var inarc = inarcs.first();
var inval1 = inarc.links(false,true)[0].reffedNode.val();
var inval2 = inarc.next().links(false,true)[0].reffedNode.val();
var outarc = outarcs.first();
var func = null;
switch (trns.role()) {
case "t1Add":
case "t2Add":
func = funcs.xpath("AddFunc");
break;
case "t3Mul":
func = funcs.xpath("MulFunc");
break;
case "t4Sub":
func = funcs.xpath("SubFunc");
break;
default: break;
}
var result = func.call(101, [inval1,inval2], me);
outarc.links(false,true)[0].reffedNode.val(result.data);
trns = trns.next();
}
}
}
</PetriNetCustomProcessor>
</TestPetriNetApproach>
<TestPetriNetFuncApproach>
<!-- KINETICS_FUNCTION = 11; auto invoke functions -->
<PetriNet roleName="arithPN" kineticsType="11">
<QueueTransitions shouldShuffle="false"/>
<Places>
<!-- initial values -->
<PlacePN roleName="p1" token="3"/>
<PlacePN roleName="p2" token="2"/>
<PlacePN roleName="p3" token="6"/>
<PlacePN roleName="p4" token="7"/>
<PlacePN roleName="p5" token="1"/>
<!-- intermediate values -->
<PlacePN roleName="p11"/>
<PlacePN roleName="p12"/>
<PlacePN roleName="p13"/>
<!-- final result value -->
<PlacePN roleName="p101"/>
</Places>
<Transitions>
<TransitionPN roleName="t1Add" functionXPath="ancestor::PhysicalSystem/Functions/AddFunc">
<InputArcs>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p1']"/>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p2']"/>
</InputArcs>
<OutputArcs>
<OutputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p11']"/>
</OutputArcs>
</TransitionPN>
<TransitionPN roleName="t2Add" functionXPath="ancestor::PhysicalSystem/Functions/AddFunc">
<InputArcs>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p4']"/>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p5']"/>
</InputArcs>
<OutputArcs>
<OutputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p12']"/>
</OutputArcs>
</TransitionPN>
<TransitionPN roleName="t3Mul" functionXPath="ancestor::PhysicalSystem/Functions/MulFunc">
<InputArcs>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p11']"/>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p3']"/>
</InputArcs>
<OutputArcs>
<OutputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p13']"/>
</OutputArcs>
</TransitionPN>
<TransitionPN roleName="t4Sub" functionXPath="ancestor::PhysicalSystem/Functions/SubFunc">
<InputArcs>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p13']"/>
<InputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p12']"/>
</InputArcs>
<OutputArcs>
<OutputArc weight="1" connector="ancestor::PetriNet/Places/PlacePN[@roleName='p101']"/>
</OutputArcs>
</TransitionPN>
</Transitions>
</PetriNet>
</TestPetriNetFuncApproach>
<!--
Capture interactions between nodes, and create a sequence diagram (also called a Message Sequence Chart (MSC)).
Once the code has run for one or more timesteps, click on View > Interactions .
The following (or something similar, should appear in a new tab:
title Sync vs Async
# To view sequence diagram, paste this text into http://www.websequencediagrams.com/
# Created by: Xholon http://www.primordion.com/Xholon/
# Date: 1508441050977 Thu Oct 19 15:24:10 GMT-400 2017
testSyncApproach_62->addFunc_64: 3,2
addFunc_64->testSyncApproach_62: 5
testSyncApproach_62->addFunc_64: 7,1
addFunc_64->testSyncApproach_62: 8
testSyncApproach_62->mulFunc_66: 5,6
mulFunc_66->testSyncApproach_62: 30
testSyncApproach_62->subFunc_65: 30,8
subFunc_65->testSyncApproach_62: 22
petriNetCustomProcessor_106->addFunc_64: 3,2
addFunc_64->petriNetCustomProcessor_106: 5
testSyncApproach_62->addFunc_64: 3,2
addFunc_64->testSyncApproach_62: 5
testSyncApproach_62->addFunc_64: 7,1
addFunc_64->testSyncApproach_62: 8
testSyncApproach_62->mulFunc_66: 5,6
mulFunc_66->testSyncApproach_62: 30
testSyncApproach_62->subFunc_65: 30,8
subFunc_65->testSyncApproach_62: 22
petriNetCustomProcessor_106->addFunc_64: 7,1
addFunc_64->petriNetCustomProcessor_106: 8
testSyncApproach_62->addFunc_64: 3,2
addFunc_64->testSyncApproach_62: 5
testSyncApproach_62->addFunc_64: 7,1
addFunc_64->testSyncApproach_62: 8
testSyncApproach_62->mulFunc_66: 5,6
mulFunc_66->testSyncApproach_62: 30
testSyncApproach_62->subFunc_65: 30,8
subFunc_65->testSyncApproach_62: 22
petriNetCustomProcessor_106->mulFunc_66: 5,6
mulFunc_66->petriNetCustomProcessor_106: 30
testSyncApproach_62->addFunc_64: 3,2
addFunc_64->testSyncApproach_62: 5
testSyncApproach_62->addFunc_64: 7,1
addFunc_64->testSyncApproach_62: 8
testSyncApproach_62->mulFunc_66: 5,6
mulFunc_66->testSyncApproach_62: 30
testSyncApproach_62->subFunc_65: 30,8
subFunc_65->testSyncApproach_62: 22
petriNetCustomProcessor_106->subFunc_65: 30,8
subFunc_65->petriNetCustomProcessor_106: 22
Note: I manually deleteted the signal 101 from each line.
-->
<InteractionsViewer/>
</PhysicalSystem>
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml,
<!-- Generated by graphviz version 2.28.0 (20140111.2315)
-->
<!-- Title: PhysicalSystem Pages: 1 -->
<svg width="243pt" height="141pt"
viewBox="0.00 0.00 243.00 140.80" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="PhysicalSystem" class="graph" transform="scale(1 1) rotate(0) translate(4 136.8)">
<title>PhysicalSystem</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-136.8 239,-136.8 239,4 -4,4"/>
<text text-anchor="middle" x="117.5" y="-8.2" font-family="Courier New" font-size="14.00">PhysicalSystem</text>
<!-- Test -->
<g id="PhysicalSystem/Test" class="node"><title>Test</title>
<polygon fill="#f0f8ff" stroke="black" points="126,-132.8 72,-132.8 72,-96.8 126,-96.8 126,-132.8"/>
<text text-anchor="middle" x="99" y="-110.6" font-family="Courier New" font-size="14.00">Test</text>
</g>
<!-- AddF -->
<g id="PhysicalSystem/Functions/AddF" class="node"><title>AddF</title>
<polygon fill="#f0f8ff" stroke="black" points="54,-60.8 0,-60.8 0,-24.8 54,-24.8 54,-60.8"/>
<text text-anchor="middle" x="27" y="-38.6" font-family="Courier New" font-size="14.00">AddF</text>
</g>
<!-- Test&#45;&gt;AddF -->
<g id="PhysicalSystem_edge1" class="edge"><title>Test&#45;&gt;AddF</title>
<path fill="none" stroke="black" d="M81.2022,-96.4966C72.396,-87.935 61.6179,-77.4562 51.9989,-68.1045"/>
<polygon fill="black" stroke="black" points="44.593,-60.9043 54.8999,-64.6487 48.178,-64.3897 51.763,-67.8751 51.763,-67.8751 51.763,-67.8751 48.178,-64.3897 48.6261,-71.1016 44.593,-60.9043 44.593,-60.9043"/>
</g>
<!-- SubF -->
<g id="PhysicalSystem/Functions/SubF" class="node"><title>SubF</title>
<polygon fill="#f0f8ff" stroke="black" points="126,-60.8 72,-60.8 72,-24.8 126,-24.8 126,-60.8"/>
<text text-anchor="middle" x="99" y="-38.6" font-family="Courier New" font-size="14.00">SubF</text>
</g>
<!-- Test&#45;&gt;SubF -->
<g id="PhysicalSystem_edge2" class="edge"><title>Test&#45;&gt;SubF</title>
<path fill="none" stroke="black" d="M99,-96.4966C99,-88.7827 99,-79.5125 99,-70.9124"/>
<polygon fill="black" stroke="black" points="99,-60.9043 103.5,-70.9043 99,-65.9043 99.0001,-70.9043 99.0001,-70.9043 99.0001,-70.9043 99,-65.9043 94.5001,-70.9044 99,-60.9043 99,-60.9043"/>
</g>
<!-- MulF -->
<g id="PhysicalSystem/Functions/MulF" class="node"><title>MulF</title>
<polygon fill="#f0f8ff" stroke="black" points="198,-60.8 144,-60.8 144,-24.8 198,-24.8 198,-60.8"/>
<text text-anchor="middle" x="171" y="-38.6" font-family="Courier New" font-size="14.00">MulF</text>
</g>
<!-- Test&#45;&gt;MulF -->
<g id="PhysicalSystem_edge3" class="edge"><title>Test&#45;&gt;MulF</title>
<path fill="none" stroke="black" d="M116.798,-96.4966C125.604,-87.935 136.382,-77.4562 146.001,-68.1045"/>
<polygon fill="black" stroke="black" points="153.407,-60.9043 149.374,-71.1016 149.822,-64.3897 146.237,-67.8751 146.237,-67.8751 146.237,-67.8751 149.822,-64.3897 143.1,-64.6487 153.407,-60.9043 153.407,-60.9043"/>
</g>
</g>
</svg>
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient>
</XholonWorkbook>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment