Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom WeakReference implementation

WeakReference in BCL was designed in pre generics era, so it's interface is not as nice as it could be. Also IsAlive property is very easy to misuse. Looking into the implementation of WeakReference trough Reflector it seems like we could implement it ourselves. Here is what I came up with:

    [SecurityPermission(Flags = SecurityPermissionFlag.UnmanagedCode)]
    public sealed class WeakRef<T> where T : class
    {
        private readonly volatile IntPtr _ptr;

        public WeakRef(T target)
            : this(target, false)
        {
        }

        [SecuritySafeCritical]
        public WeakRef(T target, bool trackResurrection)
        {
            var handle = GCHandle.Alloc(target, trackResurrection ? GCHandleType.WeakTrackResurrection : GCHandleType.Weak);
            _ptr = GCHandle.ToIntPtr(handle);
        }

        [SecuritySafeCritical]
        ~WeakRef()
        {
            var ptr = _ptr;
            if ((ptr != IntPtr.Zero) && (ptr == Interlocked.CompareExchange(ref _ptr, IntPtr.Zero, ptr)))
            {
                var handle = GCHandle.FromIntPtr(ptr);
                handle.Free();
            }
        }

        public T Target
        {
            get
            {
                var ptr = _ptr;
                if (IntPtr.Zero != ptr)
                {
                    var target = GCHandle.FromIntPtr(ptr).Target;
                    if (_ptr != IntPtr.Zero)
                    {
                        return (T)target;
                    }
                }
                return null;
            }
        }
    }

but I'm not sure I got the implementation of BCL counterpart right. Can anyone spot any issues in the code above?

like image 743
ubiq Avatar asked Aug 17 '11 03:08

ubiq


People also ask

How are weak references implemented?

When a weak reference A is created to an object B, there would be an entry in the hashtable modified or created, whose key would be the pointer to B. "Dirty" - to store a special hash-value with each object, which would be zeroed when the object is destroyed.

Why use weakref?

WeakReference and SoftReference are used when you want to keep something around in case you need it again - but you might not need it and if you do need it you can recreate it.

What is a weak reference?

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.


1 Answers

I don't spot anything wrong offhand except adding error handling. However, I prefer this implementation for its simplicity, especially since it uses the BCL version and you don't have to try as hard to "get it right":

public sealed class WeakReference<T> where T : class
{
    public WeakReference(T target) : this(target, trackResurrection)
    {}

    public WeakReference(T target, bool trackResurrection)
    {
        refTarget = new WeakReference(target, trackResurrection);
    }

    public T Target { get { return refTarget.Target as T; } }

    public bool IsAlive { get { return refTarget.IsAlive; }}

    private readonly WeakReference refTarget;
}
like image 167
Kit Avatar answered Oct 11 '22 00:10

Kit