SerialDisposable.cs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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 replaced by another disposable resource, causing automatic disposal of the previous underlying disposable resource.
  6. /// </summary>
  7. public sealed class SerialDisposable : ICancelable
  8. {
  9. private readonly object _gate = new object();
  10. private IDisposable _current;
  11. private bool _disposed;
  12. /// <summary>
  13. /// Initializes a new instance of the <see cref="T:System.Reactive.Disposables.SerialDisposable"/> class.
  14. /// </summary>
  15. public SerialDisposable()
  16. {
  17. }
  18. /// <summary>
  19. /// Gets a value that indicates whether the object is disposed.
  20. /// </summary>
  21. public bool IsDisposed
  22. {
  23. get
  24. {
  25. lock (_gate)
  26. {
  27. return _disposed;
  28. }
  29. }
  30. }
  31. /// <summary>
  32. /// Gets or sets the underlying disposable.
  33. /// </summary>
  34. /// <remarks>If the SerialDisposable has already been disposed, assignment to this property causes immediate disposal of the given disposable object. Assigning this property disposes the previous disposable object.</remarks>
  35. public IDisposable Disposable
  36. {
  37. get
  38. {
  39. return _current;
  40. }
  41. set
  42. {
  43. var shouldDispose = false;
  44. var old = default(IDisposable);
  45. lock (_gate)
  46. {
  47. shouldDispose = _disposed;
  48. if (!shouldDispose)
  49. {
  50. old = _current;
  51. _current = value;
  52. }
  53. }
  54. if (old != null)
  55. old.Dispose();
  56. if (shouldDispose && value != null)
  57. value.Dispose();
  58. }
  59. }
  60. /// <summary>
  61. /// Disposes the underlying disposable as well as all future replacements.
  62. /// </summary>
  63. public void Dispose()
  64. {
  65. var old = default(IDisposable);
  66. lock (_gate)
  67. {
  68. if (!_disposed)
  69. {
  70. _disposed = true;
  71. old = _current;
  72. _current = null;
  73. }
  74. }
  75. if (old != null)
  76. old.Dispose();
  77. }
  78. }
  79. }