public void AsCancellationToken() { ((CancellationToken)Lifetime.Immortal).CanBeCanceled.AssertIsFalse(); ((CancellationToken)Lifetime.Dead).IsCancellationRequested.AssertIsTrue(); // cancelled on death var doomed = new LifetimeSource(); CancellationToken dt = doomed.Lifetime; dt.CanBeCanceled.AssertIsTrue(); dt.IsCancellationRequested.AssertIsFalse(); doomed.EndLifetime(); dt.IsCancellationRequested.AssertIsTrue(); // already cancelled when already dead ((CancellationToken)doomed.Lifetime).IsCancellationRequested.AssertIsTrue(); // hangs on immortal var blessed = new LifetimeSource(); CancellationToken bt = blessed.Lifetime; bt.CanBeCanceled.AssertIsTrue(); bt.IsCancellationRequested.AssertIsFalse(); blessed.ImmortalizeLifetime(); bt.IsCancellationRequested.AssertIsFalse(); // knows can't be cancelled when already immortal ((CancellationToken)blessed.Lifetime).CanBeCanceled.AssertIsFalse(); // hangs on limbo InvalidCallbackMaker.AssertNotCollectedAfter(action => { var r = new LifetimeSource(); CancellationToken ct = r.Lifetime; ct.Register(action); return(ct); }); }
public void Max() { Lifetime.Dead.Max(Lifetime.Dead).IsDead.AssertIsTrue(); Lifetime.Dead.Max(Lifetime.Immortal).IsImmortal.AssertIsTrue(); Lifetime.Immortal.Max(Lifetime.Dead).IsImmortal.AssertIsTrue(); Lifetime.Immortal.Max(Lifetime.Immortal).IsImmortal.AssertIsTrue(); var s1 = new LifetimeSource(); var s2 = new LifetimeSource(); var s3 = new LifetimeSource(); var m1 = s1.Lifetime.Max(s2.Lifetime); var m2 = s1.Lifetime.Max(s3.Lifetime); var m3 = s2.Lifetime.Max(s3.Lifetime); var t1 = m1.WhenDeadTask(); var t2 = m2.WhenDeadTask(); var t3 = m3.WhenDeadTask(); // equality optimization s1.Lifetime.Max(s1.Lifetime).AssertEquals(s1.Lifetime); m1.Max(m1).AssertEquals(m1); // dead optimization s1.Lifetime.Max(Lifetime.Dead).AssertEquals(s1.Lifetime); Lifetime.Dead.Max(m1).AssertEquals(m1); // when one becomes immortal, max becomes immortal (m1.IsImmortal || m1.IsDead).AssertIsFalse(); (m2.IsImmortal || m2.IsDead).AssertIsFalse(); s1.ImmortalizeLifetime(); m1.IsImmortal.AssertIsTrue(); m2.IsImmortal.AssertIsTrue(); // when one becomes dead, max is unaffected s2.EndLifetime(); // when both become dead, max is dead (m3.IsImmortal || m3.IsDead).AssertIsFalse(); t3.AssertNotCompleted(); s3.EndLifetime(); m3.IsDead.AssertIsTrue(); t3.AssertRanToCompletion(); Task.WhenAny(t1, t2).AssertNotCompleted(); // limbo allows collection InvalidCallbackMaker.AssertCollectedAfter(a => { var r1 = new LifetimeSource(); var r2 = new LifetimeSource(); var r3 = new LifetimeSource(); var life1 = r1.Lifetime.Max(r2.Lifetime); var life2 = r1.Lifetime.Max(r3.Lifetime); var life3 = r2.Lifetime.Max(r3.Lifetime); life1.WhenDead(a); life2.WhenDead(a); life3.WhenDead(a); r1.EndLifetime(); // one dead has no effect on max going to limbo return(Tuple.Create(life1, life2, life3)); }); }
public void LifetimeImmortalityConcurrency() { var repeats = 5; foreach (var _ in Enumerable.Range(0, repeats)) { var n = 0; var source = new LifetimeSource(); TestUtil.ConcurrencyTest( threadCount: 4, callbackCount: 3000, repeatedWork: (t, i) => source.Lifetime.WhenDead(() => Interlocked.Increment(ref n)), finalWork: t => source.ImmortalizeLifetime()); n.AssertEquals(0); } }
public void Status() { // status of constants Lifetime.Immortal.IsMortal.AssertIsFalse(); Lifetime.Immortal.IsImmortal.AssertIsTrue(); Lifetime.Immortal.IsDead.AssertIsFalse(); Lifetime.Dead.IsMortal.AssertIsFalse(); Lifetime.Dead.IsImmortal.AssertIsFalse(); Lifetime.Dead.IsDead.AssertIsTrue(); // state before transition var mortal = new LifetimeSource(); mortal.Lifetime.IsMortal.AssertIsTrue(); mortal.Lifetime.IsImmortal.AssertIsFalse(); mortal.Lifetime.IsDead.AssertIsFalse(); // transition to dead var doomed = new LifetimeSource(); doomed.EndLifetime(); doomed.Lifetime.IsMortal.AssertIsFalse(); doomed.Lifetime.IsImmortal.AssertIsFalse(); doomed.Lifetime.IsDead.AssertIsTrue(); // transition to immortal var blessed = new LifetimeSource(); blessed.ImmortalizeLifetime(); blessed.Lifetime.IsMortal.AssertIsFalse(); blessed.Lifetime.IsImmortal.AssertIsTrue(); blessed.Lifetime.IsDead.AssertIsFalse(); // transition to immortal via limbo var limbo = new LimboLife(); limbo.Dispose(); GC.Collect(); limbo.Lifetime.IsMortal.AssertIsFalse(); limbo.Lifetime.IsImmortal.AssertIsTrue(); limbo.Lifetime.IsDead.AssertIsFalse(); }
public void WhenSet() { // called when immortal? var blessed = new LifetimeSource(); var preBlessedLife = blessed.Lifetime.WhenDeadTask(); blessed.ImmortalizeLifetime(); var bt = new[] { Lifetime.Immortal.WhenDeadTask(), blessed.Lifetime.WhenDeadTask(), preBlessedLife }; Task.WhenAny(bt).AssertNotCompleted(); // called when dead? var doomed = new LifetimeSource(); var preDoomedLife = doomed.Lifetime.WhenDeadTask(); doomed.EndLifetime(); var dt = new[] { preDoomedLife, doomed.Lifetime.WhenDeadTask(), Lifetime.Dead.WhenDeadTask() }; Task.WhenAll(dt).AssertRanToCompletion(); // never called from limbo var limboed = new LimboLife(); var preLimboLife = limboed.Lifetime.WhenDeadTask(); limboed.Dispose(); Task.WhenAny( preLimboLife, limboed.Lifetime.WhenDeadTask() ).AssertNotCompleted(); }
public static void Main() { "=== Hit 'Enter' to advance ===".WriteLine(); Break(); /////////////////////////////////////////////////// "Manually inspecting a lifetime as it is killed:".WriteLine(); var lifesource1 = new LifetimeSource(); "Life #1: {0}".WriteLine(lifesource1); "Ending Life #1".WriteLine(); lifesource1.EndLifetime(); "Life #1: {0}".WriteLine(lifesource1); Break(); /////////////////////////////////////////////////// "Manually inspecting a lifetime as it is immortalized:".WriteLine(); var lifesource2 = new LifetimeSource(); "Life #2: {0}".WriteLine(lifesource2); "Immortalizing Life #2".WriteLine(); lifesource2.ImmortalizeLifetime(); "Life #2: {0}".WriteLine(lifesource2); Break(); /////////////////////////////////////////////////// "Using callbacks to inspect a lifetime as it is killed:".WriteLine(); var lifesource3 = new LifetimeSource(); "Life #3: {0}".WriteLine(lifesource3); "Registering WhenDead Life #3 (before)".WriteLine(); lifesource3.Lifetime.WhenDead(() => "WhenDead Life #3 (before)".WriteLine()); "Ending Life #3".WriteLine(); lifesource3.EndLifetime(); "Life #3: {0}".WriteLine(lifesource3); "Registering WhenDead Life #3 (after)".WriteLine(); lifesource3.Lifetime.WhenDead(() => "WhenDead Life #3 (after)".WriteLine()); Break(); /////////////////////////////////////////////////// "Using conditional callbacks:".WriteLine(); var lifesource4 = new LifetimeSource(); var lifesource5 = new LifetimeSource(); "Life #4: {0}".WriteLine(lifesource4); "Life #5: {0}".WriteLine(lifesource5); "Registering WhenDead 4 (requires 5)".WriteLine(); lifesource4.Lifetime.WhenDead( () => "Running WhenDead 4 (requires 5)".WriteLine(), lifesource5.Lifetime); "Registering WhenDead 5 (requires 4)".WriteLine(); lifesource5.Lifetime.WhenDead( () => "Running WhenDead 5 (requires 4)".WriteLine(), lifesource4.Lifetime); "Ending Life #4".WriteLine(); lifesource4.EndLifetime(); "Life #4: {0}".WriteLine(lifesource4); "Ending Life #5".WriteLine(); lifesource5.EndLifetime(); "Life #5: {0}".WriteLine(lifesource5); Break(); /////////////////////////////////////////////////// CallbackGarbageTest( "Immortal Lifetime collectable callback test:", () => new LifetimeSource().Lifetime, (e, a) => e.WhenDead(a)); /////////////////////////////////////////////////// var lifetimeMortal = new LifetimeSource(); CallbackGarbageTest( "Conditioned-on-dying Lifetime collectable callback test:", () => lifetimeMortal.Lifetime, (e, a) => { var r = new LifetimeSource(); e.WhenDead(a, r.Lifetime); r.EndLifetime(); }); GC.KeepAlive(lifetimeMortal); /////////////////////////////////////////////////// CallbackGarbageTest( "Immortal CancellationToken collectable callback test:", () => new CancellationTokenSource().Token, (e, a) => e.Register(a)); /////////////////////////////////////////////////// "Garbage collection of a lifetime's source:".WriteLine(); var lifesource6 = new LifetimeSource(); var life6 = lifesource6.Lifetime; "Life #6: {0}".WriteLine(life6); "Allowing garbage collection of Life #6's source".WriteLine(); lifesource6 = null; GC.Collect(); GC.WaitForPendingFinalizers(); "Life #6: {0}".WriteLine(life6); Break(); /////////////////////////////////////////////////// "=== Hit 'Enter' to close ===".WriteLine(); Break(); }
public void Dispose() { _source.ImmortalizeLifetime(); }