summaryrefslogtreecommitdiff
path: root/src/mscorlib/corefx/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs
blob: a42e0c7983af9eff2ed00dc0c8e29ede3d380556 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace System.Threading
{
    /// <summary>
    /// Represents pre-allocated state for native overlapped I/O operations.
    /// </summary>
    /// <seealso cref="ThreadPoolBoundHandle.AllocateNativeOverlapped(PreAllocatedOverlapped)"/>
    public sealed class PreAllocatedOverlapped : IDisposable, IDeferredDisposable
    {
        internal readonly ThreadPoolBoundHandleOverlapped _overlapped;
        private DeferredDisposableLifetime<PreAllocatedOverlapped> _lifetime;

        /// <summary>
        ///     Initializes a new instance of the <see cref="PreAllocatedOverlapped"/> class, specifying 
        ///     a delegate that is invoked when each asynchronous I/O operation is complete, a user-provided 
        ///     object providing context, and managed objects that serve as buffers.
        /// </summary>
        /// <param name="callback">
        ///     An <see cref="IOCompletionCallback"/> delegate that represents the callback method 
        ///     invoked when each asynchronous I/O operation completes.
        /// </param>
        /// <param name="state">
        ///     A user-provided object that distinguishes <see cref="NativeOverlapped"/> instance produced from this
        ///     object from other <see cref="NativeOverlapped"/> instances. Can be <see langword="null"/>.
        /// </param>
        /// <param name="pinData">
        ///     An object or array of objects representing the input or output buffer for the operations. Each 
        ///     object represents a buffer, for example an array of bytes.  Can be <see langword="null"/>.
        /// </param>
        /// <remarks>
        ///     The new <see cref="PreAllocatedOverlapped"/> instance can be passed to 
        ///     <see cref="ThreadPoolBoundHandle.AllocateNativeOverlapped(PreAllocatedOverlapped)"/>, to produce
        ///     a <see cref="NativeOverlapped"/> instance that can be passed to the operating system in overlapped
        ///     I/O operations.  A single <see cref="PreAllocatedOverlapped"/> instance can only be used for 
        ///     a single native I/O operation at a time.  However, the state stored in the <see cref="PreAllocatedOverlapped"/>
        ///     instance can be reused for subsequent native operations.
        ///     <note>
        ///         The buffers specified in <paramref name="pinData"/> are pinned until <see cref="Dispose"/> is called.
        ///     </note>
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="callback"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///     This method was called after the <see cref="ThreadPoolBoundHandle"/> was disposed.
        /// </exception>
        [CLSCompliant(false)]
        public unsafe PreAllocatedOverlapped(IOCompletionCallback callback, object state, object pinData)
        {
            if (callback == null)
                throw new ArgumentNullException(nameof(callback));

            _overlapped = new ThreadPoolBoundHandleOverlapped(callback, state, pinData, this);
        }

        internal bool AddRef()
        {
            return _lifetime.AddRef(this);
        }

        internal void Release()
        {
            _lifetime.Release(this);
        }

        /// <summary>
        /// Frees the resources associated with this <see cref="PreAllocatedOverlapped"/> instance. 
        /// </summary>
        public unsafe void Dispose()
        {
            _lifetime.Dispose(this);
            GC.SuppressFinalize(this);
        }

        ~PreAllocatedOverlapped()
        {
            //
            // During shutdown, don't automatically clean up, because this instance may still be
            // reachable/usable by other code.
            //
            if (!Environment.HasShutdownStarted)
                Dispose();
        }

        unsafe void IDeferredDisposable.OnFinalRelease(bool disposed)
        {
            if (_overlapped != null)
            {
                if (disposed)
                {
                    Overlapped.Free(_overlapped._nativeOverlapped);
                }
                else
                {
                    _overlapped._boundHandle = null;
                    _overlapped._completed = false;
                    *_overlapped._nativeOverlapped = default(NativeOverlapped);
                }
            }
        }
    }
}