StableCompositeDisposable.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. namespace System.Reactive.Disposables
  5. {
  6. /// <summary>
  7. /// Represents a group of disposable resources that are disposed together.
  8. /// </summary>
  9. public abstract class StableCompositeDisposable : ICancelable
  10. {
  11. /// <summary>
  12. /// Creates a new group containing two disposable resources that are disposed together.
  13. /// </summary>
  14. /// <param name="disposable1">The first disposable resoruce to add to the group.</param>
  15. /// <param name="disposable2">The second disposable resoruce to add to the group.</param>
  16. /// <returns>Group of disposable resources that are disposed together.</returns>
  17. public static ICancelable Create(IDisposable disposable1, IDisposable disposable2)
  18. {
  19. if (disposable1 == null)
  20. throw new ArgumentNullException("disposable1");
  21. if (disposable2 == null)
  22. throw new ArgumentNullException("disposable2");
  23. return new Binary(disposable1, disposable2);
  24. }
  25. /// <summary>
  26. /// Creates a new group of disposable resources that are disposed together.
  27. /// </summary>
  28. /// <param name="disposables">Disposable resources to add to the group.</param>
  29. /// <returns>Group of disposable resources that are disposed together.</returns>
  30. public static ICancelable Create(params IDisposable[] disposables)
  31. {
  32. if (disposables == null)
  33. throw new ArgumentNullException("disposables");
  34. return new NAry(disposables);
  35. }
  36. /// <summary>
  37. /// Creates a new group of disposable resources that are disposed together.
  38. /// </summary>
  39. /// <param name="disposables">Disposable resources to add to the group.</param>
  40. /// <returns>Group of disposable resources that are disposed together.</returns>
  41. public static ICancelable Create(IEnumerable<IDisposable> disposables)
  42. {
  43. if (disposables == null)
  44. throw new ArgumentNullException("disposables");
  45. return new NAry(disposables);
  46. }
  47. /// <summary>
  48. /// Disposes all disposables in the group.
  49. /// </summary>
  50. public abstract void Dispose();
  51. /// <summary>
  52. /// Gets a value that indicates whether the object is disposed.
  53. /// </summary>
  54. public abstract bool IsDisposed
  55. {
  56. get;
  57. }
  58. class Binary : StableCompositeDisposable
  59. {
  60. private volatile IDisposable _disposable1;
  61. private volatile IDisposable _disposable2;
  62. public Binary(IDisposable disposable1, IDisposable disposable2)
  63. {
  64. _disposable1 = disposable1;
  65. _disposable2 = disposable2;
  66. }
  67. public override bool IsDisposed
  68. {
  69. get
  70. {
  71. return _disposable1 == null;
  72. }
  73. }
  74. public override void Dispose()
  75. {
  76. var old1 = Interlocked.Exchange(ref _disposable1, null);
  77. if (old1 != null)
  78. {
  79. old1.Dispose();
  80. }
  81. var old2 = Interlocked.Exchange(ref _disposable2, null);
  82. if (old2 != null)
  83. {
  84. old2.Dispose();
  85. }
  86. }
  87. }
  88. class NAry : StableCompositeDisposable
  89. {
  90. private volatile List<IDisposable> _disposables;
  91. public NAry(IDisposable[] disposables)
  92. : this((IEnumerable<IDisposable>)disposables)
  93. {
  94. }
  95. public NAry(IEnumerable<IDisposable> disposables)
  96. {
  97. _disposables = new List<IDisposable>(disposables);
  98. //
  99. // Doing this on the list to avoid duplicate enumeration of disposables.
  100. //
  101. if (_disposables.Contains(null))
  102. throw new ArgumentException(Strings_Core.DISPOSABLES_CANT_CONTAIN_NULL, "disposables");
  103. }
  104. public override bool IsDisposed
  105. {
  106. get
  107. {
  108. return _disposables == null;
  109. }
  110. }
  111. public override void Dispose()
  112. {
  113. var old = Interlocked.Exchange(ref _disposables, null);
  114. if (old != null)
  115. {
  116. foreach (var d in old)
  117. {
  118. d.Dispose();
  119. }
  120. }
  121. }
  122. }
  123. }
  124. }