From 0bf38234c6dbef8824045c81c4bd79c440a70abc Mon Sep 17 00:00:00 2001 From: Syntriax Date: Sun, 4 May 2025 19:00:54 +0300 Subject: [PATCH] feat: async serializer methods --- Engine.Core/Serialization/ISerializer.cs | 6 ++ .../Abstract/IEngineTypeYamlConverter.cs | 2 + .../BehaviourControllerConverter.cs | 9 ++ .../Converters/BehaviourConverter.cs | 9 ++ .../Converters/EngineTypeYamlConverterBase.cs | 1 + .../Converters/SerializedClassConverter.cs | 11 ++- .../Converters/StateEnableConverter.cs | 8 ++ .../Converters/UniverseConverter.cs | 31 +++--- .../Converters/UniverseObjectConverter.cs | 9 ++ .../SerializerInProgressException.cs | 6 ++ .../Engine.Serializers.Yaml/YamlSerializer.cs | 95 +++++++++++++++---- 11 files changed, 156 insertions(+), 31 deletions(-) create mode 100644 Engine.Serializers/Engine.Serializers.Yaml/SerializerInProgressException.cs diff --git a/Engine.Core/Serialization/ISerializer.cs b/Engine.Core/Serialization/ISerializer.cs index 18b9959..0ef6962 100644 --- a/Engine.Core/Serialization/ISerializer.cs +++ b/Engine.Core/Serialization/ISerializer.cs @@ -9,4 +9,10 @@ public interface ISerializer T Deserialize(string configuration); string Serialize(object instance); + + ProgressiveTask DeserializeAsync(string configuration); + ProgressiveTask DeserializeAsync(string configuration, Type type); + ProgressiveTask DeserializeAsync(string configuration); + + ProgressiveTask SerializeAsync(object instance); } diff --git a/Engine.Serializers/Engine.Serializers.Yaml/Converters/Abstract/IEngineTypeYamlConverter.cs b/Engine.Serializers/Engine.Serializers.Yaml/Converters/Abstract/IEngineTypeYamlConverter.cs index 110cc90..e9812d9 100644 --- a/Engine.Serializers/Engine.Serializers.Yaml/Converters/Abstract/IEngineTypeYamlConverter.cs +++ b/Engine.Serializers/Engine.Serializers.Yaml/Converters/Abstract/IEngineTypeYamlConverter.cs @@ -1,3 +1,4 @@ +using Syntriax.Engine.Core; using Syntriax.Engine.Core.Serialization; using YamlDotNet.Serialization; @@ -8,4 +9,5 @@ public interface IEngineTypeYamlConverter : IYamlTypeConverter { YamlSerializer Serializer { get; set; } EntityRegistry EntityRegistry { get; set; } + IProgressionTracker ProgressionTracker { get; set; } } diff --git a/Engine.Serializers/Engine.Serializers.Yaml/Converters/BehaviourControllerConverter.cs b/Engine.Serializers/Engine.Serializers.Yaml/Converters/BehaviourControllerConverter.cs index 3ebc134..770f9f1 100644 --- a/Engine.Serializers/Engine.Serializers.Yaml/Converters/BehaviourControllerConverter.cs +++ b/Engine.Serializers/Engine.Serializers.Yaml/Converters/BehaviourControllerConverter.cs @@ -17,6 +17,9 @@ public class BehaviourControllerConverter : EngineTypeYamlSerializerBase().Value.CompareTo(SERIALIZED_SCALAR_NAME) != 0) throw new(); SerializedClass instanceSerializedClass = (SerializedClass)rootDeserializer(typeof(SerializedClass))!; + ProgressionTracker.Set(isTrackingController ? .5f : ProgressionTracker.Progression, $"Creating {instanceSerializedClass.Type}"); behaviourController = (IBehaviourController)instanceSerializedClass.CreateInstance(EntityRegistry); string value = parser.Consume().Value; @@ -53,6 +57,7 @@ public class BehaviourControllerConverter : EngineTypeYamlSerializerBase().Where(b => !b.GetType().HasAttribute())); + ProgressionTracker.Set(isTrackingController ? 1f : ProgressionTracker.Progression, $"Serialized behaviour controller"); emitter.Emit(new MappingEnd()); } } diff --git a/Engine.Serializers/Engine.Serializers.Yaml/Converters/BehaviourConverter.cs b/Engine.Serializers/Engine.Serializers.Yaml/Converters/BehaviourConverter.cs index 9a9c9b4..eebfdd1 100644 --- a/Engine.Serializers/Engine.Serializers.Yaml/Converters/BehaviourConverter.cs +++ b/Engine.Serializers/Engine.Serializers.Yaml/Converters/BehaviourConverter.cs @@ -13,6 +13,9 @@ public class BehaviourConverter : EngineTypeYamlSerializerBase { public override IBehaviour? Read(IParser parser, Type type, ObjectDeserializer rootDeserializer) { + bool isTrackingController = ProgressionTracker.Progression.ApproximatelyEquals(0f); + ProgressionTracker.Set(isTrackingController ? .25f : ProgressionTracker.Progression, $"Reading behaviour information"); + string id; int priority; @@ -32,6 +35,7 @@ public class BehaviourConverter : EngineTypeYamlSerializerBase if (parser.Consume().Value.CompareTo(SERIALIZED_SCALAR_NAME) != 0) throw new(); SerializedClass instanceSerializedClass = (SerializedClass)rootDeserializer(typeof(SerializedClass))!; + ProgressionTracker.Set(isTrackingController ? .5f : ProgressionTracker.Progression, $"Creating {instanceSerializedClass.Type}"); behaviour = (IBehaviour)instanceSerializedClass.CreateInstance(EntityRegistry); if (parser.Consume().Value.CompareTo(nameof(IBehaviour.StateEnable)) != 0) @@ -46,6 +50,7 @@ public class BehaviourConverter : EngineTypeYamlSerializerBase stateEnable.Assign(behaviour); behaviour.Assign(stateEnable); + ProgressionTracker.Set(isTrackingController ? 1f : ProgressionTracker.Progression, $"Created {instanceSerializedClass.Type}"); return behaviour; } @@ -53,6 +58,9 @@ public class BehaviourConverter : EngineTypeYamlSerializerBase { IBehaviour behaviour = (IBehaviour)value!; + bool isTrackingController = ProgressionTracker.Progression.ApproximatelyEquals(0f); + ProgressionTracker.Set(isTrackingController ? .25f : ProgressionTracker.Progression, $"Serializing behaviour"); + emitter.Emit(new MappingStart()); emitter.Emit(new Scalar(nameof(IBehaviour.Id))); @@ -67,6 +75,7 @@ public class BehaviourConverter : EngineTypeYamlSerializerBase emitter.Emit(new Scalar(nameof(IBehaviour.StateEnable))); serializer(behaviour.StateEnable); + ProgressionTracker.Set(isTrackingController ? 1f : ProgressionTracker.Progression, $"Serialized behaviour"); emitter.Emit(new MappingEnd()); } } diff --git a/Engine.Serializers/Engine.Serializers.Yaml/Converters/EngineTypeYamlConverterBase.cs b/Engine.Serializers/Engine.Serializers.Yaml/Converters/EngineTypeYamlConverterBase.cs index 2b2573f..4e8d731 100644 --- a/Engine.Serializers/Engine.Serializers.Yaml/Converters/EngineTypeYamlConverterBase.cs +++ b/Engine.Serializers/Engine.Serializers.Yaml/Converters/EngineTypeYamlConverterBase.cs @@ -14,6 +14,7 @@ public abstract class EngineTypeYamlSerializerBase : IEngineTypeYamlConverter public EntityRegistry EntityRegistry { get; set; } = null!; public YamlSerializer Serializer { get; set; } = null!; + public IProgressionTracker ProgressionTracker { get; set; } = null!; public bool Accepts(Type type) => typeof(T).IsAssignableFrom(type); diff --git a/Engine.Serializers/Engine.Serializers.Yaml/Converters/SerializedClassConverter.cs b/Engine.Serializers/Engine.Serializers.Yaml/Converters/SerializedClassConverter.cs index 41c3d33..2dd9455 100644 --- a/Engine.Serializers/Engine.Serializers.Yaml/Converters/SerializedClassConverter.cs +++ b/Engine.Serializers/Engine.Serializers.Yaml/Converters/SerializedClassConverter.cs @@ -2,8 +2,9 @@ using System; using System.Collections.Generic; using System.Linq; -using Syntriax.Engine.Core.Serialization; +using Syntriax.Engine.Core; using Syntriax.Engine.Core.Factory; +using Syntriax.Engine.Core.Serialization; using YamlDotNet.Core; using YamlDotNet.Core.Events; @@ -15,6 +16,9 @@ public class SerializedClassConverter : EngineTypeYamlSerializerBase publicDictionary = []; Dictionary privateDictionary = []; @@ -39,6 +43,7 @@ public class SerializedClassConverter : EngineTypeYamlSerializerBase publics = []; Dictionary privates = []; @@ -72,6 +80,7 @@ public class SerializedClassConverter : EngineTypeYamlSerializerBase { public override IStateEnable? Read(IParser parser, Type type, ObjectDeserializer rootDeserializer) { + bool isTrackingController = ProgressionTracker.Progression.ApproximatelyEquals(0f); + ProgressionTracker.Set(isTrackingController ? .25f : ProgressionTracker.Progression, $"Reading state enable"); + bool enabled; IStateEnable stateEnable; @@ -32,6 +35,7 @@ public class StateEnableConverter : EngineTypeYamlSerializerBase stateEnable.Enabled = enabled; + ProgressionTracker.Set(isTrackingController ? .25f : ProgressionTracker.Progression, $"Read state enable"); return stateEnable; } @@ -39,6 +43,9 @@ public class StateEnableConverter : EngineTypeYamlSerializerBase { IStateEnable stateEnable = (IStateEnable)value!; + bool isTrackingController = ProgressionTracker.Progression.ApproximatelyEquals(0f); + ProgressionTracker.Set(isTrackingController ? .25f : ProgressionTracker.Progression, $"Serializing state enable"); + emitter.Emit(new MappingStart()); emitter.Emit(new Scalar(nameof(IStateEnable.Enabled))); @@ -47,6 +54,7 @@ public class StateEnableConverter : EngineTypeYamlSerializerBase emitter.Emit(new Scalar(SERIALIZED_SCALAR_NAME)); serializer(new SerializedClass(stateEnable)); + ProgressionTracker.Set(isTrackingController ? 1f : ProgressionTracker.Progression, $"Serialized state enable"); emitter.Emit(new MappingEnd()); } } diff --git a/Engine.Serializers/Engine.Serializers.Yaml/Converters/UniverseConverter.cs b/Engine.Serializers/Engine.Serializers.Yaml/Converters/UniverseConverter.cs index 982ffa5..1fbf978 100644 --- a/Engine.Serializers/Engine.Serializers.Yaml/Converters/UniverseConverter.cs +++ b/Engine.Serializers/Engine.Serializers.Yaml/Converters/UniverseConverter.cs @@ -15,6 +15,9 @@ public class UniverseConverter : EngineTypeYamlSerializerBase { public override IUniverse? Read(IParser parser, Type type, ObjectDeserializer rootDeserializer) { + bool isTrackingController = ProgressionTracker.Progression.ApproximatelyEquals(0f); + ProgressionTracker.Set(isTrackingController ? 0.1f : ProgressionTracker.Progression, "Reading universe"); + string id; IUniverse universe; @@ -30,12 +33,14 @@ public class UniverseConverter : EngineTypeYamlSerializerBase if (parser.Consume().Value.CompareTo(SERIALIZED_SCALAR_NAME) != 0) throw new(); SerializedClass instanceSerializedClass = (SerializedClass)rootDeserializer(typeof(SerializedClass))!; + ProgressionTracker.Set(isTrackingController ? .2f : ProgressionTracker.Progression, $"Creating {instanceSerializedClass.Type}"); universe = (IUniverse)instanceSerializedClass.CreateInstance(EntityRegistry); if (parser.Consume().Value.CompareTo(nameof(IUniverse.StateEnable)) != 0) throw new(); stateEnable = (IStateEnable)rootDeserializer(typeof(IStateEnable))!; + ProgressionTracker.Set(isTrackingController ? .5f : ProgressionTracker.Progression, $"Reading universe objects"); if (parser.Consume().Value.CompareTo(nameof(IUniverse.UniverseObjects)) != 0) throw new(); universeObjects = (List)rootDeserializer(typeof(List))!; @@ -47,9 +52,16 @@ public class UniverseConverter : EngineTypeYamlSerializerBase stateEnable.Assign(universe); universe.Assign(stateEnable); - foreach (IUniverseObject uo in universeObjects) - universe.Register(uo); + ProgressionTracker.Set(isTrackingController ? .9f : ProgressionTracker.Progression, "Registering universe objects"); + for (int i = 0; i < universeObjects.Count; i++) + { + IUniverseObject uo = universeObjects[i]; + ProgressionTracker.Set(isTrackingController ? .9f + .1f * ((float)i / universeObjects.Count) : ProgressionTracker.Progression, $"Registering {uo.Name}"); + universe.Register(uo); + } + + ProgressionTracker.Set(isTrackingController ? 1f : ProgressionTracker.Progression, $"Created {instanceSerializedClass.Type}"); return universe; } @@ -57,16 +69,10 @@ public class UniverseConverter : EngineTypeYamlSerializerBase { IUniverse universe = (IUniverse)value!; - IEnumerable rootUniverseObjects = universe.UniverseObjects - .Select(uo => - { - IUniverseObject root = uo; - while (root.Parent is IUniverseObject parent) - root = parent; - return root; - }) - .Where(uo => !uo.GetType().HasAttribute()) - .Distinct(); + bool isTrackingController = ProgressionTracker.Progression.ApproximatelyEquals(0f); + ProgressionTracker.Set(isTrackingController ? .25f : ProgressionTracker.Progression, $"Serializing universe"); + + IEnumerable rootUniverseObjects = universe.UniverseObjects.Where(uo => uo.Parent is null); emitter.Emit(new MappingStart()); @@ -82,6 +88,7 @@ public class UniverseConverter : EngineTypeYamlSerializerBase emitter.Emit(new Scalar(nameof(IUniverse.UniverseObjects))); serializer(rootUniverseObjects); + ProgressionTracker.Set(isTrackingController ? 1f : ProgressionTracker.Progression, $"Serialized universe"); emitter.Emit(new MappingEnd()); } } diff --git a/Engine.Serializers/Engine.Serializers.Yaml/Converters/UniverseObjectConverter.cs b/Engine.Serializers/Engine.Serializers.Yaml/Converters/UniverseObjectConverter.cs index db3c267..527e2b0 100644 --- a/Engine.Serializers/Engine.Serializers.Yaml/Converters/UniverseObjectConverter.cs +++ b/Engine.Serializers/Engine.Serializers.Yaml/Converters/UniverseObjectConverter.cs @@ -15,6 +15,8 @@ public class UniverseObjectSerializer : EngineTypeYamlSerializerBase().Value.CompareTo(nameof(IUniverseObject.Name)) != 0) throw new(); name = parser.Consume().Value; + ProgressionTracker.Set(isTrackingController ? .1f : ProgressionTracker.Progression, $"Reading {name}"); if (parser.Consume().Value.CompareTo(nameof(IUniverseObject.Id)) != 0) throw new(); @@ -36,6 +39,7 @@ public class UniverseObjectSerializer : EngineTypeYamlSerializerBase().Value.CompareTo(SERIALIZED_SCALAR_NAME) != 0) throw new(); SerializedClass instanceSerializedClass = (SerializedClass)rootDeserializer(typeof(SerializedClass))!; + ProgressionTracker.Set(isTrackingController ? .3f : ProgressionTracker.Progression, $"Creating {instanceSerializedClass.Type}"); universeObject = (IUniverseObject)instanceSerializedClass.CreateInstance(EntityRegistry); if (parser.Consume().Value.CompareTo(nameof(IUniverseObject.StateEnable)) != 0) @@ -64,6 +68,7 @@ public class UniverseObjectSerializer : EngineTypeYamlSerializerBase !c.GetType().HasAttribute())); + ProgressionTracker.Set(isTrackingController ? 1f : ProgressionTracker.Progression, $"Serializing universe object"); emitter.Emit(new MappingEnd()); } } diff --git a/Engine.Serializers/Engine.Serializers.Yaml/SerializerInProgressException.cs b/Engine.Serializers/Engine.Serializers.Yaml/SerializerInProgressException.cs new file mode 100644 index 0000000..2b03c0b --- /dev/null +++ b/Engine.Serializers/Engine.Serializers.Yaml/SerializerInProgressException.cs @@ -0,0 +1,6 @@ +using System; + +namespace Syntriax.Engine.Serializers.Yaml; + +[Serializable] +public class SerializerInProgressException() : Exception("There's already a running deserialization in progress."); diff --git a/Engine.Serializers/Engine.Serializers.Yaml/YamlSerializer.cs b/Engine.Serializers/Engine.Serializers.Yaml/YamlSerializer.cs index 93cfe4c..15d5f2f 100644 --- a/Engine.Serializers/Engine.Serializers.Yaml/YamlSerializer.cs +++ b/Engine.Serializers/Engine.Serializers.Yaml/YamlSerializer.cs @@ -2,7 +2,9 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Threading.Tasks; +using Syntriax.Engine.Core; using Syntriax.Engine.Core.Serialization; using YamlDotNet.Serialization; @@ -16,10 +18,14 @@ public class YamlSerializer : Core.Serialization.ISerializer private readonly YamlDotNet.Serialization.IDeserializer deserializer = null!; private readonly EntityRegistry entityRegistry = null!; + private readonly IProgressionTracker progressionTracker = null!; + + private readonly System.Threading.Lock Lock = new(); public YamlSerializer() { entityRegistry = new(); + progressionTracker = new ProgressionTracker(); SerializerBuilder serializerBuilder = new SerializerBuilder() .WithNamingConvention(PascalCaseNamingConvention.Instance) @@ -32,6 +38,7 @@ public class YamlSerializer : Core.Serialization.ISerializer { typeConverter.Serializer = this; typeConverter.EntityRegistry = entityRegistry; + typeConverter.ProgressionTracker = progressionTracker; deserializerBuilder = deserializerBuilder.WithTypeConverter(typeConverter); serializerBuilder = serializerBuilder.WithTypeConverter(typeConverter); @@ -49,35 +56,87 @@ public class YamlSerializer : Core.Serialization.ISerializer public string Serialize(object instance) { - return serializer.Serialize(instance); + lock (Lock) + { + return serializer.Serialize(instance); + } } - public object Deserialize(string yaml) + public object Deserialize(string configuration) { - entityRegistry.Reset(); - object result = deserializer.Deserialize(yaml)!; - entityRegistry.AssignAll(); - return result; + lock (Lock) + { + entityRegistry.Reset(); + object result = deserializer.Deserialize(configuration)!; + entityRegistry.AssignAll(); + return result; + } } - public object Deserialize(string yaml, Type type) + public object Deserialize(string configuration, Type type) { - entityRegistry.Reset(); - object result = deserializer.Deserialize(yaml, type)!; - entityRegistry.AssignAll(); - return result; + lock (Lock) + { + entityRegistry.Reset(); + object result = deserializer.Deserialize(configuration, type)!; + entityRegistry.AssignAll(); + return result; + } } - public T Deserialize(string yaml) + public T Deserialize(string configuration) { - entityRegistry.Reset(); - T result = deserializer.Deserialize(yaml); - entityRegistry.AssignAll(); - return result; + lock (Lock) + { + entityRegistry.Reset(); + T result = deserializer.Deserialize(configuration); + entityRegistry.AssignAll(); + return result; + } } - internal object InternalDeserialize(string yaml, Type type) + public ProgressiveTask DeserializeAsync(string configuration) { - return deserializer.Deserialize(yaml, type)!; + lock (Lock) + { + progressionTracker.Reset(); + Task task = Task.Run(() => Deserialize(configuration)); + return new ProgressiveTask(progressionTracker, task); + } + } + + public ProgressiveTask DeserializeAsync(string configuration, Type type) + { + lock (Lock) + { + progressionTracker.Reset(); + Task task = Task.Run(() => Deserialize(configuration, type)); + return new ProgressiveTask(progressionTracker, task); + } + } + + public ProgressiveTask DeserializeAsync(string configuration) + { + lock (Lock) + { + progressionTracker.Reset(); + Task task = Task.Run(() => Deserialize(configuration)); + return new ProgressiveTask(progressionTracker, task); + } + } + + public ProgressiveTask SerializeAsync(object instance) + { + lock (Lock) + { + progressionTracker.Reset(); + Task task = Task.Run(() => Serialize(instance)); + return new ProgressiveTask(progressionTracker, task); + } + } + + internal object InternalDeserialize(string configuration, Type type) + { + return deserializer.Deserialize(configuration, type)!; } }