1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 9 using System; 10 11 namespace Antmicro.Renode.Utilities 12 { 13 public class WeakWrapper<T> where T : class 14 { 15 // this method can be used to create *fake* WeakWrapper that holds no real WeakReference 16 // it is intended for use with methods like *Compare*, *ContainsKey* etc. yet without the overhead of creating the WeakReference CreateForComparison(T obj)17 public static WeakWrapper<T> CreateForComparison(T obj) 18 { 19 return new WeakWrapper<T>(obj, true); 20 } 21 WeakWrapper(T obj)22 public WeakWrapper(T obj) : this(obj, false) 23 { 24 } 25 ConvertToRealWeakWrapper()26 public void ConvertToRealWeakWrapper() 27 { 28 var objReferenceCopy = objReference; 29 if(objReferenceCopy == null) 30 { 31 throw new InvalidOperationException("Cannot convert real weak wrapper."); 32 } 33 34 objWeakReference = new WeakReference<T>(objReferenceCopy); 35 objReference = null; 36 } 37 Equals(object obj)38 public override bool Equals(object obj) 39 { 40 var objAsWeakWrapper = obj as WeakWrapper<T>; 41 if(objAsWeakWrapper != null) 42 { 43 T myTarget, objTarget; 44 bool hasTarget; 45 return ((hasTarget = TryGetTarget(out myTarget)) == objAsWeakWrapper.TryGetTarget(out objTarget)) && hasTarget && myTarget.Equals(objTarget); 46 } 47 48 return false; 49 } 50 GetHashCode()51 public override int GetHashCode() 52 { 53 return objHashCode; 54 } 55 TryGetTarget(out T target)56 public bool TryGetTarget(out T target) 57 { 58 if(objReference != null) 59 { 60 target = objReference; 61 return true; 62 } 63 return objWeakReference.TryGetTarget(out target); 64 } 65 WeakWrapper(T obj, bool doNotCreateWeakReference)66 private WeakWrapper(T obj, bool doNotCreateWeakReference) 67 { 68 // we can calculate the hashcode here, because according 69 // to "The Path of C#" `GetHashCode` method result should not 70 // be calculated from mutable fields, so it should not change 71 // during object's lifetime 72 objHashCode = obj.GetHashCode(); 73 if(doNotCreateWeakReference) 74 { 75 objReference = obj; 76 } 77 else 78 { 79 objWeakReference = new WeakReference<T>(obj); 80 } 81 } 82 83 private T objReference; 84 private WeakReference<T> objWeakReference; 85 private readonly int objHashCode; 86 } 87 } 88