MultipleAssignmentDisposable.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. namespace System.Reactive.Disposables
  3. {
  4. /// <summary>
  5. /// Represents a disposable resource whose underlying disposable resource can be swapped for another disposable resource.
  6. /// </summary>
  7. public sealed class MultipleAssignmentDisposable : ICancelable
  8. {
  9. private readonly object _gate = new object();
  10. private IDisposable _current;
  11. /// <summary>
  12. /// Initializes a new instance of the <see cref="T:System.Reactive.Disposables.MultipleAssignmentDisposable"/> class with no current underlying disposable.
  13. /// </summary>
  14. public MultipleAssignmentDisposable()
  15. {
  16. }
  17. /// <summary>
  18. /// Gets a value that indicates whether the object is disposed.
  19. /// </summary>
  20. public bool IsDisposed
  21. {
  22. get
  23. {
  24. lock (_gate)
  25. {
  26. // We use a sentinel value to indicate we've been disposed. This sentinel never leaks
  27. // to the outside world (see the Disposable property getter), so no-one can ever assign
  28. // this value to us manually.
  29. return _current == BooleanDisposable.True;
  30. }
  31. }
  32. }
  33. /// <summary>
  34. /// Gets or sets the underlying disposable. After disposal, the result of getting this property is undefined.
  35. /// </summary>
  36. /// <remarks>If the MutableDisposable has already been disposed, assignment to this property causes immediate disposal of the given disposable object.</remarks>
  37. public IDisposable Disposable
  38. {
  39. get
  40. {
  41. lock (_gate)
  42. {
  43. if (_current == BooleanDisposable.True /* see IsDisposed */)
  44. return DefaultDisposable.Instance; // Don't leak the sentinel value.
  45. return _current;
  46. }
  47. }
  48. set
  49. {
  50. var shouldDispose = false;
  51. lock (_gate)
  52. {
  53. shouldDispose = (_current == BooleanDisposable.True /* see IsDisposed */);
  54. if (!shouldDispose)
  55. {
  56. _current = value;
  57. }
  58. }
  59. if (shouldDispose && value != null)
  60. value.Dispose();
  61. }
  62. }
  63. /// <summary>
  64. /// Disposes the underlying disposable as well as all future replacements.
  65. /// </summary>
  66. public void Dispose()
  67. {
  68. var old = default(IDisposable);
  69. lock (_gate)
  70. {
  71. if (_current != BooleanDisposable.True /* see IsDisposed */)
  72. {
  73. old = _current;
  74. _current = BooleanDisposable.True /* see IsDisposed */;
  75. }
  76. }
  77. if (old != null)
  78. old.Dispose();
  79. }
  80. }
  81. }