From cde9fc6a8fe569203cb991121a35c2a9c7f4c420 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Tue, 22 Jan 2013 17:25:22 +0900 Subject: import 2b5dbddd740b, new directory structure in the original rx. --- .../System.Reactive.Core/Reactive/Internal/Lazy.cs | 126 +++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 Rx/NET/Source/System.Reactive.Core/Reactive/Internal/Lazy.cs (limited to 'Rx/NET/Source/System.Reactive.Core/Reactive/Internal/Lazy.cs') diff --git a/Rx/NET/Source/System.Reactive.Core/Reactive/Internal/Lazy.cs b/Rx/NET/Source/System.Reactive.Core/Reactive/Internal/Lazy.cs new file mode 100644 index 0000000..4094dce --- /dev/null +++ b/Rx/NET/Source/System.Reactive.Core/Reactive/Internal/Lazy.cs @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. + +#if NO_LAZY +#pragma warning disable 0420 + +// +// Based on ndp\clr\src\BCL\System\Lazy.cs but with LazyThreadSafetyMode.ExecutionAndPublication mode behavior hardcoded. +// + +using System.Diagnostics; +using System.Threading; +using System.Reactive; + +namespace System +{ + internal class Lazy + { + class Boxed + { + internal Boxed(T value) + { + m_value = value; + } + + internal T m_value; + } + + static Func ALREADY_INVOKED_SENTINEL = delegate { return default(T); }; + + private object m_boxed; + private Func m_valueFactory; + private volatile object m_threadSafeObj; + + public Lazy(Func valueFactory) + { + m_threadSafeObj = new object(); + m_valueFactory = valueFactory; + } + +#if !NO_DEBUGGER_ATTRIBUTES + [DebuggerBrowsable(DebuggerBrowsableState.Never)] +#endif + public T Value + { + get + { + Boxed boxed = null; + if (m_boxed != null) + { + boxed = m_boxed as Boxed; + if (boxed != null) + { + return boxed.m_value; + } + + var exc = m_boxed as Exception; + exc.Throw(); + } + + return LazyInitValue(); + } + } + + private T LazyInitValue() + { + Boxed boxed = null; + object threadSafeObj = m_threadSafeObj; + bool lockTaken = false; + try + { + if (threadSafeObj != (object)ALREADY_INVOKED_SENTINEL) + { + Monitor.Enter(threadSafeObj); + lockTaken = true; + } + + if (m_boxed == null) + { + boxed = CreateValue(); + m_boxed = boxed; + m_threadSafeObj = ALREADY_INVOKED_SENTINEL; + } + else + { + boxed = m_boxed as Boxed; + if (boxed == null) + { + var exc = m_boxed as Exception; + exc.Throw(); + } + } + } + finally + { + if (lockTaken) + Monitor.Exit(threadSafeObj); + } + + return boxed.m_value; + } + + private Boxed CreateValue() + { + Boxed boxed = null; + try + { + if (m_valueFactory == ALREADY_INVOKED_SENTINEL) + throw new InvalidOperationException(); + + Func factory = m_valueFactory; + m_valueFactory = ALREADY_INVOKED_SENTINEL; + + boxed = new Boxed(factory()); + } + catch (Exception ex) + { + m_boxed = ex; + throw; + } + + return boxed; + } + } +} +#pragma warning restore 0420 +#endif \ No newline at end of file -- cgit v1.2.3