private T FullMode(Func <T> valueFactory, ManualResetEvent waitHandle, ref Thread thread, ref int preIsValueCreated) { back: if (Interlocked.CompareExchange(ref preIsValueCreated, 1, 0) == 0) { try { thread = Thread.CurrentThread; GC.KeepAlive(thread); _target = valueFactory.Invoke(); _valueFactory = FuncHelper.GetReturnFunc(_target); Thread.VolatileWrite(ref _isValueCreated, 1); return(_target); } catch (Exception) { Thread.VolatileWrite(ref preIsValueCreated, 0); throw; } finally { waitHandle.Set(); thread = null; } } else { if (ReferenceEquals(thread, Thread.CurrentThread)) { throw new InvalidOperationException(); } else { waitHandle.WaitOne(); if (Thread.VolatileRead(ref _isValueCreated) == 1) { return(_valueFactory.Invoke()); } else { goto back; } } } }
private T NoneMode(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(); } else { threads.Add(currentThread); } } _target = valueFactory(); _valueFactory = FuncHelper.GetReturnFunc(_target); Thread.VolatileWrite(ref _isValueCreated, 1); return(_target); } catch (Exception) { Thread.VolatileWrite(ref _isValueCreated, 0); throw; } finally { // lock (threads) // This is meant to not be thread-safe { threads.Remove(Thread.CurrentThread); } } } else { return(_valueFactory.Invoke()); } }