[corlib] Cleanup type ToString formatting.
[mono.git] / mcs / class / corlib / System / Lazy.cs
1 //
2 // Lazy.cs
3 //
4 // Authors:
5 //  Zoltan Varga (vargaz@gmail.com)
6 //  Marek Safar (marek.safar@gmail.com)
7 //
8 // Copyright (C) 2009 Novell
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 #if NET_4_0
31
32 using System;
33 using System.Runtime.Serialization;
34 using System.Runtime.InteropServices;
35 using System.Security.Permissions;
36 using System.Threading;
37 using System.Diagnostics;
38
39 namespace System
40 {
41         [SerializableAttribute]
42         [ComVisibleAttribute(false)]
43         [HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
44         [DebuggerDisplay ("ThreadSafetyMode={Mode}, IsValueCreated={IsValueCreated}, IsValueFaulted={IsValueFaulted}, Value={ValueForDebugDisplay}")]
45         public class Lazy<T> 
46         {
47                 T value;
48                 Func<T> factory;
49                 object monitor;
50                 Exception exception;
51                 LazyThreadSafetyMode mode;
52                 bool inited;
53
54                 public Lazy ()
55                         : this (LazyThreadSafetyMode.ExecutionAndPublication)
56                 {
57                 }
58
59                 public Lazy (Func<T> valueFactory)
60                         : this (valueFactory, LazyThreadSafetyMode.ExecutionAndPublication)
61                 {
62                 }
63
64                 public Lazy (bool isThreadSafe)
65                         : this (Activator.CreateInstance<T>, isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None)
66                 {
67                 }
68                 
69                 public Lazy (Func<T> valueFactory, bool isThreadSafe)
70                         : this (valueFactory, isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None)
71                 {
72                 }
73
74                 public Lazy (LazyThreadSafetyMode mode)
75                         : this (Activator.CreateInstance<T>, mode)
76                 {
77                 }
78
79                 
80
81                 public Lazy (Func<T> valueFactory, LazyThreadSafetyMode mode)
82                 {
83                         if (valueFactory == null)
84                                 throw new ArgumentNullException ("valueFactory");
85                         this.factory = valueFactory;
86                         if (mode != LazyThreadSafetyMode.None)
87                                 monitor = new object ();
88                         this.mode = mode;
89                 }
90
91                 // Don't trigger expensive initialization
92                 [DebuggerBrowsable (DebuggerBrowsableState.Never)]
93                 public T Value {
94                         get {
95                                 if (inited)
96                                         return value;
97                                 if (exception != null)
98                                         throw exception;
99
100                                 return InitValue ();
101                         }
102                 }
103
104                 T InitValue ()
105                 {
106                         Func<T> init_factory;
107                         T v;
108                         
109                         switch (mode) {
110                         case LazyThreadSafetyMode.None:
111                                 init_factory = factory;
112                                 if (init_factory == null) 
113                                         throw exception = new InvalidOperationException ("The initialization function tries to access Value on this instance");
114                                 try {
115                                         factory = null;
116                                         v = init_factory ();
117                                         value = v;
118                                         Thread.MemoryBarrier ();
119                                         inited = true;
120                                 } catch (Exception ex) {
121                                         exception = ex;
122                                         throw;
123                                 }
124                                 break;
125
126                         case LazyThreadSafetyMode.PublicationOnly:
127                                 init_factory = factory;
128
129                                 //exceptions are ignored
130                                 if (init_factory != null)
131                                         v = init_factory ();
132                                 else
133                                         v = default (T);
134
135                                 lock (monitor) {
136                                         if (inited)
137                                                 return value;
138                                         value = v;
139                                         Thread.MemoryBarrier ();
140                                         inited = true;
141                                         factory = null;
142                                 }
143                                 break;
144
145                         case LazyThreadSafetyMode.ExecutionAndPublication:
146                                 lock (monitor) {
147                                         if (inited)
148                                                 return value;
149
150                                         if (factory == null)
151                                                 throw exception = new InvalidOperationException ("The initialization function tries to access Value on this instance");
152
153                                         init_factory = factory;
154                                         try {
155                                                 factory = null;
156                                                 v = init_factory ();
157                                                 value = v;
158                                                 Thread.MemoryBarrier ();
159                                                 inited = true;
160                                         } catch (Exception ex) {
161                                                 exception = ex;
162                                                 throw;
163                                         }
164                                 }
165                                 break;
166
167                         default:
168                                 throw new InvalidOperationException ("Invalid LazyThreadSafetyMode " + mode);
169                         }
170
171                         return value;
172                 }
173
174                 public bool IsValueCreated {
175                         get {
176                                 return inited;
177                         }
178                 }
179
180                 public override string ToString ()
181                 {
182                         if (inited)
183                                 return value.ToString ();
184                         else
185                                 return "Value is not created";
186                 }
187         }               
188 }
189         
190 #endif