Skip to content

Commit

Permalink
Remove obsolete TARGETTING35SP1 preprocessor directive and dead code …
Browse files Browse the repository at this point in the history
…contained within (#9744)
  • Loading branch information
h3xds1nz authored Oct 8, 2024
1 parent f07e041 commit a08882f
Show file tree
Hide file tree
Showing 8 changed files with 19 additions and 413 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace System.Windows.Markup
namespace System.Windows.Markup
#endif
{
#if !PBTCOMPILER && !TARGETTING35SP1 && !WINDOWS_BASE
#if !PBTCOMPILER && !WINDOWS_BASE
/// <summary>
/// This attribute is placed on a class to identify the property that will
/// function as an Name for the given class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,9 @@ public static bool TryGetProperty<T>(object instance, AttachableMemberIdentifier
}

// DefaultAttachedPropertyStore is used by the global AttachedPropertyServices to implement
// global attached properties for types which don't implement IAttachedProperties or DO/Dependency Property
// integration for their attached properties.
//
#if !TARGETTING35SP1
// global attached properties for types which don't implement IAttachedProperties or DO/Dependency Property
// integration for their attached properties.

sealed class DefaultAttachedPropertyStore
{
Lazy<ConditionalWeakTable<object, Dictionary<AttachableMemberIdentifier, object>>> instanceStorage =
Expand Down Expand Up @@ -237,314 +236,5 @@ public bool TryGetProperty<T>(object instance, AttachableMemberIdentifier name,
return false;
}
}
#else
//***********************************************WARNING************************************************************
// In CLR4.0 there is ConditionalWeakTable. This implementation is for 3.5 and uses a WeakKey dictionary.
// This implementation does not handle the problem where a key is rooted in a value (or graph of a value).
// This will "leak" (never get cleaned up). If we ship a 3.5 version of System.Xaml.dll we should
// consider adding logic that detects such cycles on Add and throws.
//******************************************************************************************************************
sealed class DefaultAttachedPropertyStore
{
Lazy<WeakDictionary<object, Dictionary<AttachableMemberIdentifier, object>>> instanceStorage =
new Lazy<WeakDictionary<object, Dictionary<AttachableMemberIdentifier, object>>>(
() => new WeakDictionary<object, Dictionary<AttachableMemberIdentifier, object>>(), LazyInitMode.AllowMultipleThreadSafeExecution);

public void CopyPropertiesTo(object instance, KeyValuePair<AttachableMemberIdentifier, object>[] array, int index)
{
if (instanceStorage.IsInitialized)
{
lock (instanceStorage.Value.SyncObject)
{
Dictionary<AttachableMemberIdentifier, object> instanceProperties;
if (instanceStorage.Value.TryGetValue(instance, out instanceProperties))
{
((ICollection<KeyValuePair<AttachableMemberIdentifier, object>>)instanceProperties).CopyTo(array, index);
}
}
}
}

public int GetPropertyCount(object instance)
{
if (instanceStorage.IsInitialized)
{
lock(instanceStorage.Value.SyncObject)
{
Dictionary<AttachableMemberIdentifier, object> instanceProperties;
if (instanceStorage.Value.TryGetValue(instance, out instanceProperties))
{
return instanceProperties.Count;
}
}
}
return 0;
}

// <summary>
// Remove the property 'name'. If the property doesn't exist it returns false.
// </summary>
public bool RemoveProperty(object instance, AttachableMemberIdentifier name)
{
if (instanceStorage.IsInitialized)
{
lock (instanceStorage.Value.SyncObject)
{
Dictionary<AttachableMemberIdentifier, object> instanceProperties;
if (instanceStorage.Value.TryGetValue(instance, out instanceProperties))
{
return instanceProperties.Remove(name);
}
}
}
return false;
}

// <summary>
// Set the property 'name' value to 'value', if the property doesn't currently exist this will add the property
// </summary>
public void SetProperty(object instance, AttachableMemberIdentifier name, object value)
{
//
// Accessing Value forces initialization
lock (instanceStorage.Value.SyncObject)
{
Dictionary<AttachableMemberIdentifier, object> instanceProperties;
if (!instanceStorage.Value.TryGetValue(instance, out instanceProperties))
{
instanceProperties = new Dictionary<AttachableMemberIdentifier, object>();
instanceStorage.Value.Add(instance, instanceProperties);
}
instanceProperties[name] = value;
}
}

// <summary>
// Retrieve the value of the attached property 'name'. If there is not attached property then return false.
// </summary>
public bool TryGetProperty<T>(object instance, AttachableMemberIdentifier name, out T value)
{
if (instanceStorage.IsInitialized)
{
lock (instanceStorage.Value.SyncObject)
{
Dictionary<AttachableMemberIdentifier, object> attachedProperties;
if (instanceStorage.Value.TryGetValue(instance, out attachedProperties))
{
object valueAsObj;
if (attachedProperties.TryGetValue(name, out valueAsObj) &&
valueAsObj is T)
{
value = (T)valueAsObj;
return true;
}
}
}
}
value = default(T);
return false;
}

public class WeakDictionary<K, V>
where K : class
where V : class
{
// Optimally this would be a _real_ dictionary implementation that when it ran across WeakKey's that had
// gone out of scope would immediately at least clear their value and from time to time schedule a real
// cleanup.
Dictionary<WeakKey, V> storage;
object cleanupSyncObject;

public WeakDictionary()
{
if (typeof(K) == typeof(WeakReference))
{
throw new InvalidOperationException();
}

this.cleanupSyncObject = new object();
storage = new Dictionary<WeakDictionary<K, V>.WeakKey, V>();
// kick off the cleanup process...
WeakDictionaryCleanupToken.CreateCleanupToken(this);
}

public int Count
{
get { return storage.Count; }
}

public void Add(K key, V value)
{
storage.Add(new WeakKey(key, false), value);
}

internal object SyncObject
{
get { return this.cleanupSyncObject; }
}

public void Cleanup()
{
List<WeakKey> toClean = null;

// First determine what items have died and can be removed...
lock(cleanupSyncObject)
{
foreach (var key in storage.Keys)
{
bool isAlive, needsCleanup;
key.GetValue(out isAlive, out needsCleanup);
if (!isAlive)
{
if (toClean == null)
{
toClean = new List<WeakKey>();
}
toClean.Add(key);
}
}
}

if (toClean != null)
{
// Second go and remove them...
lock(cleanupSyncObject)
{
// If toClean is > some % of the total size it is probably better
// just to create a new dictionary and migrate some set of items over
// wholesale? It is unclear whether or not this is true.
foreach (var key in toClean)
{
storage.Remove(key);
}
}
}

WeakDictionaryCleanupToken.CreateCleanupToken(this);
}

public bool Remove(K key)
{
return storage.Remove(new WeakKey(key, true));
}

public bool TryGetValue(K key, out V value)
{
return storage.TryGetValue(new WeakKey(key, true), out value);
}

public struct WeakKey : IEquatable<WeakKey>
{
int hashCode;
object reference;

public WeakKey(K key, bool lookup)
{
hashCode = key.GetHashCode();
reference = lookup ? key : (object)new WeakReference(key);
}

public override int GetHashCode()
{
return hashCode;
}

public K GetValue(out bool isAlive, out bool needsCleanup)
{
if (reference == null)
{
isAlive = false;
needsCleanup = false;
return (K)reference;
}

K value;
WeakReference wr = reference as WeakReference;
if (wr != null)
{
value = (K)wr.Target;
isAlive = value != null;
needsCleanup = !isAlive;
if (needsCleanup)
{
// This cleans up the WeakReference now that we know the
// target object is dead...
reference = null;
}
return value;
}

value = reference as K;
if (value != null)
{
isAlive = true;
needsCleanup = false;
return value;
}

throw new InvalidOperationException();
}

public bool Equals(WeakKey other)
{
WeakKey x = this;
WeakKey y = other;
bool xIsAlive, yIsAlive;
bool xNeedsCleanup, yNeedsCleanup;
K xKey = x.GetValue(out xIsAlive, out xNeedsCleanup);
K yKey = y.GetValue(out yIsAlive, out yNeedsCleanup);

// If they are both not alive then they are equivalent
if (!xIsAlive && !yIsAlive)
{
return true;
}

if (!xIsAlive || !yIsAlive)
{
return false;
}

return xKey == yKey;
}
}

// This cleanup token will be immediately thrown away and as a result it will
// (a couple of GCs later) make it into the finalization queue and when finalized
// will kick off a thread-pool job to cleanup the dictionary.

public class WeakDictionaryCleanupToken
{
WeakDictionary<K, V> storage;

WeakDictionaryCleanupToken(WeakDictionary<K, V> storage)
{
this.storage = storage;
}

~WeakDictionaryCleanupToken()
{
// Schedule cleanup
ThreadPool.QueueUserWorkItem((WaitCallback)delegate
{
storage.Cleanup();
});
}

[SuppressMessage("Microsoft.Usage", "CA1806",
Justification = "The point of this method is to create one of these and let it float away... To be finalized...")]
[SuppressMessage("Microsoft.Performance", "CA1804",
Justification = "The point of this method is to create one of these and let it float away... To be finalized...")]
public static void CreateCleanupToken(WeakDictionary<K, V> storage)
{
// Create one of these, the work is done when it is finalized which
// will be at some indeterminate point in the future...
WeakDictionaryCleanupToken token = new WeakDictionaryCleanupToken(storage);
}
}

}
}
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,7 @@ public ObjectWriterContext(XamlSavedContext savedContext,
XAML3.INameScopeDictionary rootNameScopeDictionary = null;
if (rootNameScope == null)
{
#if TARGETTING35SP1
rootNameScopeDictionary = new NameScopeDictionary(new NameScope());
#else
rootNameScopeDictionary = new NameScope();
#endif
}
else
{
Expand Down Expand Up @@ -90,11 +86,7 @@ public ObjectWriterContext(XamlSchemaContext schemaContext,
XAML3.INameScopeDictionary rootNameScopeDictionary = null;
if (rootNameScope == null)
{
#if TARGETTING35SP1
rootNameScopeDictionary = new NameScopeDictionary(new NameScope());
#else
rootNameScopeDictionary = new NameScope();
#endif
}
else
{
Expand Down Expand Up @@ -814,11 +806,7 @@ private XAML3.INameScopeDictionary LookupNameScopeDictionary(ObjectWriterFrame f
if (frame.Depth == SavedDepth + 1 &&
_settings != null && !_settings.RegisterNamesOnExternalNamescope)
{
#if TARGETTING35SP1
frame.NameScopeDictionary = new NameScopeDictionary(new NameScope());
#else
frame.NameScopeDictionary = new NameScope();
#endif
}
else
{
Expand Down Expand Up @@ -912,11 +900,7 @@ private XAML3.INameScopeDictionary HuntAroundForARootNameScope(ObjectWriterFrame
XAML3.INameScope nameScope = (XAML3.INameScope)_runtime.GetValue(inst, nameScopeProperty, false);
if (nameScope == null)
{
#if TARGETTING35SP1
nameScopeDictionary = new NameScopeDictionary(new NameScope());
#else
nameScopeDictionary = new NameScope();
#endif
_runtime.SetValue(inst, nameScopeProperty, nameScopeDictionary);
}
else
Expand All @@ -942,11 +926,7 @@ private XAML3.INameScopeDictionary HuntAroundForARootNameScope(ObjectWriterFrame
// for our own usage. For IXamlNameResolver() to use.
if (nameScopeDictionary == null)
{
#if TARGETTING35SP1
nameScopeDictionary = new NameScopeDictionary(new NameScope());
#else
nameScopeDictionary = new NameScope();
#endif
}

rootFrame.NameScopeDictionary = nameScopeDictionary;
Expand Down
Loading

0 comments on commit a08882f

Please # to comment.