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/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 47ba791..c112576 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
+ 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.
+
+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/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/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/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/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/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,
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 72e2493..0000000
Binary files a/TwistedOak.Util.Lifetime.1.0.0.nupkg and /dev/null differ
diff --git a/TwistedOak.Util.Lifetime.1.0.1.nupkg b/TwistedOak.Util.Lifetime.1.0.1.nupkg
deleted file mode 100644
index 283a839..0000000
Binary files a/TwistedOak.Util.Lifetime.1.0.1.nupkg and /dev/null differ
diff --git a/TwistedOak.Util.Lifetime.1.0.2.nupkg b/TwistedOak.Util.Lifetime.1.0.2.nupkg
deleted file mode 100644
index caee927..0000000
Binary files a/TwistedOak.Util.Lifetime.1.0.2.nupkg and /dev/null differ