예제 #1
0
        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);
            }
        }
예제 #2
0
 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());
     }
 }
예제 #3
0
파일: Lazy.cs 프로젝트: erisonliang/Theraot
        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());
        }
예제 #4
0
 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));
 }
예제 #5
0
        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());
        }
예제 #6
0
 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;
             }
         };
     }
 }
예제 #7
0
        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());
            }
        }
예제 #8
0
파일: Lazy.cs 프로젝트: csharpHub/Theraot
        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);
            }
        }