From 2d53a1a45e8d7c7dfd8d9523254b0c7e77ec8fa5 Mon Sep 17 00:00:00 2001
From: Michael Krisper <michael.krisper@tugraz.at>
Date: Mon, 9 Aug 2021 14:23:44 +0200
Subject: [PATCH] refactored CycleCaches to use ConcurrentDictionary

---
 .../AbstractDeclarationVectoRunDataFactory.cs |  6 +--
 ...tionModeCompletedBusVectoRunDataFactory.cs | 33 ++++-------------
 ...mpletedMultistageBusVectoRunDataFactory.cs | 37 ++++---------------
 ...rationModeHeavyLorryVectoRunDataFactory.cs | 12 ++----
 ...rationModePrimaryBusVectoRunDataFactory.cs | 12 ++----
 ...arationModeSingleBusVectoRunDataFactory.cs | 12 ++----
 .../EngineeringModeVectoRunDataFactory.cs     |  9 ++---
 7 files changed, 29 insertions(+), 92 deletions(-)

diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/AbstractDeclarationVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/AbstractDeclarationVectoRunDataFactory.cs
index 13ba9b48d8..d9a982f8a1 100644
--- a/VectoCore/VectoCore/InputData/Reader/Impl/AbstractDeclarationVectoRunDataFactory.cs
+++ b/VectoCore/VectoCore/InputData/Reader/Impl/AbstractDeclarationVectoRunDataFactory.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Linq;
 using TUGraz.VectoCommon.InputData;
