##// END OF EJS Templates
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'...
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()' added Safe.Dispose(IEnumerable) added PromiseExtensions.CancellationPoint to add a cancellation point to the chain of promises added IPromise<T> PromiseExtensions.Then<T>(this IPromise<T> that, Action<T> success) overloads added PromiseExtensions.Error() overloads to handle a error or(and) a cancellation

File last commit:

r182:76e8f2ba12b8 ref20160224
r207:558f34b2fb50 v2
Show More
LazyAndWeak.cs
64 lines | 2.1 KiB | text/x-csharp | CSharpLexer
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;
}
}
}
}
}
}
}