Fix blocking issue in LuaCsTimer

Logic for scheduling actions in `LuaCsHook` (see `Enqueue()` and `Update()`) caused tasks with long delays to block the execution of tasks with shorter delays.
Moved logic for `Timer.Wait()` from `LuaCsHook` to `LuaCsTimer` and corrected the blocking issue.
This commit is contained in:
Cintique
2022-05-06 15:43:17 +10:00
parent 13274aecd6
commit d244869377
2 changed files with 83 additions and 22 deletions
@@ -297,6 +297,7 @@ namespace Barotrauma
public void Update() public void Update()
{ {
Hook?.Update(); Hook?.Update();
LuaCsTimer.Update();
} }
public void Stop() public void Stop()
@@ -312,6 +313,7 @@ namespace Barotrauma
if (Thread.CurrentThread == GameMain.MainThread) if (Thread.CurrentThread == GameMain.MainThread)
{ {
Hook?.Call("stop"); Hook?.Call("stop");
LuaCsTimer.Clear();
} }
Game?.Stop(); Game?.Stop();
@@ -13,27 +13,11 @@ using System.Xml.Linq;
namespace Barotrauma namespace Barotrauma
{ {
public partial class LuaCsTimer public class LuaCsTimer
{ {
public static long LastUpdateTime = 0; public static long LastUpdateTime = 0;
public static double Time public static double Time => Timing.TotalTime;
{
get
{
return GetTime();
}
}
public static void Wait(LuaCsAction action, int millisecondDelay)
{
GameMain.LuaCs.Hook.EnqueueTimed((float)Timing.TotalTime + (millisecondDelay / 1000f), action);
}
public static double GetTime()
{
return Timing.TotalTime;
}
public static float GetUsageMemory() public static float GetUsageMemory()
{ {
@@ -43,7 +27,82 @@ namespace Barotrauma
return memory; return memory;
} }
}
private class TimerComparer : IComparer<TimedAction>
{
public int Compare(TimedAction timedAction1, TimedAction timedAction2)
{
if (timedAction1 == null || timedAction2 == null)
return 0;
return -Math.Sign(timedAction2.executionTime - timedAction1.executionTime);
}
}
private class TimedAction
{
public LuaCsAction action
{
get;
private set;
}
private int delayMs;
public double executionTime
{
get;
private set;
}
public TimedAction(LuaCsAction action, int delayMs)
{
this.action = action;
this.delayMs = delayMs;
executionTime = Time + (delayMs / 1000f);
}
}
private static List<TimedAction> timedActions = new List<TimedAction>();
private static void AddTimer(TimedAction timedAction)
{
int insertionPoint = timedActions.BinarySearch(timedAction, new TimerComparer());
if (insertionPoint < 0)
{
insertionPoint = ~insertionPoint;
}
timedActions.Insert(insertionPoint, timedAction);
}
public static void Update()
{
while (timedActions.Count > 0)
{
TimedAction timedAction = timedActions[0];
if (Time >= timedAction.executionTime)
{
timedAction.action();
timedActions.RemoveAt(0);
}
else
{
break;
}
}
}
public static void Clear()
{
timedActions = new List<TimedAction>();
}
public static void Wait(LuaCsAction action, int millisecondDelay)
{
TimedAction timedAction = new TimedAction(action, millisecondDelay);
AddTimer(timedAction);
}
}
partial class LuaCsFile partial class LuaCsFile
{ {