Exemple #1
0
        private T NoneMode(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)
            {
                Volatile.Write(ref _isValueCreated, 0);
                throw;
            }
            finally
            {
                RemoveThread(threads);
            }
        }
Exemple #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());
     }
 }
Exemple #3
0
        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());
        }
Exemple #4
0
        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, valueFactory);
                }
                else
                {
                    var threads = new HashSet <Thread>();
                    _valueFactory =
                        () => NoneMode(threads, valueFactory);
                }

                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 PublicationOnlyMode()
            {
                ValueForDebugDisplay = valueFactory();
                if (Interlocked.CompareExchange(ref _isValueCreated, 1, 0) == 0)
                {
                    _valueFactory = FuncHelper.GetReturnFunc(ValueForDebugDisplay);
                }

                return(ValueForDebugDisplay);
            }
        }
Exemple #5
0
 private T PublicationOnlyMode(Func <T> valueFactory)
 {
     _target = valueFactory();
     if (Interlocked.CompareExchange(ref _isValueCreated, 1, 0) == 0)
     {
         _valueFactory = FuncHelper.GetReturnFunc(_target);
     }
     return(_target);
 }
Exemple #6
0
        private T FullMode(Func <T> valueFactory, ref ManualResetEvent?waitHandle, ref Thread?thread)
        {
            if (waitHandle == null)
            {
                waitHandle = new ManualResetEvent(false);
            }

            while (Volatile.Read(ref _isValueCreated) != 1)
            {
                var foundThread = Interlocked.CompareExchange(ref thread, Thread.CurrentThread, null);
                if (foundThread == null)
                {
                    try
                    {
                        ValueForDebugDisplay = valueFactory.Invoke();
                        _valueFactory        = FuncHelper.GetReturnFunc(ValueForDebugDisplay);
                        Volatile.Write(ref _isValueCreated, 1);
                        return(ValueForDebugDisplay);
                    }
                    finally
                    {
                        Volatile.Write(ref thread, default);
                        waitHandle.Set();
                        if (Volatile.Read(ref _isValueCreated) == 1)
                        {
                            waitHandle.Close();
                        }
                    }
                }

                if (foundThread == Thread.CurrentThread)
                {
                    throw new InvalidOperationException();
                }

                if (waitHandle.SafeWaitHandle.IsClosed)
                {
                    continue;
                }

                try
                {
                    waitHandle.WaitOne();
                }
                catch (ObjectDisposedException exception)
                {
                    _ = exception;
                }
            }

            return(_valueFactory.Invoke());
        }
Exemple #7
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());
        }
Exemple #8
0
        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;
                    }
                }
            }
        }
Exemple #9
0
        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());
            }
        }
Exemple #10
0
        private T FullMode(Func <T> valueFactory, EventWaitHandle waitHandle, ref Thread thread, ref int preIsValueCreated)
        {
back:
            if (Interlocked.CompareExchange(ref preIsValueCreated, 1, 0) == 0)
            {
                try
                {
                    thread = Thread.CurrentThread;
                    GC.KeepAlive(thread);
                    ValueForDebugDisplay = valueFactory.Invoke();
                    _valueFactory        = FuncHelper.GetReturnFunc(ValueForDebugDisplay);
                    Volatile.Write(ref _isValueCreated, 1);
                    return(ValueForDebugDisplay);
                }
                catch (Exception)
                {
                    Volatile.Write(ref preIsValueCreated, 0);
                    throw;
                }
                finally
                {
                    waitHandle.Set();
                    thread = null;
                }
            }

            if (thread == Thread.CurrentThread)
            {
                throw new InvalidOperationException();
            }

            waitHandle.WaitOne();
            if (Volatile.Read(ref _isValueCreated) == 1)
            {
                return(_valueFactory.Invoke());
            }

            goto back;
        }
Exemple #11
0
        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);
            }
        }