// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_0
-
using System;
using System.Reflection;
-using System.Reflection.Emit;
using System.Threading;
using NUnit.Framework;
new Lazy<int> (null);
}
+
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void Ctor_Null_2 () {
- new Lazy<int> (null, LazyExecutionMode.NotThreadSafe);
+ new Lazy<int> (null, false);
}
[Test]
}
[Test]
- [ExpectedException (typeof (MissingMemberException))]
public void NoDefaultCtor () {
var l1 = new Lazy<NoDefaultCtorClass> ();
- var o = l1.Value;
+ try {
+ var o = l1.Value;
+ Assert.Fail ();
+ } catch (MissingMemberException) {
+ }
}
class NoDefaultCtorClass {
static int counter;
[Test]
- public void EnsureSingleThreadSafeExecution () {
+ public void EnsureSingleThreadSafeExecution ()
+ {
counter = 42;
+ bool started = false;
- //var l = new Lazy<int> (delegate () { return counter ++; }, LazyExecutionMode.NotThreadSafe);
- var l = new Lazy<int> (delegate () { return counter ++; }, LazyExecutionMode.EnsureSingleThreadSafeExecution);
-
+ var l = new Lazy<int> (delegate () { return counter ++; }, true);
+ bool failed = false;
object monitor = new object ();
- var threads = new Thread [10];
- for (int i = 0; i < 10; ++i) {
+ var threads = new Thread [4];
+ for (int i = 0; i < threads.Length; ++i) {
threads [i] = new Thread (delegate () {
lock (monitor) {
- Monitor.Wait (monitor);
+ if (!started) {
+ if (!Monitor.Wait (monitor, 2000))
+ failed = true;
+ }
}
int val = l.Value;
});
}
- for (int i = 0; i < 10; ++i)
+ for (int i = 0; i < threads.Length; ++i)
threads [i].Start ();
- lock (monitor)
+ lock (monitor) {
+ started = true;
Monitor.PulseAll (monitor);
-
+ }
+
+ for (int i = 0; i < threads.Length; ++i)
+ threads [i].Join ();
+
+ Assert.IsFalse (failed);
Assert.AreEqual (42, l.Value);
- }
+ }
+
+ [Test]
+ public void InitRecursion ()
+ {
+ Lazy<DefaultCtorClass> c = null;
+ c = new Lazy<DefaultCtorClass> (() => { Console.WriteLine (c.Value); return null; });
+
+ try {
+ var r = c.Value;
+ Assert.Fail ();
+ } catch (InvalidOperationException) {
+ }
+ }
+
+ [Test]
+ public void ModeNone ()
+ {
+ int x;
+ bool fail = true;
+ Lazy<int> lz = new Lazy<int> (() => { if (fail) throw new Exception (); else return 99; }, LazyThreadSafetyMode.None);
+ try {
+ x = lz.Value;
+ Assert.Fail ("#1");
+ Console.WriteLine (x);
+ } catch (Exception ex) { }
+
+ try {
+ x = lz.Value;
+ Assert.Fail ("#2");
+ } catch (Exception ex) { }
+
+ fail = false;
+ try {
+ x = lz.Value;
+ Assert.Fail ("#3");
+ } catch (Exception ex) { }
+
+ bool rec = true;
+ lz = new Lazy<int> (() => rec ? lz.Value : 99, LazyThreadSafetyMode.None);
+
+ try {
+ x = lz.Value;
+ Assert.Fail ("#4");
+ } catch (InvalidOperationException ex) { }
+
+ rec = false;
+ try {
+ x = lz.Value;
+ Assert.Fail ("#5");
+ } catch (InvalidOperationException ex) { }
+ }
+
+ [Test]
+ public void ModePublicationOnly () {
+ bool fail = true;
+ int invoke = 0;
+ Lazy<int> lz = new Lazy<int> (() => { ++invoke; if (fail) throw new Exception (); else return 99; }, LazyThreadSafetyMode.PublicationOnly);
+
+ try {
+ int x = lz.Value;
+ Assert.Fail ("#1");
+ Console.WriteLine (x);
+ } catch (Exception ex) { }
+
+ try {
+ int x = lz.Value;
+ Assert.Fail ("#2");
+ } catch (Exception ex) { }
+
+
+ Assert.AreEqual (2, invoke, "#3");
+ fail = false;
+ Assert.AreEqual (99, lz.Value, "#4");
+ Assert.AreEqual (3, invoke, "#5");
+
+ invoke = 0;
+ bool rec = true;
+ lz = new Lazy<int> (() => { ++invoke; bool r = rec; rec = false; return r ? lz.Value : 88; }, LazyThreadSafetyMode.PublicationOnly);
+
+ Assert.AreEqual (88, lz.Value, "#6");
+ Assert.AreEqual (2, invoke, "#7");
+ }
+
+ [Test]
+ public void ModeExecutionAndPublication () {
+ int invoke = 0;
+ bool fail = true;
+ Lazy<int> lz = new Lazy<int> (() => { ++invoke; if (fail) throw new Exception (); else return 99; }, LazyThreadSafetyMode.ExecutionAndPublication);
+
+ try {
+ int x = lz.Value;
+ Assert.Fail ("#1");
+ Console.WriteLine (x);
+ } catch (Exception ex) { }
+ Assert.AreEqual (1, invoke, "#2");
+
+ try {
+ int x = lz.Value;
+ Assert.Fail ("#3");
+ } catch (Exception ex) { }
+ Assert.AreEqual (1, invoke, "#4");
+
+ fail = false;
+ try {
+ int x = lz.Value;
+ Assert.Fail ("#5");
+ } catch (Exception ex) { }
+ Assert.AreEqual (1, invoke, "#6");
+
+ bool rec = true;
+ lz = new Lazy<int> (() => rec ? lz.Value : 99, LazyThreadSafetyMode.ExecutionAndPublication);
+
+ try {
+ int x = lz.Value;
+ Assert.Fail ("#7");
+ } catch (InvalidOperationException ex) { }
+
+ rec = false;
+ try {
+ int x = lz.Value;
+ Assert.Fail ("#8");
+ } catch (InvalidOperationException ex) { }
+ }
+
+ static int Return22 () {
+ return 22;
+ }
+
+ [Test]
+ public void Trivial_Lazy () {
+ var x = new Lazy<int> (Return22, false);
+ Assert.AreEqual (22, x.Value, "#1");
+ }
+
+ [Test]
+ public void ConcurrentInitialization ()
+ {
+ var init = new AutoResetEvent (false);
+ var e1_set = new AutoResetEvent (false);
+
+ var lazy = new Lazy<string> (() => {
+ init.Set ();
+ Thread.Sleep (10);
+ throw new ApplicationException ();
+ });
+
+ Exception e1 = null;
+ var thread = new Thread (() => {
+ try {
+ string value = lazy.Value;
+ } catch (Exception ex) {
+ e1 = ex;
+ e1_set.Set ();
+ }
+ });
+ thread.Start ();
+
+ Assert.IsTrue (init.WaitOne (3000), "#1");
+
+ Exception e2 = null;
+ try {
+ string value = lazy.Value;
+ } catch (Exception ex) {
+ e2 = ex;
+ }
+
+ Exception e3 = null;
+ try {
+ string value = lazy.Value;
+ } catch (Exception ex) {
+ e3 = ex;
+ }
+
+ Assert.IsTrue (e1_set.WaitOne (3000), "#2");
+ Assert.AreSame (e1, e2, "#3");
+ Assert.AreSame (e1, e3, "#4");
+ }
+
}
}
-
-#endif