From 6b4e52febbd69cc6b25735c96d89910d41e09d93 Mon Sep 17 00:00:00 2001 From: ZaneYork Date: Wed, 3 Jun 2020 10:56:31 +0800 Subject: Parallel exception aggregate fix --- .../ModLoading/Framework/RecursiveRewriter.cs | 101 ++++++++++++--------- 1 file changed, 58 insertions(+), 43 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs b/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs index c774c038..c03376d6 100644 --- a/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs +++ b/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs @@ -57,60 +57,75 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework /// Returns whether the module was modified. public bool RewriteModule() { - bool anyRewritten = false; - - foreach (TypeDefinition type in this.Module.GetTypes()) - { - if (type.BaseType == null) - continue; // special type like - - anyRewritten |= this.RewriteCustomAttributes(type.CustomAttributes); - anyRewritten |= this.RewriteGenericParameters(type.GenericParameters); - - foreach (InterfaceImplementation @interface in type.Interfaces) - anyRewritten |= this.RewriteTypeReference(@interface.InterfaceType, newType => @interface.InterfaceType = newType); - - if (type.BaseType.FullName != "System.Object") - anyRewritten |= this.RewriteTypeReference(type.BaseType, newType => type.BaseType = newType); - - foreach (MethodDefinition method in type.Methods) + Tuple aggregateResult = this.Module.GetTypes() + .AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism) + .Select(type => { - anyRewritten |= this.RewriteTypeReference(method.ReturnType, newType => method.ReturnType = newType); - anyRewritten |= this.RewriteGenericParameters(method.GenericParameters); - anyRewritten |= this.RewriteCustomAttributes(method.CustomAttributes); + try + { + bool anyRewritten = false; + if (type.BaseType == null) + return new Tuple(anyRewritten, null); // special type like - foreach (ParameterDefinition parameter in method.Parameters) - anyRewritten |= this.RewriteTypeReference(parameter.ParameterType, newType => parameter.ParameterType = newType); + anyRewritten |= this.RewriteCustomAttributes(type.CustomAttributes); + anyRewritten |= this.RewriteGenericParameters(type.GenericParameters); - foreach (var methodOverride in method.Overrides) - anyRewritten |= this.RewriteMethodReference(methodOverride); + foreach (InterfaceImplementation @interface in type.Interfaces) + anyRewritten |= this.RewriteTypeReference(@interface.InterfaceType, newType => @interface.InterfaceType = newType); - if (method.HasBody) - { - foreach (VariableDefinition variable in method.Body.Variables) - anyRewritten |= this.RewriteTypeReference(variable.VariableType, newType => variable.VariableType = newType); + if (type.BaseType.FullName != "System.Object") + anyRewritten |= this.RewriteTypeReference(type.BaseType, newType => type.BaseType = newType); - // check CIL instructions - ILProcessor cil = method.Body.GetILProcessor(); - Collection instructions = cil.Body.Instructions; - for (int i = 0; i < instructions.Count; i++) + foreach (MethodDefinition method in type.Methods) { - var instruction = instructions[i]; - if (instruction.OpCode.Code == Code.Nop) - continue; + anyRewritten |= this.RewriteTypeReference(method.ReturnType, newType => method.ReturnType = newType); + anyRewritten |= this.RewriteGenericParameters(method.GenericParameters); + anyRewritten |= this.RewriteCustomAttributes(method.CustomAttributes); - anyRewritten |= this.RewriteInstruction(instruction, cil, newInstruction => + foreach (ParameterDefinition parameter in method.Parameters) + anyRewritten |= this.RewriteTypeReference(parameter.ParameterType, newType => parameter.ParameterType = newType); + + foreach (var methodOverride in method.Overrides) + anyRewritten |= this.RewriteMethodReference(methodOverride); + + if (method.HasBody) { - anyRewritten = true; - cil.Replace(instruction, newInstruction); - instruction = newInstruction; - }); + foreach (VariableDefinition variable in method.Body.Variables) + anyRewritten |= this.RewriteTypeReference(variable.VariableType, newType => variable.VariableType = newType); + + // check CIL instructions + ILProcessor cil = method.Body.GetILProcessor(); + Collection instructions = cil.Body.Instructions; + for (int i = 0; i < instructions.Count; i++) + { + var instruction = instructions[i]; + if (instruction.OpCode.Code == Code.Nop) + continue; + + anyRewritten |= this.RewriteInstruction(instruction, cil, newInstruction => + { + anyRewritten = true; + cil.Replace(instruction, newInstruction); + instruction = newInstruction; + }); + } + } } + + return new Tuple(anyRewritten, null); } - } + catch (Exception e) + { + return new Tuple(false, e.InnerException ?? e); + } + }) + .TakeWhile(tuple => tuple.Item2 == null) // Stop on any exception occurs + .Aggregate((tupleA, tupleB) => new Tuple(tupleA.Item1 | tupleB.Item1, tupleA.Item2 ?? tupleB.Item2)); // Aggregate result and exception + if (aggregateResult.Item2 != null) + { + throw aggregateResult.Item2; // rethrow inner Exception } - - return anyRewritten; + return aggregateResult.Item1; } -- cgit From 9b41397a019e6cc32b5c1ab502fa4abdb9a9ef49 Mon Sep 17 00:00:00 2001 From: ZaneYork Date: Wed, 3 Jun 2020 11:43:13 +0800 Subject: Remove take while op(does not return first none matched item) --- src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs b/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs index c03376d6..579c3a08 100644 --- a/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs +++ b/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs @@ -119,7 +119,6 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework return new Tuple(false, e.InnerException ?? e); } }) - .TakeWhile(tuple => tuple.Item2 == null) // Stop on any exception occurs .Aggregate((tupleA, tupleB) => new Tuple(tupleA.Item1 | tupleB.Item1, tupleA.Item2 ?? tupleB.Item2)); // Aggregate result and exception if (aggregateResult.Item2 != null) { -- cgit