diff options
Diffstat (limited to 'src/mscorlib/src/System/Threading/Overlapped.cs')
-rw-r--r-- | src/mscorlib/src/System/Threading/Overlapped.cs | 422 |
1 files changed, 422 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Threading/Overlapped.cs b/src/mscorlib/src/System/Threading/Overlapped.cs new file mode 100644 index 0000000000..ee3415a511 --- /dev/null +++ b/src/mscorlib/src/System/Threading/Overlapped.cs @@ -0,0 +1,422 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +// + +/* + * This files defines the following types: + * - NativeOverlapped + * - _IOCompletionCallback + * - OverlappedData + * - Overlapped + * - OverlappedDataCache + */ + +/*============================================================================= +** +** +** +** Purpose: Class for converting information to and from the native +** overlapped structure used in asynchronous file i/o +** +** +=============================================================================*/ + + +namespace System.Threading +{ + using System; + using System.Runtime.InteropServices; + using System.Runtime.CompilerServices; + using System.Runtime.Versioning; + using System.Security; + using System.Security.Permissions; + using System.Runtime.ConstrainedExecution; + using System.Diagnostics.Contracts; + using System.Collections.Concurrent; + + #region struct NativeOverlapped + + // Valuetype that represents the (unmanaged) Win32 OVERLAPPED structure + // the layout of this structure must be identical to OVERLAPPED. + // The first five matches OVERLAPPED structure. + // The remaining are reserved at the end + [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)] + [System.Runtime.InteropServices.ComVisible(true)] + public struct NativeOverlapped + { + public IntPtr InternalLow; + public IntPtr InternalHigh; + public int OffsetLow; + public int OffsetHigh; + public IntPtr EventHandle; + } + + #endregion struct NativeOverlapped + + + #region class _IOCompletionCallback + + unsafe internal class _IOCompletionCallback + { + [System.Security.SecurityCritical] // auto-generated + IOCompletionCallback _ioCompletionCallback; + ExecutionContext _executionContext; + uint _errorCode; // Error code + uint _numBytes; // No. of bytes transferred + [SecurityCritical] + NativeOverlapped* _pOVERLAP; + + [System.Security.SecuritySafeCritical] // auto-generated + static _IOCompletionCallback() + { + } + + [System.Security.SecurityCritical] // auto-generated + internal _IOCompletionCallback(IOCompletionCallback ioCompletionCallback, ref StackCrawlMark stackMark) + { + _ioCompletionCallback = ioCompletionCallback; + // clone the exection context + _executionContext = ExecutionContext.Capture( + ref stackMark, + ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase); + } + // Context callback: same sig for SendOrPostCallback and ContextCallback + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #endif + static internal ContextCallback _ccb = new ContextCallback(IOCompletionCallback_Context); + [System.Security.SecurityCritical] + static internal void IOCompletionCallback_Context(Object state) + { + _IOCompletionCallback helper = (_IOCompletionCallback)state; + Contract.Assert(helper != null,"_IOCompletionCallback cannot be null"); + helper._ioCompletionCallback(helper._errorCode, helper._numBytes, helper._pOVERLAP); + } + + + // call back helper + [System.Security.SecurityCritical] // auto-generated + static unsafe internal void PerformIOCompletionCallback(uint errorCode, // Error code + uint numBytes, // No. of bytes transferred + NativeOverlapped* pOVERLAP // ptr to OVERLAP structure + ) + { + Overlapped overlapped; + _IOCompletionCallback helper; + + do + { + overlapped = OverlappedData.GetOverlappedFromNative(pOVERLAP).m_overlapped; + helper = overlapped.iocbHelper; + + if (helper == null || helper._executionContext == null || helper._executionContext.IsDefaultFTContext(true)) + { + // We got here because of UnsafePack (or) Pack with EC flow supressed + IOCompletionCallback callback = overlapped.UserCallback; + callback( errorCode, numBytes, pOVERLAP); + } + else + { + // We got here because of Pack + helper._errorCode = errorCode; + helper._numBytes = numBytes; + helper._pOVERLAP = pOVERLAP; + using (ExecutionContext executionContext = helper._executionContext.CreateCopy()) + ExecutionContext.Run(executionContext, _ccb, helper, true); + } + + //Quickly check the VM again, to see if a packet has arrived. + + OverlappedData.CheckVMForIOPacket(out pOVERLAP, out errorCode, out numBytes); + + } while (pOVERLAP != null); + + } + } + + #endregion class _IOCompletionCallback + + + #region class OverlappedData + + sealed internal class OverlappedData + { + // ! If you make any change to the layout here, you need to make matching change + // ! to OverlappedObject in vm\nativeoverlapped.h + internal IAsyncResult m_asyncResult; + [System.Security.SecurityCritical] // auto-generated + internal IOCompletionCallback m_iocb; + internal _IOCompletionCallback m_iocbHelper; + internal Overlapped m_overlapped; + private Object m_userObject; + private IntPtr m_pinSelf; + private IntPtr m_userObjectInternal; + private int m_AppDomainId; +#pragma warning disable 414 // Field is not used from managed. +#pragma warning disable 169 + private byte m_isArray; + private byte m_toBeCleaned; +#pragma warning restore 414 +#pragma warning restore 169 + internal NativeOverlapped m_nativeOverlapped; + +#if FEATURE_CORECLR + // Adding an empty default ctor for annotation purposes + [System.Security.SecuritySafeCritical] // auto-generated + internal OverlappedData(){} +#endif // FEATURE_CORECLR + + + [System.Security.SecurityCritical] + internal void ReInitialize() + { + m_asyncResult = null; + m_iocb = null; + m_iocbHelper = null; + m_overlapped = null; + m_userObject = null; + Contract.Assert(m_pinSelf.IsNull(), "OverlappedData has not been freed: m_pinSelf"); + m_pinSelf = (IntPtr)0; + m_userObjectInternal = (IntPtr)0; + Contract.Assert(m_AppDomainId == 0 || m_AppDomainId == AppDomain.CurrentDomain.Id, "OverlappedData is not in the current domain"); + m_AppDomainId = 0; + m_nativeOverlapped.EventHandle = (IntPtr)0; + m_isArray = 0; + m_nativeOverlapped.InternalLow = (IntPtr)0; + m_nativeOverlapped.InternalHigh = (IntPtr)0; + } + + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + unsafe internal NativeOverlapped* Pack(IOCompletionCallback iocb, Object userData) + { + if (!m_pinSelf.IsNull()) { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_Overlapped_Pack")); + } + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + + if (iocb != null) + { + m_iocbHelper = new _IOCompletionCallback(iocb, ref stackMark); + m_iocb = iocb; + } + else + { + m_iocbHelper = null; + m_iocb = null; + } + m_userObject = userData; + if (m_userObject != null) + { + if (m_userObject.GetType() == typeof(Object[])) + { + m_isArray = 1; + } + else + { + m_isArray = 0; + } + } + return AllocateNativeOverlapped(); + } + + [System.Security.SecurityCritical] // auto-generated_required + unsafe internal NativeOverlapped* UnsafePack(IOCompletionCallback iocb, Object userData) + { + if (!m_pinSelf.IsNull()) { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_Overlapped_Pack")); + } + m_userObject = userData; + if (m_userObject != null) + { + if (m_userObject.GetType() == typeof(Object[])) + { + m_isArray = 1; + } + else + { + m_isArray = 0; + } + } + m_iocb = iocb; + m_iocbHelper = null; + return AllocateNativeOverlapped(); + } + + [ComVisible(false)] + internal IntPtr UserHandle + { + get { return m_nativeOverlapped.EventHandle; } + set { m_nativeOverlapped.EventHandle = value; } + } + + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + unsafe private extern NativeOverlapped* AllocateNativeOverlapped(); + + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + unsafe internal static extern void FreeNativeOverlapped(NativeOverlapped* nativeOverlappedPtr); + + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + unsafe internal static extern OverlappedData GetOverlappedFromNative(NativeOverlapped* nativeOverlappedPtr); + + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + unsafe internal static extern void CheckVMForIOPacket(out NativeOverlapped* pOVERLAP, out uint errorCode, out uint numBytes); + } + + #endregion class OverlappedData + + + #region class Overlapped + + /// <internalonly/> + [System.Runtime.InteropServices.ComVisible(true)] + public class Overlapped + { + private OverlappedData m_overlappedData; + private static PinnableBufferCache s_overlappedDataCache = new PinnableBufferCache("System.Threading.OverlappedData", ()=> new OverlappedData()); + +#if FEATURE_CORECLR + [System.Security.SecuritySafeCritical] // auto-generated +#endif + public Overlapped() + { + m_overlappedData = (OverlappedData) s_overlappedDataCache.Allocate(); + m_overlappedData.m_overlapped = this; + } + + public Overlapped(int offsetLo, int offsetHi, IntPtr hEvent, IAsyncResult ar) + { + m_overlappedData = (OverlappedData) s_overlappedDataCache.Allocate(); + m_overlappedData.m_overlapped = this; + m_overlappedData.m_nativeOverlapped.OffsetLow = offsetLo; + m_overlappedData.m_nativeOverlapped.OffsetHigh = offsetHi; + m_overlappedData.UserHandle = hEvent; + m_overlappedData.m_asyncResult = ar; + } + + [Obsolete("This constructor is not 64-bit compatible. Use the constructor that takes an IntPtr for the event handle. http://go.microsoft.com/fwlink/?linkid=14202")] + public Overlapped(int offsetLo, int offsetHi, int hEvent, IAsyncResult ar) : this(offsetLo, offsetHi, new IntPtr(hEvent), ar) + { + } + + public IAsyncResult AsyncResult + { + get { return m_overlappedData.m_asyncResult; } + set { m_overlappedData.m_asyncResult = value; } + } + + public int OffsetLow + { + get { return m_overlappedData.m_nativeOverlapped.OffsetLow; } + set { m_overlappedData.m_nativeOverlapped.OffsetLow = value; } + } + + public int OffsetHigh + { + get { return m_overlappedData.m_nativeOverlapped.OffsetHigh; } + set { m_overlappedData.m_nativeOverlapped.OffsetHigh = value; } + } + + [Obsolete("This property is not 64-bit compatible. Use EventHandleIntPtr instead. http://go.microsoft.com/fwlink/?linkid=14202")] + public int EventHandle + { + get { return m_overlappedData.UserHandle.ToInt32(); } + set { m_overlappedData.UserHandle = new IntPtr(value); } + } + + [ComVisible(false)] + public IntPtr EventHandleIntPtr + { + get { return m_overlappedData.UserHandle; } + set { m_overlappedData.UserHandle = value; } + } + + internal _IOCompletionCallback iocbHelper + { + get { return m_overlappedData.m_iocbHelper; } + } + + internal IOCompletionCallback UserCallback + { + [System.Security.SecurityCritical] + get { return m_overlappedData.m_iocb; } + } + + /*==================================================================== + * Packs a managed overlapped class into native Overlapped struct. + * Roots the iocb and stores it in the ReservedCOR field of native Overlapped + * Pins the native Overlapped struct and returns the pinned index. + ====================================================================*/ + [System.Security.SecurityCritical] // auto-generated + [Obsolete("This method is not safe. Use Pack (iocb, userData) instead. http://go.microsoft.com/fwlink/?linkid=14202")] + [CLSCompliant(false)] + unsafe public NativeOverlapped* Pack(IOCompletionCallback iocb) + { + return Pack (iocb, null); + } + + [System.Security.SecurityCritical] // auto-generated + [CLSCompliant(false),ComVisible(false)] + unsafe public NativeOverlapped* Pack(IOCompletionCallback iocb, Object userData) + { + return m_overlappedData.Pack(iocb, userData); + } + + [System.Security.SecurityCritical] // auto-generated_required + [Obsolete("This method is not safe. Use UnsafePack (iocb, userData) instead. http://go.microsoft.com/fwlink/?linkid=14202")] + [CLSCompliant(false)] + unsafe public NativeOverlapped* UnsafePack(IOCompletionCallback iocb) + { + return UnsafePack (iocb, null); + } + + [System.Security.SecurityCritical] // auto-generated_required + [CLSCompliant(false), ComVisible(false)] + unsafe public NativeOverlapped* UnsafePack(IOCompletionCallback iocb, Object userData) + { + return m_overlappedData.UnsafePack(iocb, userData); + } + + /*==================================================================== + * Unpacks an unmanaged native Overlapped struct. + * Unpins the native Overlapped struct + ====================================================================*/ + [System.Security.SecurityCritical] // auto-generated + [CLSCompliant(false)] + unsafe public static Overlapped Unpack(NativeOverlapped* nativeOverlappedPtr) + { + if (nativeOverlappedPtr == null) + throw new ArgumentNullException("nativeOverlappedPtr"); + Contract.EndContractBlock(); + + Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped; + + return overlapped; + } + + [System.Security.SecurityCritical] // auto-generated + [CLSCompliant(false)] + unsafe public static void Free(NativeOverlapped* nativeOverlappedPtr) + { + if (nativeOverlappedPtr == null) + throw new ArgumentNullException("nativeOverlappedPtr"); + Contract.EndContractBlock(); + + Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped; + OverlappedData.FreeNativeOverlapped(nativeOverlappedPtr); + OverlappedData overlappedData = overlapped.m_overlappedData; + overlapped.m_overlappedData = null; + overlappedData.ReInitialize(); + s_overlappedDataCache.Free(overlappedData); + } + + } + + #endregion class Overlapped + +} // namespace |