public void TestSimple() { var lst = new LifetimedList <int>(); var l1 = new LifetimeDefinition(); l1.Lifetime.OnTermination(() => lst.ClearValuesIfNotAlive()); lst.Add(l1.Lifetime, 1); lst.Add(l1.Lifetime, 2); var l2 = new LifetimeDefinition(); l2.Lifetime.OnTermination(() => lst.ClearValuesIfNotAlive()); lst.AddPriorityItem(new ValueLifetimed <int>(l2.Lifetime, 3)); lst.AddPriorityItem(new ValueLifetimed <int>(l2.Lifetime, 4)); Assert.AreEqual(new List <int> { 3, 4, 1, 2 }, lst.Select(x => x.Value).ToList()); l1.Terminate(); Assert.AreEqual(new List <int> { 3, 4 }, lst.Select(x => x.Value).ToList()); lst.Add(l2.Lifetime, 5); Assert.AreEqual(new List <int> { 3, 4, 5 }, lst.Select(x => x.Value).ToList()); l2.Terminate(); Assert.AreEqual(new List <int> { }, lst.Select(x => x.Value).ToList()); //again l1 = new LifetimeDefinition(); l2 = new LifetimeDefinition(); lst.Add(l1.Lifetime, 1); Assert.AreEqual(new List <int> { 1 }, lst.Select(x => x.Value).ToList()); lst.AddPriorityItem(new ValueLifetimed <int>(l2.Lifetime, 2)); Assert.AreEqual(new List <int> { 2, 1 }, lst.Select(x => x.Value).ToList()); }
public void PriorityItemTest() { using var lifetimeDefinition = new LifetimeDefinition(); var lifetime = lifetimeDefinition.Lifetime; var list = new LifetimedList <int>(); list.Add(lifetime, 1); list.Add(lifetime, 2); using (var enumerator = list.GetEnumerator()) { Assert.IsTrue(enumerator.MoveNext()); Assert.AreEqual(1, enumerator.Current.Value); list.AddPriorityItem(lifetime, 3); Assert.IsTrue(enumerator.MoveNext()); Assert.AreEqual(2, enumerator.Current.Value); Assert.IsFalse(enumerator.MoveNext()); } using (var enumerator = list.GetEnumerator()) { Assert.IsTrue(enumerator.MoveNext()); Assert.AreEqual(3, enumerator.Current.Value); list.AddPriorityItem(lifetime, 4); Assert.IsTrue(enumerator.MoveNext()); Assert.AreEqual(1, enumerator.Current.Value); Assert.IsTrue(enumerator.MoveNext()); Assert.AreEqual(2, enumerator.Current.Value); Assert.IsFalse(enumerator.MoveNext()); } }
public virtual void Advise(Lifetime lifetime, Action <T> handler) { if (!lifetime.IsAlive) { return; } if (Signal.IsPriorityAdvise) { myListeners.AddPriorityItem(lifetime, handler); } else { myListeners.Add(lifetime, handler); } lifetime.TryOnTermination(this); }
public void EnumerationStressTest() { var hugeStruct = HugeStruct.Create(); for (var k = 0; k < 300; k++) { using var lifetimeDefinition = new LifetimeDefinition(); var lifetime = lifetimeDefinition.Lifetime; var list = new LifetimedList <HugeStruct>(); // ReSharper disable once MethodSupportsCancellation var task = Task.Factory.StartNew(() => { for (var j = 0; j < 3; j++) { Task.Factory.StartNew(() => { // ReSharper disable once AccessToDisposedClosure using (lifetimeDefinition) { while (lifetime.IsAlive) { list.ClearValuesIfNotAlive(); } } }, TaskCreationOptions.AttachedToParent | TaskCreationOptions.LongRunning); Task.Factory.StartNew(() => { // ReSharper disable once AccessToDisposedClosure using (lifetimeDefinition) { while (lifetime.IsAlive) { var copy = new List <ValueLifetimed <HugeStruct> >(); // fast enumeration foreach (var lifetimed in list) { copy.Add(lifetimed); } foreach (var value in copy) { value.Value.AssertValues(); if (lifetime.IsNotAlive) { return; } } } } }, TaskCreationOptions.AttachedToParent | TaskCreationOptions.LongRunning); Task.Factory.StartNew(() => { // ReSharper disable once AccessToDisposedClosure using (lifetimeDefinition) { while (lifetime.IsAlive) { foreach (var value in list) // slow enumeration { value.Value.AssertValues(); if (lifetime.IsNotAlive) { return; } Thread.Sleep(1); } } } }, TaskCreationOptions.AttachedToParent | TaskCreationOptions.LongRunning); } }); Parallel.Invoke(() => { using (lifetimeDefinition) { for (var i = 0; i < 100; i++) { using var localDef = lifetime.CreateNested(); for (var j = 0; j < i; j++) { list.Add(localDef.Lifetime, hugeStruct); } if (lifetime.IsNotAlive) { break; } } } }, () => { var spinWait = new SpinWait(); for (var i = 0; i < 100; i++) { list.AddPriorityItem(lifetime, hugeStruct); if (lifetime.IsNotAlive) { break; } spinWait.SpinOnce(); } }); task.Wait(); } }