Skip to content

Commit b3649c3

Browse files
committed
Reducing more allocations in signaling
1 parent a8e9d9b commit b3649c3

File tree

6 files changed

+62
-79
lines changed

6 files changed

+62
-79
lines changed

Source/Orts.Formats.Msts/SignalConfigurationFile.cs

+15
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public class SignalConfigurationFile
4343
{
4444
/// <summary>Name-indexed list of available signal functions</summary>
4545
public IDictionary<string, SignalFunction> SignalFunctions;
46+
/// <summary>Allocation-free MstsName-indexed list of available signal functions</summary>
47+
public static IDictionary<MstsSignalFunction, SignalFunction> MstsSignalFunctions;
4648
/// <summary>List of OR defined subtypes for Norman signals</summary>
4749
public IList<string> ORTSNormalSubtypes;
4850
/// <summary>Name-indexed list of available light textures</summary>
@@ -80,6 +82,19 @@ public SignalConfigurationFile(string filenamewithpath, bool ORTSMode)
8082
{ SignalFunction.UNKNOWN.Name, SignalFunction.UNKNOWN }
8183
};
8284

85+
// and the allocation-free version of the above
86+
MstsSignalFunctions = new SortedDictionary<MstsSignalFunction, SignalFunction>
87+
{
88+
{ MstsSignalFunction.NORMAL, SignalFunction.NORMAL },
89+
{ MstsSignalFunction.DISTANCE, SignalFunction.DISTANCE },
90+
{ MstsSignalFunction.REPEATER, SignalFunction.REPEATER },
91+
{ MstsSignalFunction.SHUNTING, SignalFunction.SHUNTING },
92+
{ MstsSignalFunction.INFO, SignalFunction.INFO },
93+
{ MstsSignalFunction.SPEED, SignalFunction.SPEED },
94+
{ MstsSignalFunction.ALERT, SignalFunction.ALERT },
95+
{ MstsSignalFunction.UNKNOWN, SignalFunction.UNKNOWN }
96+
};
97+
8398
// preset empty OR normal subtypes
8499
ORTSNormalSubtypes = new List<String>();
85100

Source/Orts.Simulation/Simulation/Signalling/SIGSCRfile.cs

+5-2
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,11 @@ public void SH_update_basic(SignalHead thisHead)
129129

