Esempio n. 1
0
        //
        // SetUnmanagedStructures -
        //
        //  This needs to be called for overlapped IO to function properly.
        //
        //  Fills in Overlapped Structures used in an Async Overlapped Winsock call
        //  these calls are outside the runtime and are unmanaged code, so we need
        //  to prepare specific structures and ints that lie in unmanaged memory
        //  since the Overlapped calls can be Async
        //
        internal void SetUnmanagedStructures(object objectsToPin)
        {
            if (!m_DisableOverlapped)
            {
                // Casting to object[] is very expensive.  Only do it once.
                object[] objectsToPinArray   = null;
                bool     triedCastingToArray = false;

                bool useCache = false;
                if (m_Cache != null)
                {
                    if (objectsToPin == null && m_Cache.PinnedObjects == null)
                    {
                        useCache = true;
                    }
                    else if (m_Cache.PinnedObjects != null)
                    {
                        if (m_Cache.PinnedObjectsArray == null)
                        {
                            if (objectsToPin == m_Cache.PinnedObjects)
                            {
                                useCache = true;
                            }
                        }
                        else if (objectsToPin != null)
                        {
                            triedCastingToArray = true;
                            objectsToPinArray   = objectsToPin as object[];
                            if (objectsToPinArray != null && objectsToPinArray.Length == 0)
                            {
                                objectsToPinArray = null;
                            }
                            if (objectsToPinArray != null && objectsToPinArray.Length == m_Cache.PinnedObjectsArray.Length)
                            {
                                useCache = true;
                                for (int i = 0; i < objectsToPinArray.Length; i++)
                                {
                                    if (objectsToPinArray[i] != m_Cache.PinnedObjectsArray[i])
                                    {
                                        useCache = false;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                if (!useCache && m_Cache != null)
                {
                    GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::SetUnmanagedStructures() Cache miss - freeing cache.");
                    m_Cache.Free();
                    m_Cache = null;
                }

                Socket s = (Socket)AsyncObject;
                if (m_UseOverlappedIO)
                {
                    GlobalLog.Assert(m_UnmanagedBlob == null, "BaseOverlappedAsyncResult#{0}::SetUnmanagedStructures()|Unmanaged blob already allocated. (Called twice?)", ValidationHelper.HashString(this));
                    m_UnmanagedBlob = SafeOverlappedFree.Alloc(s.SafeHandle);

                    PinUnmanagedObjects(objectsToPin);

                    //
                    // create the event handle
                    //

                    m_OverlappedEvent = new AutoResetEvent(false);

                    //
                    // fill in the overlapped structure with the event handle.
                    //

                    Marshal.WriteIntPtr(m_UnmanagedBlob.DangerousGetHandle(), Win32.OverlappedhEventOffset, m_OverlappedEvent.SafeWaitHandle.DangerousGetHandle());
                }
                else
                {
                    //
                    // Bind the Win32 Socket Handle to the ThreadPool
                    //
                    s.BindToCompletionPort();

                    if (m_Cache == null)
                    {
                        GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::EnableCompletionPort() Creating new overlapped cache.");
                        if (objectsToPinArray != null)
                        {
                            m_Cache = new OverlappedCache(new Overlapped(), objectsToPinArray, s_IOCallback);
                        }
                        else
                        {
                            m_Cache = new OverlappedCache(new Overlapped(), objectsToPin, s_IOCallback, triedCastingToArray);
                        }
                    }
                    else
                    {
                        GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::EnableCompletionPort() Using cached overlapped.");
                    }

                    m_Cache.Overlapped.AsyncResult = this;

#if DEBUG
                    unsafe { m_InitialNativeOverlapped = *((NativeOverlapped *)m_Cache.NativeOverlapped); }
#endif

                    GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::EnableCompletionPort() overlapped:" + ValidationHelper.HashString(m_Cache.Overlapped) + " NativeOverlapped = " + m_Cache.NativeOverlapped.ToString("x"));
                }
            }
        }
 internal void SetUnmanagedStructures(object objectsToPin)
 {
     if (!this.m_DisableOverlapped)
     {
         object[] pinnedObjectsArray = null;
         bool     alreadyTriedCast   = false;
         bool     flag2 = false;
         if (this.m_Cache != null)
         {
             if ((objectsToPin == null) && (this.m_Cache.PinnedObjects == null))
             {
                 flag2 = true;
             }
             else if (this.m_Cache.PinnedObjects != null)
             {
                 if (this.m_Cache.PinnedObjectsArray == null)
                 {
                     if (objectsToPin == this.m_Cache.PinnedObjects)
                     {
                         flag2 = true;
                     }
                 }
                 else if (objectsToPin != null)
                 {
                     alreadyTriedCast   = true;
                     pinnedObjectsArray = objectsToPin as object[];
                     if ((pinnedObjectsArray != null) && (pinnedObjectsArray.Length == 0))
                     {
                         pinnedObjectsArray = null;
                     }
                     if ((pinnedObjectsArray != null) && (pinnedObjectsArray.Length == this.m_Cache.PinnedObjectsArray.Length))
                     {
                         flag2 = true;
                         for (int i = 0; i < pinnedObjectsArray.Length; i++)
                         {
                             if (pinnedObjectsArray[i] != this.m_Cache.PinnedObjectsArray[i])
                             {
                                 flag2 = false;
                                 break;
                             }
                         }
                     }
                 }
             }
         }
         if (!flag2 && (this.m_Cache != null))
         {
             this.m_Cache.Free();
             this.m_Cache = null;
         }
         Socket asyncObject = (Socket)base.AsyncObject;
         if (this.m_UseOverlappedIO)
         {
             this.m_UnmanagedBlob = SafeOverlappedFree.Alloc(asyncObject.SafeHandle);
             this.PinUnmanagedObjects(objectsToPin);
             this.m_OverlappedEvent = new AutoResetEvent(false);
             Marshal.WriteIntPtr(this.m_UnmanagedBlob.DangerousGetHandle(), Win32.OverlappedhEventOffset, this.m_OverlappedEvent.SafeWaitHandle.DangerousGetHandle());
         }
         else
         {
             asyncObject.BindToCompletionPort();
             if (this.m_Cache == null)
             {
                 if (pinnedObjectsArray != null)
                 {
                     this.m_Cache = new OverlappedCache(new Overlapped(), pinnedObjectsArray, s_IOCallback);
                 }
                 else
                 {
                     this.m_Cache = new OverlappedCache(new Overlapped(), objectsToPin, s_IOCallback, alreadyTriedCast);
                 }
             }
             this.m_Cache.Overlapped.AsyncResult = this;
         }
     }
 }