Virtu/Virtu/MachineEvents.cs
Sean Fausett 0182641281 Merged machine settings into machine components.
Added save state support to all machine components.
Switched from xml serialization to binary serialization.
Refactored audio service for performance.
Bumped machine version to 0.9.0 for next release.
Miscellaneous cosmetic or minor changes.
2010-11-29 09:08:11 +13:00

108 lines
2.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
namespace Jellyfish.Virtu
{
public sealed class MachineEvent
{
public MachineEvent(int delta, Action action)
{
Delta = delta;
Action = action;
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "Delta = {0} Action = {{{1}.{2}}}", Delta, Action.Method.DeclaringType.Name, Action.Method.Name);
}
public int Delta { get; set; }
public Action Action { get; set; }
}
public sealed class MachineEvents
{
public void AddEvent(int delta, Action action)
{
var node = _used.First;
for (; node != null; node = node.Next)
{
if (delta < node.Value.Delta)
{
node.Value.Delta -= delta;
break;
}
if (node.Value.Delta > 0)
{
delta -= node.Value.Delta;
}
}
var newNode = _free.First;
if (newNode != null)
{
_free.RemoveFirst();
newNode.Value.Delta = delta;
newNode.Value.Action = action;
}
else
{
newNode = new LinkedListNode<MachineEvent>(new MachineEvent(delta, action));
}
if (node != null)
{
_used.AddBefore(node, newNode);
}
else
{
_used.AddLast(newNode);
}
}
public int FindEvent(Action action)
{
int delta = 0;
for (var node = _used.First; node != null; node = node.Next)
{
delta += node.Value.Delta;
if (object.ReferenceEquals(node.Value.Action, action)) // assumes delegate cached
{
return delta;
}
}
return 0;
}
public void HandleEvents(int delta)
{
var node = _used.First;
node.Value.Delta -= delta;
while (node.Value.Delta <= 0)
{
node.Value.Action();
RemoveEvent(node);
node = _used.First;
}
}
private void RemoveEvent(LinkedListNode<MachineEvent> node)
{
if (node.Next != null)
{
node.Next.Value.Delta += node.Value.Delta;
}
_used.Remove(node);
_free.AddFirst(node); // cache node; avoids garbage
}
private LinkedList<MachineEvent> _used = new LinkedList<MachineEvent>();
private LinkedList<MachineEvent> _free = new LinkedList<MachineEvent>();
}
}