123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- using System;
- using System.Collections.Generic;
- using System.Threading;
- namespace UniRx
- {
- /// <summary>
- /// Represents a group of disposable resources that are disposed together.
- /// </summary>
- public abstract class StableCompositeDisposable : ICancelable
- {
- /// <summary>
- /// Creates a new group containing two disposable resources that are disposed together.
- /// </summary>
- /// <param name="disposable1">The first disposable resoruce to add to the group.</param>
- /// <param name="disposable2">The second disposable resoruce to add to the group.</param>
- /// <returns>Group of disposable resources that are disposed together.</returns>
- public static ICancelable Create(IDisposable disposable1, IDisposable disposable2)
- {
- if (disposable1 == null) throw new ArgumentNullException("disposable1");
- if (disposable2 == null) throw new ArgumentNullException("disposable2");
- return new Binary(disposable1, disposable2);
- }
- /// <summary>
- /// Creates a new group containing three disposable resources that are disposed together.
- /// </summary>
- /// <param name="disposable1">The first disposable resoruce to add to the group.</param>
- /// <param name="disposable2">The second disposable resoruce to add to the group.</param>
- /// <param name="disposable3">The third disposable resoruce to add to the group.</param>
- /// <returns>Group of disposable resources that are disposed together.</returns>
- public static ICancelable Create(IDisposable disposable1, IDisposable disposable2, IDisposable disposable3)
- {
- if (disposable1 == null) throw new ArgumentNullException("disposable1");
- if (disposable2 == null) throw new ArgumentNullException("disposable2");
- if (disposable3 == null) throw new ArgumentNullException("disposable3");
- return new Trinary(disposable1, disposable2, disposable3);
- }
- /// <summary>
- /// Creates a new group containing four disposable resources that are disposed together.
- /// </summary>
- /// <param name="disposable1">The first disposable resoruce to add to the group.</param>
- /// <param name="disposable2">The second disposable resoruce to add to the group.</param>
- /// <param name="disposable3">The three disposable resoruce to add to the group.</param>
- /// <param name="disposable4">The four disposable resoruce to add to the group.</param>
- /// <returns>Group of disposable resources that are disposed together.</returns>
- public static ICancelable Create(IDisposable disposable1, IDisposable disposable2, IDisposable disposable3, IDisposable disposable4)
- {
- if (disposable1 == null) throw new ArgumentNullException("disposable1");
- if (disposable2 == null) throw new ArgumentNullException("disposable2");
- if (disposable3 == null) throw new ArgumentNullException("disposable3");
- if (disposable4 == null) throw new ArgumentNullException("disposable4");
- return new Quaternary(disposable1, disposable2, disposable3, disposable4);
- }
- /// <summary>
- /// Creates a new group of disposable resources that are disposed together.
- /// </summary>
- /// <param name="disposables">Disposable resources to add to the group.</param>
- /// <returns>Group of disposable resources that are disposed together.</returns>
- public static ICancelable Create(params IDisposable[] disposables)
- {
- if (disposables == null) throw new ArgumentNullException("disposables");
- return new NAry(disposables);
- }
- /// <summary>
- /// Creates a new group of disposable resources that are disposed together. Array is not copied, it's unsafe but optimized.
- /// </summary>
- /// <param name="disposables">Disposable resources to add to the group.</param>
- /// <returns>Group of disposable resources that are disposed together.</returns>
- public static ICancelable CreateUnsafe(IDisposable[] disposables)
- {
- return new NAryUnsafe(disposables);
- }
- /// <summary>
- /// Creates a new group of disposable resources that are disposed together.
- /// </summary>
- /// <param name="disposables">Disposable resources to add to the group.</param>
- /// <returns>Group of disposable resources that are disposed together.</returns>
- public static ICancelable Create(IEnumerable<IDisposable> disposables)
- {
- if (disposables == null) throw new ArgumentNullException("disposables");
- return new NAry(disposables);
- }
- /// <summary>
- /// Disposes all disposables in the group.
- /// </summary>
- public abstract void Dispose();
- /// <summary>
- /// Gets a value that indicates whether the object is disposed.
- /// </summary>
- public abstract bool IsDisposed
- {
- get;
- }
- class Binary : StableCompositeDisposable
- {
- int disposedCallCount = -1;
- private volatile IDisposable _disposable1;
- private volatile IDisposable _disposable2;
- public Binary(IDisposable disposable1, IDisposable disposable2)
- {
- _disposable1 = disposable1;
- _disposable2 = disposable2;
- }
- public override bool IsDisposed
- {
- get
- {
- return disposedCallCount != -1;
- }
- }
- public override void Dispose()
- {
- if (Interlocked.Increment(ref disposedCallCount) == 0)
- {
- _disposable1.Dispose();
- _disposable2.Dispose();
- }
- }
- }
- class Trinary : StableCompositeDisposable
- {
- int disposedCallCount = -1;
- private volatile IDisposable _disposable1;
- private volatile IDisposable _disposable2;
- private volatile IDisposable _disposable3;
- public Trinary(IDisposable disposable1, IDisposable disposable2, IDisposable disposable3)
- {
- _disposable1 = disposable1;
- _disposable2 = disposable2;
- _disposable3 = disposable3;
- }
- public override bool IsDisposed
- {
- get
- {
- return disposedCallCount != -1;
- }
- }
- public override void Dispose()
- {
- if (Interlocked.Increment(ref disposedCallCount) == 0)
- {
- _disposable1.Dispose();
- _disposable2.Dispose();
- _disposable3.Dispose();
- }
- }
- }
- class Quaternary : StableCompositeDisposable
- {
- int disposedCallCount = -1;
- private volatile IDisposable _disposable1;
- private volatile IDisposable _disposable2;
- private volatile IDisposable _disposable3;
- private volatile IDisposable _disposable4;
- public Quaternary(IDisposable disposable1, IDisposable disposable2, IDisposable disposable3, IDisposable disposable4)
- {
- _disposable1 = disposable1;
- _disposable2 = disposable2;
- _disposable3 = disposable3;
- _disposable4 = disposable4;
- }
- public override bool IsDisposed
- {
- get
- {
- return disposedCallCount != -1;
- }
- }
- public override void Dispose()
- {
- if (Interlocked.Increment(ref disposedCallCount) == 0)
- {
- _disposable1.Dispose();
- _disposable2.Dispose();
- _disposable3.Dispose();
- _disposable4.Dispose();
- }
- }
- }
- class NAry : StableCompositeDisposable
- {
- int disposedCallCount = -1;
- private volatile List<IDisposable> _disposables;
- public NAry(IDisposable[] disposables)
- : this((IEnumerable<IDisposable>)disposables)
- {
- }
- public NAry(IEnumerable<IDisposable> disposables)
- {
- _disposables = new List<IDisposable>(disposables);
- //
- // Doing this on the list to avoid duplicate enumeration of disposables.
- //
- if (_disposables.Contains(null)) throw new ArgumentException("Disposables can't contains null", "disposables");
- }
- public override bool IsDisposed
- {
- get
- {
- return disposedCallCount != -1;
- }
- }
- public override void Dispose()
- {
- if (Interlocked.Increment(ref disposedCallCount) == 0)
- {
- foreach (var d in _disposables)
- {
- d.Dispose();
- }
- }
- }
- }
- class NAryUnsafe : StableCompositeDisposable
- {
- int disposedCallCount = -1;
- private volatile IDisposable[] _disposables;
- public NAryUnsafe(IDisposable[] disposables)
- {
- _disposables = disposables;
- }
- public override bool IsDisposed
- {
- get
- {
- return disposedCallCount != -1;
- }
- }
- public override void Dispose()
- {
- if (Interlocked.Increment(ref disposedCallCount) == 0)
- {
- var len = _disposables.Length;
- for (int i = 0; i < len; i++)
- {
- _disposables[i].Dispose();
- }
- }
- }
- }
- }
- }
|