Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Homework2.Tests/Homework2.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.NET 7 умер

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Перейдите на .NET 8

<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Homework2\Homework2.csproj" />
</ItemGroup>
</Project>
81 changes: 81 additions & 0 deletions Homework2.Tests/LazyTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
namespace Homework2.Tests;

public class Tests
{
private static IEnumerable<TestCaseData> LazyForResultTest => new TestCaseData[]
{
new TestCaseData(new LazySingleThread<int>(() => 2)),
new TestCaseData(new LazyMultyThread<int>(() => 2)),
};

private static IEnumerable<TestCaseData> LazyForMultipleCallTest => new TestCaseData[]
{
new TestCaseData(new LazySingleThread<object>(() => new object())),
new TestCaseData(new LazyMultyThread<object>(() => new object())),
};

private static IEnumerable<TestCaseData> LazyForExceptionTest => new TestCaseData[]
{
new TestCaseData(new LazySingleThread<object>(() => throw new Exception())),
new TestCaseData(new LazyMultyThread<object>(() => throw new Exception())),
};

[TestCaseSource(nameof(LazyForResultTest))]
public void SingleLazyCallReturnResultTest(ILazy<int> lazy)
{
Assert.That(lazy.Get(), Is.EqualTo(2));
}

[TestCaseSource(nameof(LazyForMultipleCallTest))]
public void MultipleLazyCallReturnsSameResultTest(ILazy<object> lazy)
{
object fstCallObject = lazy.Get()!;
object sndCallObject = lazy.Get()!;
Assert.That(fstCallObject, Is.EqualTo(sndCallObject));
}

[TestCaseSource(nameof(LazyForExceptionTest))]
public void LazyThrowsExceptionTest(ILazy<object> lazy)
{
Assert.Throws<Exception>(() => lazy.Get());
}

[Test]
public static void MultiThreadsReturnSameResultLazyTest()
{
var lazy = new LazyMultyThread<object>(() => new object());
var threads = new Thread[20];

var manualResetEvent = new ManualResetEvent(false);

var arrayOfResults = new object[20];
for (int i = 0; i < 20; i++)
{
int localI = i;
threads[i] = new Thread(() =>
{
manualResetEvent.WaitOne();
arrayOfResults[localI] = lazy.Get()!;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лучше "!" вообще никогда не пользоваться, потому что он убивает весь профит от nullability-анализа. Проверяйте явно на null лучше.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не поправлено. Можно, кстати, lazy.Get() ?? new Object();

});
}

foreach (var thread in threads)
{
thread.Start();
}

manualResetEvent.Set();

This comment was marked as resolved.


foreach (var thread in threads)
{
thread.Join();
}

for (int i = 0; i < 19; i++)
{
Assert.That(arrayOfResults[i], Is.EqualTo(arrayOfResults[i + 1]));
}
}


Comment on lines +79 to +80
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лишние пустые строчки. Если они даже при беглом просмотре кода не бросаются Вам в глаза, Вам надо первый курс раззачесть :)

}
1 change: 1 addition & 0 deletions Homework2.Tests/Usings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using NUnit.Framework;
9 changes: 9 additions & 0 deletions Homework2/Homework2.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
31 changes: 31 additions & 0 deletions Homework2/Homework2.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 25.0.1706.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Homework2", "Homework2.csproj", "{62DE394A-FA36-4AAE-92D4-E758A1023000}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Homework2.Tests", "..\Homework2.Tests\Homework2.Tests.csproj", "{9D5DF180-207E-4939-BC5E-873DA34309DA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{62DE394A-FA36-4AAE-92D4-E758A1023000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{62DE394A-FA36-4AAE-92D4-E758A1023000}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62DE394A-FA36-4AAE-92D4-E758A1023000}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62DE394A-FA36-4AAE-92D4-E758A1023000}.Release|Any CPU.Build.0 = Release|Any CPU
{9D5DF180-207E-4939-BC5E-873DA34309DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D5DF180-207E-4939-BC5E-873DA34309DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D5DF180-207E-4939-BC5E-873DA34309DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D5DF180-207E-4939-BC5E-873DA34309DA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2604FC35-D54E-4E08-88FE-BC3F2DAE3C53}
EndGlobalSection
EndGlobal
9 changes: 9 additions & 0 deletions Homework2/ILazy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Homework2;

/// <summary>
/// Interface for multy and single threads Lazy calculation.
/// </summary>
public interface ILazy<T>
{
T? Get();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Всё ещё надо комментарии

}
63 changes: 63 additions & 0 deletions Homework2/LazyMultyThread.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace Homework2;

/// <summary>
/// Lazy calculation class which works correctly with multithreading.
/// </summary>
public class LazyMultyThread<T> : ILazy<T>
{
private Func<T>? supplier;
private bool isFirstCall = true;
private Exception? supplierException = null;
private readonly object lockObject;
private T? result = default;

/// <summary>
/// Create new incstance of LazyMultThread class.
/// </summary>
/// <param name="calculation">Function that Lazy calculate</param>
public LazyMultyThread(Func<T> calculation)
{
supplier = calculation;
lockObject = new();
}

/// <summary>
/// Method that returns calculated one time value.
/// </summary>
public T? Get()
{
if (Volatile.Read(ref isFirstCall))
{
lock (lockObject)
{
if (Volatile.Read(ref isFirstCall))
{
try
{
if (supplier == null)
{
throw new InvalidOperationException();
}
result = supplier();
return result;
}
catch (Exception exception)
{
supplierException = exception;
}
finally
{
supplier = null;
Volatile.Write(ref isFirstCall, false);//volatile write, result, supplier = null, supplierException in memory
}
}
}
}
if (Volatile.Read(ref supplierException) == null) //volatile read, values ​​in memory are now in the cache of all threads
{
return result;
}
throw supplierException!;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут тоже пустая строчка не нужна

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не поправлено

}
53 changes: 53 additions & 0 deletions Homework2/LazySingleThread.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
namespace Homework2;

/// <summary>
/// Lazy calculation class which works with singlethreading.
/// </summary>
public class LazySingleThread<T> : ILazy<T>
{
private Func<T>? supplier;
private bool isFirstCall = true;
private Exception? supplierException = null;
private T? result = default;

/// <summary>
/// Create new incstance of LazySingleThread class.
/// </summary>
/// <param name="calculation">Function that Lazy calculate</param>
public LazySingleThread(Func<T> calculation)
{
supplier = calculation;
}

/// <summary>
/// Method that returns calculated one time value.
/// </summary>
public T? Get()
{
if (isFirstCall)
{
try
{
if (supplier == null)
{
throw new InvalidOperationException();
}
result = supplier();
}
catch (Exception exception)
{
supplierException = exception;
}
finally
{
supplier = null;
isFirstCall = false;
}
}
if (supplierException == null)
{
return result;
}
throw supplierException;
}
}