public static void RefCountDisposable_SuppliesAsManyDependentDisposablesAsYouNeed_ButOnlyGetsDisposedAfterAllDependentsAreDisposedOf() { //Can be used as part of a synchonization mechanism var refCountDisposable = new RefCountDisposable( Disposable.Create(() => Debug.WriteLine("Underlying disposable has been disposed."))); var firstDependentDisposable = refCountDisposable.GetDisposable(); var secondDependentDisposable = refCountDisposable.GetDisposable(); var thirdDependentDisposable = refCountDisposable.GetDisposable(); Console.WriteLine("Disposing of the second dependent."); secondDependentDisposable.Dispose(); Console.WriteLine("Trying to dispose of the RefCountDisposable"); refCountDisposable.Dispose(); Console.WriteLine($"Evidently it fails! RefCountDisposable is disposed: {refCountDisposable.IsDisposed}"); Console.WriteLine("Disposing of the third dependent."); thirdDependentDisposable.Dispose(); Console.WriteLine("Disposing of the first dependent."); firstDependentDisposable.Dispose(); Console.WriteLine($"Now that the last dependent is disposed, RefCountDisposable is disposed: {refCountDisposable.IsDisposed}"); }
public void RefCountDisposable_RefCounting() { var d = new BooleanDisposable(); var r = new RefCountDisposable(d); Assert.False(d.IsDisposed); var d1 = r.GetDisposable(); var d2 = r.GetDisposable(); Assert.False(d.IsDisposed); d1.Dispose(); Assert.False(d.IsDisposed); d2.Dispose(); Assert.False(d.IsDisposed); // CHECK r.Dispose(); Assert.True(d.IsDisposed); Assert.True(r.IsDisposed); var d3 = r.GetDisposable(); // CHECK d3.Dispose(); }
/// <summary> /// RefCountDisposable 可以使用 GetDisposable 来生成新的 Disposable,并且只会在生成的 Disposable 全部调用完 Dispose 之后,才会执行自己的 Dispose /// </summary> public static void RefCountDisposable() { var refCount = new RefCountDisposable(Disposable.Create(() => Console.WriteLine("Disposing refCount"))); var d1 = refCount.GetDisposable(); var d2 = refCount.GetDisposable(); refCount.Dispose(); Console.WriteLine("Disposing 1st"); d1.Dispose(); Console.WriteLine("Disposing 2nd"); d2.Dispose(); }
public async void AsyncDisposeTest() { pipe = new EventPipe(); var endThing = new TaskCompletionSource <bool>(); var disposer = new RefCountDisposable(Disposable.Create(() => endThing.SetResult(true))); for (var i = 0; i < 100; i++) { pipe.ObserveFirst.Subscribe(new TestObserver(i, outp, "first", disposer.GetDisposable())); pipe.ObserveConcurrent.Subscribe(new TestObserver(i, outp, "reader", disposer.GetDisposable())); pipe.ObserveSynchronous.Subscribe(new TestObserver(i, outp, "writer", disposer.GetDisposable())); } disposer.Dispose(); //var testTask = new List<Task>(); var totalDisposer = new RefCountDisposable(Disposable.Create(() => pipe.Complete())); var rand = new Random(); Parallel.ForEach(Enumerable.Range(0, 99), async x => { using (totalDisposer.GetDisposable()) { using (var scp = testProv.CreateScope()) { var e = new MessageEvent { IgnoreThis = false, Services = scp.ServiceProvider.CreateScope().ServiceProvider, Scenario = VersaCommsID.FromEnum(EVersaCommIDType.Scenario, 0), Player = new UnionType <VersaCommsID, IPlayer>(0), Terminal = new UnionType <VersaCommsID, IVersaWriter>(0), FullMessage = x.ToString(), Entity = new UnionType <VersaCommsID, IEntity>(0), }; await Task.Yield(); await pipe.ProcessEvent(e); } } }); //totalDisposer.Dispose(); //scp.Dispose(); //await Task.WhenAll(testTask); await Task.Delay(200); totalDisposer.Dispose(); //await Task.Delay(200); await endThing.Task; //pipe.Dispose(); }
/// <summary> /// Runs or observes a single catchup batch asynchronously for multiple catchup instances. /// </summary> public static IObservable <ReadModelCatchupStatus> SingleBatchAsync( params ReadModelCatchup <ReadModelDbContext>[] catchups) { return(Observable.Create <ReadModelCatchupStatus>(observer => { if (!catchups?.Any() ?? true) { observer.OnCompleted(); return Disposable.Empty; } var completions = new RefCountDisposable(Disposable.Create(observer.OnCompleted)); var subscriptions = new CompositeDisposable(); catchups.ForEach(catchup => { var completion = completions.GetDisposable(); var sub = catchup.SingleBatchAsync() .Subscribe(onNext: observer.OnNext, onCompleted: completion.Dispose); subscriptions.Add(sub); }); completions.Dispose(); return subscriptions; })); }
public IDisposable Subscribe(ICompletableObserver observer) { var velocity = GetVelocity(_property).ToReactiveProperty(); var outerDisposable = new SingleAssignmentDisposable(); var currentTween = new SerialDisposable(); var observerCompletion = new RefCountDisposable(Disposable.Create(observer.OnCompleted)); outerDisposable.Disposable = new CompositeDisposable ( _target.Subscribe(x => { // Prevent observer from completing while there is a tween in progress var tweenCompletion = observerCompletion.GetDisposable(); // Dispose any previous tween in progress, if any currentTween.Disposable = new CompositeDisposable ( Tween(_property, x, _duration, velocity.Value, _easer) .SubscribeAndForget(tweenCompletion.Dispose), tweenCompletion ); }, () => observerCompletion.Dispose()), currentTween ); return(outerDisposable); }
public void RefCountDisposable_AsFactory_Test() { // arrange const int COUNT = 10; var innerDisposable = new BooleanDisposable(); var dispFactory = new RefCountDisposable(innerDisposable); // act var dispodables = from i in Enumerable.Range(0, COUNT) // will produce a related disposable select dispFactory.GetDisposable(); dispodables = dispodables.ToArray(); dispFactory.Dispose(); // Start with single reference // verify foreach (IDisposable d in dispodables) { Assert.IsFalse(innerDisposable.IsDisposed); Assert.IsFalse(dispFactory.IsDisposed); d.Dispose(); } Assert.IsTrue(dispFactory.IsDisposed); Assert.IsTrue(innerDisposable.IsDisposed); }
public static ISequence <ISequence <T> > Window <T>(this ISequence <T> source, int windowSize, int queueLimit = 1) { if (queueLimit < 1) { throw new ArgumentOutOfRangeException("queueLimit must be greater that one."); } return(Create <ISequence <T> >(context => { Task <bool> lastCopyToResult = null; var i = source.Start(context); var subscription = new RefCountDisposable(i); return Iterator.Create <ISequence <T> >(async(r, c) => { if (lastCopyToResult != null && await lastCopyToResult.ConfigureAwait(false) == false) { return false; } if (!await i.MoveNext(c).ConfigureAwait(false)) { return false; } var queue = new AsyncQueue <T>(queueLimit); await queue.OnNext(i.Current, c).ConfigureAwait(false); r.Value = Create(context2 => new AnonymousIterator <T>(queue.MoveNext, () => queue.Current, queue.Dispose, Enumerable.Empty <Task>, context2)); var keepAlive = subscription.GetDisposable(); lastCopyToResult = CopyToQueue(i, queue, windowSize - 1, CancellationToken.None, true).Finally(keepAlive.Dispose); return true; }, context, subscription); })); }
public IDisposable Subscribe(IObserver <TElement> observer) { var release = refCount.GetDisposable(); var subscription = subject.Subscribe(observer); return(StableCompositeDisposable.Create(release, subscription)); }
public IDisposable Subscribe(UniRx.IObserver <TElement> observer) { IDisposable disposable = refCount.GetDisposable(); IDisposable disposable2 = subject.Subscribe(observer); return(StableCompositeDisposable.Create(disposable, disposable2)); }
static IObservable <T> AddRef <T>(IObservable <T> xs, RefCountDisposable r) { return(Observable.Create <T>((IObserver <T> observer) => new CompositeDisposable(new IDisposable[] { r.GetDisposable(), xs.Subscribe(observer) }))); }
public void GetDisposableDisposeFirst() { int i = 0; var src = Disposable.Create(() => i++); var d = new RefCountDisposable(src); var des = d.GetDisposable(); Assert.AreNotSame(src, des, "#1"); d.Dispose(); // triggers final disposable, up to refcount. Assert.AreEqual(0, i, "#2"); des.Dispose(); Assert.AreEqual(1, i, "#3"); Assert.IsTrue(d.IsDisposed); des = d.GetDisposable(); des.Dispose(); Assert.AreEqual(1, i, "#4"); }
private static void RefCountDisposable() { Demo.DisplayHeader("The RefCountDisposable - dispose the underlying disposable when all referencing disposables are dispsosed"); var inner = Disposable.Create(() => Console.WriteLine("Disposing inner-disposable")); var refCountDisposable = new RefCountDisposable(inner); var d1 = refCountDisposable.GetDisposable(); var d2 = refCountDisposable.GetDisposable(); var d3 = refCountDisposable.GetDisposable(); refCountDisposable.Dispose(); Console.WriteLine("Disposing 1st"); d1.Dispose(); Console.WriteLine("Disposing 2nd"); d2.Dispose(); Console.WriteLine("Disposing 3rd"); d3.Dispose(); }
public void Open() { if (String.IsNullOrEmpty(connectionName)) { return; } lock (sync) { //если две нитки используют один RasHelper и одна уже получила ссылку if (connectionRef != Disposable.Empty) { return; } //если соединение есть и его открыли мы тогда берем ссылку if (connection != null && !connection.IsDisposed) { connectionRef = connection.GetDisposable(); return; } //если соединение открыли не мы, тогда выходим if (RasConnection.GetActiveConnections().Any(c => c.EntryName == connectionName)) { return; } string phonebookPath = null; foreach (var path in GetPhoneBooks()) { using (var book = new RasPhoneBook()) { book.Open(path); if (book.Entries.Any(e => e.Name.Match(connectionName))) { phonebookPath = book.Path; } } } if (phonebookPath == null) { log.Warn($"Не удалось найти соединение {connectionName}, удаленное соединение устанавливаться не будет"); return; } using (var dialer = new RasDialer()) { dialer.PhoneBookPath = phonebookPath; dialer.EntryName = connectionName; var handle = dialer.Dial(); var rasConnection = RasConnection.GetActiveConnections().FirstOrDefault(c => c.Handle == handle); connection = new RefCountDisposable(Disposable.Create(() => rasConnection?.HangUp())); connectionRef = connection.GetDisposable(); connection.Dispose(); } } }
public void GetDisposableDisposeLater() { int i = 0; var src = Disposable.Create(() => i++); var d = new RefCountDisposable(src); var des = d.GetDisposable(); Assert.AreNotSame(src, des, "#1"); Assert.AreEqual(0, i, "#2"); des.Dispose(); Assert.AreEqual(0, i, "#3"); Assert.IsFalse(d.IsDisposed); des = d.GetDisposable(); des.Dispose(); Assert.AreEqual(0, i, "#4"); d.Dispose(); // finally, it calls src dispose Assert.AreEqual(1, i, "#5"); }
public void RefCountDisposable_Throw_If_Disposed() { var d = new BooleanDisposable(); var r = new RefCountDisposable(d, true); r.Dispose(); Assert.True(d.IsDisposed); ReactiveAssert.Throws <ObjectDisposedException>(() => { r.GetDisposable(); }); }
public void RefCountDisposable_PrimaryDisposesFirst() { var d = new BooleanDisposable(); var r = new RefCountDisposable(d); Assert.False(d.IsDisposed); var d1 = r.GetDisposable(); var d2 = r.GetDisposable(); Assert.False(d.IsDisposed); d1.Dispose(); Assert.False(d.IsDisposed); r.Dispose(); Assert.False(d.IsDisposed); d2.Dispose(); Assert.True(d.IsDisposed); }
public static IDisposable Subscribe(Func <ObservableConsole, IDisposable> subscribe) { lock (_systemConsoleSwapLock) { if (_refCount is null || _refCount.IsDisposed) { var console = new ConsoleOutput { _originalOutputWriter = Console.Out, _originalErrorWriter = Console.Error }; _out = new MultiplexingTextWriter(); _error = new MultiplexingTextWriter(); Console.SetOut(_out); Console.SetError(_error); _refCount = new RefCountDisposable(Disposable.Create(() => { _out = null; _error = null; _refCount = null; console.RestoreSystemConsole(); })); } var writerForCurrentContext = EnsureInitializedForCurrentAsyncContext(); var observableConsole = new ObservableConsole( @out: _out.GetObservable(), error: _error.GetObservable()); return(new CompositeDisposable { _refCount, _refCount.GetDisposable(), subscribe(observableConsole), writerForCurrentContext }); IDisposable EnsureInitializedForCurrentAsyncContext() => new CompositeDisposable { _out.EnsureInitializedForCurrentAsyncContext(), _error.EnsureInitializedForCurrentAsyncContext() }; } }
protected override IDisposable SubscribeCore(IObserver <TElement> observer) { if (_refCount != null) { // // [OK] Use of unsafe Subscribe: called on a known subject implementation. // var release = _refCount.GetDisposable(); var subscription = _subject.Subscribe/*Unsafe*/ (observer); return(StableCompositeDisposable.Create(release, subscription)); } // // [OK] Use of unsafe Subscribe: called on a known subject implementation. // return(_subject.Subscribe/*Unsafe*/ (observer)); }
public async ValueTask <LockHolder> GetLockAsync(CancellationToken cancellationToken) { var refCount = refCountDisposable.GetDisposable(); if (refCountDisposable.IsDisposed) { return(new LockHolder(false, refCount, null)); } else { try { await semaphoreSlim.WaitAsync(cancellationToken).ConfigureAwait(false); } catch { refCount.Dispose(); throw; } return(new LockHolder(true, refCount, semaphoreSlim)); } }
public GroupedObservable(TKey key, IObservable <TElement> underlyingObservable, RefCountDisposable mergedDisposable) { this.Key = key; this.underlyingObservable = new AnonymousObservable <TElement>(observer => new CompositeDisposable(mergedDisposable.GetDisposable(), underlyingObservable.Subscribe(observer))); }
public RepositoryWrapper(string path) { _repository = new LibGit2Sharp.Repository(path); _refCountDisposable = new RefCountDisposable(_repository); _disposable = _refCountDisposable.GetDisposable(); }
public IDisposable AddRef() => _refCountDisposable.GetDisposable();
private static void Impl(bool primaryFirst, bool primaryRandom, IEnumerable <int> nDependents) { var rand = new Random(); foreach (var n in nDependents) { var e = new ManualResetEvent(false); var hasDependent = new ManualResetEvent(false); var r = new RefCountDisposable(Disposable.Create(() => { e.Set(); })); var d = default(IDisposable); if (primaryFirst) { d = r.GetDisposable(); r.Dispose(); } else if (primaryRandom) { var sleep = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0; ThreadPool.QueueUserWorkItem(_ => { hasDependent.WaitOne(); Helpers.SleepOrSpin(sleep); r.Dispose(); }); if (n == 0) { hasDependent.Set(); } } Console.Write(n + " - "); var cd = new CountdownEvent(n * 2); for (int i = 0; i < n; i++) { var j = i; var sleep1 = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0; var sleep2 = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0; var sleep3 = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0; ThreadPool.QueueUserWorkItem(_ => { Helpers.SleepOrSpin(sleep1); Console.Write("+"); var f = r.GetDisposable(); if (j == 0) { hasDependent.Set(); } Helpers.SleepOrSpin(sleep2); ThreadPool.QueueUserWorkItem(__ => { Helpers.SleepOrSpin(sleep3); f.Dispose(); Console.Write("-"); cd.Signal(); }); cd.Signal(); }); } cd.Wait(); if (primaryFirst) { d.Dispose(); } else if (!primaryRandom) { r.Dispose(); } e.WaitOne(); Console.WriteLine("."); } }