diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a7ee6f9..d8b5c0b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,6 +1,17 @@
name: Build
on: [push]
jobs:
+ build-Ubuntu:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: "7.x"
+ - name: Build
+ run: for f in $(find . -name "*.sln"); do dotnet build $f; done
+ - name: Run tests
+ run: for f in $(find . -name "*.sln"); do dotnet test $f; done
build-Windows:
runs-on: windows-latest
steps:
@@ -10,4 +21,7 @@ jobs:
dotnet-version: "7.x"
- name: Build
shell: bash
- run: for f in $(find . -name "*.sln"); do dotnet build $f; done
\ No newline at end of file
+ run: for f in $(find . -name "*.sln"); do dotnet build $f; done
+ - name: Run tests
+ shell: bash
+ run: for f in $(find . -name "*.sln"); do dotnet test $f; done
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index e69de29..0000000
diff --git a/HW02LAZY/LAZY/LAZY.csproj b/HW02LAZY/LAZY/LAZY.csproj
new file mode 100644
index 0000000..2cedbdc
--- /dev/null
+++ b/HW02LAZY/LAZY/LAZY.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/HW02LAZY/LAZY/LAZY.sln b/HW02LAZY/LAZY/LAZY.sln
new file mode 100644
index 0000000..89ff063
--- /dev/null
+++ b/HW02LAZY/LAZY/LAZY.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33213.308
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LAZY", "LAZY.csproj", "{276FC7DD-D798-45F9-8C47-316B22DFCC01}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LazyTests", "..\LazyTests\LazyTests.csproj", "{BDC0A084-C741-4787-87FD-DD66C13ABC5C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {276FC7DD-D798-45F9-8C47-316B22DFCC01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {276FC7DD-D798-45F9-8C47-316B22DFCC01}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {276FC7DD-D798-45F9-8C47-316B22DFCC01}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {276FC7DD-D798-45F9-8C47-316B22DFCC01}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BDC0A084-C741-4787-87FD-DD66C13ABC5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BDC0A084-C741-4787-87FD-DD66C13ABC5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BDC0A084-C741-4787-87FD-DD66C13ABC5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BDC0A084-C741-4787-87FD-DD66C13ABC5C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {6BC94BD4-BE73-414F-AC89-B2C3C2B80B0C}
+ EndGlobalSection
+EndGlobal
diff --git a/HW02LAZY/LAZY/Lazy.cs b/HW02LAZY/LAZY/Lazy.cs
new file mode 100644
index 0000000..e027e91
--- /dev/null
+++ b/HW02LAZY/LAZY/Lazy.cs
@@ -0,0 +1,116 @@
+using System.Runtime.InteropServices;
+
+
+namespace MyLazy;
+
+public interface ILazy {
+ T? Get();
+ }
+
+///
+/// Thread non-safe realisation of built-in Lazy class
+///
+/// Type of supplier function returning value
+public class LazySingleThread : ILazy
+{
+ private bool _isCalculated = false;
+ private T? _result;
+ private Func _supplier;
+
+ ///
+ /// Creates object of this class
+ ///
+ /// Function, providing calculation
+ public LazySingleThread(Func supplier)
+ {
+ _supplier = supplier;
+ }
+
+ ///
+ /// Calls for lazy initialised object. First time runs calculation
+ /// via supplier function. Following times returns precalculated value
+ ///
+ /// Result of running supplier function
+ public T? Get()
+ {
+ if (!_isCalculated) {
+ try
+ {
+ _result = _supplier();
+ }
+ catch
+ {
+ _result = default(T);
+ }
+ }
+ _isCalculated = true;
+ return _result;
+ }
+}
+
+///
+/// Thread safe realisation of built-in Lazy class
+///
+/// Type of supplier function returning value
+public class LazyMultiThread : ILazy
+{
+ private Object _lockObject = new();
+ private bool _isCalculated = false;
+ private T? _result;
+ private Func _supplier;
+
+ ///
+ /// Creates object of this class
+ ///
+ /// Function, providing calculation
+ public LazyMultiThread(Func supplier)
+ {
+ _supplier = supplier;
+ }
+
+ ///
+ /// Calls for lazy initialised object. First time runs calculation
+ /// via supplier function. Following times returns precalculated value
+ ///
+ /// Result of running supplier function
+ public T? Get()
+ {
+ if (Volatile.Read(ref _isCalculated)) {
+ return _result;
+ }
+
+ lock (_lockObject)
+ {
+ if (Volatile.Read(ref _isCalculated))
+ return _result;
+
+ try
+ {
+ _result = _supplier();
+ Volatile.Write(ref _isCalculated, true);
+ }
+ catch
+ {
+ _result = default(T);
+ }
+
+ return _result;
+ }
+ }
+}
+
+public class Counter
+{
+ private static int _counterValue = 0;
+ public static int CounterValue => _counterValue;
+ public static int Calculation()
+ {
+ return ++_counterValue;
+ }
+}
+internal class MyLazy
+{
+ static void Main()
+ {
+ }
+}
diff --git a/HW02LAZY/LazyTests/LazyTests.cs b/HW02LAZY/LazyTests/LazyTests.cs
new file mode 100644
index 0000000..a419625
--- /dev/null
+++ b/HW02LAZY/LazyTests/LazyTests.cs
@@ -0,0 +1,122 @@
+using System.Diagnostics;
+using System.Xml.Schema;
+using MyLazy;
+
+namespace LazyTests;
+
+///
+/// Fraction calculation. Throws exception
+/// if deviding zero
+///
+public class Fraction
+{
+ int _numerator;
+ int _denominator;
+
+ public Fraction(int numerator, int denominator)
+ {
+ _numerator = numerator;
+ _denominator = denominator;
+ }
+
+ public double Calculate()
+ {
+ if (_denominator != 0)
+ {
+ return (double)_numerator / _denominator;
+ }
+ else
+ {
+ throw new Exception("Zero division achtung");
+ }
+ }
+}
+
+///
+/// Counts calculation attempts from all working threads
+///
+public class Counter
+{
+ private int _counterValue = 0;
+ public int CounterValue => _counterValue;
+ public int Calculation()
+ {
+ return ++_counterValue;
+ }
+}
+
+[TestClass]
+public class LazySingleThreadTests
+{
+ [TestMethod]
+ public void ExceptionGetTest()
+ {
+ var successCalc = new Fraction(5, 2);
+ var exceptionCalc = new Fraction(5, 0);
+ var successLazy = new LazySingleThread(successCalc.Calculate);
+ var exceptionLazy = new LazySingleThread(exceptionCalc.Calculate);
+
+ Assert.IsTrue(successLazy.Get() == 2.5);
+ Assert.IsTrue(exceptionLazy.Get() == default(double));
+ }
+
+ [TestMethod]
+ public void GetTest()
+ {
+ var counter = new Counter();
+ var iterations = 20;
+ var lazyCalculator = new LazySingleThread(counter.Calculation);
+
+ for (var i = 0; i < iterations; ++i)
+ lazyCalculator.Get();
+
+ Assert.IsTrue(lazyCalculator.Get() == 1);
+ Assert.IsTrue(counter.CounterValue == 1);
+ }
+}
+
+[TestClass]
+public class LazyMultiThreadTests
+{
+ [TestMethod]
+ public void ExceptionGetTest()
+ {
+ var successCalc = new Fraction(5, 2);
+ var exceptionCalc = new Fraction(5, 0);
+ var successLazy = new LazyMultiThread(successCalc.Calculate);
+ var exceptionLazy = new LazyMultiThread(exceptionCalc.Calculate);
+
+ Assert.IsTrue(successLazy.Get() == 2.5);
+ Assert.IsTrue(exceptionLazy.Get() == default(double));
+ }
+ [TestMethod]
+ public void GetTest()
+ {
+ var threadCount = 20;
+ var threadIterations = 20;
+ var threads = new Thread[threadCount];
+ var counter = new Counter();
+ var lazyCalculator = new LazyMultiThread(counter.Calculation);
+
+ for (var i = 0; i < threadCount; ++i)
+ {
+ threads[i] = new Thread(() => {
+ for (var i = 0; i < threadIterations; ++i) {
+ lazyCalculator.Get();
+ }});
+ }
+
+ for (var i = 0; i < threadCount; ++i) {
+ threads[i].Start();
+ }
+
+ for (var i = 0; i < threadCount; ++i) {
+ threads[i].Join();
+ }
+
+ Assert.IsTrue(lazyCalculator.Get() == 1);
+ Assert.IsTrue(counter.CounterValue == 1);
+ }
+}
+
+
diff --git a/HW02LAZY/LazyTests/LazyTests.csproj b/HW02LAZY/LazyTests/LazyTests.csproj
new file mode 100644
index 0000000..0397427
--- /dev/null
+++ b/HW02LAZY/LazyTests/LazyTests.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HW02LAZY/LazyTests/Usings.cs b/HW02LAZY/LazyTests/Usings.cs
new file mode 100644
index 0000000..ab67c7e
--- /dev/null
+++ b/HW02LAZY/LazyTests/Usings.cs
@@ -0,0 +1 @@
+global using Microsoft.VisualStudio.TestTools.UnitTesting;
\ No newline at end of file