diff --git a/OpenRA.Game/Sync.cs b/OpenRA.Game/Sync.cs index 1551b5fdd4..0cfe283921 100644 --- a/OpenRA.Game/Sync.cs +++ b/OpenRA.Game/Sync.cs @@ -20,22 +20,20 @@ namespace OpenRA { [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public sealed class SyncAttribute : Attribute { } - public interface ISync { } // marker interface + + // Marker interface + public interface ISync { } public static class Sync { - static readonly ConcurrentCache HashMethods = - new ConcurrentCache(GenerateHashFunc); - static readonly ConcurrentCache> HashFunctions = - new ConcurrentCache>( - type => (Func)HashMethods[type].CreateDelegate(typeof(Func))); + static Cache> hashFuncCache = new Cache>(t => GenerateHashFunc(t)); public static int CalculateSyncHash(object obj) { - return HashFunctions[obj.GetType()](obj); + return hashFuncCache[obj.GetType()](obj); } - static readonly Dictionary SpecializedHashMethods = new Dictionary + static Dictionary hashFunctions = new Dictionary() { { typeof(int2), ((Func)HashInt2).Method }, { typeof(CPos), ((Func)HashCPos).Method }, @@ -53,8 +51,8 @@ namespace OpenRA static void EmitSyncOpcodes(Type type, ILGenerator il) { - if (SpecializedHashMethods.ContainsKey(type)) - il.EmitCall(OpCodes.Call, SpecializedHashMethods[type], null); + if (hashFunctions.ContainsKey(type)) + il.EmitCall(OpCodes.Call, hashFunctions[type], null); else if (type == typeof(bool)) { var l = il.DefineLabel(); @@ -72,9 +70,9 @@ namespace OpenRA il.Emit(OpCodes.Xor); } - static DynamicMethod GenerateHashFunc(Type t) + public static Func GenerateHashFunc(Type t) { - var d = new DynamicMethod("Hash_{0}".F(t.Name), typeof(int), new Type[] { typeof(object) }, t); + var d = new DynamicMethod("hash_{0}".F(t.Name), typeof(int), new Type[] { typeof(object) }, t); var il = d.GetILGenerator(); var this_ = il.DeclareLocal(t).LocalIndex; il.Emit(OpCodes.Ldarg_0); @@ -82,17 +80,13 @@ namespace OpenRA il.Emit(OpCodes.Stloc, this_); il.Emit(OpCodes.Ldc_I4_0); - var neededSync = false; - - const BindingFlags Binding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly; - + const BindingFlags Binding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; foreach (var field in t.GetFields(Binding).Where(x => x.HasAttribute())) { il.Emit(OpCodes.Ldloc, this_); il.Emit(OpCodes.Ldfld, field); EmitSyncOpcodes(field.FieldType, il); - neededSync = true; } foreach (var prop in t.GetProperties(Binding).Where(x => x.HasAttribute())) @@ -101,23 +95,10 @@ namespace OpenRA il.EmitCall(OpCodes.Call, prop.GetGetMethod(), null); EmitSyncOpcodes(prop.PropertyType, il); - neededSync = true; - } - - if (t.BaseType != null) - { - var baseHashFunc = HashMethods[t.BaseType]; - if (baseHashFunc != null) - { - il.Emit(OpCodes.Ldloc, this_); - il.EmitCall(OpCodes.Call, baseHashFunc, null); - il.Emit(OpCodes.Xor); - neededSync = true; - } } il.Emit(OpCodes.Ret); - return neededSync ? d : null; + return (Func)d.CreateDelegate(typeof(Func)); } public static int HashInt2(int2 i2) diff --git a/OpenRA.Test/OpenRA.Game/SyncTest.cs b/OpenRA.Test/OpenRA.Game/SyncTest.cs deleted file mode 100644 index f7fa71d5f2..0000000000 --- a/OpenRA.Test/OpenRA.Game/SyncTest.cs +++ /dev/null @@ -1,78 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using NUnit.Framework; -using OpenRA.Traits; - -namespace OpenRA.Test -{ - [TestFixture] - class SyncTest - { - class Complex : ISync - { - [Sync] - public bool Bool = true; - [Sync] - public int Int = -123456789; - [Sync] - public int2 Int2 = new int2(123, -456); - [Sync] - public CPos CPos = new CPos(123, -456); - [Sync] - public CVec CVec = new CVec(123, -456); - [Sync] - public WDist WDist = new WDist(123); - [Sync] - public WPos WPos = new WPos(123, -456, int.MaxValue); - [Sync] - public WVec WVec = new WVec(123, -456, int.MaxValue); - [Sync] - public WAngle WAngle = new WAngle(123); - [Sync] - public WRot WRot = new WRot(new WAngle(123), new WAngle(-456), new WAngle(int.MaxValue)); - [Sync] - public Target Target = Target.FromPos(new WPos(123, -456, int.MaxValue)); - } - - [TestCase(TestName = "Sync hashing has not accidentally changed")] - public void ComplexHash() - { - // If you have intentionally changed the values used for sync hashing, just update the expected value. - Assert.AreEqual(-2024026914, Sync.CalculateSyncHash(new Complex())); - } - - class Flat : ISync - { - [Sync] - int a = 123456789; - [Sync] - bool b = true; - } - - class Base : ISync - { - [Sync] - bool b = true; - } - - class Derived : Base - { - [Sync] - int a = 123456789; - } - - [TestCase(TestName = "All sync members in inheritance hierarchy are hashed")] - public void DerivedHash() - { - Assert.AreEqual(Sync.CalculateSyncHash(new Flat()), Sync.CalculateSyncHash(new Derived())); - } - } -} diff --git a/OpenRA.Test/OpenRA.Test.csproj b/OpenRA.Test/OpenRA.Test.csproj index 04390022b1..6c080bd939 100644 --- a/OpenRA.Test/OpenRA.Test.csproj +++ b/OpenRA.Test/OpenRA.Test.csproj @@ -49,7 +49,6 @@ -