Fix ActionQueue ordering.
This enforces a well defined ordering for ActionQueue to ensure it runs actions in the the order one would expect.
This commit is contained in:
@@ -384,9 +384,9 @@ namespace OpenRA
|
||||
|
||||
// Note: These delayed actions should only be used by widgets or disposing objects
|
||||
// - things that depend on a particular world should be queuing them on the worldactor.
|
||||
static ActionQueue delayedActions = new ActionQueue();
|
||||
public static void RunAfterTick(Action a) { delayedActions.Add(a); }
|
||||
public static void RunAfterDelay(int delay, Action a) { delayedActions.Add(a, delay); }
|
||||
static volatile ActionQueue delayedActions = new ActionQueue();
|
||||
public static void RunAfterTick(Action a) { delayedActions.Add(a, Game.RunTime); }
|
||||
public static void RunAfterDelay(int delayMilliseconds, Action a) { delayedActions.Add(a, Game.RunTime + delayMilliseconds); }
|
||||
|
||||
static void TakeScreenshotInner()
|
||||
{
|
||||
@@ -487,7 +487,7 @@ namespace OpenRA
|
||||
|
||||
static void LogicTick()
|
||||
{
|
||||
delayedActions.PerformActions();
|
||||
delayedActions.PerformActions(Game.RunTime);
|
||||
|
||||
if (OrderManager.Connection.ConnectionState != lastConnectionState)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Primitives
|
||||
{
|
||||
@@ -17,37 +18,56 @@ namespace OpenRA.Primitives
|
||||
/// </summary>
|
||||
public class ActionQueue
|
||||
{
|
||||
object syncRoot = new object();
|
||||
PriorityQueue<DelayedAction> actions = new PriorityQueue<DelayedAction>();
|
||||
readonly List<DelayedAction> actions = new List<DelayedAction>();
|
||||
|
||||
public void Add(Action a) { Add(a, 0); }
|
||||
public void Add(Action a, int delay)
|
||||
public void Add(Action a, int desiredTime)
|
||||
{
|
||||
lock (syncRoot)
|
||||
actions.Add(new DelayedAction(a, Game.RunTime + delay));
|
||||
if (a == null)
|
||||
throw new ArgumentNullException("a");
|
||||
|
||||
lock (actions)
|
||||
{
|
||||
var action = new DelayedAction(a, desiredTime);
|
||||
var index = Index(action);
|
||||
actions.Insert(index, action);
|
||||
}
|
||||
}
|
||||
|
||||
public void PerformActions()
|
||||
public void PerformActions(int currentTime)
|
||||
{
|
||||
Action a = () => { };
|
||||
lock (syncRoot)
|
||||
DelayedAction[] pendingActions;
|
||||
lock (actions)
|
||||
{
|
||||
var t = Game.RunTime;
|
||||
while (!actions.Empty && actions.Peek().Time <= t)
|
||||
{
|
||||
var da = actions.Pop();
|
||||
a = da.Action + a;
|
||||
}
|
||||
var dummyAction = new DelayedAction(null, currentTime);
|
||||
var index = Index(dummyAction);
|
||||
if (index <= 0)
|
||||
return;
|
||||
|
||||
pendingActions = new DelayedAction[index];
|
||||
actions.CopyTo(0, pendingActions, 0, index);
|
||||
actions.RemoveRange(0, index);
|
||||
}
|
||||
|
||||
a();
|
||||
foreach (var delayedAction in pendingActions)
|
||||
delayedAction.Action();
|
||||
}
|
||||
|
||||
int Index(DelayedAction action)
|
||||
{
|
||||
// Returns the index of the next action with a strictly greater time.
|
||||
var index = actions.BinarySearch(action);
|
||||
if (index < 0)
|
||||
return ~index;
|
||||
while (index < actions.Count && action.CompareTo(actions[index]) >= 0)
|
||||
index++;
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
struct DelayedAction : IComparable<DelayedAction>
|
||||
{
|
||||
public int Time;
|
||||
public Action Action;
|
||||
public readonly int Time;
|
||||
public readonly Action Action;
|
||||
|
||||
public DelayedAction(Action action, int time)
|
||||
{
|
||||
@@ -59,5 +79,10 @@ namespace OpenRA.Primitives
|
||||
{
|
||||
return Time.CompareTo(other.Time);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Time: " + Time + " Action: " + Action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user