dfc7d472726db21a1914aa5b3370ad87fc9e9731
[mono.git] / mcs / class / Facades / System.Threading.Overlapped / ClrThreadPoolPreAllocatedOverlapped.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 namespace System.Threading
6 {
7     /// <summary>
8     /// Represents pre-allocated state for native overlapped I/O operations.
9     /// </summary>
10     /// <seealso cref="ThreadPoolBoundHandle.AllocateNativeOverlapped(PreAllocatedOverlapped)"/>
11     public sealed class PreAllocatedOverlapped : IDisposable, IDeferredDisposable
12     {
13         internal readonly ThreadPoolBoundHandleOverlapped _overlapped;
14         private DeferredDisposableLifetime<PreAllocatedOverlapped> _lifetime;
15
16         /// <summary>
17         ///     Initializes a new instance of the <see cref="PreAllocatedOverlapped"/> class, specifying 
18         ///     a delegate that is invoked when each asynchronous I/O operation is complete, a user-provided 
19         ///     object providing context, and managed objects that serve as buffers.
20         /// </summary>
21         /// <param name="callback">
22         ///     An <see cref="IOCompletionCallback"/> delegate that represents the callback method 
23         ///     invoked when each asynchronous I/O operation completes.
24         /// </param>
25         /// <param name="state">
26         ///     A user-provided object that distinguishes <see cref="NativeOverlapped"/> instance produced from this
27         ///     object from other <see cref="NativeOverlapped"/> instances. Can be <see langword="null"/>.
28         /// </param>
29         /// <param name="pinData">
30         ///     An object or array of objects representing the input or output buffer for the operations. Each 
31         ///     object represents a buffer, for example an array of bytes.  Can be <see langword="null"/>.
32         /// </param>
33         /// <remarks>
34         ///     The new <see cref="PreAllocatedOverlapped"/> instance can be passed to 
35         ///     <see cref="ThreadPoolBoundHandle.AllocateNativeOverlapped(PreAllocatedOverlapped)"/>, to produce
36         ///     a <see cref="NativeOverlapped"/> instance that can be passed to the operating system in overlapped
37         ///     I/O operations.  A single <see cref="PreAllocatedOverlapped"/> instance can only be used for 
38         ///     a single native I/O operation at a time.  However, the state stored in the <see cref="PreAllocatedOverlapped"/>
39         ///     instance can be reused for subsequent native operations.
40         ///     <note>
41         ///         The buffers specified in <paramref name="pinData"/> are pinned until <see cref="Dispose"/> is called.
42         ///     </note>
43         /// </remarks>
44         /// <exception cref="ArgumentNullException">
45         ///     <paramref name="callback"/> is <see langword="null"/>.
46         /// </exception>
47         /// <exception cref="ObjectDisposedException">
48         ///     This method was called after the <see cref="ThreadPoolBoundHandle"/> was disposed.
49         /// </exception>
50         public unsafe PreAllocatedOverlapped(IOCompletionCallback callback, object state, object pinData)
51         {
52             if (callback == null)
53                 throw new ArgumentNullException(nameof(callback));
54
55             _overlapped = new ThreadPoolBoundHandleOverlapped(callback, state, pinData, this);
56         }
57
58         internal bool AddRef()
59         {
60             return _lifetime.AddRef(this);
61         }
62
63         internal void Release()
64         {
65             _lifetime.Release(this);
66         }
67
68         /// <summary>
69         /// Frees the resources associated with this <see cref="PreAllocatedOverlapped"/> instance. 
70         /// </summary>
71         public unsafe void Dispose()
72         {
73             _lifetime.Dispose(this);
74             GC.SuppressFinalize(this);
75         }
76
77         ~PreAllocatedOverlapped()
78         {
79             //
80             // During shutdown, don't automatically clean up, because this instance may still be
81             // reachable/usable by other code.
82             //
83             if (!Environment.HasShutdownStarted)
84                 Dispose();
85         }
86
87         unsafe void IDeferredDisposable.OnFinalRelease(bool disposed)
88         {
89             if (_overlapped != null)
90             {
91                 if (disposed)
92                 {
93                     Overlapped.Free(_overlapped._nativeOverlapped);
94                 }
95                 else
96                 {
97                     _overlapped._boundHandle = null;
98                     _overlapped._completed = false;
99                     *_overlapped._nativeOverlapped = default(NativeOverlapped);
100                 }
101             }
102         }
103     }
104 }