-
Notifications
You must be signed in to change notification settings - Fork 0
Lazy #74
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
vologin-dmitry
wants to merge
4
commits into
master
Choose a base branch
from
Lazy
base: master
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
Lazy #74
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
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
There are no files selected for viewing
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 |
|---|---|---|
| @@ -1,7 +1,17 @@ | ||
| image: Visual Studio 2017 | ||
| image: Visual Studio 2019 | ||
|
|
||
| init: | ||
| - git config --global core.autocrlf true | ||
|
|
||
| environment: | ||
| matrix: | ||
| - solution: Semester4/Lazy/Lazy.sln | ||
|
|
||
| before_build: | ||
| - nuget restore semester2/6.1/HW6T2.sln | ||
| - nuget restore %solution% | ||
|
|
||
| build: | ||
| project: semester2/2.3/2.3.sln | ||
| project: $(solution) | ||
|
|
||
| test_script: | ||
| - dotnet test %solution% |
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,26 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>netcoreapp3.1</TargetFramework> | ||
|
|
||
| <IsPackable>true</IsPackable> | ||
| <GenerateProgramFile>true</GenerateProgramFile> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="FsCheck" Version="3.0.0-alpha4" /> | ||
| <PackageReference Include="FsUnit" Version="4.0.1" /> | ||
| <PackageReference Include="nunit" Version="3.12.0" /> | ||
| <PackageReference Include="NUnit3TestAdapter" Version="3.15.1" /> | ||
| <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <Compile Include="LazyTests.fs" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\Lazy\Lazy.fsproj" /> | ||
| </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,96 @@ | ||
| module Lazy.Tests | ||
|
|
||
| open System.Threading | ||
| open NUnit.Framework | ||
| open FsUnit | ||
| open LazyFactory | ||
| open ILazy | ||
|
|
||
| [<Test>] | ||
| let ``simple int single thread lazy test`` () = | ||
| let holder = LazyFactory<int>.CreateSingleThreadLazy <| fun () -> 1 | ||
| holder.Get() |> should equal 1 | ||
|
|
||
| [<Test>] | ||
| let ``simple string single thread lazy test`` () = | ||
| let holder = LazyFactory<string>.CreateSingleThreadLazy <| fun () -> "h" + "e" + "l" + "l" + "o" | ||
| holder.Get() |> should equal "hello" | ||
|
|
||
| [<Test>] | ||
| let ``array single thread lazy test`` () = | ||
| let holder = | ||
| LazyFactory<List<int>> | ||
| .CreateSingleThreadLazy(fun () -> | ||
| [ 2; 4; 1; 3; 4; 52; 9; 17; 33; 36 ] | ||
| |> List.map (fun x -> x * 1000) | ||
| |> List.filter (fun x -> x % 3 = 0)) | ||
|
|
||
| holder.Get() |> should equal [ 3000; 9000; 33000; 36000 ] | ||
|
|
||
| [<Test>] | ||
| let ``called once single thread test`` () = | ||
| let mutable counter = 0 | ||
| let holder = LazyFactory<unit>.CreateSingleThreadLazy(fun () -> counter <- counter + 1) | ||
| for i in 1..100 do | ||
| holder.Get() | ||
| counter |> should equal 1 | ||
|
|
||
| [<Test>] | ||
| let ``called once test multi thread with lock`` () = | ||
| let mutable counter = ref 0 | ||
| let holder = LazyFactory<int>.LockMultiThreadLazy(fun () -> Interlocked.Increment(counter)) | ||
| for i in 1..100 do | ||
| holder.Get() |> ignore | ||
| counter.contents |> should equal 1 | ||
|
|
||
| [<Test>] | ||
| let ``called once test lock free with lock`` () = | ||
| let mutable counter = ref 0 | ||
| let holder = LazyFactory<int>.LockFreeLazy(fun () -> Interlocked.Increment(counter)) | ||
| for i in 1..100 do | ||
| holder.Get() |> ignore | ||
| counter.contents |> should equal 1 | ||
|
|
||
| [<Test>] | ||
| let ``lot of thread multi thread lock test`` () = | ||
| let holder = LazyFactory<obj>.LockMultiThreadLazy(fun () -> obj()) | ||
| let toCompare = holder.Get() | ||
| for i in 1..100500 do | ||
| holder.Get() |> should equal toCompare | ||
|
|
||
| [<Test>] | ||
| let ``lot of thread lock free test`` () = | ||
| let holder = LazyFactory<obj>.LockFreeLazy(fun () -> obj()) | ||
| let toCompare = holder.Get() | ||
| for i in 1..100500 do | ||
| holder.Get() |> should equal toCompare | ||
|
|
||
| [<Test>] | ||
| let ``simple work lock free test`` () = | ||
| let holder = LazyFactory<int>.LockFreeLazy(fun () -> 1) | ||
| holder.Get() |> should equal 1 | ||
|
|
||
| [<Test>] | ||
| let ``simple work multi thread lock test`` () = | ||
| let holder = LazyFactory<int>.LockMultiThreadLazy(fun () -> 1) | ||
| holder.Get() |> should equal 1 | ||
|
|
||
| let LazyTestHelper (object : ILazy<'a>, expected) = | ||
| let threadWork () = | ||
| object.Get() |> should equal expected | ||
|
|
||
| let threads = Array.init 10 (fun _ -> Thread(threadWork)) | ||
|
|
||
| for thread in threads do | ||
| thread.Start() | ||
|
|
||
| for thread in threads do | ||
| thread.Join() | ||
|
|
||
| [<Test>] | ||
| let ``multithread lock free lazy`` () = | ||
| LazyTestHelper(LazyFactory<string>.LockFreeLazy(fun _ -> "hello" + " " + "world"), "hello world") | ||
|
|
||
| [<Test>] | ||
| let ``multithread lock lazy`` () = | ||
| LazyTestHelper(LazyFactory<string>.LockMultiThreadLazy(fun _ -> "hello" + " " + "world"), "hello world") | ||
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("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Lazy", "Lazy\Lazy.fsproj", "{F2726A51-E1AF-4B6D-8F33-91D669445C02}" | ||
| EndProject | ||
| Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Lazy.Tests", "Lazy.Tests\Lazy.Tests.fsproj", "{41A66F38-8DB3-473C-B876-9E7C87CAF01F}" | ||
| EndProject | ||
| Global | ||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| Debug|Any CPU = Debug|Any CPU | ||
| Release|Any CPU = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| {F2726A51-E1AF-4B6D-8F33-91D669445C02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {F2726A51-E1AF-4B6D-8F33-91D669445C02}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {F2726A51-E1AF-4B6D-8F33-91D669445C02}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {F2726A51-E1AF-4B6D-8F33-91D669445C02}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| {41A66F38-8DB3-473C-B876-9E7C87CAF01F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {41A66F38-8DB3-473C-B876-9E7C87CAF01F}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {41A66F38-8DB3-473C-B876-9E7C87CAF01F}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {41A66F38-8DB3-473C-B876-9E7C87CAF01F}.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,7 @@ | ||
| module ILazy | ||
|
|
||
| /// Interface that describes lazy computations | ||
| type ILazy<'a> = | ||
| /// If Get() called first time, calculates func and returns result, | ||
| /// otherwise, returns already computed function | ||
| abstract member Get: unit -> 'a |
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,17 @@ | ||
| module SingleThreadLazy | ||
|
|
||
| open ILazy | ||
|
|
||
| /// Simple lazy class realization for single thread work | ||
| type SingleThreadLazy<'a>(supplier : unit -> 'a) = | ||
| let mutable result = None | ||
| interface ILazy<'a> with | ||
|
|
||
| /// If Get() called first time, calculates func and returns result, | ||
| /// otherwise, returns already computed function | ||
| member this.Get() = | ||
| match result with | ||
| | Some x -> x | ||
| | None -> | ||
| result <- Some(supplier()) | ||
| result.Value |
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,15 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>netcoreapp3.1</TargetFramework> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <Compile Include="ILazy.fs" /> | ||
| <Compile Include="Lazy.fs" /> | ||
| <Compile Include="LockMultithreadLazy.fs" /> | ||
| <Compile Include="LockFreeLazy.fs" /> | ||
| <Compile Include="LazyFactory.fs" /> | ||
| </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,17 @@ | ||
| module LazyFactory | ||
|
|
||
| open ILazy | ||
| open SingleThreadLazy | ||
| open LockMultiThreadLazy | ||
| open LockFreeLazy | ||
|
|
||
| /// Creates lazy classes of various types | ||
| type LazyFactory<'a> = | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тоже неплохо бы комментарии |
||
| /// Creates single thread lazy object | ||
| static member CreateSingleThreadLazy supplier = SingleThreadLazy<'a>(supplier) :> ILazy<'a> | ||
|
|
||
| /// Creates multithread lazy object that works without locks | ||
| static member LockFreeLazy supplier = LockFreeLazy<'a>(supplier) :> ILazy<'a> | ||
|
|
||
| /// Creates simple multithread lazy based on locks | ||
| static member LockMultiThreadLazy supplier = LockMultiThreadLazy<'a>(supplier) :> ILazy<'a> | ||
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 @@ | ||
| module LockFreeLazy | ||
|
|
||
| open ILazy | ||
| open System.Threading | ||
|
|
||
| /// Simple lazy class realization for multi thread work | ||
| /// without locks | ||
| type LockFreeLazy<'a>(supplier : unit -> 'a) = | ||
| let mutable desiredResult = None | ||
| let mutable startResult = None | ||
| let mutable computed = false | ||
| interface ILazy<'a> with | ||
|
|
||
| /// If Get() called first time, calculates func and returns result, | ||
| /// otherwise, returns already computed function | ||
| member this.Get() = | ||
| if not computed then | ||
| desiredResult <- Some(supplier()) | ||
| Interlocked.CompareExchange(ref startResult, desiredResult, None) |> ignore | ||
| computed <- true | ||
| desiredResult.Value |
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,23 @@ | ||
| module LockMultiThreadLazy | ||
|
|
||
| open ILazy | ||
|
|
||
| /// Simple lazy class realization for multi thread work | ||
| /// based on lock | ||
| type LockMultiThreadLazy<'a>(supplier : unit->'a) = | ||
| let mutable result = None | ||
| let locker = obj() | ||
| interface ILazy<'a> with | ||
| /// If Get() called first time, calculates func and returns result, | ||
| /// otherwise, returns already computed function | ||
|
|
||
| member this.Get() = | ||
| match result with | ||
| | Some x -> x | ||
| | None -> | ||
| lock locker <| fun () -> | ||
| match result with | ||
| | Some x -> x | ||
| | None -> | ||
| result <- Some(supplier()) | ||
| result.Value |
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.
Так это ж не многопоточно. Тесты пока нигде не проверяют, что если из нескольких потоков подёргать Lazy, всё хорошо будет. Тем более что самое интересное в многопоточном случае --- это гонки при первом Get, а тут он делается даже до цикла, так что если бы цикл был параллельным, это бы тоже было непоказательно