@@ -17,10 +18,9 @@ using TUGraz.VectoCore.Utils;
 namespace TUGraz.VectoCore.InputData.Reader.Impl {
 	public abstract class AbstractDeclarationVectoRunDataFactory : LoggingObject, IVectoRunDataFactory
 	{
-		protected static readonly object CyclesCacheLock = new object();
 
-		protected static readonly Dictionary<MissionType, DrivingCycleData> CyclesCache =
-			new Dictionary<MissionType, DrivingCycleData>();
+		protected static readonly ConcurrentDictionary<MissionType, DrivingCycleData> CyclesCache =
+			new ConcurrentDictionary<MissionType, DrivingCycleData>();
 
 		protected readonly IDeclarationInputDataProvider InputDataProvider;
 
diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedBusVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedBusVectoRunDataFactory.cs
index 536bcd20d3..4b792d4814 100644
--- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedBusVectoRunDataFactory.cs
+++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedBusVectoRunDataFactory.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Linq;
 using System.Xml;
@@ -28,10 +29,8 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl
 {
 	public class DeclarationModeCompletedBusVectoRunDataFactory : LoggingObject, IVectoRunDataFactory
 	{
-		protected static readonly object CyclesCacheLock = new object();
-
-		protected static readonly Dictionary<MissionType, DrivingCycleData> CyclesCache =
-			new Dictionary<MissionType, DrivingCycleData>();
+		protected static readonly ConcurrentDictionary<MissionType, DrivingCycleData> CyclesCache =
+			new ConcurrentDictionary<MissionType, DrivingCycleData>();
 
 		protected readonly IDeclarationInputDataProvider InputDataProvider;
 		protected IDeclarationReport Report;
@@ -229,17 +228,8 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl
 		}
 
 
-		protected VectoRunData CreateVectoRunDataSpecific(Mission mission, KeyValuePair<LoadingType, Tuple<Kilogram, double?>> loading, int modeIdx)
-		{
-			DrivingCycleData cycle;
-			lock (CyclesCacheLock) {
-				if (CyclesCache.ContainsKey(mission.MissionType)) {
-					cycle = CyclesCache[mission.MissionType];
-				} else {
-					cycle = DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false);
-					CyclesCache.Add(mission.MissionType, cycle);
-				}
-			}
+		protected VectoRunData CreateVectoRunDataSpecific(Mission mission, KeyValuePair<LoadingType, Tuple<Kilogram, double?>> loading, int modeIdx) {
+			var cycle = CyclesCache.GetOrAdd(mission.MissionType, _ => DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false));
 			
 			var simulationRunData = new VectoRunData {
 				Loading = loading.Key,
@@ -274,17 +264,8 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl
 		}
 
 		
-		protected VectoRunData CreateVectoRunDataGeneric(Mission mission, KeyValuePair<LoadingType, Tuple<Kilogram, double?>> loading, Segment primarySegment, int modeIdx)
-		{
-			DrivingCycleData cycle;
-			lock (CyclesCacheLock) {
-				if (CyclesCache.ContainsKey(mission.MissionType)) {
-					cycle = CyclesCache[mission.MissionType];
-				} else {
-					cycle = DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false);
-					CyclesCache.Add(mission.MissionType, cycle);
-				}
-			}
+		protected VectoRunData CreateVectoRunDataGeneric(Mission mission, KeyValuePair<LoadingType, Tuple<Kilogram, double?>> loading, Segment primarySegment, int modeIdx) {
+			var cycle = CyclesCache.GetOrAdd(mission.MissionType, _ => DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false));
 
 			var primaryBusAuxiliaries = PrimaryVehicle.Components.BusAuxiliaries;
 
diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedMultistageBusVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedMultistageBusVectoRunDataFactory.cs
index 05d3dd421e..afcd55422c 100644
--- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedMultistageBusVectoRunDataFactory.cs
+++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedMultistageBusVectoRunDataFactory.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Linq;
 using TUGraz.VectoCommon.Exceptions;
@@ -18,15 +19,12 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl
 {
 	public class DeclarationModeCompletedMultistageBusVectoRunDataFactory : LoggingObject, IVectoRunDataFactory
 	{
-		protected static readonly object CyclesCacheLock = new object();
-		protected static readonly Dictionary<MissionType, DrivingCycleData> CyclesCache =
-			new Dictionary<MissionType, DrivingCycleData>();
-
+		protected static readonly ConcurrentDictionary<MissionType, DrivingCycleData> CyclesCache =
+			new ConcurrentDictionary<MissionType, DrivingCycleData>();
 
 		protected readonly IMultistageBusInputDataProvider InputDataProvider;
 		protected IDeclarationReport Report;
 
-
 		protected Segment _segmentCompletedBus;
 		protected AxleGearData _axlegearData;
 		protected AngledriveData _angledriveData;
@@ -34,7 +32,6 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl
 		protected RetarderData _retarderData;
 		protected ShiftStrategyParameters _gearshiftData;
 		private DriverData _driverData;
-		
 
 		protected DeclarationDataAdapterMultistageBus DataAdapterSpecific = new DeclarationDataAdapterMultistageBus();
 
@@ -244,20 +241,8 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl
 
 		protected VectoRunData CreateVectoRunDataSpecific(Mission mission, KeyValuePair<LoadingType, Tuple<Kilogram, double?>> loading, int modeIdx)
 		{
-			DrivingCycleData cycle;
-			lock (CyclesCacheLock)
-			{
-				if (CyclesCache.ContainsKey(mission.MissionType))
-				{
-					cycle = CyclesCache[mission.MissionType];
-				}
-				else
-				{
-					cycle = DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false);
-					CyclesCache.Add(mission.MissionType, cycle);
-				}
-			}
-
+			var cycle = CyclesCache.GetOrAdd(mission.MissionType, _ => DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false));
+			
 			var simulationRunData = new VectoRunData
 			{
 				Loading = loading.Key,
@@ -294,16 +279,8 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl
 		
 		protected VectoRunData CreateVectoRunDataGeneric(Mission mission, KeyValuePair<LoadingType, Tuple<Kilogram, double?>> loading, Segment primarySegment, int modeIdx)
 		{
-			DrivingCycleData cycle;
-			lock (CyclesCacheLock) {
-				if (CyclesCache.ContainsKey(mission.MissionType)) {
-					cycle = CyclesCache[mission.MissionType];
-				} else {
-					cycle = DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false);
-					CyclesCache.Add(mission.MissionType, cycle);
-				}
-			}
-
+			var cycle = CyclesCache.GetOrAdd(mission.MissionType, _ => DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false));
+			
 			var primaryBusAuxiliaries = PrimaryVehicle.Components.BusAuxiliaries;
 
 			var simulationRunData = new VectoRunData {
diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeHeavyLorryVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeHeavyLorryVectoRunDataFactory.cs
index 37545d3f37..475359c981 100644
--- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeHeavyLorryVectoRunDataFactory.cs
+++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeHeavyLorryVectoRunDataFactory.cs
@@ -147,15 +147,9 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl
 			var engine = InputDataProvider.JobInputData.Vehicle.Components.EngineInputData;
 			var engineModes = engine.EngineModes;
 			var engineMode = engineModes[modeIdx];
-			DrivingCycleData cycle;
-			lock (CyclesCacheLock) {
-				if (CyclesCache.ContainsKey(mission.MissionType)) {
-					cycle = CyclesCache[mission.MissionType];
-				} else {
-					cycle = DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false);
-					CyclesCache.Add(mission.MissionType, cycle);
-				}
-			}
+
+			var cycle = CyclesCache.GetOrAdd(mission.MissionType, _ => DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false));
+			
 			var simulationRunData = new VectoRunData {
 				Loading = loading.Key,
 				VehicleData = DataAdapter.CreateVehicleData(vehicle, _segment, mission, loading, _allowVocational),
diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModePrimaryBusVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModePrimaryBusVectoRunDataFactory.cs
index 5b54fb576f..511cece77c 100644
--- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModePrimaryBusVectoRunDataFactory.cs
+++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModePrimaryBusVectoRunDataFactory.cs
@@ -102,15 +102,9 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl
 			var engine = vehicle.Components.EngineInputData;
 			var engineModes = engine.EngineModes;
 			var engineMode = engineModes[modeIdx];
-			DrivingCycleData cycle;
-			lock (CyclesCacheLock) {
-				if (CyclesCache.ContainsKey(mission.MissionType)) {
-					cycle = CyclesCache[mission.MissionType];
-				} else {
-					cycle = DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false);
-					CyclesCache.Add(mission.MissionType, cycle);
-				}
-			}
+
+			var cycle = CyclesCache.GetOrAdd(mission.MissionType, _ => DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false));
+
 			var simulationRunData = new VectoRunData {
 				Loading = loading.Key,
 				VehicleData = DataAdapter.CreateVehicleData(vehicle, _segment, mission, loading, _allowVocational),
diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeSingleBusVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeSingleBusVectoRunDataFactory.cs
index a4a9cd71a9..194b348591 100644
--- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeSingleBusVectoRunDataFactory.cs
+++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeSingleBusVectoRunDataFactory.cs
@@ -73,15 +73,9 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl {
 			var engine = vehicle.Components.EngineInputData;
 			var engineModes = engine.EngineModes;
 			var engineMode = engineModes[modeIdx];
-			DrivingCycleData cycle;
-			lock (CyclesCacheLock) {
-				if (CyclesCache.ContainsKey(mission.MissionType)) {
-					cycle = CyclesCache[mission.MissionType];
-				} else {
-					cycle = DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false);
-					CyclesCache.Add(mission.MissionType, cycle);
-				}
-			}
+
+			var cycle = CyclesCache.GetOrAdd(mission.MissionType, _ => DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased, "", false));
+			
 			var simulationRunData = new VectoRunData {
 				Loading = loading.Key,
 				VehicleData = DataAdapter.CreateVehicleData(vehicle, _segment, mission, loading, _allowVocational),
diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs
index a3b012014f..de50e17655 100644
--- a/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs
+++ b/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs
@@ -42,6 +42,7 @@ using TUGraz.VectoCore.Models.Simulation.Data;
 using TUGraz.VectoCore.Models.Simulation.Impl;
 using TUGraz.VectoCore.Models.SimulationComponent.Data;
 using TUGraz.VectoCore.Models.SimulationComponent.Impl;
+using TUGraz.VectoCore.Utils;
 
 [assembly: InternalsVisibleTo("VectoCoreTest")]
 
@@ -133,9 +134,7 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl
 										CrossWindCorrectionMode.VAirBetaLookupTable;
 				//var ptoTransmissionData = dao.CreatePTOTransmissionData(vehicle.Components.PTOTransmissionInputData);
 
-				var drivingCycle = CyclesCache.ContainsKey(cycle.CycleData.Source)
-					? CyclesCache[cycle.CycleData.Source]
-					: DrivingCycleDataReader.ReadFromDataTable(cycle.CycleData, cycle.Name, crossWindRequired);
+				var drivingCycle = CyclesCache.GetOrAdd(cycle.CycleData.Source, _=>DrivingCycleDataReader.ReadFromDataTable(cycle.CycleData, cycle.Name, crossWindRequired));
 
 				var vehicleData = dao.CreateVehicleData(vehicle);
 				yield return new VectoRunData
@@ -226,9 +225,7 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl
 							: null;
 
 
-					var drivingCycle = CyclesCache.ContainsKey(cycle.CycleData.Source)
-						? CyclesCache[cycle.CycleData.Source]
-						: DrivingCycleDataReader.ReadFromDataTable(cycle.CycleData, cycle.Name, crossWindRequired);
+					var drivingCycle = CyclesCache.GetOrAdd(cycle.CycleData.Source, _=> DrivingCycleDataReader.ReadFromDataTable(cycle.CycleData, cycle.Name, crossWindRequired));
 
 					var electricMachines =
 						dao.CreateElectricMachines(vehicle.Components.ElectricMachines,
-- 
GitLab