Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / clr / src / BCL / System / Runtime / InteropServices / GCHandleCookieTable.cs / 1 / GCHandleCookieTable.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== #if MDA_SUPPORTED namespace System.Runtime.InteropServices { using System; using System.Collections; using System.Collections.Generic; using System.Threading; using ObjectHandle = IntPtr; using GCHandleCookie = IntPtr; // Internal class used to map a GCHandle to an IntPtr. Instead of handing out the underlying CLR // handle, we now hand out a cookie that can later be converted back to the CLR handle it // is associated with. internal class GCHandleCookieTable { private const int MaxListSize = 0xFFFFFF; private const uint CookieMaskIndex = 0x00FFFFFF; private const uint CookieMaskSentinal = 0xFF000000; internal GCHandleCookieTable() { m_HandleList = new ObjectHandle[10]; m_CycleCounts = new byte[10]; m_HandleToCookieMap = new Hashtable(); m_FreeIndex = 1; for (int i=0; i < 10; i++) { m_HandleList[i] = ObjectHandle.Zero; m_CycleCounts[i] = 0; } } // Retrieve a cookie for the passed in handle. If no cookie has yet been allocated for // this handle, one will be created. This method is thread safe. internal GCHandleCookie FindOrAddHandle(ObjectHandle handle) { // Don't accept a null object handle if (handle == ObjectHandle.Zero) return GCHandleCookie.Zero; // First see if we already have a cookie for this handle. object tempobj = null; tempobj = m_HandleToCookieMap[handle]; if (tempobj != null) return (GCHandleCookie)tempobj; GCHandleCookie cookie = GCHandleCookie.Zero; // First, try the m_FreeIndex as a quick check int idx = m_FreeIndex; if ((idx < m_HandleList.Length) && (m_HandleList[idx] == ObjectHandle.Zero)) { if (Interlocked.CompareExchange(ref m_HandleList[idx], handle, ObjectHandle.Zero) == ObjectHandle.Zero) { cookie = GetCookieFromData((uint)idx, m_CycleCounts[idx]); // Set our next guess just one higher if valid as this index is no longer a good guess. if (idx+1 < m_HandleList.Length) m_FreeIndex = idx+1; } } // Free index was taken...find an empty entry in the objecthandle list and fill it with the handle if (cookie == GCHandleCookie.Zero) { for (idx = 1; idx < MaxListSize; idx++) { // If we found an empty entry, try to use it. if (m_HandleList[idx] == ObjectHandle.Zero) { if (Interlocked.CompareExchange(ref m_HandleList[idx], handle, ObjectHandle.Zero) == ObjectHandle.Zero) { cookie = GetCookieFromData((uint)idx, m_CycleCounts[idx]); // Set our next guess just one higher if we ended up traversing the array. if (idx+1 < m_HandleList.Length) m_FreeIndex = idx+1; break; } } // Make sure we have enough space in the list to continue the search. if (idx+1 >= m_HandleList.Length) { lock(this) { if (idx+1 >= m_HandleList.Length) { GrowArrays(); } } } } } // If we overflowed the array, we're out of memory. if (cookie == GCHandleCookie.Zero) throw new OutOfMemoryException(Environment.GetResourceString("OutOfMemory_GCHandleMDA")); // Now that we have a cookie - remember it in our hash table. lock (this) { // First check to see if another thread already added the handle. tempobj = m_HandleToCookieMap[handle]; if (tempobj != null) { // The handle has already been added so release the cookie m_HandleList[idx] = ObjectHandle.Zero; cookie = (GCHandleCookie)tempobj; } else { // This handle hasn't been added to the map yet so add it. m_HandleToCookieMap[handle] = cookie; } } return cookie; } // Get a handle. internal ObjectHandle GetHandle(GCHandleCookie cookie) { ObjectHandle oh = ObjectHandle.Zero; if (!ValidateCookie(cookie)) return ObjectHandle.Zero; oh = m_HandleList[GetIndexFromCookie(cookie)]; return oh; } // Remove the handle from the cookie table if it is present. // // IMPORTANT: This method is NOT synchronized so the caller of this function must ensure // it is only called once for a given handle. internal void RemoveHandleIfPresent(ObjectHandle handle) { if (handle == ObjectHandle.Zero) return; object tempobj = m_HandleToCookieMap[handle]; if (tempobj != null) { GCHandleCookie cookie = (GCHandleCookie)tempobj; // Remove it from the array first if (!ValidateCookie(cookie)) return; int index = GetIndexFromCookie(cookie); m_CycleCounts[index]++; m_HandleList[index] = ObjectHandle.Zero; // Remove it from the hashtable last m_HandleToCookieMap.Remove(handle); // Update our guess m_FreeIndex = index; } } private bool ValidateCookie(GCHandleCookie cookie) { int index; byte xorData; GetDataFromCookie(cookie, out index, out xorData); // Validate the index if (index >= MaxListSize) return false; if (index >= m_HandleList.Length) return false; if (m_HandleList[index] == ObjectHandle.Zero) return false; // Validate the xorData byte (this contains the cycle count and appdomain id). byte ADID = (byte)(AppDomain.CurrentDomain.Id % 0xFF); byte goodData = (byte)(m_CycleCounts[index] ^ ADID); if (xorData != goodData) return false; return true; } // Double the size of our arrays - must be called with the lock taken. private void GrowArrays() { int CurrLength = m_HandleList.Length; ObjectHandle[] newHandleList = new ObjectHandle[CurrLength*2]; byte[] newCycleCounts = new byte[CurrLength*2]; Array.Copy(m_HandleList, newHandleList, CurrLength); Array.Copy(m_CycleCounts, newCycleCounts, CurrLength); m_HandleList = newHandleList; m_CycleCounts = newCycleCounts; } // Generate a cookie based on the index, cyclecount, and current domain id. private GCHandleCookie GetCookieFromData(uint index, byte cycleCount) { byte ADID = (byte) (AppDomain.CurrentDomain.Id % 0xFF); return (GCHandleCookie) (((cycleCount ^ ADID) << 24) + index + 1); } // Break down the cookie into its parts private void GetDataFromCookie(GCHandleCookie cookie, out int index, out byte xorData) { uint intCookie = (uint)cookie; index = (int)(intCookie & CookieMaskIndex) - 1; xorData = (byte)((intCookie & CookieMaskSentinal) >> 24); } // Just get the index from the cookie private int GetIndexFromCookie(GCHandleCookie cookie) { uint intCookie = (uint)cookie; return (int)(intCookie & CookieMaskIndex) - 1; } private Hashtable m_HandleToCookieMap; private ObjectHandle[] m_HandleList; private byte[] m_CycleCounts; int m_FreeIndex; } } #endif // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== #if MDA_SUPPORTED namespace System.Runtime.InteropServices { using System; using System.Collections; using System.Collections.Generic; using System.Threading; using ObjectHandle = IntPtr; using GCHandleCookie = IntPtr; // Internal class used to map a GCHandle to an IntPtr. Instead of handing out the underlying CLR // handle, we now hand out a cookie that can later be converted back to the CLR handle it // is associated with. internal class GCHandleCookieTable { private const int MaxListSize = 0xFFFFFF; private const uint CookieMaskIndex = 0x00FFFFFF; private const uint CookieMaskSentinal = 0xFF000000; internal GCHandleCookieTable() { m_HandleList = new ObjectHandle[10]; m_CycleCounts = new byte[10]; m_HandleToCookieMap = new Hashtable(); m_FreeIndex = 1; for (int i=0; i < 10; i++) { m_HandleList[i] = ObjectHandle.Zero; m_CycleCounts[i] = 0; } } // Retrieve a cookie for the passed in handle. If no cookie has yet been allocated for // this handle, one will be created. This method is thread safe. internal GCHandleCookie FindOrAddHandle(ObjectHandle handle) { // Don't accept a null object handle if (handle == ObjectHandle.Zero) return GCHandleCookie.Zero; // First see if we already have a cookie for this handle. object tempobj = null; tempobj = m_HandleToCookieMap[handle]; if (tempobj != null) return (GCHandleCookie)tempobj; GCHandleCookie cookie = GCHandleCookie.Zero; // First, try the m_FreeIndex as a quick check int idx = m_FreeIndex; if ((idx < m_HandleList.Length) && (m_HandleList[idx] == ObjectHandle.Zero)) { if (Interlocked.CompareExchange(ref m_HandleList[idx], handle, ObjectHandle.Zero) == ObjectHandle.Zero) { cookie = GetCookieFromData((uint)idx, m_CycleCounts[idx]); // Set our next guess just one higher if valid as this index is no longer a good guess. if (idx+1 < m_HandleList.Length) m_FreeIndex = idx+1; } } // Free index was taken...find an empty entry in the objecthandle list and fill it with the handle if (cookie == GCHandleCookie.Zero) { for (idx = 1; idx < MaxListSize; idx++) { // If we found an empty entry, try to use it. if (m_HandleList[idx] == ObjectHandle.Zero) { if (Interlocked.CompareExchange(ref m_HandleList[idx], handle, ObjectHandle.Zero) == ObjectHandle.Zero) { cookie = GetCookieFromData((uint)idx, m_CycleCounts[idx]); // Set our next guess just one higher if we ended up traversing the array. if (idx+1 < m_HandleList.Length) m_FreeIndex = idx+1; break; } } // Make sure we have enough space in the list to continue the search. if (idx+1 >= m_HandleList.Length) { lock(this) { if (idx+1 >= m_HandleList.Length) { GrowArrays(); } } } } } // If we overflowed the array, we're out of memory. if (cookie == GCHandleCookie.Zero) throw new OutOfMemoryException(Environment.GetResourceString("OutOfMemory_GCHandleMDA")); // Now that we have a cookie - remember it in our hash table. lock (this) { // First check to see if another thread already added the handle. tempobj = m_HandleToCookieMap[handle]; if (tempobj != null) { // The handle has already been added so release the cookie m_HandleList[idx] = ObjectHandle.Zero; cookie = (GCHandleCookie)tempobj; } else { // This handle hasn't been added to the map yet so add it. m_HandleToCookieMap[handle] = cookie; } } return cookie; } // Get a handle. internal ObjectHandle GetHandle(GCHandleCookie cookie) { ObjectHandle oh = ObjectHandle.Zero; if (!ValidateCookie(cookie)) return ObjectHandle.Zero; oh = m_HandleList[GetIndexFromCookie(cookie)]; return oh; } // Remove the handle from the cookie table if it is present. // // IMPORTANT: This method is NOT synchronized so the caller of this function must ensure // it is only called once for a given handle. internal void RemoveHandleIfPresent(ObjectHandle handle) { if (handle == ObjectHandle.Zero) return; object tempobj = m_HandleToCookieMap[handle]; if (tempobj != null) { GCHandleCookie cookie = (GCHandleCookie)tempobj; // Remove it from the array first if (!ValidateCookie(cookie)) return; int index = GetIndexFromCookie(cookie); m_CycleCounts[index]++; m_HandleList[index] = ObjectHandle.Zero; // Remove it from the hashtable last m_HandleToCookieMap.Remove(handle); // Update our guess m_FreeIndex = index; } } private bool ValidateCookie(GCHandleCookie cookie) { int index; byte xorData; GetDataFromCookie(cookie, out index, out xorData); // Validate the index if (index >= MaxListSize) return false; if (index >= m_HandleList.Length) return false; if (m_HandleList[index] == ObjectHandle.Zero) return false; // Validate the xorData byte (this contains the cycle count and appdomain id). byte ADID = (byte)(AppDomain.CurrentDomain.Id % 0xFF); byte goodData = (byte)(m_CycleCounts[index] ^ ADID); if (xorData != goodData) return false; return true; } // Double the size of our arrays - must be called with the lock taken. private void GrowArrays() { int CurrLength = m_HandleList.Length; ObjectHandle[] newHandleList = new ObjectHandle[CurrLength*2]; byte[] newCycleCounts = new byte[CurrLength*2]; Array.Copy(m_HandleList, newHandleList, CurrLength); Array.Copy(m_CycleCounts, newCycleCounts, CurrLength); m_HandleList = newHandleList; m_CycleCounts = newCycleCounts; } // Generate a cookie based on the index, cyclecount, and current domain id. private GCHandleCookie GetCookieFromData(uint index, byte cycleCount) { byte ADID = (byte) (AppDomain.CurrentDomain.Id % 0xFF); return (GCHandleCookie) (((cycleCount ^ ADID) << 24) + index + 1); } // Break down the cookie into its parts private void GetDataFromCookie(GCHandleCookie cookie, out int index, out byte xorData) { uint intCookie = (uint)cookie; index = (int)(intCookie & CookieMaskIndex) - 1; xorData = (byte)((intCookie & CookieMaskSentinal) >> 24); } // Just get the index from the cookie private int GetIndexFromCookie(GCHandleCookie cookie) { uint intCookie = (uint)cookie; return (int)(intCookie & CookieMaskIndex) - 1; } private Hashtable m_HandleToCookieMap; private ObjectHandle[] m_HandleList; private byte[] m_CycleCounts; int m_FreeIndex; } } #endif // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- MessageBuilder.cs
- ContentDisposition.cs
- RawStylusSystemGestureInputReport.cs
- ErrorWebPart.cs
- ConfigXmlSignificantWhitespace.cs
- SQLStringStorage.cs
- TempFiles.cs
- XPathSelectionIterator.cs
- SymbolMethod.cs
- StreamResourceInfo.cs
- XmlCharacterData.cs
- Guid.cs
- assemblycache.cs
- CheckBoxPopupAdapter.cs
- _TransmitFileOverlappedAsyncResult.cs
- PerfCounterSection.cs
- Column.cs
- DocumentsTrace.cs
- IssuanceLicense.cs
- ProjectionQueryOptionExpression.cs
- EditorZoneBase.cs
- ScrollProviderWrapper.cs
- StatusBar.cs
- MapPathBasedVirtualPathProvider.cs
- BoundPropertyEntry.cs
- CalendarButton.cs
- NavigationPropertySingletonExpression.cs
- _NegoStream.cs
- AnnotationHighlightLayer.cs
- References.cs
- TextEndOfParagraph.cs
- PeerEndPoint.cs
- IpcChannelHelper.cs
- DeviceContexts.cs
- InputLanguageCollection.cs
- CopyNodeSetAction.cs
- SkewTransform.cs
- XmlNamespaceManager.cs
- TraceHandler.cs
- RoutingConfiguration.cs
- GetResponse.cs
- ControlCollection.cs
- NumericExpr.cs
- TrustLevel.cs
- LassoHelper.cs
- StylusCollection.cs
- ExpressionBinding.cs
- BuildProvidersCompiler.cs
- EventWaitHandle.cs
- SchemaImporterExtensionsSection.cs
- CapabilitiesPattern.cs
- ContextMarshalException.cs
- SspiNegotiationTokenProvider.cs
- DeviceFiltersSection.cs
- SecurityTraceRecordHelper.cs
- ControlAdapter.cs
- Size3D.cs
- SchemaMerger.cs
- DragCompletedEventArgs.cs
- EntityDataSourceQueryBuilder.cs
- TextBoxRenderer.cs
- DataViewManagerListItemTypeDescriptor.cs
- DynamicRenderer.cs
- SqlConnectionPoolGroupProviderInfo.cs
- SmtpDigestAuthenticationModule.cs
- Pair.cs
- XmlEnumAttribute.cs
- PointHitTestResult.cs
- View.cs
- _OSSOCK.cs
- ContentElement.cs
- RotateTransform.cs
- CutCopyPasteHelper.cs
- TypeExtensionConverter.cs
- LambdaCompiler.Statements.cs
- PropertyValue.cs
- RoleManagerSection.cs
- ButtonBase.cs
- BreakSafeBase.cs
- TemplateKey.cs
- AdornerDecorator.cs
- SubpageParagraph.cs
- OperandQuery.cs
- Misc.cs
- CalendarDateChangedEventArgs.cs
- PolyBezierSegment.cs
- Propagator.cs
- CoreSwitches.cs
- PrintDocument.cs
- WmlTextBoxAdapter.cs
- ConstNode.cs
- SqlInfoMessageEvent.cs
- ContainerParaClient.cs
- DefaultMergeHelper.cs
- DesignerActionUIService.cs
- WebPartsPersonalizationAuthorization.cs
- ClosableStream.cs
- DependsOnAttribute.cs
- PseudoWebRequest.cs
- KeyEvent.cs