PageRenderTime 42ms CodeModel.GetById 32ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/Aurora/Framework/Utilities/Lazy.cs

https://bitbucket.org/VirtualReality/software-testing
C# | 264 lines | 185 code | 23 blank | 56 comment | 21 complexity | a7cb7d63c69896baea39f568623e08dd MD5 | raw file
  1/*
  2 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
  3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4 *
  5 * Redistribution and use in source and binary forms, with or without
  6 * modification, are permitted provided that the following conditions are met:
  7 *     * Redistributions of source code must retain the above copyright
  8 *       notice, this list of conditions and the following disclaimer.
  9 *     * Redistributions in binary form must reproduce the above copyright
 10 *       notice, this list of conditions and the following disclaimer in the
 11 *       documentation and/or other materials provided with the distribution.
 12 *     * Neither the name of the Aurora-Sim Project nor the
 13 *       names of its contributors may be used to endorse or promote products
 14 *       derived from this software without specific prior written permission.
 15 *
 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 26 */
 27
 28//
 29// Lazy.cs
 30//
 31// Authors:
 32//  Zoltan Varga (vargaz@gmail.com)
 33//  Marek Safar (marek.safar@gmail.com)
 34//
 35// Copyright (C) 2009 Novell
 36//
 37// Permission is hereby granted, free of charge, to any person obtaining
 38// a copy of this software and associated documentation files (the
 39// "Software"), to deal in the Software without restriction, including
 40// without limitation the rights to use, copy, modify, merge, publish,
 41// distribute, sublicense, and/or sell copies of the Software, and to
 42// permit persons to whom the Software is furnished to do so, subject to
 43// the following conditions:
 44// 
 45// The above copyright notice and this permission notice shall be
 46// included in all copies or substantial portions of the Software.
 47// 
 48// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 49// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 50// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 51// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 52// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 53// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 54// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 55//
 56
 57using System;
 58using System.Diagnostics;
 59using System.Runtime.InteropServices;
 60using System.Security.Permissions;
 61using System.Threading;
 62
 63namespace Aurora.Framework.Utilities
 64{
 65    public enum LazyThreadSafetyMode
 66    {
 67        None,
 68        PublicationOnly,
 69        ExecutionAndPublication
 70    }
 71
 72    [Serializable]
 73    [ComVisible(false)]
 74    [HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
 75    public class Lazy<T>
 76    {
 77        private readonly LazyThreadSafetyMode mode;
 78        private readonly object monitor;
 79        private Exception exception;
 80        private Func<T> factory;
 81        private bool inited;
 82        private T value;
 83
 84        public Lazy()
 85            : this(LazyThreadSafetyMode.ExecutionAndPublication)
 86        {
 87        }
 88
 89        public Lazy(Func<T> valueFactory)
 90            : this(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication)
 91        {
 92        }
 93
 94        public Lazy(bool isThreadSafe)
 95            : this(
 96                Activator.CreateInstance<T>,
 97                isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None)
 98        {
 99        }
100
101        public Lazy(Func<T> valueFactory, bool isThreadSafe)
102            : this(valueFactory, isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None
103                )
104        {
105        }
106
107        public Lazy(LazyThreadSafetyMode mode)
108            : this(Activator.CreateInstance<T>, mode)
109        {
110        }
111
112        public Lazy(Func<T> valueFactory, LazyThreadSafetyMode mode)
113        {
114            if (valueFactory == null)
115                throw new ArgumentNullException("valueFactory");
116            this.factory = valueFactory;
117            if (mode != LazyThreadSafetyMode.None)
118                monitor = new object();
119            this.mode = mode;
120        }
121
122        // Don't trigger expensive initialization
123        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
124        public T Value
125        {
126            get
127            {
128                if (inited)
129                    return value;
130                if (exception != null)
131                    throw exception;
132
133                return InitValue();
134            }
135        }
136
137        public bool IsValueCreated
138        {
139            get { return inited; }
140        }
141
142        private T InitValue()
143        {
144            switch (mode)
145            {
146                case LazyThreadSafetyMode.None:
147                    {
148                        var init_factory = factory;
149                        if (init_factory == null)
150                            throw exception =
151                                  new InvalidOperationException(
152                                      "The initialization function tries to access Value on this instance");
153                        try
154                        {
155                            factory = null;
156                            T v = init_factory();
157                            value = v;
158                            Thread.MemoryBarrier();
159                            inited = true;
160                        }
161                        catch (Exception ex)
162                        {
163                            exception = ex;
164                            throw;
165                        }
166                        break;
167                    }
168                case LazyThreadSafetyMode.PublicationOnly:
169                    {
170                        var init_factory = factory;
171                        T v;
172
173                        //exceptions are ignored
174                        v = init_factory != null ? init_factory() : default(T);
175
176                        lock (monitor)
177                        {
178                            if (inited)
179                                return value;
180                            value = v;
181                            Thread.MemoryBarrier();
182                            inited = true;
183                            factory = null;
184                        }
185                        break;
186                    }
187                case LazyThreadSafetyMode.ExecutionAndPublication:
188                    {
189                        lock (monitor)
190                        {
191                            if (inited)
192                                return value;
193
194                            if (factory == null)
195                                throw exception =
196                                      new InvalidOperationException(
197                                          "The initialization function tries to access Value on this instance");
198
199                            var init_factory = factory;
200                            try
201                            {
202                                factory = null;
203                                T v = init_factory();
204                                value = v;
205                                Thread.MemoryBarrier();
206                                inited = true;
207                            }
208                            catch (Exception ex)
209                            {
210                                exception = ex;
211                                throw;
212                            }
213                        }
214                        break;
215                    }
216                default:
217                    throw new InvalidOperationException("Invalid LazyThreadSafetyMode " + mode);
218            }
219
220            if (monitor == null)
221            {
222                value = factory();
223                inited = true;
224            }
225            else
226            {
227                lock (monitor)
228                {
229                    if (inited)
230                        return value;
231
232                    if (factory == null)
233                        throw new InvalidOperationException(
234                            "The initialization function tries to access Value on this instance");
235
236                    var init_factory = factory;
237                    try
238                    {
239                        factory = null;
240                        T v = init_factory();
241                        value = v;
242                        Thread.MemoryBarrier();
243                        inited = true;
244                    }
245                    catch
246                    {
247                        factory = init_factory;
248                        throw;
249                    }
250                }
251            }
252
253            return value;
254        }
255
256        public override string ToString()
257        {
258            if (inited)
259                return value.ToString();
260            else
261                return "Value is not created";
262        }
263    }
264}