public CursorBranch(Cursor <T> cursor, int currentIndex, CompositeDisposable parentDisposables) { Contract.Requires(cursor != null); Contract.Requires(cursor.branches != null); Contract.Requires(cursor.elements != null); Contract.Requires(cursor.latestIndex >= -1); Contract.Requires(currentIndex >= 0); Contract.Requires(currentIndex >= cursor.firstElementIndex); Contract.Requires(currentIndex > cursor.latestIndex || cursor.elements.Count >= cursor.latestIndex - currentIndex); Contract.Requires(!cursor.stopped || currentIndex <= cursor.latestIndex + 1); Contract.Requires(parentDisposables != null); Contract.Ensures(this.cursor == cursor); Contract.Ensures(this.currentIndex == currentIndex); Contract.Ensures(IsForwardOnly == cursor.IsForwardOnly); Contract.Ensures(IsSequenceTerminated == cursor.IsSequenceTerminated); Contract.Ensures(LatestIndex == cursor.latestIndex); Contract.Ensures(CurrentIndex == currentIndex); Contract.Ensures(AtEndOfSequence == (cursor.IsSequenceTerminated && currentIndex == cursor.latestIndex + 1)); Contract.Ensures(cursor.AtEndOfSequence == Contract.OldValue(cursor.AtEndOfSequence)); this.cursor = cursor; this.currentIndex = currentIndex; parentDisposables.Add(this); cursor.branches.Add(this); bool removed = false; var subscription = Disposable.Create(() => { if (!removed) { // Set this variable first in case of reentry. removed = true; parentDisposables.Remove(this); cursor.branches.Remove(this); } }); disposables.Add(subscription); Contract.Assert(currentIndex > cursor.latestIndex || cursor.elements.Count >= cursor.latestIndex - currentIndex); }
protected override void Main() { TraceDescription(Instructions.MulticastLab); int current = 0; IObservable<int> source = Observable .Interval(TimeSpan.FromSeconds(1)) .Select(_ => current++) .Multicast(() => new ReplaySubject<int>()) .RefCount(); using (var disposables = new CompositeDisposable()) { do { var key = WaitForKey(); switch (key.KeyChar) { case '+': case '=': var id = (char)('A' + disposables.Count); var subscription = source.Subscribe(ConsoleOutput(id.ToString())); disposables.Add(subscription); break; case '-': case '_': if (disposables.Count > 0) { disposables.Remove(disposables.Last()); } break; default: return; } } while (true); } }
public static IDisposable Schedule(this IScheduler scheduler, Action<Action> action) { // InvokeRec1 var group = new CompositeDisposable(1); var gate = new object(); Action recursiveAction = null; recursiveAction = () => action(() => { var isAdded = false; var isDone = false; var d = default(IDisposable); d = scheduler.Schedule(() => { lock (gate) { if (isAdded) group.Remove(d); else isDone = true; } recursiveAction(); }); lock (gate) { if (!isDone) { group.Add(d); isAdded = true; } } }); group.Add(scheduler.Schedule(recursiveAction)); return group; }
public void CompositeDisposable_RemoveOptimizationBehavior() { var g = new CompositeDisposable(); var m = new Dictionary<int, IDisposable>(); var r = new List<int>(); var N = 100; for (int i = 0; i < N; i++) { var j = i; var d = Disposable.Create(() => r.Add(j)); m[j] = d; g.Add(d); } var d1 = Enumerable.Range(0, N).Where(i => i % 2 == 0).ToArray(); foreach (var i in d1) g.Remove(m[i]); Assert.IsTrue(r.SequenceEqual(d1)); var d2 = Enumerable.Range(0, N).Where(i => i % 3 == 0).ToArray(); foreach (var i in d2) g.Remove(m[i]); Assert.IsTrue(r.SequenceEqual(d1.Concat(d2.Where(x => !d1.Any(y => x == y))))); var d3 = Enumerable.Range(0, N).Where(i => i % 5 == 0).ToArray(); foreach (var i in d3) g.Remove(m[i]); Assert.IsTrue(r.SequenceEqual(d1.Concat(d2.Where(x => !d1.Any(y => x == y))).Concat(d3.Where(x => !d1.Any(y => x == y) && !d2.Any(y => x == y))))); g.Dispose(); var z = r.Except(d1.Union(d2).Union(d3)).ToArray(); Assert.IsTrue(z.SequenceEqual(Enumerable.Range(0, N).Where(i => !(i % 2 == 0 || i % 3 == 0 || i % 5 == 0)))); }
public void CompositeDisposable_Remove() { var disp1 = false; var disp2 = false; var d1 = Disposable.Create(() => { disp1 = true; }); var d2 = Disposable.Create(() => { disp2 = true; }); var g = new CompositeDisposable(d1, d2); Assert.AreEqual(2, g.Count); Assert.IsTrue(g.Contains(d1)); Assert.IsTrue(g.Contains(d2)); Assert.IsTrue(g.Remove(d1)); Assert.AreEqual(1, g.Count); Assert.IsFalse(g.Contains(d1)); Assert.IsTrue(g.Contains(d2)); Assert.IsTrue(disp1); Assert.IsTrue(g.Remove(d2)); Assert.IsFalse(g.Contains(d1)); Assert.IsFalse(g.Contains(d2)); Assert.IsTrue(disp2); var disp3 = false; var d3 = Disposable.Create(() => { disp3 = true; }); Assert.IsFalse(g.Remove(d3)); Assert.IsFalse(disp3); }
static void Impl(int disposeAt) { var rand = new Random(); var g = new CompositeDisposable(); Console.Write("Dispose @ = {0} - ", disposeAt); if (disposeAt == 0) { g.Dispose(); Console.Write("{GD} "); } if (disposeAt == 1) { var sleep = rand.Next(0, 5) > 1 /* 60% chance */ ? rand.Next(2, 1000) : 0; ThreadPool.QueueUserWorkItem(_ => { Helpers.SleepOrSpin(sleep); g.Dispose(); Console.Write("{GD} "); }); } var n = rand.Next(0, 1000); var cd = new CountdownEvent(n); var ds = Enumerable.Range(0, n).Select(_ => Disposable.Create(() => cd.Signal())).ToArray(); var m = rand.Next(1, 100); var jobs = ds.GroupBy(_ => rand.Next() % m).Select(Enumerable.ToList).ToList(); Console.Write("N = {0}, M = {1} - ", n, m); var done = new CountdownEvent(jobs.Count); foreach (var job in jobs) { var sleep = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0; var sleepAt = Enumerable.Range(0, rand.Next(0, job.Count) / rand.Next(1, 100)).ToArray(); var sleeps = sleepAt.Select(_ => rand.Next(0, 50)).ToArray(); var rem = rand.Next(0, 3) == 0; /* 33% chance */ var remAt = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0; var mine = job; ThreadPool.QueueUserWorkItem(_ => { Helpers.SleepOrSpin(sleep); var j = 0; foreach (var d in mine) { var dd = d; if (sleepAt.Contains(j)) Helpers.SleepOrSpin(sleeps[j]); g.Add(dd); Console.Write("+"); if (rem) { ThreadPool.QueueUserWorkItem(__ => { Helpers.SleepOrSpin(remAt); g.Remove(dd); Console.Write("-"); }); } j++; } done.Signal(); }); } done.Wait(); if (disposeAt == 2) { g.Dispose(); Console.Write("{GD} "); } cd.Wait(); Console.WriteLine("."); }