Explorar el Código

Adding StableCompositeAsyncDisposable.

Bart De Smet hace 8 años
padre
commit
b38efd044f

+ 98 - 0
AsyncRx.NET/System.Reactive.Async/System/Reactive/Disposables/StableCompositeAsyncDisposable.cs

@@ -0,0 +1,98 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Disposables
+{
+    public abstract class StableCompositeAsyncDisposable : IAsyncDisposable
+    {
+        public static StableCompositeAsyncDisposable Create(IAsyncDisposable disposable1, IAsyncDisposable disposable2)
+        {
+            if (disposable1 == null)
+                throw new ArgumentNullException(nameof(disposable1));
+            if (disposable2 == null)
+                throw new ArgumentNullException(nameof(disposable2));
+
+            return new Binary(disposable1, disposable2);
+        }
+
+        public static StableCompositeAsyncDisposable Create(params IAsyncDisposable[] disposables)
+        {
+            if (disposables == null)
+                throw new ArgumentNullException(nameof(disposables));
+
+            return new NAry(disposables);
+        }
+
+        public static StableCompositeAsyncDisposable Create(IEnumerable<IAsyncDisposable> disposables)
+        {
+            if (disposables == null)
+                throw new ArgumentNullException(nameof(disposables));
+
+            return new NAry(disposables);
+        }
+
+        public abstract Task DisposeAsync();
+
+        private sealed class Binary : StableCompositeAsyncDisposable
+        {
+            private volatile IAsyncDisposable _disposable1;
+            private volatile IAsyncDisposable _disposable2;
+
+            public Binary(IAsyncDisposable disposable1, IAsyncDisposable disposable2)
+            {
+                _disposable1 = disposable1;
+                _disposable2 = disposable2;
+            }
+
+            public override async Task DisposeAsync()
+            {
+                var d1 = Interlocked.Exchange(ref _disposable1, null);
+                if (d1 != null)
+                {
+                    await d1.DisposeAsync().ConfigureAwait(false);
+                }
+
+                var d2 = Interlocked.Exchange(ref _disposable2, null);
+                if (d2 != null)
+                {
+                    await d2.DisposeAsync().ConfigureAwait(false);
+                }
+            }
+        }
+
+        private sealed class NAry : StableCompositeAsyncDisposable
+        {
+            private volatile List<IAsyncDisposable> _disposables;
+
+            public NAry(IAsyncDisposable[] disposables)
+                : this((IEnumerable<IAsyncDisposable>)disposables)
+            {
+            }
+
+            public NAry(IEnumerable<IAsyncDisposable> disposables)
+            {
+                _disposables = new List<IAsyncDisposable>(disposables);
+            }
+
+            public override async Task DisposeAsync()
+            {
+                var old = Interlocked.Exchange(ref _disposables, null);
+                if (old != null)
+                {
+                    foreach (var d in old)
+                    {
+                        if (d != null)
+                        {
+                            await d.DisposeAsync().ConfigureAwait(false);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}