From 3fcbaa8a3373b072b9b23536690b137825d75cb2 Mon Sep 17 00:00:00 2001 From: Oliver Coad Date: Wed, 20 Dec 2017 14:30:48 +1100 Subject: [PATCH 1/2] Changed to netstandard2.0 --- .gitignore | 5 + Lifetime.sln | 37 ++- Lifetime/Lifetime.csproj | 92 ++---- Lifetime/Properties/AssemblyInfo.cs | 30 -- LifetimeExample/App.config | 2 +- LifetimeExample/LifetimeExample.csproj | 30 +- LifetimeExample/Properties/AssemblyInfo.cs | 14 +- LifetimeTest/LifetimeTest.csproj | 74 ++--- LifetimeTest/Properties/AssemblyInfo.cs | 22 +- LifetimeTest/packages.config | 5 + Surface.dgml | 362 --------------------- TwistedOak.Util.Lifetime.1.0.0.nupkg | Bin 13800 -> 0 bytes TwistedOak.Util.Lifetime.1.0.1.nupkg | Bin 13841 -> 0 bytes TwistedOak.Util.Lifetime.1.0.2.nupkg | Bin 14267 -> 0 bytes 14 files changed, 116 insertions(+), 557 deletions(-) delete mode 100644 Lifetime/Properties/AssemblyInfo.cs create mode 100644 LifetimeTest/packages.config delete mode 100644 Surface.dgml delete mode 100644 TwistedOak.Util.Lifetime.1.0.0.nupkg delete mode 100644 TwistedOak.Util.Lifetime.1.0.1.nupkg delete mode 100644 TwistedOak.Util.Lifetime.1.0.2.nupkg diff --git a/.gitignore b/.gitignore index 04a46b4..e4f7fba 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,8 @@ TestResults/* *.suo *.user _ReSharper.* +.vs/ +*.nupkg +**/packages/* +*.nuget.props +*.nuget.targets \ No newline at end of file diff --git a/Lifetime.sln b/Lifetime.sln index a9083c8..62ddfa8 100644 --- a/Lifetime.sln +++ b/Lifetime.sln @@ -1,11 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lifetime", "Lifetime\Lifetime.csproj", "{C5F0A258-0AA4-4644-AD4B-134811518025}" +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2010 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lifetime", "Lifetime\Lifetime.csproj", "{A7112E6A-0643-439F-9F33-B2713FCA9F3A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LifetimeTest", "LifetimeTest\LifetimeTest.csproj", "{B448C282-D446-4624-9A42-7B2CCFA517EB}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LifetimeTest", "LifetimeTest\LifetimeTest.csproj", "{0387C1F5-0D00-4C79-8C47-7DBA35109679}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LifetimeExample", "LifetimeExample\LifetimeExample.csproj", "{9DB14478-561D-4B6F-8919-F5E9D26B4978}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LifetimeExample", "LifetimeExample\LifetimeExample.csproj", "{C00A62C7-7DD3-4068-BB6A-0F2C4B2A9C63}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -13,20 +15,23 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C5F0A258-0AA4-4644-AD4B-134811518025}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C5F0A258-0AA4-4644-AD4B-134811518025}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C5F0A258-0AA4-4644-AD4B-134811518025}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C5F0A258-0AA4-4644-AD4B-134811518025}.Release|Any CPU.Build.0 = Release|Any CPU - {B448C282-D446-4624-9A42-7B2CCFA517EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B448C282-D446-4624-9A42-7B2CCFA517EB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B448C282-D446-4624-9A42-7B2CCFA517EB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B448C282-D446-4624-9A42-7B2CCFA517EB}.Release|Any CPU.Build.0 = Release|Any CPU - {9DB14478-561D-4B6F-8919-F5E9D26B4978}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9DB14478-561D-4B6F-8919-F5E9D26B4978}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9DB14478-561D-4B6F-8919-F5E9D26B4978}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9DB14478-561D-4B6F-8919-F5E9D26B4978}.Release|Any CPU.Build.0 = Release|Any CPU + {A7112E6A-0643-439F-9F33-B2713FCA9F3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A7112E6A-0643-439F-9F33-B2713FCA9F3A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A7112E6A-0643-439F-9F33-B2713FCA9F3A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A7112E6A-0643-439F-9F33-B2713FCA9F3A}.Release|Any CPU.Build.0 = Release|Any CPU + {0387C1F5-0D00-4C79-8C47-7DBA35109679}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0387C1F5-0D00-4C79-8C47-7DBA35109679}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0387C1F5-0D00-4C79-8C47-7DBA35109679}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0387C1F5-0D00-4C79-8C47-7DBA35109679}.Release|Any CPU.Build.0 = Release|Any CPU + {C00A62C7-7DD3-4068-BB6A-0F2C4B2A9C63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C00A62C7-7DD3-4068-BB6A-0F2C4B2A9C63}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C00A62C7-7DD3-4068-BB6A-0F2C4B2A9C63}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C00A62C7-7DD3-4068-BB6A-0F2C4B2A9C63}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6D60882C-2C32-4145-B94F-28FE940DF8B7} + EndGlobalSection EndGlobal diff --git a/Lifetime/Lifetime.csproj b/Lifetime/Lifetime.csproj index 47ba791..f34fc31 100644 --- a/Lifetime/Lifetime.csproj +++ b/Lifetime/Lifetime.csproj @@ -1,65 +1,33 @@ - - - + + - 10.0 - Debug - AnyCPU - {C5F0A258-0AA4-4644-AD4B-134811518025} - Library - Properties - TwistedOak.Util - Lifetime - v4.0 - Profile5 - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + netstandard2.0 + true + TwistedOak.Util.Lifetime + 1.0.3 + Craig Gidney + --company + --product + Lifetime (improved CancellationToken) + +A small library that implements an improved version of System.Threading.CancellationToken with support for removable registrations, to allow for garbage collection in the presence of long-lived tokens, plus some related utilities. + +Motivation: cancellation tokens can be the source of memory "leaks", because an unbounded number of completed operations may have registered now-pointless callbacks on a token that can't be released or cancelled. The callbacks may reference all kinds of data, preventing effective garbage collection. Using a Lifetime allows fixing these issues because callback registrations can be given lifetimes of their own. + +Additional utilities: LifetimeSource, LifetimeExchanger, DisposableLifetime, Max, Min, CreateDependentSource. + Twisted Oak Studios, 2012 + https://github.com/TwistedOakStudios/Lifetime/blob/master/License.txt + https://github.com/TwistedOakStudios/Lifetime + http://i.imgur.com/WP3EF.png + lifetime cancellation token + Using .Net Standard 2.0 + + + - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - bin\Debug\Lifetime.XML + + + bin\Release\netstandard2.0\Lifetime.xml - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\Lifetime.XML - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + diff --git a/Lifetime/Properties/AssemblyInfo.cs b/Lifetime/Properties/AssemblyInfo.cs deleted file mode 100644 index f68930a..0000000 --- a/Lifetime/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Resources; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Lifetime")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Lifetime")] -[assembly: AssemblyCopyright("Copyright © 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("en")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/LifetimeExample/App.config b/LifetimeExample/App.config index 8e15646..731f6de 100644 --- a/LifetimeExample/App.config +++ b/LifetimeExample/App.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/LifetimeExample/LifetimeExample.csproj b/LifetimeExample/LifetimeExample.csproj index 593d6bc..7cd7cd0 100644 --- a/LifetimeExample/LifetimeExample.csproj +++ b/LifetimeExample/LifetimeExample.csproj @@ -1,16 +1,16 @@  - + Debug AnyCPU - {9DB14478-561D-4B6F-8919-F5E9D26B4978} + {C00A62C7-7DD3-4068-BB6A-0F2C4B2A9C63} Exe - Properties LifetimeExample LifetimeExample - v4.5 + v4.6.1 512 + true AnyCPU @@ -31,9 +31,16 @@ prompt 4 - - Program - + + + + + + + + + + @@ -43,16 +50,9 @@ - {c5f0a258-0aa4-4644-ad4b-134811518025} + {a7112e6a-0643-439f-9f33-b2713fca9f3a} Lifetime - \ No newline at end of file diff --git a/LifetimeExample/Properties/AssemblyInfo.cs b/LifetimeExample/Properties/AssemblyInfo.cs index 9b46c3a..428a3be 100644 --- a/LifetimeExample/Properties/AssemblyInfo.cs +++ b/LifetimeExample/Properties/AssemblyInfo.cs @@ -2,7 +2,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LifetimeExample")] @@ -10,26 +10,26 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("LifetimeExample")] -[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyCopyright("Copyright © 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("209163d7-43d7-44f6-b417-7f4cdc7f2f65")] +[assembly: Guid("c00a62c7-7dd3-4068-bb6a-0f2c4b2a9c63")] // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // -// You can specify all the values or you can default the Build and Revision Numbers +// You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] diff --git a/LifetimeTest/LifetimeTest.csproj b/LifetimeTest/LifetimeTest.csproj index b64639e..657a485 100644 --- a/LifetimeTest/LifetimeTest.csproj +++ b/LifetimeTest/LifetimeTest.csproj @@ -1,21 +1,24 @@  - + + Debug AnyCPU - {B448C282-D446-4624-9A42-7B2CCFA517EB} + {0387C1F5-0D00-4C79-8C47-7DBA35109679} Library Properties LifetimeTest LifetimeTest - v4.5 + v4.6.1 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 10.0 + 15.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages False UnitTest + + true @@ -35,60 +38,41 @@ 4 + + ..\packages\MSTest.TestFramework.1.2.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + + + ..\packages\MSTest.TestFramework.1.2.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + - - - - - - - - - - - - + - - - - + + + + + + - {c5f0a258-0aa4-4644-ad4b-134811518025} + {a7112e6a-0643-439f-9f33-b2713fca9f3a} Lifetime - - - - - False - - - False - - - False - - - False - - - - - + \ No newline at end of file diff --git a/LifetimeTest/Properties/AssemblyInfo.cs b/LifetimeTest/Properties/AssemblyInfo.cs index c3e55c2..06f6347 100644 --- a/LifetimeTest/Properties/AssemblyInfo.cs +++ b/LifetimeTest/Properties/AssemblyInfo.cs @@ -1,36 +1,20 @@ -using System.Reflection; +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. [assembly: AssemblyTitle("LifetimeTest")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("LifetimeTest")] -[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyCopyright("Copyright © 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("548511f6-68c9-45de-82ee-841ee5b0336b")] +[assembly: Guid("0387c1f5-0d00-4c79-8c47-7dba35109679")] -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/LifetimeTest/packages.config b/LifetimeTest/packages.config new file mode 100644 index 0000000..cf2d094 --- /dev/null +++ b/LifetimeTest/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Surface.dgml b/Surface.dgml deleted file mode 100644 index 0a6a3d3..0000000 --- a/Surface.dgml +++ /dev/null @@ -1,362 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/TwistedOak.Util.Lifetime.1.0.0.nupkg b/TwistedOak.Util.Lifetime.1.0.0.nupkg deleted file mode 100644 index 72e2493a0a7065a21c8dd0a5504101d1e4fda13f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13800 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 Vs(9n(mDo-6|2lf7Sme37`hQp4&9VRh diff --git a/TwistedOak.Util.Lifetime.1.0.1.nupkg b/TwistedOak.Util.Lifetime.1.0.1.nupkg deleted file mode 100644 index 283a83993fad3d1b8d2e7223c8e08e1d2a9bcae1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13841 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 Ne-ph@5b|AL{Xa)y<#hl6 diff --git a/TwistedOak.Util.Lifetime.1.0.2.nupkg b/TwistedOak.Util.Lifetime.1.0.2.nupkg deleted file mode 100644 index caee927b906cb5dfa5f9c096869cd602e8a39e52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14267 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 From 142dd4904fa9b3fedefa2d08edd64d1bc4775d34 Mon Sep 17 00:00:00 2001 From: Oliver Coad Date: Wed, 20 Dec 2017 14:31:43 +1100 Subject: [PATCH 2/2] Some simple refactoring using C#7 syntax --- Lifetime/DisposableLifetime.cs | 10 +++------ Lifetime/Lifetime.cs | 34 ++++++++++++++----------------- Lifetime/Lifetime.csproj | 4 ++-- Lifetime/LifetimeExchanger.cs | 6 +++--- Lifetime/LifetimeSource.cs | 10 ++++----- Lifetime/Soul/AnonymousSoul.cs | 14 +++++-------- Lifetime/Soul/CollapsingSoul.cs | 25 ++++++++++++----------- Lifetime/Soul/DeadSoul.cs | 2 +- Lifetime/Soul/DoublyLinkedNode.cs | 28 +++++++++++++++---------- Lifetime/Soul/ImmortalSoul.cs | 2 +- Lifetime/Soul/MortalSoul.cs | 5 +++-- Lifetime/Soul/Soul.cs | 22 ++++++++++---------- LifetimeExample/Program.cs | 9 ++++---- 13 files changed, 82 insertions(+), 89 deletions(-) diff --git a/Lifetime/DisposableLifetime.cs b/Lifetime/DisposableLifetime.cs index 6ce1c67..8769f09 100644 --- a/Lifetime/DisposableLifetime.cs +++ b/Lifetime/DisposableLifetime.cs @@ -10,14 +10,10 @@ namespace TwistedOak.Util { public sealed class DisposableLifetime : IDisposable { private readonly LifetimeSource _source = new LifetimeSource(); ///The lifetime that transitions from mortal to dead when the managing DisposableLifetime is disposed. - public Lifetime Lifetime { get { return _source.Lifetime; } } + public Lifetime Lifetime => _source.Lifetime; ///Transitions the exposed lifetime from mortal to dead. - public void Dispose() { - _source.EndLifetime(); - } + public void Dispose() => _source.EndLifetime(); ///Returns a text representation of the disposable lifetime's current state. - public override string ToString() { - return _source.ToString(); - } + public override string ToString() => _source.ToString(); } } diff --git a/Lifetime/Lifetime.cs b/Lifetime/Lifetime.cs index 64bcceb..604be89 100644 --- a/Lifetime/Lifetime.cs +++ b/Lifetime/Lifetime.cs @@ -22,18 +22,20 @@ public struct Lifetime : IEquatable { /// public static readonly Lifetime Dead = new Lifetime(DeadSoul.Instance); + //Must default to ImmortalSould.Instance in property rather than using auto-prop and setting default + //in contructor so that default(Lifetime).Soul is ImmortalSoul.Instance not null private readonly ISoul _defSoul; - internal ISoul Soul { get { return _defSoul ?? ImmortalSoul.Instance; } } + internal ISoul Soul => _defSoul ?? ImmortalSoul.Instance; internal Lifetime(ISoul soul) { - this._defSoul = soul; + _defSoul = soul; } - /// Determines if this lifetime is still transiently mortal. - public bool IsMortal { get { return Soul.Phase == Phase.Mortal; } } - /// Determines if this lifetime is permanently immortal. - public bool IsImmortal { get { return Soul.Phase == Phase.Immortal; } } - /// Determines if this lifetime is permanently dead. - public bool IsDead { get { return Soul.Phase == Phase.Dead; } } + ///Determines if this lifetime is still transiently mortal. + public bool IsMortal => Soul.Phase == Phase.Mortal; + ///Determines if this lifetime is permanently immortal. + public bool IsImmortal => Soul.Phase == Phase.Immortal; + ///Determines if this lifetime is permanently dead. + public bool IsDead => Soul.Phase == Phase.Dead; /// /// Registers an action to perform when this lifetime is dead. @@ -49,7 +51,7 @@ internal Lifetime(ISoul soul) { /// Defaults to an immortal lifetime. /// public void WhenDead(Action action, Lifetime registrationLifetime = default(Lifetime)) { - if (action == null) throw new ArgumentNullException("action"); + if (action == null) throw new ArgumentNullException(nameof(action)); var s = Soul; s.DependentRegister( () => { if (s.Phase == Phase.Dead) action(); }, @@ -94,19 +96,13 @@ public static implicit operator Lifetime(CancellationToken token) { return source.Lifetime; } - ///Determines if the other lifetime has the same source. + /// Determines if the other lifetime has the same source. /// The lifetime that this lifetime is being compared to. - public bool Equals(Lifetime other) { - return Equals(Soul, other.Soul); - } + public bool Equals(Lifetime other) => Equals(Soul, other.Soul); ///Returns the hash code for this lifetime, based on its source. - public override int GetHashCode() { - return Soul.GetHashCode(); - } + public override int GetHashCode() => Soul.GetHashCode(); ///Determines if the other object is a lifetime with the same source. - public override bool Equals(object obj) { - return obj is Lifetime && Equals((Lifetime)obj); - } + public override bool Equals(object obj) => obj is Lifetime && Equals((Lifetime)obj); ///Returns a text representation of the lifetime's current state. public override string ToString() { if (Soul.Phase == Phase.Mortal) return "Alive"; diff --git a/Lifetime/Lifetime.csproj b/Lifetime/Lifetime.csproj index f34fc31..c112576 100644 --- a/Lifetime/Lifetime.csproj +++ b/Lifetime/Lifetime.csproj @@ -6,8 +6,8 @@ TwistedOak.Util.Lifetime 1.0.3 Craig Gidney - --company - --product + Twisted Oak Studios + Lifetime (improved CancellationToken) A small library that implements an improved version of System.Threading.CancellationToken with support for removable registrations, to allow for garbage collection in the presence of long-lived tokens, plus some related utilities. diff --git a/Lifetime/LifetimeExchanger.cs b/Lifetime/LifetimeExchanger.cs index 32a2234..cc0d507 100644 --- a/Lifetime/LifetimeExchanger.cs +++ b/Lifetime/LifetimeExchanger.cs @@ -4,9 +4,9 @@ namespace TwistedOak.Util { ///Creates lifetimes when requested, setting them when the next lifetime is requested. public sealed class LifetimeExchanger { private LifetimeSource _active = new LifetimeSource(); - + ///Returns the current lifetime, that will be killed or immortalized before the next lifetime is created by the exchanger. - public Lifetime ActiveLifetime { get { return _active.Lifetime; } } + public Lifetime ActiveLifetime => _active.Lifetime; ///Returns a newly created mortal lifetime after killing the previously created lifetime (if any). public Lifetime StartNextAndEndPreviousLifetime() { @@ -20,7 +20,7 @@ public Lifetime StartNextAndEndPreviousLifetime() { public Lifetime StartNextAndImmortalizePreviousLifetime() { var next = new LifetimeSource(); var prev = Interlocked.Exchange(ref _active, next); - if (prev != null) prev.ImmortalizeLifetime(); + prev?.ImmortalizeLifetime(); return next.Lifetime; } } diff --git a/Lifetime/LifetimeSource.cs b/Lifetime/LifetimeSource.cs index 5226728..850dbfa 100644 --- a/Lifetime/LifetimeSource.cs +++ b/Lifetime/LifetimeSource.cs @@ -11,9 +11,9 @@ namespace TwistedOak.Util { [DebuggerDisplay("{ToString()}")] public sealed class LifetimeSource { private readonly MortalSoul _soul = new MortalSoul(); - - /// The lifetime exposed and managed by the lifetime source. - public Lifetime Lifetime { get; private set; } + + ///The lifetime exposed and managed by the lifetime source. + public Lifetime Lifetime { get; } ///Creates a new lifetime source managing a new initially mortal lifetime. public LifetimeSource() { @@ -45,8 +45,6 @@ public void ImmortalizeLifetime() { } ///Returns a text representation of the lifetime source's current state. - public override string ToString() { - return Lifetime.ToString(); - } + public override string ToString() => Lifetime.ToString(); } } diff --git a/Lifetime/Soul/AnonymousSoul.cs b/Lifetime/Soul/AnonymousSoul.cs index 593ea2c..6691f0a 100644 --- a/Lifetime/Soul/AnonymousSoul.cs +++ b/Lifetime/Soul/AnonymousSoul.cs @@ -2,21 +2,17 @@ using System.Diagnostics; namespace TwistedOak.Util.Soul { - ///A soul implemented by delegates passed to its constructor. + /// A soul implemented by delegates passed to its constructor. [DebuggerStepThrough] internal sealed class AnonymousSoul : ISoul { private readonly Func _phase; private readonly Func _register; public AnonymousSoul(Func phase, Func register) { - if (phase == null) throw new ArgumentNullException("phase"); - if (register == null) throw new ArgumentNullException("register"); - this._phase = phase; - this._register = register; + _phase = phase ?? throw new ArgumentNullException(nameof(phase)); + _register = register ?? throw new ArgumentNullException(nameof(register)); } - public Phase Phase { get { return this._phase(); } } - public RegistrationRemover Register(Action action) { - return this._register(action); - } + public Phase Phase => _phase(); + public RegistrationRemover Register(Action action) => _register(action); } } diff --git a/Lifetime/Soul/CollapsingSoul.cs b/Lifetime/Soul/CollapsingSoul.cs index 4a4ce04..f2977c4 100644 --- a/Lifetime/Soul/CollapsingSoul.cs +++ b/Lifetime/Soul/CollapsingSoul.cs @@ -1,23 +1,25 @@ using System; namespace TwistedOak.Util.Soul { - ///Delegates to an underlying soul that is replaced with one of the permanent souls once it is no longer mortal. + /// + /// Delegates to an underlying soul that is replaced with one of the permanent + /// souls once it is no longer mortal. + /// internal sealed class CollapsingSoul : ISoul { private bool _collapsed; private ISoul _subSoul; public CollapsingSoul(ISoul subSoul) { - this._subSoul = subSoul; - + _subSoul = subSoul; + // flatten multiple levels of wrapping - var r = subSoul as CollapsingSoul; - if (r != null) this._subSoul = r._subSoul; - + if(subSoul is CollapsingSoul cS) _subSoul = cS._subSoul; + // ensure collapse occurs once the sub soul becomes fixed - Register(() => TryOptimize()); + Register(() => tryOptimize()); } - private Phase TryOptimize() { + private Phase tryOptimize() { var phase = _subSoul.Phase; if (_collapsed) return phase; // already optimized if (phase == Phase.Mortal) return phase; // can't optimize yet @@ -27,9 +29,8 @@ private Phase TryOptimize() { _subSoul = Phase.AsPermanentSoul(); return phase; } - public Phase Phase { get { return TryOptimize(); } } - public RegistrationRemover Register(Action action) { - return _subSoul.Register(action); - } + + public Phase Phase => tryOptimize(); + public RegistrationRemover Register(Action action) => _subSoul.Register(action); } } diff --git a/Lifetime/Soul/DeadSoul.cs b/Lifetime/Soul/DeadSoul.cs index 45fbb9a..9835831 100644 --- a/Lifetime/Soul/DeadSoul.cs +++ b/Lifetime/Soul/DeadSoul.cs @@ -6,7 +6,7 @@ internal sealed class DeadSoul : ISoul { ///The single instance of the permanently dead soul. public static readonly ISoul Instance = new DeadSoul(); private DeadSoul() {} - public Phase Phase { get { return Phase.Dead; } } + public Phase Phase => Phase.Dead; public RegistrationRemover Register(Action action) { action(); return Soul.EmptyRemover; diff --git a/Lifetime/Soul/DoublyLinkedNode.cs b/Lifetime/Soul/DoublyLinkedNode.cs index 75acc0f..4bb97ee 100644 --- a/Lifetime/Soul/DoublyLinkedNode.cs +++ b/Lifetime/Soul/DoublyLinkedNode.cs @@ -7,19 +7,22 @@ internal sealed class DoublyLinkedNode { private DoublyLinkedNode _next; private DoublyLinkedNode _prev; private readonly T _item; - + ///Creates a node doubly linked to itself. - public static DoublyLinkedNode CreateEmptyCycle() { - return new DoublyLinkedNode(); - } + public static DoublyLinkedNode CreateEmptyCycle() + => new DoublyLinkedNode(); + private DoublyLinkedNode() { - this._next = this._prev = this; + _next = _prev = this; } - ///Creates a new node containing the given item, inserted preceeding this node. - public DoublyLinkedNode Prepend(T item) { - return new DoublyLinkedNode(item, this); - } + /// + /// Creates a new node containing the given item, + /// inserted preceeding this node. + /// + public DoublyLinkedNode Prepend(T item) + => new DoublyLinkedNode(item, this); + private DoublyLinkedNode(T item, DoublyLinkedNode next) { this._item = item; this._next = next; @@ -35,13 +38,16 @@ public void Unlink() { this._next = this._prev = this; } - ///Enumerates all the nodes, except this one, that are in the same circular linked list. + /// + /// Enumerates all the nodes, except this one, + /// that are in the same circular linked list. + /// public IEnumerable EnumerateOthers() { var h = this; while (true) { var n = h._next; if (n == this) break; - if (ReferenceEquals(n, h)) + if (ReferenceEquals(n, h)) throw new InvalidOperationException("List destructively modified while being enumerated."); h = n; yield return h._item; diff --git a/Lifetime/Soul/ImmortalSoul.cs b/Lifetime/Soul/ImmortalSoul.cs index 0093e0d..b13afcc 100644 --- a/Lifetime/Soul/ImmortalSoul.cs +++ b/Lifetime/Soul/ImmortalSoul.cs @@ -6,7 +6,7 @@ internal sealed class ImmortalSoul : ISoul { ///The single instance of the permanently dead soul. public static readonly ISoul Instance = new ImmortalSoul(); private ImmortalSoul() { } - public Phase Phase { get { return Phase.Immortal; } } + public Phase Phase => Phase.Immortal; public RegistrationRemover Register(Action action) { action(); return Soul.EmptyRemover; diff --git a/Lifetime/Soul/MortalSoul.cs b/Lifetime/Soul/MortalSoul.cs index 543247d..843927f 100644 --- a/Lifetime/Soul/MortalSoul.cs +++ b/Lifetime/Soul/MortalSoul.cs @@ -30,7 +30,7 @@ public void TransitionPermanently(Phase newPhase) { Phase = newPhase; // callbacks - callbacks = _callbacks == null ? null : _callbacks.EnumerateOthers().ToArray(); + callbacks = _callbacks?.EnumerateOthers().ToArray(); _callbacks = null; } if (callbacks != null) @@ -54,7 +54,8 @@ public RegistrationRemover Register(Action action) { } // add callback for when finished - if (_callbacks == null) _callbacks = DoublyLinkedNode.CreateEmptyCycle(); + if (_callbacks == null) + _callbacks = DoublyLinkedNode.CreateEmptyCycle(); weakNode = new WeakReference(_callbacks.Prepend(action)); } diff --git a/Lifetime/Soul/Soul.cs b/Lifetime/Soul/Soul.cs index f5a55d2..6019300 100644 --- a/Lifetime/Soul/Soul.cs +++ b/Lifetime/Soul/Soul.cs @@ -10,23 +10,20 @@ internal static class Soul { /// Returns a soul permanently stuck in the given phase. /// A permanently mortal soul is considered to be immortal. /// - public static ISoul AsPermanentSoul(this Phase phase) { - return phase == Phase.Dead - ? DeadSoul.Instance + public static ISoul AsPermanentSoul(this Phase phase) + => phase == Phase.Dead + ? DeadSoul.Instance : ImmortalSoul.Instance; - } /// /// Returns a lifetime permanently stuck in the given phase. /// A permanently mortal soul is considered to be immortal. /// - public static Lifetime AsPermanentLifetime(this Phase phase) { - return new Lifetime(phase.AsPermanentSoul()); - } + public static Lifetime AsPermanentLifetime(this Phase phase) => new Lifetime(phase.AsPermanentSoul()); ///Returns a lifetime for the given soul, collapsing it to a simpler soul when possible. public static Lifetime AsCollapsingLifetime(this ISoul soul) { // avoid any wrapping if possible - var p = soul.Phase; - if (p != Phase.Mortal) return p.AsPermanentLifetime(); + var phase = soul.Phase; + if (phase != Phase.Mortal) return phase.AsPermanentLifetime(); return new Lifetime(new CollapsingSoul(soul)); } @@ -60,7 +57,10 @@ public static RegistrationRemover InterdependentRegister(this ISoul soul1, Func< }; } - ///Registers a callback to the dependent soul that only occurs if the necessary soul doesn't die first, ensuring everything is cleaned up properly. + /// + /// Registers a callback to the dependent soul that only occurs if the necessary soul doesn't die first, + /// ensuring everything is cleaned up properly. + /// public static RegistrationRemover DependentRegister(this ISoul soul, Action action, ISoul necessarySoul) { if (soul == null) throw new ArgumentNullException("soul"); if (action == null) throw new ArgumentNullException("action"); @@ -91,7 +91,7 @@ public static RegistrationRemover DependentRegister(this ISoul soul, Action acti ///Combines two souls by using a custom function to combine their phases. public static ISoul Combine(this ISoul soul1, ISoul soul2, Func phaseCombiner) { - Func getPhase = () => phaseCombiner(soul1.Phase, soul2.Phase); + Phase getPhase() => phaseCombiner(soul1.Phase, soul2.Phase); return new AnonymousSoul( getPhase, action => { diff --git a/LifetimeExample/Program.cs b/LifetimeExample/Program.cs index 4afa3b8..0c92588 100644 --- a/LifetimeExample/Program.cs +++ b/LifetimeExample/Program.cs @@ -2,10 +2,9 @@ using System.Threading; using TwistedOak.Util; -public static class Program { - private static void WriteLine(this string text, params object[] arg) { - Console.WriteLine(text, arg); - } +public static class Program +{ + private static void WriteLine(this string text, params object[] arg) => Console.WriteLine(text, arg); private static void Break() { Console.WriteLine("---"); Console.ReadLine(); @@ -120,7 +119,7 @@ private static void CallbackGarbageTest(string name, Func lostTokenMaker, new Action(() => { // register many callbacks with closures containing large amounts of memory be run when the lifetime/token ends/cancels // (these callbacks will never run; the sources are collected) - for (var i = 0; i < 2000; i++) { + for(var i = 0; i < 2000; i++) { var r = new byte[2000]; callbackRegistrar( lostToken,