Skip to content

Commit

Permalink
Complete rewrite - abstracted, reduced duplication, and modularized b…
Browse files Browse the repository at this point in the history
…ase for futher work
  • Loading branch information
prasannavl committed May 11, 2015
1 parent 04b6582 commit ebdf2aa
Show file tree
Hide file tree
Showing 35 changed files with 825 additions and 728 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,6 @@
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

appveyor.yml merge=ours
VersionInfo.cs merge=ours
2 changes: 2 additions & 0 deletions LiquidState.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiquidState.Sample", "Liqui
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F654A99E-F9FF-418E-8A2D-6CAD0406788E}"
ProjectSection(SolutionItems) = preProject
.gitattributes = .gitattributes
.gitignore = .gitignore
appveyor.yml = appveyor.yml
LiquidState\LiquidState.nuspec = LiquidState\LiquidState.nuspec
README.md = README.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Threading;
using System.Threading.Tasks;
using LiquidState.Awaitable.Core;
using LiquidState.Common;
using LiquidState.Configuration;
using LiquidState.Core;
using LiquidState.Scaffold;

namespace LiquidState.Machines
namespace LiquidState.Awaitable
{
public class AsyncStateMachine<TState, TTrigger> : IAwaitableStateMachine<TState, TTrigger>
{
Expand Down Expand Up @@ -132,6 +133,7 @@ public async Task FireAsync<TArgument>(ParameterizedTrigger<TTrigger, TArgument>
queueMonitor.Enter();
if (machine.Monitor.TryEnter())
{
// Try to execute inline if the process queue is empty.
if (queueCount == 0)
{
queueMonitor.Exit();
Expand Down Expand Up @@ -161,6 +163,8 @@ public async Task FireAsync<TArgument>(ParameterizedTrigger<TTrigger, TArgument>

if (flag)
{
// Fast path was not taken. Queue up the delgates.

var tcs = new TaskCompletionSource<bool>();
actionsQueue = actionsQueue.Enqueue(async () =>
{
Expand Down Expand Up @@ -191,6 +195,7 @@ public async Task FireAsync(TTrigger trigger)
queueMonitor.Enter();
if (machine.Monitor.TryEnter())
{
// Try to execute inline if the process queue is empty.
if (queueCount == 0)
{
queueMonitor.Exit();
Expand Down Expand Up @@ -218,8 +223,11 @@ public async Task FireAsync(TTrigger trigger)
}
}


if (flag)
{
// Fast path was not taken. Queue up the delgates.

var tcs = new TaskCompletionSource<bool>();
actionsQueue = actionsQueue.Enqueue(async () =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
using System.Diagnostics.Contracts;
using System.Threading;
using System.Threading.Tasks;
using LiquidState.Awaitable.Core;
using LiquidState.Common;
using LiquidState.Configuration;
using LiquidState.Core;
using LiquidState.Representations;

namespace LiquidState.Machines
namespace LiquidState.Awaitable
{
public class AwaitableStateMachine<TState, TTrigger> : IAwaitableStateMachine<TState, TTrigger>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
using System.Diagnostics.Contracts;
using System.Threading;
using System.Threading.Tasks;
using LiquidState.Common;
using LiquidState.Configuration;
using LiquidState.Awaitable.Core;
using LiquidState.Core;

namespace LiquidState.Machines
namespace LiquidState.Awaitable
{
public class AwaitableStateMachineWithScheduler<TState, TTrigger> : IAwaitableStateMachine<TState, TTrigger>
{
Expand Down
34 changes: 34 additions & 0 deletions LiquidState/Awaitable/Core/AbstractStateMachine.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Collections.Generic;
using LiquidState.Core;
using LiquidState.Synchronous.Core;

namespace LiquidState.Awaitable.Core
{
public abstract class AbstractStateMachine<TState, TTrigger> : AbstractStateMachineCore<TState, TTrigger>
{
protected internal StateRepresentation<TState, TTrigger> CurrentStateRepresentation;
protected internal Dictionary<TState, StateRepresentation<TState, TTrigger>> Representations;

public abstract void Fire<TArgument>(ParameterizedTrigger<TTrigger, TArgument> parameterizedTrigger,
TArgument argument);

public abstract void Fire(TTrigger trigger);
public abstract void MoveToState(TState state, StateTransitionOption option = StateTransitionOption.Default);

public override TState CurrentState
{
get { return CurrentStateRepresentation.State; }
}

public override IEnumerable<TTrigger> CurrentPermittedTriggers
{
get
{
foreach (var triggerRepresentation in CurrentStateRepresentation.Triggers)
{
yield return triggerRepresentation.Trigger;
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Diagnostics.Contracts;
using System.Threading.Tasks;
using LiquidState.Common;
using LiquidState.Core;
using LiquidState.Representations;

namespace LiquidState.Configuration
Expand Down Expand Up @@ -340,7 +341,7 @@ internal static AwaitableStateRepresentation<TState, TTrigger> FindOrCreateState
return rep;
}

internal static AwaitableTriggerRepresentation<TTrigger, TState> FindOrCreateTriggerConfig(TTrigger trigger,
internal static AwaitableTriggerRepresentation<TTrigger, TState> FindOrCreateTriggerRepresentation(TTrigger trigger,
AwaitableStateRepresentation<TState, TTrigger> stateRepresentation)
{
Contract.Requires(stateRepresentation != null);
Expand Down Expand Up @@ -369,7 +370,7 @@ private AwaitableStateConfigurationHelper<TState, TTrigger> PermitInternalSync(F
Contract.Requires<ArgumentNullException>(trigger != null);
Contract.Requires<ArgumentNullException>(resultingState != null);

var rep = FindOrCreateTriggerConfig(trigger, currentStateRepresentation);
var rep = FindOrCreateTriggerRepresentation(trigger, currentStateRepresentation);

rep.NextStateRepresentation = FindOrCreateStateRepresentation(resultingState, config);
rep.OnTriggerAction = onEntryAction;
Expand All @@ -387,7 +388,7 @@ private AwaitableStateConfigurationHelper<TState, TTrigger> PermitInternalSync<T

Contract.Assume(trigger.Trigger != null);

var rep = FindOrCreateTriggerConfig(trigger.Trigger, currentStateRepresentation);
var rep = FindOrCreateTriggerRepresentation(trigger.Trigger, currentStateRepresentation);

rep.NextStateRepresentation = FindOrCreateStateRepresentation(resultingState, config);
rep.OnTriggerAction = onEntryAction;
Expand All @@ -403,7 +404,7 @@ private AwaitableStateConfigurationHelper<TState, TTrigger> PermitInternalAsync(
Contract.Requires<ArgumentNullException>(trigger != null);
Contract.Requires<ArgumentNullException>(resultingState != null);

var rep = FindOrCreateTriggerConfig(trigger, currentStateRepresentation);
var rep = FindOrCreateTriggerRepresentation(trigger, currentStateRepresentation);

rep.NextStateRepresentation = FindOrCreateStateRepresentation(resultingState, config);
rep.OnTriggerAction = onEntryAsyncAction;
Expand All @@ -424,7 +425,7 @@ private AwaitableStateConfigurationHelper<TState, TTrigger> PermitInternalAsync<

Contract.Assume(trigger.Trigger != null);

var rep = FindOrCreateTriggerConfig(trigger.Trigger, currentStateRepresentation);
var rep = FindOrCreateTriggerRepresentation(trigger.Trigger, currentStateRepresentation);

rep.NextStateRepresentation = FindOrCreateStateRepresentation(resultingState, config);
rep.OnTriggerAction = onEntryAsyncAction;
Expand All @@ -442,7 +443,7 @@ private AwaitableStateConfigurationHelper<TState, TTrigger> PermitInternalTrigge
Contract.Requires<ArgumentNullException>(trigger != null);
Contract.Requires<ArgumentNullException>(resultingState != null);

var rep = FindOrCreateTriggerConfig(trigger, currentStateRepresentation);
var rep = FindOrCreateTriggerRepresentation(trigger, currentStateRepresentation);

rep.NextStateRepresentation = FindOrCreateStateRepresentation(resultingState, config);
rep.OnTriggerAction = onEntryAsyncAction;
Expand All @@ -462,7 +463,7 @@ private AwaitableStateConfigurationHelper<TState, TTrigger> PermitInternalTrigge

Contract.Assume(trigger.Trigger != null);

var rep = FindOrCreateTriggerConfig(trigger.Trigger, currentStateRepresentation);
var rep = FindOrCreateTriggerRepresentation(trigger.Trigger, currentStateRepresentation);

rep.NextStateRepresentation = FindOrCreateStateRepresentation(resultingState, config);
rep.OnTriggerAction = onEntryAsyncAction;
Expand All @@ -480,7 +481,7 @@ private AwaitableStateConfigurationHelper<TState, TTrigger> PermitInternalPredic
Contract.Requires<ArgumentNullException>(trigger != null);
Contract.Requires<ArgumentNullException>(resultingState != null);

var rep = FindOrCreateTriggerConfig(trigger, currentStateRepresentation);
var rep = FindOrCreateTriggerRepresentation(trigger, currentStateRepresentation);

rep.NextStateRepresentation = FindOrCreateStateRepresentation(resultingState, config);
rep.OnTriggerAction = onEntryAsyncAction;
Expand All @@ -500,7 +501,7 @@ private AwaitableStateConfigurationHelper<TState, TTrigger> PermitInternalPredic

Contract.Assume(trigger.Trigger != null);

var rep = FindOrCreateTriggerConfig(trigger.Trigger, currentStateRepresentation);
var rep = FindOrCreateTriggerRepresentation(trigger.Trigger, currentStateRepresentation);

rep.NextStateRepresentation = FindOrCreateStateRepresentation(resultingState, config);
rep.OnTriggerAction = onEntryAsyncAction;
Expand All @@ -515,7 +516,7 @@ private AwaitableStateConfigurationHelper<TState, TTrigger> IgnoreInternal(Func<
{
Contract.Requires<ArgumentNullException>(trigger != null);

var rep = FindOrCreateTriggerConfig(trigger, currentStateRepresentation);
var rep = FindOrCreateTriggerRepresentation(trigger, currentStateRepresentation);

rep.NextStateRepresentation = null;
rep.ConditionalTriggerPredicate = predicate;
Expand All @@ -529,7 +530,7 @@ private AwaitableStateConfigurationHelper<TState, TTrigger> IgnoreInternalPredic
{
Contract.Requires<ArgumentNullException>(trigger != null);

var rep = FindOrCreateTriggerConfig(trigger, currentStateRepresentation);
var rep = FindOrCreateTriggerRepresentation(trigger, currentStateRepresentation);

rep.NextStateRepresentation = null;
rep.ConditionalTriggerPredicate = predicate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using LiquidState.Common;
using LiquidState.Configuration;
using LiquidState.Core;
using LiquidState.Representations;

namespace LiquidState.Configuration
namespace LiquidState.Awaitable.Core
{
public class AwaitableStateMachineConfiguration<TState, TTrigger>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Threading.Tasks;
using LiquidState.Common;
using LiquidState.Core;

namespace LiquidState.Machines
namespace LiquidState.Awaitable.Core
{
[ContractClass(typeof (AwaitableStateMachineContract<,>))]
public interface IAwaitableStateMachine<TState, TTrigger>
Expand Down
85 changes: 85 additions & 0 deletions LiquidState/Core/AbstractStateMachineCore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Threading;
using LiquidState.Common;

namespace LiquidState.Core
{
public abstract class AbstractStateMachineCore<TState, TTrigger> : IStateMachineCore<TState, TTrigger>
{
public event Action<TriggerStateEventArgs<TState, TTrigger>> UnhandledTrigger;
public event Action<TransitionEventArgs<TState, TTrigger>> InvalidState;
public event Action<TransitionEventArgs<TState, TTrigger>> TransitionStarted;
public event Action<TransitionExecutedEventArgs<TState, TTrigger>> TransitionExecuted;

public void Pause()
{
Interlocked.Exchange(ref isEnabled, 0);
}

public void Resume()
{
Interlocked.Exchange(ref isEnabled, 1);
}

private int isEnabled = 1;

public abstract IEnumerable<TTrigger> CurrentPermittedTriggers { get; }
public abstract TState CurrentState { get; }

public bool IsEnabled
{
get { return Interlocked.CompareExchange(ref isEnabled, -1, -1) == 1; }
}

public void RaiseInvalidTrigger(TTrigger trigger)
{
var handler = UnhandledTrigger;
if (handler != null) handler.Invoke(new TriggerStateEventArgs<TState, TTrigger>(CurrentState, trigger));
}

public void RaiseInvalidState(TState targetState)
{
var handler = InvalidState;
if (handler != null)
handler.Invoke(new TransitionEventArgs<TState, TTrigger>(CurrentState, targetState));
}

public void RaiseInvalidState(TState targetState, TTrigger trigger)
{
var handler = InvalidState;
if (handler != null)
handler.Invoke(new TransitionEventArgs<TState, TTrigger>(CurrentState, targetState, trigger));
}

public void RaiseTransitionStarted(TState targetState)
{
var handler = TransitionStarted;
if (handler != null)
handler.Invoke(new TransitionEventArgs<TState, TTrigger>(CurrentState, targetState));
}


public void RaiseTransitionStarted(TState targetState, TTrigger trigger)
{
var handler = TransitionStarted;
if (handler != null)
handler.Invoke(new TransitionEventArgs<TState, TTrigger>(CurrentState, targetState, trigger));
}

public void RaiseTransitionExecuted(TState pastState)
{
var handler = TransitionExecuted;
if (handler != null)
handler.Invoke(new TransitionExecutedEventArgs<TState, TTrigger>(CurrentState, pastState));
}


public void RaiseTransitionExecuted(TState pastState, TTrigger trigger)
{
var handler = TransitionExecuted;
if (handler != null)
handler.Invoke(new TransitionExecutedEventArgs<TState, TTrigger>(CurrentState, pastState, trigger));
}
}
}
Loading

0 comments on commit ebdf2aa

Please sign in to comment.