Skip to content

Commit

Permalink
-F: deferred execution and test case
Browse files Browse the repository at this point in the history
  • Loading branch information
diclogic committed Oct 3, 2015

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
1 parent a37ee99 commit 68183cd
Showing 10 changed files with 320 additions and 48 deletions.
4 changes: 2 additions & 2 deletions src/Cocktail.NET.sln
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Launcher", "Launcher\Launch
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demos", "Demos\Demos.csproj", "{C318BDB0-D222-47E4-8839-017459FE48F2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core.Aux", "Core.Aux", "{BBFA7810-3C6F-4470-BD53-E540A01DCE30}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Aux", "_Aux", "{BBFA7810-3C6F-4470-BD53-E540A01DCE30}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cocktail.System", "Cocktail.System\Cocktail.System.csproj", "{4C9E24DA-5B89-4785-889A-15AC228598AD}"
EndProject
@@ -145,10 +145,10 @@ Global
GlobalSection(NestedProjects) = preSolution
{D42AA6CC-660E-48BA-921D-63BA35847DD1} = {E4301CC1-92B7-452E-8A22-67B7179C1A9A}
{EDC79724-FBA0-4FD4-8EAD-6DC042175DCF} = {E4301CC1-92B7-452E-8A22-67B7179C1A9A}
{B6DCD891-699A-4E04-98BA-565C9C7D8A64} = {E4301CC1-92B7-452E-8A22-67B7179C1A9A}
{9DD077F4-2628-477A-82D3-8738EB24B29B} = {F5EDFC49-CA10-489C-9917-33D6575B3738}
{D037F0C4-144B-443B-8DEC-14A0540BBC87} = {F5EDFC49-CA10-489C-9917-33D6575B3738}
{4C9E24DA-5B89-4785-889A-15AC228598AD} = {BBFA7810-3C6F-4470-BD53-E540A01DCE30}
{B6DCD891-699A-4E04-98BA-565C9C7D8A64} = {BBFA7810-3C6F-4470-BD53-E540A01DCE30}
{A16281B2-6010-400F-A47D-4B27BFCDA13E} = {168BA961-0ED3-4864-96B3-D1F3705C9B39}
{BF621C27-EEE8-40B4-808A-B8EC3F7F1CD2} = {168BA961-0ED3-4864-96B3-D1F3705C9B39}
EndGlobalSection
38 changes: 35 additions & 3 deletions src/Cocktail/SpaceTime.cs
Original file line number Diff line number Diff line change
@@ -72,16 +72,25 @@ RedoEntry Filter(IEnumerable<IHId> STs, IDictionary<TStateId,IHId> dict)
}
}

private struct DeferredExecution
{
public string FunctionName;
public IEnumerable<KeyValuePair<string,StateRef>> stateParams; //< can we preparse it?
public IEnumerable<object> constArgs;
}

private static IStdLib m_stdlib = InvocationBuilder.Build<IStdLib>("Cocktail");

// ========== components ===============
protected SpacetimeStorage m_storageComponent;
// =====================================

private IHIdFactory m_idFactory;
private IHTimestamp m_currentTime;
private List<RedoEntry> m_RedoList = new List<RedoEntry>();
private object m_executionLock = new object();
private SortedList<IHEvent, ExecutionFraction> m_incomingExecutions = new SortedList<IHEvent, ExecutionFraction>();
private Queue<DeferredExecution> m_deferredExecutions = new Queue<DeferredExecution>();

private IHEvent m_executingEvent;
private IHId m_pullRequestedBy = null;
protected VMState m_vm;
@@ -90,6 +99,10 @@ RedoEntry Filter(IEnumerable<IHId> STs, IDictionary<TStateId,IHId> dict)
public IHEvent LatestEvent { get { return m_currentTime.Event; } }
public TStateId StorageSID { get { return m_storageComponent.StateId; } }

