[System.Threading.Tasks.Dataflow] Replace implementation with CoreFx version
[mono.git] / mcs / class / System.Threading.Tasks.Dataflow / CoreFxSources / Internal / ActionOnDispose.cs
1 // Copyright (c) Microsoft. All rights reserved.
2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4 // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
5 //
6 // ActionOnDispose.cs
7 //
8 //
9 // Implemention of IDisposable that runs a delegate on Dispose.
10 //
11 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
12
13 using System.Diagnostics;
14 using System.Diagnostics.CodeAnalysis;
15 using System.Diagnostics.Contracts;
16
17 namespace System.Threading.Tasks.Dataflow.Internal
18 {
19     /// <summary>Provider of disposables that run actions.</summary>
20     internal sealed class Disposables
21     {
22         /// <summary>An IDisposable that does nothing.</summary>
23         internal readonly static IDisposable Nop = new NopDisposable();
24
25         /// <summary>Creates an IDisposable that runs an action when disposed.</summary>
26         /// <typeparam name="T1">Specifies the type of the first argument.</typeparam>
27         /// <typeparam name="T2">Specifies the type of the second argument.</typeparam>
28         /// <param name="action">The action to invoke.</param>
29         /// <param name="arg1">The first argument.</param>
30         /// <param name="arg2">The second argument.</param>
31         /// <returns>The created disposable.</returns>
32         internal static IDisposable Create<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
33         {
34             Contract.Requires(action != null, "Non-null disposer action required.");
35             return new Disposable<T1, T2>(action, arg1, arg2);
36         }
37
38         /// <summary>Creates an IDisposable that runs an action when disposed.</summary>
39         /// <typeparam name="T1">Specifies the type of the first argument.</typeparam>
40         /// <typeparam name="T2">Specifies the type of the second argument.</typeparam>
41         /// <typeparam name="T3">Specifies the type of the third argument.</typeparam>
42         /// <param name="action">The action to invoke.</param>
43         /// <param name="arg1">The first argument.</param>
44         /// <param name="arg2">The second argument.</param>
45         /// <param name="arg3">The third argument.</param>
46         /// <returns>The created disposable.</returns>
47         internal static IDisposable Create<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
48         {
49             Contract.Requires(action != null, "Non-null disposer action required.");
50             return new Disposable<T1, T2, T3>(action, arg1, arg2, arg3);
51         }
52
53         /// <summary>A disposable that's a nop.</summary>
54         [DebuggerDisplay("Disposed = true")]
55         private sealed class NopDisposable : IDisposable
56         {
57             void IDisposable.Dispose() { }
58         }
59
60         /// <summary>An IDisposable that will run a delegate when disposed.</summary>
61         [DebuggerDisplay("Disposed = {Disposed}")]
62         private sealed class Disposable<T1, T2> : IDisposable
63         {
64             /// <summary>First state argument.</summary>
65             private readonly T1 _arg1;
66             /// <summary>Second state argument.</summary>
67             private readonly T2 _arg2;
68             /// <summary>The action to run when disposed. Null if disposed.</summary>
69             private Action<T1, T2> _action;
70
71             /// <summary>Initializes the ActionOnDispose.</summary>
72             /// <param name="action">The action to run when disposed.</param>
73             /// <param name="arg1">The first argument.</param>
74             /// <param name="arg2">The second argument.</param>
75             internal Disposable(Action<T1, T2> action, T1 arg1, T2 arg2)
76             {
77                 Contract.Requires(action != null, "Non-null action needed for disposable");
78                 _action = action;
79                 _arg1 = arg1;
80                 _arg2 = arg2;
81             }
82
83             /// <summary>Gets whether the IDisposable has been disposed.</summary>
84             [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
85             private bool Disposed { get { return _action == null; } }
86
87             /// <summary>Invoke the action.</summary>
88             void IDisposable.Dispose()
89             {
90                 Action<T1, T2> toRun = _action;
91                 if (toRun != null &&
92                     Interlocked.CompareExchange(ref _action, null, toRun) == toRun)
93                 {
94                     toRun(_arg1, _arg2);
95                 }
96             }
97         }
98
99         /// <summary>An IDisposable that will run a delegate when disposed.</summary>
100         [DebuggerDisplay("Disposed = {Disposed}")]
101         private sealed class Disposable<T1, T2, T3> : IDisposable
102         {
103             /// <summary>First state argument.</summary>
104             private readonly T1 _arg1;
105             /// <summary>Second state argument.</summary>
106             private readonly T2 _arg2;
107             /// <summary>Third state argument.</summary>
108             private readonly T3 _arg3;
109             /// <summary>The action to run when disposed. Null if disposed.</summary>
110             private Action<T1, T2, T3> _action;
111
112             /// <summary>Initializes the ActionOnDispose.</summary>
113             /// <param name="action">The action to run when disposed.</param>
114             /// <param name="arg1">The first argument.</param>
115             /// <param name="arg2">The second argument.</param>
116             /// <param name="arg3">The third argument.</param>
117             internal Disposable(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
118             {
119                 Contract.Requires(action != null, "Non-null action needed for disposable");
120                 _action = action;
121                 _arg1 = arg1;
122                 _arg2 = arg2;
123                 _arg3 = arg3;
124             }
125
126             /// <summary>Gets whether the IDisposable has been disposed.</summary>
127             [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
128             private bool Disposed { get { return _action == null; } }
129
130             /// <summary>Invoke the action.</summary>
131             void IDisposable.Dispose()
132             {
133                 Action<T1, T2, T3> toRun = _action;
134                 if (toRun != null &&
135                     Interlocked.CompareExchange(ref _action, null, toRun) == toRun)
136                 {
137                     toRun(_arg1, _arg2, _arg3);
138                 }
139             }
140         }
141     }
142 }