Mercurial > pub > ImplabNet
view Implab/Components/LazyAndWeak.cs @ 239:eedf4d834e67 v2
fix
author | cin |
---|---|
date | Wed, 13 Dec 2017 19:54:45 +0300 |
parents | 76e8f2ba12b8 |
children | 3a6e18c432be |
line wrap: on
line source
using System; using System.Threading; namespace Implab.Components { /// <summary> /// Creates an instace on-demand and allows it to be garbage collected. /// </summary> /// <remarks> /// Usefull when dealing with memory-intensive objects which are frequently used. /// This class is similar to <see cref="ObjectPool{T}"/> except it is a singleton. /// </remarks> public class LazyAndWeak<T> where T : class { readonly Func<T> m_factory; readonly object m_lock; WeakReference m_reference; public LazyAndWeak(Func<T> factory, bool useLock) { Safe.ArgumentNotNull(factory, "factory"); m_factory = factory; m_lock = useLock ? new object() : null; } public LazyAndWeak(Func<T> factory) : this(factory, false) { } public T Value { get { while (true) { var weak = m_reference; T value; if (weak != null) { value = weak.Target as T; if (value != null) return value; } if (m_lock == null) { value = m_factory(); if (Interlocked.CompareExchange(ref m_reference, new WeakReference(value), weak) == weak) return value; } else { lock (m_lock) { // double check weak = m_reference; if (weak != null) { value = weak.Target as T; if (value != null) return value; } // we are safe to write value = m_factory(); m_reference = new WeakReference(value); return value; } } } } } } }