// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System.Reactive.Concurrency; using System.Threading; namespace System.Reactive.Disposables { /// /// Represents a disposable resource whose disposal invocation will be scheduled on the specified . /// public sealed class ScheduledDisposable : ICancelable { private readonly IScheduler _scheduler; private volatile IDisposable _disposable; /// /// Initializes a new instance of the class that uses an on which to dispose the disposable. /// /// Scheduler where the disposable resource will be disposed on. /// Disposable resource to dispose on the given scheduler. /// or is null. public ScheduledDisposable(IScheduler scheduler, IDisposable disposable) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (disposable == null) throw new ArgumentNullException("disposable"); _scheduler = scheduler; _disposable = disposable; } /// /// Gets the scheduler where the disposable resource will be disposed on. /// public IScheduler Scheduler { get { return _scheduler; } } /// /// Gets the underlying disposable. After disposal, the result is undefined. /// public IDisposable Disposable { get { var current = _disposable; if (current == BooleanDisposable.True) return DefaultDisposable.Instance; // Don't leak the sentinel value. return current; } } /// /// Gets a value that indicates whether the object is disposed. /// public bool IsDisposed { get { return _disposable == BooleanDisposable.True; } } /// /// Disposes the wrapped disposable on the provided scheduler. /// public void Dispose() { Scheduler.Schedule(DisposeInner); } private void DisposeInner() { #pragma warning disable 0420 var disposable = Interlocked.Exchange(ref _disposable, BooleanDisposable.True); #pragma warning restore 0420 if (disposable != BooleanDisposable.True) { disposable.Dispose(); } } } }