SingleAssignmentDisposable.cs 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. using System;
  2. using System.Collections;
  3. namespace UniRx
  4. {
  5. // should be use Interlocked.CompareExchange for Threadsafe?
  6. // but CompareExchange cause ExecutionEngineException on iOS.
  7. // AOT...
  8. // use lock instead
  9. public sealed class SingleAssignmentDisposable : IDisposable, ICancelable
  10. {
  11. readonly object gate = new object();
  12. IDisposable current;
  13. bool disposed;
  14. public bool IsDisposed { get { lock (gate) { return disposed; } } }
  15. public IDisposable Disposable
  16. {
  17. get
  18. {
  19. return current;
  20. }
  21. set
  22. {
  23. var old = default(IDisposable);
  24. bool alreadyDisposed;
  25. lock (gate)
  26. {
  27. alreadyDisposed = disposed;
  28. old = current;
  29. if (!alreadyDisposed)
  30. {
  31. if (value == null) return;
  32. current = value;
  33. }
  34. }
  35. if (alreadyDisposed && value != null)
  36. {
  37. value.Dispose();
  38. return;
  39. }
  40. if (old != null) throw new InvalidOperationException("Disposable is already set");
  41. }
  42. }
  43. public void Dispose()
  44. {
  45. IDisposable old = null;
  46. lock (gate)
  47. {
  48. if (!disposed)
  49. {
  50. disposed = true;
  51. old = current;
  52. current = null;
  53. }
  54. }
  55. if (old != null) old.Dispose();
  56. }
  57. }
  58. }