diff options
Diffstat (limited to 'src/mscorlib/corefx/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs')
-rw-r--r-- | src/mscorlib/corefx/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/mscorlib/corefx/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs b/src/mscorlib/corefx/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs new file mode 100644 index 0000000000..a42e0c7983 --- /dev/null +++ b/src/mscorlib/corefx/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs @@ -0,0 +1,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); + } + } + } + } +} |