130130
public void SH_process_script(SignalHead thisHead, SignalScripts.SCRScripts signalScript, SIGSCRfile sigscr)
131131
{
132-
133-
int[] localFloats = new int[signalScript.totalLocalFloats];
132+
if (thisHead.LocalFloats == null)
133+
thisHead.LocalFloats = signalScript.totalLocalFloats == 0 ? Array.Empty<int>() : new int[signalScript.totalLocalFloats];
134+
else
135+
Array.Clear(thisHead.LocalFloats, 0, thisHead.LocalFloats.Length);
136+
int[] localFloats = thisHead.LocalFloats;
134137

135138
// process script
136139

Source/Orts.Simulation/Simulation/Signalling/SignalHead.cs

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public class SignalHead
5656

5757
public string SignalTypeName => signalType?.Name ?? string.Empty;
5858

59+
public int[] LocalFloats;
60+
5961
/// <summary>
6062
/// Constructor for signals
6163
/// </summary>

Source/Orts.Simulation/Simulation/Signalling/SignalObject.cs

+15-9
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ public enum Permission
138138

139139
public bool CallOnEnabled = false; // set if signal script file uses CallOn functionality
140140

141+
private readonly List<int> SectionsWithAlternativePath = new List<int>();
142+
private readonly List<int> SectionsWithAltPathSet = new List<int>();
143+
141144
public bool enabled
142145
{
143146
get
@@ -763,7 +766,7 @@ public MstsSignalAspect this_sig_mr(SignalFunction function)
763766
public MstsSignalAspect this_sig_mr(MstsSignalFunction msfn_type)
764767
{
765768
bool sigfound = false;
766-
return this_sig_mr(signalRef.SignalFunctions[msfn_type.ToString()], ref sigfound);
769+
return this_sig_mr(SignalConfigurationFile.MstsSignalFunctions[msfn_type], ref sigfound);
767770
}
768771

769772
/// <summary>
@@ -862,7 +865,7 @@ public MstsSignalAspect this_sig_lr(SignalFunction function)
862865
public MstsSignalAspect this_sig_lr(MstsSignalFunction msfn_type)
863866
{
864867
bool sigfound = false;
865-
return this_sig_lr(signalRef.SignalFunctions[msfn_type.ToString()], ref sigfound);
868+
return this_sig_lr(SignalConfigurationFile.MstsSignalFunctions[msfn_type], ref sigfound);
866869
}
867870

868871
/// <summary>
@@ -1399,10 +1402,13 @@ public int SONextSignal(SignalFunction function)
13991402
if (!isSignalNormal())
14001403
{
14011404
TrackCircuitSignalList thisList = thisSection.CircuitItems.TrackCircuitSignals[direction][function];
1402-
foreach (TrackCircuitSignalItem item in thisList.TrackCircuitItem.Where(item => item.SignalRef.TCOffset > TCOffset))
1405+
for (int i = 0; i < thisList.TrackCircuitItem.Count; i++)
14031406
{
1404-
signalFound = item.SignalRef.thisRef;
1405-
break;
1407+
if (thisList.TrackCircuitItem[i].SignalRef.TCOffset > TCOffset)
1408+
{
1409+
signalFound = thisList.TrackCircuitItem[i].SignalRef.thisRef;
1410+
break;
1411+
}
14061412
}
14071413
}
14081414

@@ -2689,9 +2695,9 @@ private void getBlockState_notRouted()
26892695

26902696
if (isSignalNormal() && hasFixedRoute)
26912697
{
2692-
foreach (Train.TCRouteElement thisElement in fixedRoute)
2698+
for (int i = 0; i < fixedRoute.Count; i++)
26932699
{
2694-
TrackCircuitSection thisSection = signalRef.TrackCircuitList[thisElement.TCSectionIndex];
2700+
TrackCircuitSection thisSection = signalRef.TrackCircuitList[fixedRoute[i].TCSectionIndex];
26952701
if (thisSection.CircuitState.HasTrainsOccupying())
26962702
{
26972703
localBlockState = InternalBlockstate.OccupiedSameDirection;
@@ -2980,8 +2986,8 @@ private bool getBlockState_pathBased(Train.TCSubpathRoute thisRoute, Train.Train
29802986
/// </summary>
29812987
private bool getBlockState_locationBased(Train.TCSubpathRoute thisRoute, Train.TrainRouted thisTrain, bool AIPermissionRequest)
29822988
{
2983-
List<int> SectionsWithAlternativePath = new List<int>();
2984-
List<int> SectionsWithAltPathSet = new List<int>();
2989+
SectionsWithAlternativePath.Clear();
2990+
SectionsWithAltPathSet.Clear();
29852991
bool altRouteAssigned = false;
29862992

29872993
bool returnvalue = false;

Source/Orts.Simulation/Simulation/Signalling/TrackCircuitSection.cs

+9-68
Original file line numberDiff line numberDiff line change
@@ -658,10 +658,7 @@ public void Reserve(Train.TrainRouted thisTrain, Train.TCSubpathRoute thisRoute)
658658

659659
// remove from claim or deadlock claim
660660

661-
if (CircuitState.TrainClaimed.ContainsTrain(thisTrain))
662-
{
663-
CircuitState.TrainClaimed = removeFromQueue(CircuitState.TrainClaimed, thisTrain);
664-
}
661+
CircuitState.TrainClaimed.RemoveTrain(thisTrain);
665662

666663
// get element in routepath to find required alignment
667664

@@ -902,15 +899,8 @@ public void SetOccupied(Train.TrainRouted thisTrain, int reqDistanceTravelledM)
902899
CircuitState.TrainReserved = null;
903900
CircuitState.SignalReserved = -1;
904901

905-
if (CircuitState.TrainClaimed.ContainsTrain(thisTrain))
906-
{
907-
CircuitState.TrainClaimed = removeFromQueue(CircuitState.TrainClaimed, thisTrain);
908-
}
909-
910-
if (CircuitState.TrainPreReserved.ContainsTrain(thisTrain))
911-
{
912-
CircuitState.TrainPreReserved = removeFromQueue(CircuitState.TrainPreReserved, thisTrain);
913-
}
902+
CircuitState.TrainClaimed.RemoveTrain(thisTrain);
903+
CircuitState.TrainPreReserved.RemoveTrain(thisTrain);
914904

915905
float distanceToClear = reqDistanceTravelledM + Length + thisTrain.Train.standardOverlapM;
916906

@@ -1191,15 +1181,8 @@ public void RemoveTrain(Train.TrainRouted thisTrain, bool resetEndSignal)
11911181
ClearOccupied(thisTrain, resetEndSignal); // call clear occupy to reset signals and switches //
11921182
}
11931183

1194-
if (CircuitState.TrainClaimed.ContainsTrain(thisTrain))
1195-
{
1196-
CircuitState.TrainClaimed = removeFromQueue(CircuitState.TrainClaimed, thisTrain);
1197-
}
1198-
1199-
if (CircuitState.TrainPreReserved.ContainsTrain(thisTrain))
1200-
{
1201-
CircuitState.TrainPreReserved = removeFromQueue(CircuitState.TrainPreReserved, thisTrain);
1202-
}
1184+
CircuitState.TrainClaimed.RemoveTrain(thisTrain);
1185+
CircuitState.TrainPreReserved.RemoveTrain(thisTrain);
12031186
}
12041187

12051188

@@ -1223,26 +1206,16 @@ public void UnreserveTrain(Train.TrainRouted thisTrain, bool resetEndSignal)
12231206
ClearOccupied(thisTrain, resetEndSignal); // call clear occupy to reset signals and switches //
12241207
}
12251208

1226-
if (CircuitState.TrainClaimed.ContainsTrain(thisTrain))
1227-
{
1228-
CircuitState.TrainClaimed = removeFromQueue(CircuitState.TrainClaimed, thisTrain);
1229-
}
1230-
1231-
if (CircuitState.TrainPreReserved.ContainsTrain(thisTrain))
1232-
{
1233-
CircuitState.TrainPreReserved = removeFromQueue(CircuitState.TrainPreReserved, thisTrain);
1234-
}
1209+
CircuitState.TrainClaimed.RemoveTrain(thisTrain);
1210+
CircuitState.TrainPreReserved.RemoveTrain(thisTrain);
12351211
}
12361212

12371213
/// <summary>
12381214
/// Remove train clain from section
12391215
/// </summary>
12401216
public void UnclaimTrain(Train.TrainRouted thisTrain)
12411217
{
1242-
if (CircuitState.TrainClaimed.ContainsTrain(thisTrain))
1243-
{
1244-
CircuitState.TrainClaimed = removeFromQueue(CircuitState.TrainClaimed, thisTrain);
1245-
}
1218+
CircuitState.TrainClaimed.RemoveTrain(thisTrain);
12461219
}
12471220

12481221
/// <summary>
@@ -1307,38 +1280,6 @@ public void ClearReversalClaims(Train.TrainRouted thisTrain)
13071280
}
13081281
}
13091282

1310-
/// <summary>
1311-
/// Remove specified train from queue
1312-
/// </summary>
1313-
static TrainQueue removeFromQueue(TrainQueue thisQueue, Train.TrainRouted thisTrain)
1314-
{
1315-
List<Train.TrainRouted> tempList = new List<Train.TrainRouted>();
1316-
TrainQueue newQueue = new TrainQueue();
1317-
1318-
// extract trains from queue and store in list - this will revert the order!
1319-
// do not store train which is to be removed
1320-
1321-
int queueCount = thisQueue.Count;
1322-
while (queueCount > 0)
1323-
{
1324-
Train.TrainRouted queueTrain = thisQueue.Dequeue();
1325-
if (thisTrain == null || queueTrain.Train != thisTrain.Train)
1326-
{
1327-
tempList.Add(queueTrain);
1328-
}
1329-
queueCount = thisQueue.Count;
1330-
}
1331-
1332-
// restore the order by requeing
1333-
1334-
foreach (Train.TrainRouted queueTrain in tempList)
1335-
{
1336-
newQueue.Enqueue(queueTrain);
1337-
}
1338-
1339-
return (newQueue);
1340-
}
1341-
13421283
/// <summary>
13431284
/// align pins switch or crossover
13441285
/// </summary>
@@ -1948,7 +1889,7 @@ public bool CanPlaceTrain(Train thisTrain, float offset, float trainLength)
19481889

19491890
// get other trains in section
19501891

1951-
Dictionary<Train, float> trainInfo = new Dictionary<Train, float>();
1892+
Dictionary<Train, float> trainInfo;
19521893
float offsetFromStart = offset;
19531894

19541895
// test train ahead of rear end (for non-placed trains, always use direction 0)

Source/Orts.Simulation/Simulation/Signalling/TrainQueue.cs

+16
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,21 @@ public bool ContainsTrain(Train.TrainRouted thisTrain)
4040
if (thisTrain == null) return (false);
4141
return (Contains(thisTrain.Train.routedForward) || Contains(thisTrain.Train.routedBackward));
4242
}
43+
44+
/// <summary>
45+
/// Dequeue the whole queue and re-enqueue the unmatched trains
46+
/// </summary>
47+
/// <param name="thisTrain"></param>
48+
public void RemoveTrain(Train.TrainRouted thisTrain)
49+
{
50+
if (thisTrain == null) return;
51+
var queueCount = Count; // loop through the original count to cover all trains in the queue
52+
for (var i = 0; i < queueCount; i++)
53+
{
54+
var queueTrain = Dequeue();
55+
if (queueTrain != null & queueTrain.Train != thisTrain.Train)
56+
Enqueue(queueTrain);
57+
}
58+
}
4359
}
4460
}

0 commit comments

Comments
 (0)