internal void ExtractCache(ref OverlappedCache overlappedCache) { if (!m_UseOverlappedIO && !m_DisableOverlapped) { // Have to be super careful. Socket isn't synchronized, so if a user calls End() twice, we don't want to // copy out this cache twice which could result in posting an IO with a deleted NativeOverlapped. OverlappedCache cache = m_Cache == null ? null : Interlocked.Exchange <OverlappedCache>(ref m_Cache, null); if (cache != null) { // If overlappedCache is null, just slap it in there. There's a chance for a conflict, // resulting in a OverlappedCache getting finalized, but it's better than // the interlocked. This won't be an issue in most 'correct' cases. if (overlappedCache == null) { overlappedCache = cache; } else { OverlappedCache oldCache = Interlocked.Exchange <OverlappedCache>(ref overlappedCache, cache); if (oldCache != null) { oldCache.Free(); } } } ReleaseUnmanagedStructures(); } }
internal static void InterlockedFree(ref OverlappedCache overlappedCache) { OverlappedCache cache = overlappedCache == null ? null : Interlocked.Exchange <OverlappedCache>(ref overlappedCache, null); if (cache != null) { cache.Free(); } }
internal void ExtractCache(ref OverlappedCache overlappedCache) { if (!this.m_UseOverlappedIO && !this.m_DisableOverlapped) { OverlappedCache cache = (this.m_Cache == null) ? null : Interlocked.Exchange <OverlappedCache>(ref this.m_Cache, null); if (cache != null) { if (overlappedCache == null) { overlappedCache = cache; } else { OverlappedCache cache2 = Interlocked.Exchange <OverlappedCache>(ref overlappedCache, cache); if (cache2 != null) { cache2.Free(); } } } this.ReleaseUnmanagedStructures(); } }
// // 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")); } } }