From d08990595050830b32b27481b32f93f19d6f03cb Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 21 Sep 2023 15:41:30 +0300 Subject: [PATCH 01/11] =?UTF-8?q?=D0=9E=D1=81=D0=BD=D0=BE=D0=B2=D0=BD?= =?UTF-8?q?=D0=BE=D0=B9=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE=D0=BD?= =?UTF-8?q?=D0=B0=D0=BB,=20=D1=87=D0=B0=D1=81=D1=82=D0=B8=D1=87=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy/Lazy.sln | 31 +++++++++++++++++++++ Lazy/Lazy/ILazy.cs | 6 +++++ Lazy/Lazy/Lazy.csproj | 11 ++++++++ Lazy/Lazy/MultiThreadLazy.cs | 39 +++++++++++++++++++++++++++ Lazy/Lazy/SingleThreadLazy.cs | 39 +++++++++++++++++++++++++++ Lazy/TestsForLazy/TestsForLazy.cs | 31 +++++++++++++++++++++ Lazy/TestsForLazy/TestsForLazy.csproj | 23 ++++++++++++++++ Lazy/TestsForLazy/Usings.cs | 1 + 8 files changed, 181 insertions(+) create mode 100644 Lazy/Lazy.sln create mode 100644 Lazy/Lazy/ILazy.cs create mode 100644 Lazy/Lazy/Lazy.csproj create mode 100644 Lazy/Lazy/MultiThreadLazy.cs create mode 100644 Lazy/Lazy/SingleThreadLazy.cs create mode 100644 Lazy/TestsForLazy/TestsForLazy.cs create mode 100644 Lazy/TestsForLazy/TestsForLazy.csproj create mode 100644 Lazy/TestsForLazy/Usings.cs diff --git a/Lazy/Lazy.sln b/Lazy/Lazy.sln new file mode 100644 index 0000000..60ca094 --- /dev/null +++ b/Lazy/Lazy.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33403.182 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lazy", "Lazy\Lazy.csproj", "{F8C3CCDA-224A-4684-8E2E-B649BDBB08D3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsForLazy", "TestsForLazy\TestsForLazy.csproj", "{A08651D9-B95A-4E33-A8B0-D5635E0523C8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F8C3CCDA-224A-4684-8E2E-B649BDBB08D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8C3CCDA-224A-4684-8E2E-B649BDBB08D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8C3CCDA-224A-4684-8E2E-B649BDBB08D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8C3CCDA-224A-4684-8E2E-B649BDBB08D3}.Release|Any CPU.Build.0 = Release|Any CPU + {A08651D9-B95A-4E33-A8B0-D5635E0523C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A08651D9-B95A-4E33-A8B0-D5635E0523C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A08651D9-B95A-4E33-A8B0-D5635E0523C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A08651D9-B95A-4E33-A8B0-D5635E0523C8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8BB48519-EA16-4F07-8949-4E4CC34A90F4} + EndGlobalSection +EndGlobal diff --git a/Lazy/Lazy/ILazy.cs b/Lazy/Lazy/ILazy.cs new file mode 100644 index 0000000..833c125 --- /dev/null +++ b/Lazy/Lazy/ILazy.cs @@ -0,0 +1,6 @@ +namespace Lazy; + +public interface ILazy +{ + T Get(); +} \ No newline at end of file diff --git a/Lazy/Lazy/Lazy.csproj b/Lazy/Lazy/Lazy.csproj new file mode 100644 index 0000000..424caff --- /dev/null +++ b/Lazy/Lazy/Lazy.csproj @@ -0,0 +1,11 @@ + + + + Exe + net7.0 + enable + enable + Library + + + diff --git a/Lazy/Lazy/MultiThreadLazy.cs b/Lazy/Lazy/MultiThreadLazy.cs new file mode 100644 index 0000000..54cf89b --- /dev/null +++ b/Lazy/Lazy/MultiThreadLazy.cs @@ -0,0 +1,39 @@ +using System.Reflection.Metadata.Ecma335; + +namespace Lazy; + +public class MultiThreadLazy : ILazy +{ + private Func functionForLazy; + private Object objectLock = new (); + private bool initialized = false; + private T resultSuppiler; + private Exception exceptionSuppiler = null; + + public MultiThreadLazy(Func function) + { + functionForLazy = function; + } + + public T Get() + { + if (!initialized) + { + lock(objectLock) + { + try + { + resultSuppiler = functionForLazy(); + } + catch (Exception ex) + { + exceptionSuppiler = ex; + throw exceptionSuppiler; + } + initialized = true; + return resultSuppiler; + } + } + return resultSuppiler; + } +} \ No newline at end of file diff --git a/Lazy/Lazy/SingleThreadLazy.cs b/Lazy/Lazy/SingleThreadLazy.cs new file mode 100644 index 0000000..6564943 --- /dev/null +++ b/Lazy/Lazy/SingleThreadLazy.cs @@ -0,0 +1,39 @@ +namespace Lazy; + +public class SingleThreadLazy : ILazy +{ + private Func functionForLazy; + private bool flagForCounting = false; + private T resultSuppiler; + private Exception exceptionFromSuppiler = null; + public SingleThreadLazy(Func function) + { + functionForLazy = function; + } + + public T Get() + { + if (!flagForCounting) + { + try + { + resultSuppiler = functionForLazy(); + } + catch (Exception exception) + { + exceptionFromSuppiler = exception; + throw exceptionFromSuppiler; + } + flagForCounting = true; + return resultSuppiler; + } + else + { + if (exceptionFromSuppiler != null) + { + throw exceptionFromSuppiler; + } + return resultSuppiler; + } + } +} \ No newline at end of file diff --git a/Lazy/TestsForLazy/TestsForLazy.cs b/Lazy/TestsForLazy/TestsForLazy.cs new file mode 100644 index 0000000..d0718c1 --- /dev/null +++ b/Lazy/TestsForLazy/TestsForLazy.cs @@ -0,0 +1,31 @@ +namespace TestsForLazy; +using Lazy; + +public class Tests +{ + private static Func function = () => DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss:fff"); + + [TestCaseSource(nameof(Lazys))] + public void SimpleExample(ILazy lazy) + { + Assert.That(lazy.Get(), Is.EqualTo(lazy.Get())); + } + + [Test] + public void ExampleWithException() + { + var singleThreadLazy = new SingleThreadLazy(() => throw new InvalidOperationException()); + var multiThreadLazy = new MultiThreadLazy(() => throw new InvalidOperationException()); + Assert.Throws(() => singleThreadLazy.Get()); + Assert.Throws(() => singleThreadLazy.Get()); + Assert.Throws(() => multiThreadLazy.Get()); + Assert.Throws(() => multiThreadLazy.Get()); + } + + private static IEnumerable Lazys + => new TestCaseData[] + { + new TestCaseData(new SingleThreadLazy(function)), + new TestCaseData(new MultiThreadLazy(function)), + }; +} \ No newline at end of file diff --git a/Lazy/TestsForLazy/TestsForLazy.csproj b/Lazy/TestsForLazy/TestsForLazy.csproj new file mode 100644 index 0000000..70890c4 --- /dev/null +++ b/Lazy/TestsForLazy/TestsForLazy.csproj @@ -0,0 +1,23 @@ + + + + net7.0 + enable + enable + + false + + + + + + + + + + + + + + + diff --git a/Lazy/TestsForLazy/Usings.cs b/Lazy/TestsForLazy/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/Lazy/TestsForLazy/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file From d2023b9c8a368c7e00ecb1eb559f6d81adbd3be2 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 22 Sep 2023 18:38:11 +0300 Subject: [PATCH 02/11] =?UTF-8?q?=D0=9D=D0=B5=D0=B4=D0=BE=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BD=D0=BD=D1=8B=D0=B5=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy/Lazy/FunctionsForTests.cs | 18 +++++++++ Lazy/Lazy/MultiThreadLazy.cs | 20 +++++++--- Lazy/TestsForLazy/TestsForLazy.cs | 66 ++++++++++++++++++++++--------- 3 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 Lazy/Lazy/FunctionsForTests.cs diff --git a/Lazy/Lazy/FunctionsForTests.cs b/Lazy/Lazy/FunctionsForTests.cs new file mode 100644 index 0000000..d0e2f13 --- /dev/null +++ b/Lazy/Lazy/FunctionsForTests.cs @@ -0,0 +1,18 @@ +using System.Net.Http.Headers; + +namespace Lazy; + +public static class FunctionsForTests +{ + public static volatile int howMutchFunctionBeenCalled = 0; + public static int FunctionForLazyWithCounter() + { + howMutchFunctionBeenCalled++; + return howMutchFunctionBeenCalled; + } + + public static int FunctionWithInvalidOperationException() + { + throw new InvalidOperationException(); + } +} \ No newline at end of file diff --git a/Lazy/Lazy/MultiThreadLazy.cs b/Lazy/Lazy/MultiThreadLazy.cs index 54cf89b..362d9ed 100644 --- a/Lazy/Lazy/MultiThreadLazy.cs +++ b/Lazy/Lazy/MultiThreadLazy.cs @@ -6,7 +6,7 @@ public class MultiThreadLazy : ILazy { private Func functionForLazy; private Object objectLock = new (); - private bool initialized = false; + private volatile bool initialized = false; private T resultSuppiler; private Exception exceptionSuppiler = null; @@ -17,9 +17,18 @@ public MultiThreadLazy(Func function) public T Get() { - if (!initialized) + if (initialized) { - lock(objectLock) + if (exceptionSuppiler != null) + { + throw exceptionSuppiler; + } + return resultSuppiler; + } + + lock (objectLock) + { + if (!initialized) { try { @@ -28,12 +37,11 @@ public T Get() catch (Exception ex) { exceptionSuppiler = ex; - throw exceptionSuppiler; + throw; } initialized = true; - return resultSuppiler; } + return resultSuppiler; } - return resultSuppiler; } } \ No newline at end of file diff --git a/Lazy/TestsForLazy/TestsForLazy.cs b/Lazy/TestsForLazy/TestsForLazy.cs index d0718c1..a18b51d 100644 --- a/Lazy/TestsForLazy/TestsForLazy.cs +++ b/Lazy/TestsForLazy/TestsForLazy.cs @@ -2,30 +2,60 @@ namespace TestsForLazy; using Lazy; public class Tests -{ - private static Func function = () => DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss:fff"); - - [TestCaseSource(nameof(Lazys))] - public void SimpleExample(ILazy lazy) +{ + [Test] + public void SimpleExample() { - Assert.That(lazy.Get(), Is.EqualTo(lazy.Get())); + var singleThreadLazy = new SingleThreadLazy(() => FunctionsForTests.FunctionForLazyWithCounter()); + Assert.That(singleThreadLazy.Get(), Is.EqualTo(singleThreadLazy.Get())); + Assert.That(FunctionsForTests.FunctionForLazyWithCounter(), Is.Not.EqualTo(singleThreadLazy.Get())); + FunctionsForTests.howMutchFunctionBeenCalled = 0; + var multiThreadLazy = new MultiThreadLazy(() => FunctionsForTests.FunctionForLazyWithCounter()); + var arrayThreads = new Thread[10]; + object value = null; + for (int i = 0; i < arrayThreads.Length; i++) + { + arrayThreads[i] = new Thread(() => { value = multiThreadLazy.Get(); }); + } + + foreach (var thread in arrayThreads) + { + thread.Start(); + } + + foreach (var element in arrayThreads) + { + element.Join(); + } + + foreach (var element in arrayThreads) + { + Assert.That(1, Is.EqualTo(value)); + } } - [Test] + [Test]//? public void ExampleWithException() { - var singleThreadLazy = new SingleThreadLazy(() => throw new InvalidOperationException()); - var multiThreadLazy = new MultiThreadLazy(() => throw new InvalidOperationException()); + var singleThreadLazy = new SingleThreadLazy(() => FunctionsForTests.FunctionWithInvalidOperationException()); Assert.Throws(() => singleThreadLazy.Get()); Assert.Throws(() => singleThreadLazy.Get()); - Assert.Throws(() => multiThreadLazy.Get()); - Assert.Throws(() => multiThreadLazy.Get()); - } - private static IEnumerable Lazys - => new TestCaseData[] - { - new TestCaseData(new SingleThreadLazy(function)), - new TestCaseData(new MultiThreadLazy(function)), - }; + var multiThreadLazy = new MultiThreadLazy(() => FunctionsForTests.FunctionWithInvalidOperationException()); + var arrayThreads = new Thread[10]; + for (int i = 0;i < arrayThreads.Length; i++) + { + arrayThreads[i] = new Thread(() => multiThreadLazy.Get()); + } + + foreach (var element in arrayThreads) + { + Assert.Throws(() => element.Start()); + } + + foreach (var element in arrayThreads) + { + element.Join(); + } + } } \ No newline at end of file From a1eed468ee83d61692ce8f51a449707cb1f1a3a5 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 25 Sep 2023 14:30:29 +0300 Subject: [PATCH 03/11] =?UTF-8?q?=D0=94=D0=BE=D0=B4=D0=B5=D0=BB=D0=B0?= =?UTF-8?q?=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy/Lazy/MultiThreadLazy.cs | 9 +++-- Lazy/Lazy/SingleThreadLazy.cs | 9 +++-- Lazy/TestsForLazy/TestsForLazy.cs | 55 ++++++++++++++++++++++++++++--- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/Lazy/Lazy/MultiThreadLazy.cs b/Lazy/Lazy/MultiThreadLazy.cs index 362d9ed..2711687 100644 --- a/Lazy/Lazy/MultiThreadLazy.cs +++ b/Lazy/Lazy/MultiThreadLazy.cs @@ -8,7 +8,7 @@ public class MultiThreadLazy : ILazy private Object objectLock = new (); private volatile bool initialized = false; private T resultSuppiler; - private Exception exceptionSuppiler = null; + private Exception exceptionSuppiler = default; public MultiThreadLazy(Func function) { @@ -19,7 +19,7 @@ public T Get() { if (initialized) { - if (exceptionSuppiler != null) + if (exceptionSuppiler != default) { throw exceptionSuppiler; } @@ -37,7 +37,10 @@ public T Get() catch (Exception ex) { exceptionSuppiler = ex; - throw; + } + if (exceptionSuppiler != default) + { + throw exceptionSuppiler; } initialized = true; } diff --git a/Lazy/Lazy/SingleThreadLazy.cs b/Lazy/Lazy/SingleThreadLazy.cs index 6564943..586f28c 100644 --- a/Lazy/Lazy/SingleThreadLazy.cs +++ b/Lazy/Lazy/SingleThreadLazy.cs @@ -5,7 +5,7 @@ public class SingleThreadLazy : ILazy private Func functionForLazy; private bool flagForCounting = false; private T resultSuppiler; - private Exception exceptionFromSuppiler = null; + private Exception exceptionFromSuppiler = default; public SingleThreadLazy(Func function) { functionForLazy = function; @@ -15,6 +15,7 @@ public T Get() { if (!flagForCounting) { + flagForCounting = true; try { resultSuppiler = functionForLazy(); @@ -22,14 +23,16 @@ public T Get() catch (Exception exception) { exceptionFromSuppiler = exception; + } + if (exceptionFromSuppiler != default) + { throw exceptionFromSuppiler; } - flagForCounting = true; return resultSuppiler; } else { - if (exceptionFromSuppiler != null) + if (exceptionFromSuppiler != default) { throw exceptionFromSuppiler; } diff --git a/Lazy/TestsForLazy/TestsForLazy.cs b/Lazy/TestsForLazy/TestsForLazy.cs index a18b51d..1b55a9d 100644 --- a/Lazy/TestsForLazy/TestsForLazy.cs +++ b/Lazy/TestsForLazy/TestsForLazy.cs @@ -1,5 +1,6 @@ namespace TestsForLazy; using Lazy; +using Newtonsoft.Json.Linq; public class Tests { @@ -11,7 +12,7 @@ public void SimpleExample() Assert.That(FunctionsForTests.FunctionForLazyWithCounter(), Is.Not.EqualTo(singleThreadLazy.Get())); FunctionsForTests.howMutchFunctionBeenCalled = 0; var multiThreadLazy = new MultiThreadLazy(() => FunctionsForTests.FunctionForLazyWithCounter()); - var arrayThreads = new Thread[10]; + var arrayThreads = new Thread[Environment.ProcessorCount]; object value = null; for (int i = 0; i < arrayThreads.Length; i++) { @@ -34,7 +35,7 @@ public void SimpleExample() } } - [Test]//? + [Test] public void ExampleWithException() { var singleThreadLazy = new SingleThreadLazy(() => FunctionsForTests.FunctionWithInvalidOperationException()); @@ -42,15 +43,59 @@ public void ExampleWithException() Assert.Throws(() => singleThreadLazy.Get()); var multiThreadLazy = new MultiThreadLazy(() => FunctionsForTests.FunctionWithInvalidOperationException()); - var arrayThreads = new Thread[10]; + var arrayThreads = new Thread[Environment.ProcessorCount]; + object value = null; for (int i = 0;i < arrayThreads.Length; i++) { - arrayThreads[i] = new Thread(() => multiThreadLazy.Get()); + arrayThreads[i] = new Thread(() => + { + try + { + value = multiThreadLazy.Get(); + } + catch (InvalidOperationException) + { + Assert.True(true); + } + }); } foreach (var element in arrayThreads) { - Assert.Throws(() => element.Start()); + element.Start(); + } + + foreach (var element in arrayThreads) + { + element.Join(); + } + } + + [Test] + public void ThreadRaceTest() + { + var multiThreadLazy = new SingleThreadLazy(() => FunctionsForTests.FunctionForLazyWithCounter()); + var arrayThreads = new Thread[Environment.ProcessorCount]; + object value = null; + + for (int i = 0; i < arrayThreads.Length; i++) + { + arrayThreads[i] = new Thread(() => + { + value = multiThreadLazy.Get(); + lock (value) + { + if ((int)value != 1) + { + Assert.IsTrue(true); + } + } + }); + } + + foreach (var element in arrayThreads) + { + element.Start(); } foreach (var element in arrayThreads) From f9f3ba902c4f22294876e27e98b192f33c852dd6 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 25 Sep 2023 14:49:05 +0300 Subject: [PATCH 04/11] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=80?= =?UTF-8?q?=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy/Lazy/FunctionsForTests.cs | 15 ++++++++++++--- Lazy/Lazy/ILazy.cs | 6 ++++++ Lazy/Lazy/MultiThreadLazy.cs | 7 ++++--- Lazy/Lazy/SingleThreadLazy.cs | 4 ++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/Lazy/Lazy/FunctionsForTests.cs b/Lazy/Lazy/FunctionsForTests.cs index d0e2f13..f08066a 100644 --- a/Lazy/Lazy/FunctionsForTests.cs +++ b/Lazy/Lazy/FunctionsForTests.cs @@ -1,16 +1,25 @@ -using System.Net.Http.Headers; - -namespace Lazy; +namespace Lazy; +/// +/// Class for checking Lazy +/// public static class FunctionsForTests { public static volatile int howMutchFunctionBeenCalled = 0; + + /// + /// Function that counts how much it is caused by + /// public static int FunctionForLazyWithCounter() { howMutchFunctionBeenCalled++; return howMutchFunctionBeenCalled; } + /// + /// Function that throws InvalidOperationException + /// + /// public static int FunctionWithInvalidOperationException() { throw new InvalidOperationException(); diff --git a/Lazy/Lazy/ILazy.cs b/Lazy/Lazy/ILazy.cs index 833c125..025119a 100644 --- a/Lazy/Lazy/ILazy.cs +++ b/Lazy/Lazy/ILazy.cs @@ -1,6 +1,12 @@ namespace Lazy; +/// +/// The class implementing deferred creation +/// public interface ILazy { + /// + /// Getting the created object + /// T Get(); } \ No newline at end of file diff --git a/Lazy/Lazy/MultiThreadLazy.cs b/Lazy/Lazy/MultiThreadLazy.cs index 2711687..95e220f 100644 --- a/Lazy/Lazy/MultiThreadLazy.cs +++ b/Lazy/Lazy/MultiThreadLazy.cs @@ -1,6 +1,4 @@ -using System.Reflection.Metadata.Ecma335; - -namespace Lazy; +namespace Lazy; public class MultiThreadLazy : ILazy { @@ -10,6 +8,9 @@ public class MultiThreadLazy : ILazy private T resultSuppiler; private Exception exceptionSuppiler = default; + /// + /// Constructor for storing the object creation function + /// public MultiThreadLazy(Func function) { functionForLazy = function; diff --git a/Lazy/Lazy/SingleThreadLazy.cs b/Lazy/Lazy/SingleThreadLazy.cs index 586f28c..dc0a072 100644 --- a/Lazy/Lazy/SingleThreadLazy.cs +++ b/Lazy/Lazy/SingleThreadLazy.cs @@ -6,6 +6,10 @@ public class SingleThreadLazy : ILazy private bool flagForCounting = false; private T resultSuppiler; private Exception exceptionFromSuppiler = default; + + /// + /// Constructor for storing the object creation function + /// public SingleThreadLazy(Func function) { functionForLazy = function; From 7f3b5f77f61187f9311cb2c8f7ea75510e78bd99 Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 30 Sep 2023 14:54:55 +0300 Subject: [PATCH 05/11] =?UTF-8?q?=D0=A0=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy/Lazy.sln | 4 +- Lazy/Lazy/FunctionsForTests.cs | 12 ++-- Lazy/Lazy/ILazy.cs | 4 +- Lazy/Lazy/MultiThreadLazy.cs | 56 +++++++++--------- Lazy/Lazy/SingleThreadLazy.cs | 19 +++--- Lazy/TestsForLazy/TestsForLazy.cs | 96 +++++++++++++++++++------------ 6 files changed, 108 insertions(+), 83 deletions(-) diff --git a/Lazy/Lazy.sln b/Lazy/Lazy.sln index 60ca094..ccbe521 100644 --- a/Lazy/Lazy.sln +++ b/Lazy/Lazy.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.4.33403.182 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lazy", "Lazy\Lazy.csproj", "{F8C3CCDA-224A-4684-8E2E-B649BDBB08D3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lazy", "Lazy\Lazy.csproj", "{F8C3CCDA-224A-4684-8E2E-B649BDBB08D3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsForLazy", "TestsForLazy\TestsForLazy.csproj", "{A08651D9-B95A-4E33-A8B0-D5635E0523C8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestsForLazy", "TestsForLazy\TestsForLazy.csproj", "{A08651D9-B95A-4E33-A8B0-D5635E0523C8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Lazy/Lazy/FunctionsForTests.cs b/Lazy/Lazy/FunctionsForTests.cs index f08066a..c370240 100644 --- a/Lazy/Lazy/FunctionsForTests.cs +++ b/Lazy/Lazy/FunctionsForTests.cs @@ -3,24 +3,24 @@ /// /// Class for checking Lazy /// -public static class FunctionsForTests +public class FunctionsForTests { - public static volatile int howMutchFunctionBeenCalled = 0; + public volatile int howMuchFunctionBeenCalled = 0; /// /// Function that counts how much it is caused by /// - public static int FunctionForLazyWithCounter() + public int FunctionForLazyWithCounter() { - howMutchFunctionBeenCalled++; - return howMutchFunctionBeenCalled; + howMuchFunctionBeenCalled++; + return howMuchFunctionBeenCalled; } /// /// Function that throws InvalidOperationException /// /// - public static int FunctionWithInvalidOperationException() + public int FunctionWithInvalidOperationException() { throw new InvalidOperationException(); } diff --git a/Lazy/Lazy/ILazy.cs b/Lazy/Lazy/ILazy.cs index 025119a..aeaa425 100644 --- a/Lazy/Lazy/ILazy.cs +++ b/Lazy/Lazy/ILazy.cs @@ -1,12 +1,12 @@ namespace Lazy; /// -/// The class implementing deferred creation +/// The class implements, Gets the created object /// public interface ILazy { /// /// Getting the created object /// - T Get(); + T? Get(); } \ No newline at end of file diff --git a/Lazy/Lazy/MultiThreadLazy.cs b/Lazy/Lazy/MultiThreadLazy.cs index 95e220f..bf4b43b 100644 --- a/Lazy/Lazy/MultiThreadLazy.cs +++ b/Lazy/Lazy/MultiThreadLazy.cs @@ -2,50 +2,50 @@ public class MultiThreadLazy : ILazy { - private Func functionForLazy; + private Func supplier; private Object objectLock = new (); - private volatile bool initialized = false; - private T resultSuppiler; - private Exception exceptionSuppiler = default; + private volatile bool isCalculated = false; + private T? resultSuppiler; + private Exception? exceptionSuppiler = default; /// /// Constructor for storing the object creation function /// public MultiThreadLazy(Func function) { - functionForLazy = function; + supplier = function; } - public T Get() + public T? Get() { - if (initialized) + if (!isCalculated) { - if (exceptionSuppiler != default) + lock (objectLock) { - throw exceptionSuppiler; + if (!isCalculated) + { + try + { + resultSuppiler = supplier(); + supplier = null; + } + catch (Exception ex) + { + exceptionSuppiler = ex; + } + if (exceptionSuppiler != default) + { + throw exceptionSuppiler; + } + isCalculated = true; + } } - return resultSuppiler; } - lock (objectLock) + if (exceptionSuppiler != default) { - if (!initialized) - { - try - { - resultSuppiler = functionForLazy(); - } - catch (Exception ex) - { - exceptionSuppiler = ex; - } - if (exceptionSuppiler != default) - { - throw exceptionSuppiler; - } - initialized = true; - } - return resultSuppiler; + throw exceptionSuppiler; } + return resultSuppiler; } } \ No newline at end of file diff --git a/Lazy/Lazy/SingleThreadLazy.cs b/Lazy/Lazy/SingleThreadLazy.cs index dc0a072..9a10ee8 100644 --- a/Lazy/Lazy/SingleThreadLazy.cs +++ b/Lazy/Lazy/SingleThreadLazy.cs @@ -2,27 +2,28 @@ public class SingleThreadLazy : ILazy { - private Func functionForLazy; - private bool flagForCounting = false; - private T resultSuppiler; - private Exception exceptionFromSuppiler = default; + private Func supplier; + private bool isCalculated = false; + private T? resultSuppiler; + private Exception? exceptionFromSuppiler = default; /// /// Constructor for storing the object creation function /// public SingleThreadLazy(Func function) { - functionForLazy = function; + supplier = function; } - public T Get() + public T? Get() { - if (!flagForCounting) + if (!isCalculated) { - flagForCounting = true; + isCalculated = true; try { - resultSuppiler = functionForLazy(); + resultSuppiler = supplier(); + supplier = null; } catch (Exception exception) { diff --git a/Lazy/TestsForLazy/TestsForLazy.cs b/Lazy/TestsForLazy/TestsForLazy.cs index 1b55a9d..6cca690 100644 --- a/Lazy/TestsForLazy/TestsForLazy.cs +++ b/Lazy/TestsForLazy/TestsForLazy.cs @@ -1,22 +1,24 @@ namespace TestsForLazy; using Lazy; -using Newtonsoft.Json.Linq; public class Tests -{ +{ + private static FunctionsForTests globalFunctionsForTestsForSingleThread = new(); + private static FunctionsForTests globalFunctionsForTestsForMultiThread = new(); + [Test] - public void SimpleExample() + public void SimpleExampleWithMultiThreadLazy() { - var singleThreadLazy = new SingleThreadLazy(() => FunctionsForTests.FunctionForLazyWithCounter()); - Assert.That(singleThreadLazy.Get(), Is.EqualTo(singleThreadLazy.Get())); - Assert.That(FunctionsForTests.FunctionForLazyWithCounter(), Is.Not.EqualTo(singleThreadLazy.Get())); - FunctionsForTests.howMutchFunctionBeenCalled = 0; - var multiThreadLazy = new MultiThreadLazy(() => FunctionsForTests.FunctionForLazyWithCounter()); - var arrayThreads = new Thread[Environment.ProcessorCount]; - object value = null; + var functionsForTests = new FunctionsForTests(); + var result = 1; + var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionForLazyWithCounter()); + var arrayThreads = new Thread[10]; for (int i = 0; i < arrayThreads.Length; i++) { - arrayThreads[i] = new Thread(() => { value = multiThreadLazy.Get(); }); + arrayThreads[i] = new Thread(() => + { + Assert.That(result, Is.EqualTo(multiThreadLazy.Get())); + }); } foreach (var thread in arrayThreads) @@ -28,35 +30,29 @@ public void SimpleExample() { element.Join(); } - - foreach (var element in arrayThreads) - { - Assert.That(1, Is.EqualTo(value)); - } } [Test] - public void ExampleWithException() + public void ExampleWithExceptionWithMultiThreadLazy() { - var singleThreadLazy = new SingleThreadLazy(() => FunctionsForTests.FunctionWithInvalidOperationException()); - Assert.Throws(() => singleThreadLazy.Get()); - Assert.Throws(() => singleThreadLazy.Get()); - - var multiThreadLazy = new MultiThreadLazy(() => FunctionsForTests.FunctionWithInvalidOperationException()); - var arrayThreads = new Thread[Environment.ProcessorCount]; - object value = null; + var functionsForTests = new FunctionsForTests(); + var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionWithInvalidOperationException()); + var arrayThreads = new Thread[10]; + object? value = null; for (int i = 0;i < arrayThreads.Length; i++) { arrayThreads[i] = new Thread(() => { + bool isExceptionWasThrown = false; try { value = multiThreadLazy.Get(); } catch (InvalidOperationException) { - Assert.True(true); + isExceptionWasThrown = true; } + Assert.True(isExceptionWasThrown); }); } @@ -71,25 +67,39 @@ public void ExampleWithException() } } + [TestCaseSource(nameof(LazyForTestWithFunctionWithCounter))] + public void SimpleExampleWithOneThread(ILazy lazy) + { + var result = 1; + for (int i = 0; i < 10; ++i) + { + Assert.That(result, Is.EqualTo(lazy.Get())); + } + } + + [TestCaseSource(nameof(LazyForTestWithFunctionWithException))] + public void ExampleWithExceptionWithOneThread(ILazy lazy) + { + for (int i = 0; i < 10; ++i) + { + Assert.Throws(() => lazy.Get()); + } + } + [Test] public void ThreadRaceTest() { - var multiThreadLazy = new SingleThreadLazy(() => FunctionsForTests.FunctionForLazyWithCounter()); - var arrayThreads = new Thread[Environment.ProcessorCount]; - object value = null; + var functionsForTests = new FunctionsForTests(); + var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionForLazyWithCounter()); + var arrayThreads = new Thread[10]; + + var correctResult = 1; for (int i = 0; i < arrayThreads.Length; i++) { arrayThreads[i] = new Thread(() => { - value = multiThreadLazy.Get(); - lock (value) - { - if ((int)value != 1) - { - Assert.IsTrue(true); - } - } + Assert.That(correctResult, Is.EqualTo(multiThreadLazy.Get())); }); } @@ -103,4 +113,18 @@ public void ThreadRaceTest() element.Join(); } } + + private static IEnumerable LazyForTestWithFunctionWithCounter + => new TestCaseData[] + { + new TestCaseData(new MultiThreadLazy(() => globalFunctionsForTestsForSingleThread.FunctionForLazyWithCounter())), + new TestCaseData(new SingleThreadLazy(() => globalFunctionsForTestsForMultiThread.FunctionForLazyWithCounter())), + }; + + private static IEnumerable LazyForTestWithFunctionWithException + => new TestCaseData[] + { + new TestCaseData(new SingleThreadLazy(() => globalFunctionsForTestsForSingleThread.FunctionWithInvalidOperationException())), + new TestCaseData(new MultiThreadLazy(() => globalFunctionsForTestsForMultiThread.FunctionWithInvalidOperationException())), + }; } \ No newline at end of file From 914f98496b77d80f5e60a1d4798aa6e72038e151 Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 7 Oct 2023 16:09:55 +0300 Subject: [PATCH 06/11] =?UTF-8?q?=D0=A0=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy/Lazy/FunctionsForTests.cs | 27 ---------------- Lazy/Lazy/ILazy.cs | 4 +-- Lazy/Lazy/MultiThreadLazy.cs | 19 ++++++++---- Lazy/Lazy/SingleThreadLazy.cs | 33 +++++++++++--------- Lazy/TestsForLazy/TestsForLazy.cs | 51 ++++--------------------------- 5 files changed, 39 insertions(+), 95 deletions(-) delete mode 100644 Lazy/Lazy/FunctionsForTests.cs diff --git a/Lazy/Lazy/FunctionsForTests.cs b/Lazy/Lazy/FunctionsForTests.cs deleted file mode 100644 index c370240..0000000 --- a/Lazy/Lazy/FunctionsForTests.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Lazy; - -/// -/// Class for checking Lazy -/// -public class FunctionsForTests -{ - public volatile int howMuchFunctionBeenCalled = 0; - - /// - /// Function that counts how much it is caused by - /// - public int FunctionForLazyWithCounter() - { - howMuchFunctionBeenCalled++; - return howMuchFunctionBeenCalled; - } - - /// - /// Function that throws InvalidOperationException - /// - /// - public int FunctionWithInvalidOperationException() - { - throw new InvalidOperationException(); - } -} \ No newline at end of file diff --git a/Lazy/Lazy/ILazy.cs b/Lazy/Lazy/ILazy.cs index aeaa425..29aaacb 100644 --- a/Lazy/Lazy/ILazy.cs +++ b/Lazy/Lazy/ILazy.cs @@ -1,12 +1,12 @@ namespace Lazy; /// -/// The class implements, Gets the created object +/// The class implements an object whose function is called only once. /// public interface ILazy { /// - /// Getting the created object + /// Gets the created object. /// T? Get(); } \ No newline at end of file diff --git a/Lazy/Lazy/MultiThreadLazy.cs b/Lazy/Lazy/MultiThreadLazy.cs index bf4b43b..de1ac31 100644 --- a/Lazy/Lazy/MultiThreadLazy.cs +++ b/Lazy/Lazy/MultiThreadLazy.cs @@ -2,8 +2,8 @@ public class MultiThreadLazy : ILazy { - private Func supplier; - private Object objectLock = new (); + private Func? supplier; + private readonly Object objectLock = new (); private volatile bool isCalculated = false; private T? resultSuppiler; private Exception? exceptionSuppiler = default; @@ -26,16 +26,23 @@ public MultiThreadLazy(Func function) { try { - resultSuppiler = supplier(); - supplier = null; + if (supplier == null) + { + resultSuppiler = default; + } + else + { + resultSuppiler = supplier(); + } } catch (Exception ex) { exceptionSuppiler = ex; } - if (exceptionSuppiler != default) + finally { - throw exceptionSuppiler; + supplier = null; + GC.Collect(); } isCalculated = true; } diff --git a/Lazy/Lazy/SingleThreadLazy.cs b/Lazy/Lazy/SingleThreadLazy.cs index 9a10ee8..38392d8 100644 --- a/Lazy/Lazy/SingleThreadLazy.cs +++ b/Lazy/Lazy/SingleThreadLazy.cs @@ -2,7 +2,7 @@ public class SingleThreadLazy : ILazy { - private Func supplier; + private Func? supplier; private bool isCalculated = false; private T? resultSuppiler; private Exception? exceptionFromSuppiler = default; @@ -19,29 +19,32 @@ public SingleThreadLazy(Func function) { if (!isCalculated) { - isCalculated = true; try { - resultSuppiler = supplier(); - supplier = null; + if (supplier == null) + { + resultSuppiler = default; + } + else + { + resultSuppiler = supplier(); + } } - catch (Exception exception) + catch (Exception ex) { - exceptionFromSuppiler = exception; + exceptionFromSuppiler = ex; } - if (exceptionFromSuppiler != default) + finally { - throw exceptionFromSuppiler; + supplier = null; + GC.Collect(); } - return resultSuppiler; + isCalculated = true; } - else + if (exceptionFromSuppiler != default) { - if (exceptionFromSuppiler != default) - { - throw exceptionFromSuppiler; - } - return resultSuppiler; + throw exceptionFromSuppiler; } + return resultSuppiler; } } \ No newline at end of file diff --git a/Lazy/TestsForLazy/TestsForLazy.cs b/Lazy/TestsForLazy/TestsForLazy.cs index 6cca690..54e9590 100644 --- a/Lazy/TestsForLazy/TestsForLazy.cs +++ b/Lazy/TestsForLazy/TestsForLazy.cs @@ -3,21 +3,20 @@ namespace TestsForLazy; public class Tests { - private static FunctionsForTests globalFunctionsForTestsForSingleThread = new(); - private static FunctionsForTests globalFunctionsForTestsForMultiThread = new(); + private static readonly FunctionsForTests globalFunctionsForTestsForSingleThread = new(); + private static readonly FunctionsForTests globalFunctionsForTestsForMultiThread = new(); [Test] public void SimpleExampleWithMultiThreadLazy() { var functionsForTests = new FunctionsForTests(); - var result = 1; var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionForLazyWithCounter()); var arrayThreads = new Thread[10]; for (int i = 0; i < arrayThreads.Length; i++) { arrayThreads[i] = new Thread(() => { - Assert.That(result, Is.EqualTo(multiThreadLazy.Get())); + Assert.That(Equals(multiThreadLazy.Get(), 1)); }); } @@ -32,48 +31,12 @@ public void SimpleExampleWithMultiThreadLazy() } } - [Test] - public void ExampleWithExceptionWithMultiThreadLazy() - { - var functionsForTests = new FunctionsForTests(); - var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionWithInvalidOperationException()); - var arrayThreads = new Thread[10]; - object? value = null; - for (int i = 0;i < arrayThreads.Length; i++) - { - arrayThreads[i] = new Thread(() => - { - bool isExceptionWasThrown = false; - try - { - value = multiThreadLazy.Get(); - } - catch (InvalidOperationException) - { - isExceptionWasThrown = true; - } - Assert.True(isExceptionWasThrown); - }); - } - - foreach (var element in arrayThreads) - { - element.Start(); - } - - foreach (var element in arrayThreads) - { - element.Join(); - } - } - [TestCaseSource(nameof(LazyForTestWithFunctionWithCounter))] public void SimpleExampleWithOneThread(ILazy lazy) { - var result = 1; for (int i = 0; i < 10; ++i) { - Assert.That(result, Is.EqualTo(lazy.Get())); + Assert.That(Equals(lazy.Get(), 1)); } } @@ -82,7 +45,7 @@ public void ExampleWithExceptionWithOneThread(ILazy lazy) { for (int i = 0; i < 10; ++i) { - Assert.Throws(() => lazy.Get()); + Assert.Throws(() => lazy.Get()); } } @@ -93,13 +56,11 @@ public void ThreadRaceTest() var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionForLazyWithCounter()); var arrayThreads = new Thread[10]; - var correctResult = 1; - for (int i = 0; i < arrayThreads.Length; i++) { arrayThreads[i] = new Thread(() => { - Assert.That(correctResult, Is.EqualTo(multiThreadLazy.Get())); + Assert.That(Equals(multiThreadLazy.Get(), 1)); }); } From 41fc3c9d51f6f780cf614d11b505fc94c315dbbb Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 7 Oct 2023 16:13:33 +0300 Subject: [PATCH 07/11] =?UTF-8?q?=D0=97=D0=B0=D0=B1=D1=8B=D1=82=D1=8B?= =?UTF-8?q?=D0=B9=20=D1=84=D0=B0=D0=B9=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy/TestsForLazy/FunctionsForTests.cs | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 Lazy/TestsForLazy/FunctionsForTests.cs diff --git a/Lazy/TestsForLazy/FunctionsForTests.cs b/Lazy/TestsForLazy/FunctionsForTests.cs new file mode 100644 index 0000000..8f902c7 --- /dev/null +++ b/Lazy/TestsForLazy/FunctionsForTests.cs @@ -0,0 +1,28 @@ +namespace Lazy; + +/// +/// Class implements functions for checking Lazy +/// +public class FunctionsForTests +{ + private int howMuchFunctionBeenCalled = 0; + + /// + /// Function that counts how much it is caused by + /// + public int FunctionForLazyWithCounter() + { + Interlocked.Increment(ref howMuchFunctionBeenCalled); + return howMuchFunctionBeenCalled; + } + + /// + /// Function that throws InvalidOperationException + /// + /// + public int FunctionWithInvalidOperationException() + { + var firstNumber = 1; + return firstNumber / 0; + } +} \ No newline at end of file From 93a167eff502a2f84d105361e301232636967983 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 10 Oct 2023 14:30:47 +0300 Subject: [PATCH 08/11] =?UTF-8?q?=D0=A7=D0=B0=D1=81=D1=82=D1=8C=20=D1=80?= =?UTF-8?q?=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy/Lazy/SingleThreadLazy.cs | 6 +----- Lazy/TestsForLazy/FunctionsForTests.cs | 2 +- Lazy/TestsForLazy/TestsForLazy.cs | 21 +++++++++++++++++---- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Lazy/Lazy/SingleThreadLazy.cs b/Lazy/Lazy/SingleThreadLazy.cs index 38392d8..50bc7ae 100644 --- a/Lazy/Lazy/SingleThreadLazy.cs +++ b/Lazy/Lazy/SingleThreadLazy.cs @@ -21,11 +21,7 @@ public SingleThreadLazy(Func function) { try { - if (supplier == null) - { - resultSuppiler = default; - } - else + if (supplier != null) { resultSuppiler = supplier(); } diff --git a/Lazy/TestsForLazy/FunctionsForTests.cs b/Lazy/TestsForLazy/FunctionsForTests.cs index 8f902c7..4e9bd2a 100644 --- a/Lazy/TestsForLazy/FunctionsForTests.cs +++ b/Lazy/TestsForLazy/FunctionsForTests.cs @@ -23,6 +23,6 @@ public int FunctionForLazyWithCounter() public int FunctionWithInvalidOperationException() { var firstNumber = 1; - return firstNumber / 0; + return 1 / 0; } } \ No newline at end of file diff --git a/Lazy/TestsForLazy/TestsForLazy.cs b/Lazy/TestsForLazy/TestsForLazy.cs index 54e9590..6136cd2 100644 --- a/Lazy/TestsForLazy/TestsForLazy.cs +++ b/Lazy/TestsForLazy/TestsForLazy.cs @@ -12,11 +12,13 @@ public void SimpleExampleWithMultiThreadLazy() var functionsForTests = new FunctionsForTests(); var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionForLazyWithCounter()); var arrayThreads = new Thread[10]; + var arrayNumbers = new int[10]; + for (int i = 0; i < arrayThreads.Length; i++) { arrayThreads[i] = new Thread(() => { - Assert.That(Equals(multiThreadLazy.Get(), 1)); + arrayNumbers[i] = multiThreadLazy.Get(); }); } @@ -29,6 +31,11 @@ public void SimpleExampleWithMultiThreadLazy() { element.Join(); } + + foreach (var element in arrayNumbers) + { + Assert.That(element, Is.EqualTo(1)); + } } [TestCaseSource(nameof(LazyForTestWithFunctionWithCounter))] @@ -36,7 +43,7 @@ public void SimpleExampleWithOneThread(ILazy lazy) { for (int i = 0; i < 10; ++i) { - Assert.That(Equals(lazy.Get(), 1)); + Assert.That(lazy.Get(), Is.EqualTo(1)); } } @@ -55,12 +62,13 @@ public void ThreadRaceTest() var functionsForTests = new FunctionsForTests(); var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionForLazyWithCounter()); var arrayThreads = new Thread[10]; + var arrayNumbers = new int[10]; for (int i = 0; i < arrayThreads.Length; i++) { arrayThreads[i] = new Thread(() => - { - Assert.That(Equals(multiThreadLazy.Get(), 1)); + { + arrayNumbers[i] = multiThreadLazy.Get(); }); } @@ -73,6 +81,11 @@ public void ThreadRaceTest() { element.Join(); } + + foreach (var element in arrayNumbers) + { + Assert.That(multiThreadLazy.Get(), Is.EqualTo(1)); + } } private static IEnumerable LazyForTestWithFunctionWithCounter From d40eae5b76e8d99995ceb19bb96b76eea51c3f20 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 10 Oct 2023 14:32:20 +0300 Subject: [PATCH 09/11] =?UTF-8?q?=D0=A7=D0=B0=D1=81=D1=82=D1=8C=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy/TestsForLazy/FunctionsForTests.cs | 2 +- Lazy/TestsForLazy/TestsForLazy.cs | 19 +++---------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/Lazy/TestsForLazy/FunctionsForTests.cs b/Lazy/TestsForLazy/FunctionsForTests.cs index 4e9bd2a..8f902c7 100644 --- a/Lazy/TestsForLazy/FunctionsForTests.cs +++ b/Lazy/TestsForLazy/FunctionsForTests.cs @@ -23,6 +23,6 @@ public int FunctionForLazyWithCounter() public int FunctionWithInvalidOperationException() { var firstNumber = 1; - return 1 / 0; + return firstNumber / 0; } } \ No newline at end of file diff --git a/Lazy/TestsForLazy/TestsForLazy.cs b/Lazy/TestsForLazy/TestsForLazy.cs index 6136cd2..2714cad 100644 --- a/Lazy/TestsForLazy/TestsForLazy.cs +++ b/Lazy/TestsForLazy/TestsForLazy.cs @@ -12,13 +12,11 @@ public void SimpleExampleWithMultiThreadLazy() var functionsForTests = new FunctionsForTests(); var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionForLazyWithCounter()); var arrayThreads = new Thread[10]; - var arrayNumbers = new int[10]; - for (int i = 0; i < arrayThreads.Length; i++) { arrayThreads[i] = new Thread(() => { - arrayNumbers[i] = multiThreadLazy.Get(); + Assert.That(multiThreadLazy.Get(), Is.EqualTo(1)); }); } @@ -31,11 +29,6 @@ public void SimpleExampleWithMultiThreadLazy() { element.Join(); } - - foreach (var element in arrayNumbers) - { - Assert.That(element, Is.EqualTo(1)); - } } [TestCaseSource(nameof(LazyForTestWithFunctionWithCounter))] @@ -62,13 +55,12 @@ public void ThreadRaceTest() var functionsForTests = new FunctionsForTests(); var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionForLazyWithCounter()); var arrayThreads = new Thread[10]; - var arrayNumbers = new int[10]; for (int i = 0; i < arrayThreads.Length; i++) { arrayThreads[i] = new Thread(() => - { - arrayNumbers[i] = multiThreadLazy.Get(); + { + Assert.That(Equals(multiThreadLazy.Get(), 1)); }); } @@ -81,11 +73,6 @@ public void ThreadRaceTest() { element.Join(); } - - foreach (var element in arrayNumbers) - { - Assert.That(multiThreadLazy.Get(), Is.EqualTo(1)); - } } private static IEnumerable LazyForTestWithFunctionWithCounter From acfaf47dd1935e843db79aaf152279f606757d2a Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 14 Oct 2023 15:45:01 +0300 Subject: [PATCH 10/11] =?UTF-8?q?=D0=A0=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy/Lazy/MultiThreadLazy.cs | 1 - Lazy/Lazy/SingleThreadLazy.cs | 1 - Lazy/TestsForLazy/TestsForLazy.cs | 28 +++++++++++++++++++++++++--- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/Lazy/Lazy/MultiThreadLazy.cs b/Lazy/Lazy/MultiThreadLazy.cs index de1ac31..9bca5ea 100644 --- a/Lazy/Lazy/MultiThreadLazy.cs +++ b/Lazy/Lazy/MultiThreadLazy.cs @@ -42,7 +42,6 @@ public MultiThreadLazy(Func function) finally { supplier = null; - GC.Collect(); } isCalculated = true; } diff --git a/Lazy/Lazy/SingleThreadLazy.cs b/Lazy/Lazy/SingleThreadLazy.cs index 50bc7ae..e4f9747 100644 --- a/Lazy/Lazy/SingleThreadLazy.cs +++ b/Lazy/Lazy/SingleThreadLazy.cs @@ -33,7 +33,6 @@ public SingleThreadLazy(Func function) finally { supplier = null; - GC.Collect(); } isCalculated = true; } diff --git a/Lazy/TestsForLazy/TestsForLazy.cs b/Lazy/TestsForLazy/TestsForLazy.cs index 2714cad..35e5a3f 100644 --- a/Lazy/TestsForLazy/TestsForLazy.cs +++ b/Lazy/TestsForLazy/TestsForLazy.cs @@ -12,11 +12,18 @@ public void SimpleExampleWithMultiThreadLazy() var functionsForTests = new FunctionsForTests(); var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionForLazyWithCounter()); var arrayThreads = new Thread[10]; + + var arrayResult = new int[10]; + for (int i = 0; i < arrayThreads.Length; i++) { + var local = i; arrayThreads[i] = new Thread(() => { - Assert.That(multiThreadLazy.Get(), Is.EqualTo(1)); + for (var j = local; j < 10; j++) + { + arrayResult[j] = multiThreadLazy.Get(); + } }); } @@ -29,6 +36,11 @@ public void SimpleExampleWithMultiThreadLazy() { element.Join(); } + + foreach (var element in arrayResult) + { + Assert.That(Equals(element, 1)); + } } [TestCaseSource(nameof(LazyForTestWithFunctionWithCounter))] @@ -55,12 +67,17 @@ public void ThreadRaceTest() var functionsForTests = new FunctionsForTests(); var multiThreadLazy = new MultiThreadLazy(() => functionsForTests.FunctionForLazyWithCounter()); var arrayThreads = new Thread[10]; + var arrayResult = new int[10]; for (int i = 0; i < arrayThreads.Length; i++) { + var local = i; arrayThreads[i] = new Thread(() => - { - Assert.That(Equals(multiThreadLazy.Get(), 1)); + { + for (var j = local; j < 10; j++) + { + arrayResult[j] = multiThreadLazy.Get(); + } }); } @@ -73,6 +90,11 @@ public void ThreadRaceTest() { element.Join(); } + + foreach (var element in arrayResult) + { + Assert.That(Equals(element, 1)); + } } private static IEnumerable LazyForTestWithFunctionWithCounter From a325505fef088352dce1f253b9b8a8c408746194 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 27 Dec 2023 13:53:59 +0300 Subject: [PATCH 11/11] =?UTF-8?q?=D0=A0=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy/TestsForLazy/FunctionsForTests.cs | 4 ++-- Lazy/TestsForLazy/TestsForLazy.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Lazy/TestsForLazy/FunctionsForTests.cs b/Lazy/TestsForLazy/FunctionsForTests.cs index 8f902c7..86afc36 100644 --- a/Lazy/TestsForLazy/FunctionsForTests.cs +++ b/Lazy/TestsForLazy/FunctionsForTests.cs @@ -17,10 +17,10 @@ public int FunctionForLazyWithCounter() } /// - /// Function that throws InvalidOperationException + /// Function that throws DivideByZeroException /// /// - public int FunctionWithInvalidOperationException() + public int DivideByZeroException() { var firstNumber = 1; return firstNumber / 0; diff --git a/Lazy/TestsForLazy/TestsForLazy.cs b/Lazy/TestsForLazy/TestsForLazy.cs index 35e5a3f..6ffc03e 100644 --- a/Lazy/TestsForLazy/TestsForLazy.cs +++ b/Lazy/TestsForLazy/TestsForLazy.cs @@ -39,7 +39,7 @@ public void SimpleExampleWithMultiThreadLazy() foreach (var element in arrayResult) { - Assert.That(Equals(element, 1)); + Assert.That(element, Is.EqualTo(1)); } } @@ -93,7 +93,7 @@ public void ThreadRaceTest() foreach (var element in arrayResult) { - Assert.That(Equals(element, 1)); + Assert.That(element, Is.EqualTo(1)); } } @@ -107,7 +107,7 @@ private static IEnumerable LazyForTestWithFunctionWithCounter private static IEnumerable LazyForTestWithFunctionWithException => new TestCaseData[] { - new TestCaseData(new SingleThreadLazy(() => globalFunctionsForTestsForSingleThread.FunctionWithInvalidOperationException())), - new TestCaseData(new MultiThreadLazy(() => globalFunctionsForTestsForMultiThread.FunctionWithInvalidOperationException())), + new TestCaseData(new SingleThreadLazy(() => globalFunctionsForTestsForSingleThread.DivideByZeroException())), + new TestCaseData(new MultiThreadLazy(() => globalFunctionsForTestsForMultiThread.DivideByZeroException())), }; } \ No newline at end of file