// This is for execution-based replication/redundancy.
// not used yet
private SortedList<IHEvent, ExecutionFraction> m_incomingExecutions = new SortedList<IHEvent, ExecutionFraction>();


public Spacetime(IHTimestamp stamp, IHIdFactory idFactory)
:this(stamp, idFactory, Enumerable.Empty<State>())
@@ -208,7 +221,7 @@ public StateSnapshot ExportStateSnapshot(TStateId stateId)
if (state == null)
return StateSnapshot.CreateNull(stateId);

return state.Snapshot();
return state.Snapshot();
}

///// <summary>
@@ -297,15 +310,34 @@ private void ExecuteIncomingQueue()
}
}

public void DeferExecute(string funcName, IEnumerable<KeyValuePair<string, StateRef>> stateParams, params object[] constArgs)
{
DeferredExecution deferred;
deferred.FunctionName = funcName;
deferred.stateParams = stateParams;
deferred.constArgs = constArgs;
m_deferredExecutions.Enqueue(deferred);
}

public bool Execute(string funcName, IEnumerable<KeyValuePair<string, StateRef>> stateParams, params object[] constArgs)
{
if (this == null)
throw new RuntimeException("Can't find SpaceTime to execute in. Did you forgot use `WithIn` syntax");

lock (m_executionLock)
{
return ExecuteArgs(funcName, stateParams, constArgs);
var bOK = ExecuteArgs(funcName, stateParams, constArgs);
if (!bOK)
return false;

// ------------ start deferred chronon --------------
while (m_deferredExecutions.Count > 0)
{
var deferred = m_deferredExecutions.Dequeue();
ExecuteArgs(deferred.FunctionName, deferred.stateParams, deferred.constArgs);
}
}
return true;
}

protected bool ExecuteArgs(string funcName, IEnumerable<KeyValuePair<string,StateRef>> stateParams, IEnumerable<object> constArgs)
17 changes: 17 additions & 0 deletions src/Cocktail/StateTrigger.cs
Original file line number Diff line number Diff line change
@@ -7,6 +7,12 @@

