Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to understand Microsoft's implementation of WeakReference

As a seasoned C++ programmer trying to get accustomed to .NET, there's an implementation detail in Microsoft's WeakReference "Target" property that's bugging me...

public class WeakReference : ISerializable
{
    internal IntPtr m_handle;
    internal bool m_IsLongReference;
                 ...
    public virtual object Target
    {
        [SecuritySafeCritical]
        get
        {
            IntPtr handle = this.m_handle;
            if (IntPtr.Zero == handle)
            {
                return null;
            }
            object result = GCHandle.InternalGet(handle);
            if (!(this.m_handle == IntPtr.Zero))
            {
                return result;
            }
            return null;
        }
        [SecuritySafeCritical]
        set
        {
            IntPtr handle = this.m_handle;
            if (handle == IntPtr.Zero)
            {
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
            }
            object oldValue = GCHandle.InternalGet(handle);
            handle = this.m_handle;
            if (handle == IntPtr.Zero)
            {
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
            }
            GCHandle.InternalCompareExchange(handle, value, oldValue, false);
            GC.KeepAlive(this);
        }
    }
     ...
       }

The thing that's bugging me is this - why are they checking the validity of m_handle twice? Particularly in the 'set' method - the use of the GC.KeepAlive at the end of the method should keep the WeakReference from being garbage collected, and thus keep the handle non-zero - right?

And in the case of the 'get' - once we've actually retrieved a reference to the target via InternalGet, why bother checking the original m_handle value again? All I can think is that perhaps they're trying to guard against the WeakReference being disposed and finalized either during or after the InternalGet - but surely, couldn't it also be disposed and finalized before we get around to returning the object? I just can't come up w/ a valid explanation as to why this double-checking is necessary here...

like image 754
Kevin Avatar asked Dec 29 '11 19:12

Kevin


People also ask

When should WeakReference be used in garbage collection?

A weak reference permits the garbage collector to collect the object while still allowing the application to access the object. A weak reference is valid only during the indeterminate amount of time until the object is collected when no strong references exist.

What is strong reference and weak reference in c#?

A weak reference is a way to have some pointer to an object that does have any reference (strong reference). In . NET, any normal reference to another object is a strong reference . That is, when you declare a variable of a type that is not a primitive/value type, you are declaring a strong reference.

What is the use of weak reference in java?

Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed. Weak references are most often used to implement canonicalizing mappings. Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable.

What's a Weakreference when would you want to use one?

Weak references are all about garbage collection. A standard object will not "disappear" until all references to it are severed, this means all the references your various objects have to it have to be removed before garbage collection will consider it garbage.


1 Answers

All I can think is that perhaps they're trying to guard against the WeakReference being disposed and finalized either during or after the InternalGet

That's exactly right.

but surely, couldn't it also be disposed and finalized before we get around to returning the object?

No, because at that point, a strong pointer must have been created to the object. InternalGet returns a strong pointer, and if that strong pointer, stored in oldValue, is to the object, now the object can no longer be reclaimed by the garbage collector.

like image 54
Pascal Cuoq Avatar answered Sep 19 '22 21:09

Pascal Cuoq