public void AssignNullAfterDispose() { var d = new SingleAssignmentDisposable (); d.Dispose (); d.Disposable = null; // should not result in NRE, nor treated as if it assigned an instance. d.Disposable = Disposable.Create (() => {}); }
public void AssignMultipleOnceAfterDispose() { var d = new SingleAssignmentDisposable (); d.Disposable = Disposable.Create (() => {}); d.Dispose (); d.Disposable = Disposable.Create (() => {}); }
public void SingleAssignmentDisposable_DisposeAfterSet() { var disposed = false; var d = new SingleAssignmentDisposable(); var dd = Disposable.Create(() => { disposed = true; }); d.Disposable = dd; Assert.AreSame(dd, d.Disposable); Assert.IsFalse(disposed); d.Dispose(); Assert.IsTrue(disposed); d.Dispose(); Assert.IsTrue(disposed); Assert.IsTrue(d.IsDisposed); }
public void SingleAssignmentRxOfficial() { var d = new SingleAssignmentDisposable(); d.IsDisposed.IsFalse(); var id1 = new IdDisp(1); var id2 = new IdDisp(2); var id3 = new IdDisp(3); // dispose first d.Dispose(); d.IsDisposed.IsTrue(); d.Disposable = id1; id1.IsDisposed.IsTrue(); d.Disposable = id2; id2.IsDisposed.IsTrue(); d.Disposable = id3; id3.IsDisposed.IsTrue(); // normal flow d = new SingleAssignmentDisposable(); id1 = new IdDisp(1); id2 = new IdDisp(2); id3 = new IdDisp(3); d.Disposable = id1; id1.IsDisposed.IsFalse(); d.Dispose(); id1.IsDisposed.IsTrue(); d.Disposable = id2; id2.IsDisposed.IsTrue(); d.Disposable = id3; id3.IsDisposed.IsTrue(); // exception flow d = new SingleAssignmentDisposable(); id1 = new IdDisp(1); id2 = new IdDisp(2); id3 = new IdDisp(3); d.Disposable = id1; AssertEx.Catch<InvalidOperationException>(() => d.Disposable = id2); // null d = new SingleAssignmentDisposable(); id1 = new IdDisp(1); d.Disposable = null; d.Dispose(); d.Disposable = null; }
private static void Impl() { var rand = new Random(); for (int i = 0; i < 1000; i++) { var d = new SingleAssignmentDisposable(); var e = new ManualResetEvent(false); var cd = new CountdownEvent(2); var sleep1 = rand.Next(0, 1) == 0 ? 0 : rand.Next(2, 100); var sleep2 = rand.Next(0, 1) == 0 ? 0 : rand.Next(2, 100); ThreadPool.QueueUserWorkItem(_ => { Helpers.SleepOrSpin(sleep1); Console.Write("{DB} "); d.Dispose(); Console.Write("{DE} "); cd.Signal(); }); ThreadPool.QueueUserWorkItem(_ => { Helpers.SleepOrSpin(sleep2); Console.Write("{AB} "); d.Disposable = Disposable.Create(() => e.Set()); Console.Write("{AE} "); cd.Signal(); }); e.WaitOne(); cd.Wait(); Console.WriteLine("."); } }
private static void RefCountWithPost_(IEnumerable<Tuple<int, int>> parameters) { var worker = new Thread(() => { SynchronizationContext.SetSynchronizationContext(new MySyncCtx()); foreach (var p in parameters) { var N = p.Item1; var M = p.Item2; Console.Write("N = {0}, M = {1} - ", N, M); var bar = new Bar(); var foo = Observable.FromEventPattern<FooEventArgs>(h => { /*Console.Write("+");*/ bar.Foo += h; }, h => { bar.Foo -= h; /*Console.Write("-"); */}); var e = new ManualResetEvent(false); var cd = new CountdownEvent(M * 2); for (int i = 0; i < M; i++) { var f = new SingleAssignmentDisposable(); ThreadPool.QueueUserWorkItem(_ => { f.Disposable = foo.Subscribe(__ => { /*Console.Write("!");*/ }); cd.Signal(); }); ThreadPool.QueueUserWorkItem(_ => { f.Dispose(); cd.Signal(); }); } var hasObserved = 0; Console.Write("{SB}"); var d = foo.Subscribe(x => { // // [on BARTDE-M6500 with CPU and RAM pressure] // // Up to 8K concurrent observers, we typically don't see a time gap (expected worst-case behavior). // The code below uses an event to check the desired behavior of eventually tuning in to the event stream. // Console.Write("&" + x.EventArgs.Qux); e.Set(); Interlocked.Exchange(ref hasObserved, 1); }); Console.Write("{SE}"); var t = new Thread(() => { Console.Write("{TB}"); var i = 0; while (Thread.VolatileRead(ref hasObserved) == 0) bar.OnFoo(i++); Console.Write("{TE}"); }); t.Start(); t.Join(); cd.Wait(); e.WaitOne(); d.Dispose(); Console.WriteLine("."); } }); worker.Start(); worker.Join(); }
private static void RefCount_(IEnumerable<Tuple<int, int>> parameters) { foreach (var p in parameters) { var N = p.Item1; var M = p.Item2; Console.Write("N = {0}, M = {1} - ", N, M); var bar = new Bar(); var foo = Observable.FromEventPattern<FooEventArgs>(h => { Console.Write("+"); bar.Foo += h; }, h => { bar.Foo -= h; Console.Write("-"); }); var res = new List<int>(); var n = 0; var e = new ManualResetEvent(false); var cd = new CountdownEvent(M * 2); for (int i = 0; i < M; i++) { var f = new SingleAssignmentDisposable(); ThreadPool.QueueUserWorkItem(_ => { f.Disposable = foo.Subscribe(__ => { Console.Write("!"); }); cd.Signal(); }); ThreadPool.QueueUserWorkItem(_ => { f.Dispose(); cd.Signal(); }); } Console.Write("{SB}"); var d = foo.Subscribe(x => { //Console.Write("&"); if (++n == N) e.Set(); res.Add(x.EventArgs.Qux); }); Console.Write("{SE}"); var t = new Thread(() => { Console.Write("{TB}"); for (int i = 0; i < N; i++) bar.OnFoo(i); Console.Write("{TE}"); }); t.Start(); t.Join(); cd.Wait(); e.WaitOne(); d.Dispose(); if (!res.SequenceEqual(Enumerable.Range(0, N))) { Console.WriteLine("Panic!"); break; } Console.WriteLine("."); } }
public void SingleAssignmentDisposable_DisposeBeforeSet() { var disposed = false; var d = new SingleAssignmentDisposable(); var dd = Disposable.Create(() => { disposed = true; }); Assert.IsFalse(disposed); d.Dispose(); Assert.IsFalse(disposed); Assert.IsTrue(d.IsDisposed); d.Disposable = dd; Assert.IsTrue(disposed); //Assert.IsNull(d.Disposable); // BREAKING CHANGE v2 > v1.x - Undefined behavior after disposal. d.Disposable.Dispose(); // This should be a nop. d.Dispose(); Assert.IsTrue(disposed); }
public void SchedulePeriodic() { var evt = new ManualResetEvent(false); var id = Thread.CurrentThread.ManagedThreadId; var disp = DispatcherHelpers.EnsureDispatcher(); var sch = new DispatcherScheduler(disp); var d = new SingleAssignmentDisposable(); d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); if (n == 3) { d.Dispose(); sch.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); }); } if (n > 3) { Assert.Fail(); } return n + 1; }); evt.WaitOne(); disp.InvokeShutdown(); }
public void SchedulePeriodic_Nested() { var evt = new ManualResetEvent(false); var id = Thread.CurrentThread.ManagedThreadId; var lbl = CreateLabel(); var sch = new ControlScheduler(lbl); sch.Schedule(() => { lbl.Text = "Okay"; var d = new SingleAssignmentDisposable(); d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n => { lbl.Text = "Okay " + n; Assert.NotEqual(id, Thread.CurrentThread.ManagedThreadId); if (n == 3) { d.Dispose(); sch.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.Equal("Okay 3", lbl.Text); Assert.NotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); }); } return n + 1; }); }); evt.WaitOne(); Application.Exit(); }
public void Start(IHostController hostController) { AppHosting.SetupChannel(); var d = new SingleAssignmentDisposable(); if (keepAlive) { d.Disposable = Observable.Interval(TimeSpan.FromMilliseconds(500)) .Subscribe(i => { try { if (!hostController.isAlive()) { d.Dispose(); Process.GetCurrentProcess().Kill(); } } catch (Exception err) { dbg.Error(err); Process.GetCurrentProcess().Kill(); } }); } var live555 = new Live555(videoBuffer, metadataReceiver); live555.Play(mediaStreamInfo, playbackController); d.Dispose(); }