private T CachingNoneMode(HashSet <Thread> threads, Func <T> valueFactory) { if (Volatile.Read(ref _isValueCreated) != 0) { return(_valueFactory.Invoke()); } try { AddThread(threads); ValueForDebugDisplay = valueFactory(); _valueFactory = FuncHelper.GetReturnFunc(ValueForDebugDisplay); Volatile.Write(ref _isValueCreated, 1); return(ValueForDebugDisplay); } catch (Exception exception) { _valueFactory = FuncHelper.GetThrowFunc <T>(exception); throw; } finally { RemoveThread(threads); } }
private T CachingFullMode(Func <T> valueFactory, ManualResetEvent waitHandle, ref Thread thread) { if (Interlocked.CompareExchange(ref _isValueCreated, 1, 0) == 0) { try { thread = Thread.CurrentThread; GC.KeepAlive(thread); _target = valueFactory.Invoke(); _valueFactory = FuncHelper.GetReturnFunc(_target); return(_target); } catch (Exception exc) { _valueFactory = FuncHelper.GetThrowFunc <T>(exc); throw; } finally { waitHandle.Set(); thread = null; } } else { if (ReferenceEquals(thread, Thread.CurrentThread)) { throw new InvalidOperationException(); } waitHandle.WaitOne(); return(_valueFactory.Invoke()); } }
private T CachingFullMode(Func <T> valueFactory, EventWaitHandle waitHandle, ref Thread thread) { if (Interlocked.CompareExchange(ref _isValueCreated, 1, 0) == 0) { try { thread = Thread.CurrentThread; GC.KeepAlive(thread); ValueForDebugDisplay = valueFactory.Invoke(); _valueFactory = FuncHelper.GetReturnFunc(ValueForDebugDisplay); return(ValueForDebugDisplay); } catch (Exception exc) { _valueFactory = FuncHelper.GetThrowFunc <T>(exc); throw; } finally { waitHandle.Set(); thread = null; } } if (thread == Thread.CurrentThread) { throw new InvalidOperationException(); } waitHandle.WaitOne(); return(_valueFactory.Invoke()); }
public CacheNeedle(Func <T> valueFactory, T target, bool trackResurrection, bool cacheExceptions) : base(target, trackResurrection) { if (valueFactory == null) { throw new ArgumentNullException("valueFactory"); } _valueFactory = valueFactory; if (cacheExceptions) { _valueFactory = () => { try { return(valueFactory.Invoke()); } catch (Exception exc) { _valueFactory = FuncHelper.GetThrowFunc <T>(exc); throw; } }; } _waitHandle = new StructNeedle <ManualResetEventSlim>(new ManualResetEventSlim(false)); }
private T CachingFullMode(Func <T> valueFactory, ref ManualResetEvent?waitHandle, ref Thread?thread) { if (waitHandle == null) { waitHandle = new ManualResetEvent(false); } if (Interlocked.CompareExchange(ref _isValueCreated, 1, 0) == 0) { Volatile.Write(ref thread, Thread.CurrentThread); try { ValueForDebugDisplay = valueFactory.Invoke(); _valueFactory = FuncHelper.GetReturnFunc(ValueForDebugDisplay); return(ValueForDebugDisplay); } catch (Exception exc) { _valueFactory = FuncHelper.GetThrowFunc <T>(exc); throw; } finally { Volatile.Write(ref thread, null); waitHandle.Set(); waitHandle.Close(); } } if (Volatile.Read(ref thread) == Thread.CurrentThread) { throw new InvalidOperationException(); } if (waitHandle.SafeWaitHandle.IsClosed) { return(_valueFactory.Invoke()); } try { waitHandle.WaitOne(); } catch (ObjectDisposedException exception) { _ = exception; } return(_valueFactory.Invoke()); }
public LazyNeedle(Func <T> valueFactory, bool cacheExceptions) : base(false) { _valueFactory = valueFactory ?? throw new ArgumentNullException(nameof(valueFactory)); if (cacheExceptions) { _valueFactory = () => { try { return(valueFactory.Invoke()); } catch (Exception exc) { _valueFactory = FuncHelper.GetThrowFunc <T>(exc); throw; } }; } }
private T CachingNoneMode(Func <T> valueFactory, HashSet <Thread> threads) { // NOTICE this method has no null check var currentThread = Thread.CurrentThread; if (Thread.VolatileRead(ref _isValueCreated) == 0) { try { // lock (threads) // This is meant to not be thread-safe { if (threads.Contains(currentThread)) { throw new InvalidOperationException(); } threads.Add(currentThread); } _target = valueFactory(); _valueFactory = FuncHelper.GetReturnFunc(_target); Thread.VolatileWrite(ref _isValueCreated, 1); return(_target); } catch (Exception exception) { _valueFactory = FuncHelper.GetThrowFunc <T>(exception); throw; } finally { // lock (threads) // This is meant to not be thread-safe { threads.Remove(Thread.CurrentThread); } } } else { return(_valueFactory.Invoke()); } }
private Lazy(Func <T> valueFactory, LazyThreadSafetyMode mode, bool cacheExceptions) { if (valueFactory == null) { throw new ArgumentNullException(nameof(valueFactory)); } switch (mode) { case LazyThreadSafetyMode.None: { if (cacheExceptions) { var threads = new HashSet <Thread>(); _valueFactory = () => CachingNoneMode(threads); } else { var threads = new HashSet <Thread>(); _valueFactory = () => NoneMode(threads); } } break; case LazyThreadSafetyMode.PublicationOnly: { _valueFactory = PublicationOnlyMode; } break; default: /*LazyThreadSafetyMode.ExecutionAndPublication*/ { if (cacheExceptions) { Thread? thread = null; ManualResetEvent?manualResetEvent = null; _valueFactory = () => CachingFullMode(valueFactory, ref manualResetEvent, ref thread); } else { Thread? thread = null; ManualResetEvent?manualResetEvent = null; _valueFactory = () => FullMode(valueFactory, ref manualResetEvent, ref thread); } } break; } T CachingNoneMode(HashSet <Thread> threads) { if (Volatile.Read(ref _isValueCreated) != 0) { return(_valueFactory.Invoke()); } try { // lock (threads) // This is meant to not be thread-safe { var currentThread = Thread.CurrentThread; if (threads.Contains(currentThread)) { throw new InvalidOperationException(); } threads.Add(currentThread); } ValueForDebugDisplay = valueFactory(); _valueFactory = FuncHelper.GetReturnFunc(ValueForDebugDisplay); Volatile.Write(ref _isValueCreated, 1); return(ValueForDebugDisplay); } catch (Exception exception) { _valueFactory = FuncHelper.GetThrowFunc <T>(exception); throw; } finally { // lock (threads) // This is meant to not be thread-safe { threads.Remove(Thread.CurrentThread); } } } T NoneMode(HashSet <Thread> threads) { if (Volatile.Read(ref _isValueCreated) != 0) { return(_valueFactory.Invoke()); } try { // lock (threads) // This is meant to not be thread-safe { var currentThread = Thread.CurrentThread; if (threads.Contains(currentThread)) { throw new InvalidOperationException(); } threads.Add(currentThread); } ValueForDebugDisplay = valueFactory(); _valueFactory = FuncHelper.GetReturnFunc(ValueForDebugDisplay); Volatile.Write(ref _isValueCreated, 1); return(ValueForDebugDisplay); } catch (Exception) { Volatile.Write(ref _isValueCreated, 0); throw; } finally { // lock (threads) // This is meant to not be thread-safe { threads.Remove(Thread.CurrentThread); } } } T PublicationOnlyMode() { ValueForDebugDisplay = valueFactory(); if (Interlocked.CompareExchange(ref _isValueCreated, 1, 0) == 0) { _valueFactory = FuncHelper.GetReturnFunc(ValueForDebugDisplay); } return(ValueForDebugDisplay); } }