public InvariantObjectAndGCHandle(object value, object handle) { #if NET6_0 Token = new DependentHandle(handle, value); #else Value = value; Handle = GCHandle.Alloc(handle, GCHandleType.Weak); #endif }
/// <summary> /// Initializes a new instance of the <see cref="DelegateBreakout"/> struct. /// </summary> /// <param name="delegate">The delegate.</param> /// <param name="onCollection">The method to invoke when <paramref name="delegate"/>'s target is garbage collected.</param> public DelegateBreakout(Delegate @delegate, Action onCollection) { delegateString = @delegate.Method.ToString(); if (@delegate.Target != null && onCollection != null) { delegateOrMethodInfo = @delegate.Method; target = new DependentHandle <object, GarbageAlerter>(@delegate.Target, new GarbageAlerter(onCollection)); } else { delegateOrMethodInfo = new WeakReference <Delegate>(@delegate); target = null; } }
/// <summary> /// Assigns a sync table entry to the object in a thread-safe way. /// </summary> public static unsafe int AssignEntry(object obj, int *pHeader) { // Allocate the synchronization object outside the lock Lock lck = new Lock(); DeadEntryCollector collector = new DeadEntryCollector(); DependentHandle handle = new DependentHandle(obj, collector); try { using (LockHolder.Hold(s_lock)) { // After acquiring the lock check whether another thread already assigned the sync entry if (ObjectHeader.GetSyncEntryIndex(*pHeader, out int hashOrIndex)) { return(hashOrIndex); } int syncIndex; if (s_freeEntryList != 0) { // Grab a free entry from the list syncIndex = s_freeEntryList; ref Entry freeEntry = ref s_entries[syncIndex]; s_freeEntryList = freeEntry.Next; freeEntry.Next = 0; } else { if (s_unusedEntryIndex >= s_entries.Length) { // No free entries, use the slow path. This call may OOM. Grow(); } // Grab the next unused entry Debug.Assert(s_unusedEntryIndex < s_entries.Length); syncIndex = s_unusedEntryIndex++; } ref Entry entry = ref s_entries[syncIndex];