namespace Cocktail
{
public enum TriggerConditionType
{
Changed,
Customized,
}

public class StaticTriggerAttribute : Attribute
{
public Action<State> Trigger { get; set; }
@@ -40,6 +46,17 @@ public abstract partial class State
protected Dictionary<int, StateTrigger> m_triggers = new Dictionary<int,StateTrigger>();
int m_idx = 0;

// Well-known conditions
private readonly Func<State, bool> s_Changed = (s) => true;

public int RegisterInlineTrigger(TriggerConditionType type, Action<State> response)
{
if (type == TriggerConditionType.Changed)
return RegisterInlineTrigger(response, s_Changed);

throw new ArgumentOutOfRangeException("Unsupported trigger condition type");
}

public int RegisterInlineTrigger(Action<State> response, Func<State, bool> condition)
{
var tr = new StateTrigger(GetType(), response, condition);
52 changes: 22 additions & 30 deletions src/Cocktail/VMBackend/Function.cs
Original file line number Diff line number Diff line change
@@ -6,8 +6,6 @@
namespace Cocktail.Interp
{



/// <summary>
/// the class for function instances that matches a form
/// </summary>
@@ -26,17 +24,10 @@ public Function(MethodInfo methodInfo)
// TODO: need Cocktail to C# invocation adapter
m_fn = (args) => methodInfo.Invoke(null, args);
}
public void Exec(IScope scope, IEnumerable<StateParamInst> states, IEnumerable<object> constArgs)

public void Exec(object[] argList)
{
if (!Form.Check(states, constArgs))
throw new ApplicationException("The invocation doesn't match the form of the event declaration");
var argList = Form.GenArgList(scope, states, constArgs).ToArray();
m_fn(argList);

// TODO: remove it, this is not how we sync states
foreach (var stateInst in states)
stateInst.arg.Sync();
}

//public static Function Make<P1>(Action<IEnumerable<StateParam>,P1> fn)
@@ -46,6 +37,12 @@ public void Exec(IScope scope, IEnumerable<StateParamInst> states, IEnumerable<o
//}
}

public struct ArgsMetainfo
{
public object[] args;
public IEnumerable<State> rwStates;
}

public sealed class FunctionForm : IComparable<FunctionForm>, IEquatable<FunctionForm>
{
readonly Dictionary<string, StateParam> m_stateTypes;
@@ -67,16 +64,28 @@ private static string GenerateSign(IEnumerable<StateParam> stateInfo, IEnumerabl
return "";
}

public IEnumerable<object> GenArgList(IScope scope, IEnumerable<StateParamInst> states, IEnumerable<object> constArgs)
public ArgsMetainfo Fill(IScope scope, IEnumerable<StateParamInst> states, IEnumerable<object> constArgs)
{
ArgsMetainfo retval;
if (!Check(states, constArgs))
throw new ApplicationException("The invocation doesn't match the form of the event declaration");

IEnumerable<KeyValuePair<object,int>> stateArgs = states.Select<StateParamInst, StateParamInst>((spi) =>
{
StateParam sp;
if (!m_stateTypes.TryGetValue(spi.name, out sp))
throw new ApplicationException(string.Format("can't find state param '{0}'", spi.name));
var newspi = new StateParamInst() { name = sp.name, type = sp.type, index = sp.index, arg = spi.arg };
return newspi;
}).Select((spi) => ConvertCocktailToCSharp(scope, spi));
}).Select((spi) => spi.ConvertCocktailToCSharp(scope));

retval.args = SortArgList(stateArgs, constArgs).ToArray();
retval.rwStates = stateArgs.Select(kv => (State)kv.Key);
return retval;
}

public IEnumerable<object> SortArgList(IEnumerable<KeyValuePair<object,int>> stateArgs, IEnumerable<object> constArgs)
{
bool bStateRemain, bConstRemain;
var stateEnumerator = stateArgs.GetEnumerator();
var constEnumerator = constArgs.GetEnumerator();
@@ -107,23 +116,6 @@ public IEnumerable<object> GenArgList(IScope scope, IEnumerable<StateParamInst>
while (bStateRemain || bConstRemain);
}

private static KeyValuePair<object, int> ConvertCocktailToCSharp(IScope scope, StateParamInst spi)
{
var stateRefType = spi.arg.GetType();
if (typeof(DirectStateRef).IsAssignableFrom(stateRefType))
{
var ret = (spi.arg as DirectStateRef).GetObject(null);
return new KeyValuePair<object, int>(ret, spi.index);
}
else if (typeof(ScopedStateRef).IsAssignableFrom(stateRefType))
{
var ret = (spi.arg as ScopedStateRef).GetObject(scope);
return new KeyValuePair<object, int>(ret, spi.index);
}

throw new ArgumentOutOfRangeException("Unknown StateRef");
}

public bool Check(IEnumerable<StateParam> states, IEnumerable<Type> constParams)
{
//var eqsts = from st in m_stateTypes.Values
10 changes: 5 additions & 5 deletions src/Cocktail/VMBackend/LangVM.cs
Original file line number Diff line number Diff line change
@@ -164,17 +164,17 @@ public void Call(IScope scope, string eventName, IEnumerable<KeyValuePair<string
, MakeSignatureString(stateParams, constTypes) ));

// --------- Execute --------------
func.Exec(scope, GenStateParamInsts(states), constArgs);
var argList = func.Form.Fill(scope, GenStateParamInsts(states), constArgs);
func.Exec(argList.args);

// --------- Fire Inline Triggers -------
// the result of inline trigger is in same chronon
// the trigger can only do:
// 1) access/modify the state it belongs to
// 2) add new entry to the pending chronon list of the executing ST
// 3) fail the chronon
foreach (var sref in states)
// -3) fail the chronon-
foreach (var state in argList.rwStates)
{
var state = sref.Value.GetObject(scope);
state.FireInlineTriggers();
}

@@ -183,7 +183,7 @@ public void Call(IScope scope, string eventName, IEnumerable<KeyValuePair<string

// Internal

FunctionSignature Find(string name, IEnumerable<StateParam> stateParams, IEnumerable<Type> constParams )
FunctionSignature Find(string name, IEnumerable<StateParam> stateParams, IEnumerable<Type> constParams)
{
List<FunctionSignature> funcGroup;
if (!m_declGroups.TryGetValue(name, out funcGroup))
18 changes: 18 additions & 0 deletions src/Cocktail/VMBackend/Parameter.cs
Original file line number Diff line number Diff line change
@@ -18,6 +18,24 @@ public bool Equals(StateParam rhs)
public class StateParamInst : StateParam
{
public StateRef arg;

public KeyValuePair<object, int> ConvertCocktailToCSharp(IScope scope)
{
var spi = this;
var stateRefType = spi.arg.GetType();
if (typeof(DirectStateRef).IsAssignableFrom(stateRefType))
{
var ret = (spi.arg as DirectStateRef).GetObject(null);
return new KeyValuePair<object, int>(ret, spi.index);
}
else if (typeof(ScopedStateRef).IsAssignableFrom(stateRefType))
{
var ret = (spi.arg as ScopedStateRef).GetObject(scope);
return new KeyValuePair<object, int>(ret, spi.index);
}

throw new ArgumentOutOfRangeException("Unknown StateRef");
}
}

public class StateParamComparer : IEqualityComparer<StateParam>
13 changes: 5 additions & 8 deletions src/Demos/Accounting/BaseAccoutingDemo.cs
Original file line number Diff line number Diff line change
@@ -22,7 +22,6 @@ public abstract class BaseAccountingDemo : BaseModel
protected AABB m_worldBox;
protected double m_accumulate = 0;
protected List<Spacetime> m_spacetimes = new List<Spacetime>();
protected IHIdFactory m_idFactory;
protected VMSpacetime m_vmST;
//protected NamingSvcClient m_namingSvc;
protected IAccounting m_accountingInvoker;
@@ -33,28 +32,26 @@ public abstract class BaseAccountingDemo : BaseModel
public BaseAccountingDemo()
{
// reset all global states, to allow model switching
ServiceManager.Reset();
ServiceManager.Init();
m_vmST = ServiceManager.ComputeNode.VMSpacetimeForUnitTest;

//m_namingSvc = NamingSvcClient.Instance;
m_accountingInvoker = InvocationBuilder.Build<IAccounting>();
m_idFactory = ServiceManager.ComputeNode.HIdFactory;
m_vmST = new VMSpacetime(m_idFactory.CreateFromRoot(), m_idFactory);
}

public override void Init(AABB worldBox)
{
m_worldBox = worldBox;

ServiceManager.Init(m_vmST);

if (!m_vmST.VMExist(typeof(IAccounting)))
throw new ApplicationException("Accounting functions are not declared in VM yet");

// --- init demo objects ---

{
var initialST = new Spacetime(m_idFactory.CreateFromRoot(), ITCEvent.CreateZero(), m_idFactory);
var secondST = new Spacetime(m_idFactory.CreateFromRoot(), ITCEvent.CreateZero(), m_idFactory);
var idFactory = ServiceManager.ComputeNode.HIdFactory;
var initialST = new Spacetime(idFactory.CreateFromRoot(), ITCEvent.CreateZero(), idFactory);
var secondST = new Spacetime(idFactory.CreateFromRoot(), ITCEvent.CreateZero(), idFactory);
m_spacetimes.AddRange(new[] { initialST, secondST });
}

Loading

0 comments on commit 68183cd

Please sign in to comment.