LazyAndWeak.cs
63 lines
| 2.0 KiB
| text/x-csharp
|
CSharpLexer
cin
|
r178 | using System; | ||
using System.Threading; | ||||
namespace Implab.Components { | ||||
cin
|
r180 | /// <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 is a singleton. | ||||
/// </remarks> | ||||
cin
|
r178 | 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 { | ||||
cin
|
r180 | lock (m_lock) { | ||
// double check | ||||
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; | ||||
} | ||||
cin
|
r178 | } | ||
} | ||||
} | ||||
} | ||||
} | ||||
} | ||||