-
Notifications
You must be signed in to change notification settings - Fork 0
HW2 Lazy Evaluation #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
khusainovilas
wants to merge
18
commits into
main
Choose a base branch
from
task2-lazy-evaluation
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
e7f347a
init implementation of ILazy
khusainovilas 91a3a9a
add common unit test for lazy evaluation
khusainovilas 5a23601
add tests for commonality between two implementations
khusainovilas 2004877
add files for 2 tests
khusainovilas 2d64352
remove .idea folder and fix gitignore
khusainovilas 27c4315
add singleThreaded tests
khusainovilas 451fec6
add multiThreaded tests
khusainovilas 7fa74bb
change lazy multiThreaded tests
khusainovilas 87ebb50
Merge branch 'main' into task2-lazy-evaluation
khusainovilas 9fe44fa
remove unnecessary files and make minor code update
khusainovilas 10a0fdd
Merge branch 'task2-lazy-evaluation' of https://github.com/khusainovi…
khusainovilas 8bd83ca
fix CI problem
khusainovilas 3869255
make minor code update in tests
khusainovilas 1963e05
fix: remove nullable types
khusainovilas 215d8e0
fix nullable mismatches
khusainovilas 9000569
Upgrade project to .NET 9
khusainovilas 0926435
fix remarks
khusainovilas a382fcd
fix remarks
khusainovilas File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| | ||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LazyEvaluation", "LazyEvaluation\LazyEvaluation.csproj", "{D2A3863F-D69C-419E-9580-826C8718A7E5}" | ||
| EndProject | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LazyEvaluation.Test", "LazyEvaluation.Test\LazyEvaluation.Test.csproj", "{C9B07A5A-EAD9-461C-B638-858E14BD4E7E}" | ||
| EndProject | ||
| Global | ||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| Debug|Any CPU = Debug|Any CPU | ||
| Release|Any CPU = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| {D2A3863F-D69C-419E-9580-826C8718A7E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {D2A3863F-D69C-419E-9580-826C8718A7E5}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {D2A3863F-D69C-419E-9580-826C8718A7E5}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {D2A3863F-D69C-419E-9580-826C8718A7E5}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| {C9B07A5A-EAD9-461C-B638-858E14BD4E7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {C9B07A5A-EAD9-461C-B638-858E14BD4E7E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {C9B07A5A-EAD9-461C-B638-858E14BD4E7E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {C9B07A5A-EAD9-461C-B638-858E14BD4E7E}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| EndGlobalSection | ||
| EndGlobal |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net9.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
|
|
||
| <IsPackable>false</IsPackable> | ||
| <IsTestProject>true</IsTestProject> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="coverlet.collector" Version="6.0.0"/> | ||
| <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/> | ||
| <PackageReference Include="NUnit" Version="3.14.0"/> | ||
| <PackageReference Include="NUnit.Analyzers" Version="3.9.0"/> | ||
| <PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <Using Include="NUnit.Framework"/> | ||
| </ItemGroup> | ||
|
|
||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <AdditionalFiles Include="stylecop.json" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\LazyEvaluation\LazyEvaluation.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| // <copyright file="LazyEvaluationTest.cs" company="khusainovilas"> | ||
| // Copyright (c) khusainovilas. All rights reserved. | ||
| // </copyright> | ||
|
|
||
| namespace LazyEvaluation.Test; | ||
|
|
||
| /// <summary> | ||
| /// Unit tests for lazy evaluation. | ||
| /// </summary> | ||
| public abstract class LazyEvaluationTest | ||
| { | ||
| /// <summary> | ||
| /// Verifies that the supplier delegate is called exactly one time. | ||
| /// </summary> | ||
| [Test] | ||
| public void Lazy_Get_NonNullSupplier_SupplierCalledOnce() | ||
| { | ||
| var callCount = 0; | ||
|
|
||
| var supplier = new Func<string?>(() => | ||
| { | ||
| callCount++; | ||
| return "test"; | ||
| }); | ||
|
|
||
| var lazy = this.CreateLazy(supplier); | ||
|
|
||
| var result1 = lazy.Get(); | ||
| var result2 = lazy.Get(); | ||
|
|
||
| Assert.Multiple(() => | ||
| { | ||
| Assert.That(result1, Is.EqualTo("test")); | ||
| Assert.That(result2, Is.EqualTo("test")); | ||
| Assert.That(callCount, Is.EqualTo(1)); | ||
| }); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Verifies that multiple calls to Get() return the same result. | ||
| /// </summary> | ||
| [Test] | ||
| public void Lazy_Get_SimpleString_NonNullSupplier_SameResult() | ||
| { | ||
| var supplier = new Func<string?>(() => "test"); | ||
| var lazy = this.CreateLazy(supplier); | ||
|
|
||
| var result1 = lazy.Get(); | ||
| var result2 = lazy.Get(); | ||
|
|
||
| Assert.That(result2, Is.EqualTo(result1)); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Verifies that constructing with a null supplier throws ArgumentNullException. | ||
| /// </summary> | ||
| [Test] | ||
| public void Lazy_Constructor_NullSupplier_ThrowsException() | ||
| { | ||
| Assert.Throws<ArgumentNullException>(() => | ||
| { | ||
| Func<string?> supplier = null!; | ||
| this.CreateLazy(supplier); | ||
| }); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Verifies that Get() correctly handles a null result from the supplier. | ||
| /// </summary> | ||
| [Test] | ||
| public void Lazy_Get_NullResultSupplier_ReturnsNull() | ||
| { | ||
| var callCount = 0; | ||
| var supplier = new Func<string?>(() => | ||
| { | ||
| callCount++; | ||
| return null; | ||
| }); | ||
|
|
||
| var lazy = this.CreateLazy(supplier); | ||
|
|
||
| Assert.Multiple(() => | ||
| { | ||
| Assert.That(lazy.Get(), Is.Null); | ||
| Assert.That(lazy.Get(), Is.Null); | ||
| Assert.That(callCount, Is.EqualTo(1)); | ||
| }); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// abstract method for creating an ILazy instance. | ||
| /// </summary> | ||
| /// <param name="supplier">function responsible for computing the value.</param> | ||
| /// <typeparam name="T">the type of the computed value.</typeparam> | ||
| /// <returns>a new ILazy instance.</returns> | ||
| protected abstract ILazy<T> CreateLazy<T>(Func<T> supplier); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| // <copyright file="LazyMultiThreadedTest.cs" company="khusainovilas"> | ||
| // Copyright (c) khusainovilas. All rights reserved. | ||
| // </copyright> | ||
|
|
||
| namespace LazyEvaluation.Test; | ||
|
|
||
| /// <summary> | ||
| /// Unit tests for LazyMultiThreaded implementation. | ||
| /// </summary> | ||
| public class LazyMultiThreadedTest : LazyEvaluationTest | ||
| { | ||
| /// <summary> | ||
| /// Verifies that the supplier is called exactly once during concurrent Get() calls in LazyMultiThreaded. | ||
| /// </summary> | ||
| [Test] | ||
| public void LazyMultiThreaded_Get_String_SingleSupplierCall() | ||
| { | ||
| var callCount = 0; | ||
| var lazy = this.CreateLazy(() => | ||
| { | ||
| Interlocked.Increment(ref callCount); | ||
| return "test"; | ||
| }); | ||
|
|
||
| const int threadsCount = 100; | ||
| var threads = new Thread[threadsCount]; | ||
| var results = new string[threadsCount]; | ||
|
|
||
| var startEvent = new ManualResetEvent(false); | ||
|
|
||
| for (var i = 0; i < threadsCount; i++) | ||
| { | ||
| var index = i; | ||
| threads[i] = new Thread(() => | ||
| { | ||
| results[index] = lazy.Get(); | ||
khusainovilas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }); | ||
| } | ||
|
|
||
| startEvent.Set(); | ||
|
|
||
| foreach (var thread in threads) | ||
| { | ||
| thread.Start(); | ||
| } | ||
|
|
||
| foreach (var thread in threads) | ||
| { | ||
| thread.Join(); | ||
| } | ||
|
|
||
| Assert.Multiple(() => | ||
| { | ||
| Assert.That(results, Has.All.EqualTo("test")); | ||
| Assert.That(callCount, Is.EqualTo(1)); | ||
| }); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| protected override ILazy<T> CreateLazy<T>(Func<T> supplier) | ||
| { | ||
| return new LazyMultiThreaded<T>(supplier); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| // <copyright file="LazySingleThreadedTest.cs" company="khusainovilas"> | ||
| // Copyright (c) khusainovilas. All rights reserved. | ||
| // </copyright> | ||
|
|
||
| namespace LazyEvaluation.Test; | ||
|
|
||
| /// <summary> | ||
| /// Unit tests for LazySingleThreaded implementation. | ||
| /// </summary> | ||
| public class LazySingleThreadedTest : LazyEvaluationTest | ||
khusainovilas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| /// <summary> | ||
| /// Test for correct work Get() with double. | ||
| /// </summary> | ||
| [Test] | ||
| public void LazySingleThreaded_Get_Double_ReturnsCorrectValue() | ||
| { | ||
| var callCount = 0; | ||
| var lazy = this.CreateLazy(() => | ||
| { | ||
| callCount++; | ||
| return 1.5; | ||
| }); | ||
|
|
||
| var result1 = lazy.Get(); | ||
| var result2 = lazy.Get(); | ||
|
|
||
| Assert.Multiple(() => | ||
| { | ||
| Assert.That(result1, Is.EqualTo(1.5).Within(1e-9)); | ||
| Assert.That(result2, Is.EqualTo(1.5).Within(1e-9)); | ||
| Assert.That(callCount, Is.EqualTo(1)); | ||
| }); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Test for handling exception from supplier in Get(). | ||
| /// </summary> | ||
| [Test] | ||
| public void LazySingleThreaded_Get_Double_ThrowsException() | ||
| { | ||
| var lazy = this.CreateLazy<double?>(() => throw new InvalidOperationException("Supplier failed")); | ||
| Assert.Throws<InvalidOperationException>(() => lazy.Get()); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| protected override ILazy<T> CreateLazy<T>(Func<T> supplier) | ||
| { | ||
| return new LazySingleThreaded<T>(supplier); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", | ||
| "settings": { | ||
| "documentationRules": { | ||
| "companyName": "khusainovilas", | ||
| "copyrightText": "Copyright (c) {companyName}. All rights reserved." | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // <copyright file="ILazy.cs" company="khusainovilas"> | ||
| // Copyright (c) khusainovilas. All rights reserved. | ||
| // </copyright> | ||
|
|
||
| namespace LazyEvaluation; | ||
|
|
||
| /// <summary> | ||
| /// Defines a contract for lazy evaluation, where a value of type T is computed only on the first call and cached for subsequent access. | ||
| /// </summary> | ||
| /// <typeparam name="T">The type of the value to be lazily computed.</typeparam> | ||
| public interface ILazy<T> | ||
| { | ||
| /// <summary> | ||
| /// Gets the lazily computed value. The value is computed on the first call and cached for subsequent calls. | ||
| /// </summary> | ||
| /// <returns>The computed or cached value.</returns> | ||
| T Get(); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Library</OutputType> | ||
| <TargetFramework>net9.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <AdditionalFiles Include="stylecop.json" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| // <copyright file="LazyMultiThreaded.cs" company="khusainovilas"> | ||
| // Copyright (c) khusainovilas. All rights reserved. | ||
| // </copyright> | ||
|
|
||
| namespace LazyEvaluation; | ||
|
|
||
| /// <summary> | ||
| /// A multithreaded implementation of the ILazy interface for lazy evaluation. | ||
| /// </summary> | ||
| /// <typeparam name="T">The type of the value produced by the lazy computation.</typeparam> | ||
| public class LazyMultiThreaded<T> : ILazy<T> | ||
| { | ||
| private readonly object lockObject = new(); | ||
| private Func<T>? supplier; | ||
| private T? value; | ||
| private volatile bool isComputed; | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="LazyMultiThreaded{T}"/> class. | ||
| /// </summary> | ||
| /// <param name="supplier">The delegate that produces the value when needed.</param> | ||
| public LazyMultiThreaded(Func<T> supplier) | ||
| { | ||
| this.supplier = supplier ?? throw new ArgumentNullException(nameof(supplier)); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public T Get() | ||
| { | ||
| if (this.isComputed) | ||
| { | ||
| return this.value!; | ||
| } | ||
|
|
||
| lock (this.lockObject) | ||
| { | ||
| if (this.isComputed) | ||
| { | ||
| return this.value!; | ||
| } | ||
|
|
||
| this.value = this.supplier!(); | ||
| this.isComputed = true; | ||
| this.supplier = null!; | ||
| } | ||
|
|
||
| return this.value!; | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
здесь как раз нужно startEvent выставить, чтобы потоки остановились