Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / _LocalDataStore.cs / 1305376 / _LocalDataStore.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*==============================================================================
**
** Class: LocalDataStore
**
**
** Purpose: Class that stores local data. This class is used in cooperation
** with the _LocalDataStoreMgr class.
**
**
=============================================================================*/
namespace System {
using System;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Diagnostics.Contracts;
// Helper class to aid removal of LocalDataStore from the LocalDataStoreMgr
// LocalDataStoreMgr does not holds references to LocalDataStoreHolder. It holds
// references to LocalDataStore only. LocalDataStoreHolder finalizer will run once
// the only outstanding reference to the store is in LocalDataStoreMgr.
sealed internal class LocalDataStoreHolder
{
private LocalDataStore m_Store;
public LocalDataStoreHolder(LocalDataStore store)
{
m_Store = store;
}
~LocalDataStoreHolder()
{
LocalDataStore store = m_Store;
if (store == null)
return;
store.Dispose();
}
public LocalDataStore Store
{
get
{
return m_Store;
}
}
}
sealed internal class LocalDataStoreElement
{
private Object m_value;
private long m_cookie; // This is immutable cookie of the slot used to verify that
// the value is indeed indeed owned by the slot. Necessary
// to avoid resurection holes.
public LocalDataStoreElement(long cookie)
{
m_cookie = cookie;
}
public Object Value
{
get
{
return m_value;
}
set
{
m_value = value;
}
}
public long Cookie
{
get
{
return m_cookie;
}
}
}
// This class will not be marked serializable
sealed internal class LocalDataStore
{
private LocalDataStoreElement[] m_DataTable;
private LocalDataStoreMgr m_Manager;
/*=========================================================================
** Initialize the data store.
=========================================================================*/
public LocalDataStore(LocalDataStoreMgr mgr, int InitialCapacity)
{
// Store the manager of the local data store.
m_Manager = mgr;
// Allocate the array that will contain the data.
m_DataTable = new LocalDataStoreElement[InitialCapacity];
}
/*=========================================================================
** Delete this store from its manager
=========================================================================*/
internal void Dispose()
{
m_Manager.DeleteLocalDataStore(this);
}
/*=========================================================================
** Retrieves the value from the specified slot.
=========================================================================*/
public Object GetData(LocalDataStoreSlot slot)
{
// Validate the slot.
m_Manager.ValidateSlot(slot);
// Cache the slot index to avoid synchronization issues.
int slotIdx = slot.Slot;
if (slotIdx >= 0)
{
// Delay expansion of m_DataTable if we can
if (slotIdx >= m_DataTable.Length)
return null;
// Retrieve the data from the given slot.
LocalDataStoreElement element = m_DataTable[slotIdx];
//Initially we prepopulate the elements to be null.
if (element == null)
return null;
// Check that the element is owned by this slot by comparing cookies.
// This is necesary to avoid resurection ----s.
if (element.Cookie == slot.Cookie)
return element.Value;
// Fall thru and throw exception
}
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SlotHasBeenFreed"));
}
/*==========================================================================
** Sets the data in the specified slot.
=========================================================================*/
public void SetData(LocalDataStoreSlot slot, Object data)
{
// Validate the slot.
m_Manager.ValidateSlot(slot);
// Cache the slot index to avoid synchronization issues.
int slotIdx = slot.Slot;
if (slotIdx >= 0)
{
LocalDataStoreElement element = (slotIdx < m_DataTable.Length) ? m_DataTable[slotIdx] : null;
if (element == null)
{
element = PopulateElement(slot);
}
// Check that the element is owned by this slot by comparing cookies.
// This is necesary to avoid resurection ----s.
if (element.Cookie == slot.Cookie)
{
// Set the data on the given slot.
element.Value = data;
return;
}
// Fall thru and throw exception
}
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SlotHasBeenFreed"));
}
/*=========================================================================
** This method does clears the unused slot.
* Assumes lock on m_Manager is taken
=========================================================================*/
internal void FreeData(int slot, long cookie)
{
// We try to delay allocate the dataTable (in cases like the manager clearing a
// just-freed slot in all stores
if (slot >= m_DataTable.Length)
return;
LocalDataStoreElement element = m_DataTable[slot];
if (element != null && element.Cookie == cookie)
m_DataTable[slot] = null;
}
/*==========================================================================
** Method used to expand the capacity of the local data store.
=========================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
private LocalDataStoreElement PopulateElement(LocalDataStoreSlot slot)
{
bool tookLock = false;
RuntimeHelpers.PrepareConstrainedRegions();
try {
Monitor.Enter(m_Manager, ref tookLock);
// Make sure that the slot was not freed in the meantime
int slotIdx = slot.Slot;
if (slotIdx < 0)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SlotHasBeenFreed"));
if (slotIdx >= m_DataTable.Length)
{
int capacity = m_Manager.GetSlotTableLength();
// Validate that the specified capacity is larger than the current one.
Contract.Assert(capacity >= m_DataTable.Length, "LocalDataStore corrupted: capacity >= m_DataTable.Length");
// Allocate the new data table.
LocalDataStoreElement[] NewDataTable = new LocalDataStoreElement[capacity];
// Copy all the objects into the new table.
Array.Copy(m_DataTable, NewDataTable, m_DataTable.Length);
// Save the new table.
m_DataTable = NewDataTable;
}
// Validate that there is enough space in the local data store now
Contract.Assert(slotIdx < m_DataTable.Length, "LocalDataStore corrupted: slotIdx < m_DataTable.Length");
if (m_DataTable[slotIdx] == null)
m_DataTable[slotIdx] = new LocalDataStoreElement(slot.Cookie);
return m_DataTable[slotIdx];
}
finally {
if (tookLock)
Monitor.Exit(m_Manager);
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*==============================================================================
**
** Class: LocalDataStore
**
**
** Purpose: Class that stores local data. This class is used in cooperation
** with the _LocalDataStoreMgr class.
**
**
=============================================================================*/
namespace System {
using System;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Diagnostics.Contracts;
// Helper class to aid removal of LocalDataStore from the LocalDataStoreMgr
// LocalDataStoreMgr does not holds references to LocalDataStoreHolder. It holds
// references to LocalDataStore only. LocalDataStoreHolder finalizer will run once
// the only outstanding reference to the store is in LocalDataStoreMgr.
sealed internal class LocalDataStoreHolder
{
private LocalDataStore m_Store;
public LocalDataStoreHolder(LocalDataStore store)
{
m_Store = store;
}
~LocalDataStoreHolder()
{
LocalDataStore store = m_Store;
if (store == null)
return;
store.Dispose();
}
public LocalDataStore Store
{
get
{
return m_Store;
}
}
}
sealed internal class LocalDataStoreElement
{
private Object m_value;
private long m_cookie; // This is immutable cookie of the slot used to verify that
// the value is indeed indeed owned by the slot. Necessary
// to avoid resurection holes.
public LocalDataStoreElement(long cookie)
{
m_cookie = cookie;
}
public Object Value
{
get
{
return m_value;
}
set
{
m_value = value;
}
}
public long Cookie
{
get
{
return m_cookie;
}
}
}
// This class will not be marked serializable
sealed internal class LocalDataStore
{
private LocalDataStoreElement[] m_DataTable;
private LocalDataStoreMgr m_Manager;
/*=========================================================================
** Initialize the data store.
=========================================================================*/
public LocalDataStore(LocalDataStoreMgr mgr, int InitialCapacity)
{
// Store the manager of the local data store.
m_Manager = mgr;
// Allocate the array that will contain the data.
m_DataTable = new LocalDataStoreElement[InitialCapacity];
}
/*=========================================================================
** Delete this store from its manager
=========================================================================*/
internal void Dispose()
{
m_Manager.DeleteLocalDataStore(this);
}
/*=========================================================================
** Retrieves the value from the specified slot.
=========================================================================*/
public Object GetData(LocalDataStoreSlot slot)
{
// Validate the slot.
m_Manager.ValidateSlot(slot);
// Cache the slot index to avoid synchronization issues.
int slotIdx = slot.Slot;
if (slotIdx >= 0)
{
// Delay expansion of m_DataTable if we can
if (slotIdx >= m_DataTable.Length)
return null;
// Retrieve the data from the given slot.
LocalDataStoreElement element = m_DataTable[slotIdx];
//Initially we prepopulate the elements to be null.
if (element == null)
return null;
// Check that the element is owned by this slot by comparing cookies.
// This is necesary to avoid resurection ----s.
if (element.Cookie == slot.Cookie)
return element.Value;
// Fall thru and throw exception
}
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SlotHasBeenFreed"));
}
/*==========================================================================
** Sets the data in the specified slot.
=========================================================================*/
public void SetData(LocalDataStoreSlot slot, Object data)
{
// Validate the slot.
m_Manager.ValidateSlot(slot);
// Cache the slot index to avoid synchronization issues.
int slotIdx = slot.Slot;
if (slotIdx >= 0)
{
LocalDataStoreElement element = (slotIdx < m_DataTable.Length) ? m_DataTable[slotIdx] : null;
if (element == null)
{
element = PopulateElement(slot);
}
// Check that the element is owned by this slot by comparing cookies.
// This is necesary to avoid resurection ----s.
if (element.Cookie == slot.Cookie)
{
// Set the data on the given slot.
element.Value = data;
return;
}
// Fall thru and throw exception
}
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SlotHasBeenFreed"));
}
/*=========================================================================
** This method does clears the unused slot.
* Assumes lock on m_Manager is taken
=========================================================================*/
internal void FreeData(int slot, long cookie)
{
// We try to delay allocate the dataTable (in cases like the manager clearing a
// just-freed slot in all stores
if (slot >= m_DataTable.Length)
return;
LocalDataStoreElement element = m_DataTable[slot];
if (element != null && element.Cookie == cookie)
m_DataTable[slot] = null;
}
/*==========================================================================
** Method used to expand the capacity of the local data store.
=========================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
private LocalDataStoreElement PopulateElement(LocalDataStoreSlot slot)
{
bool tookLock = false;
RuntimeHelpers.PrepareConstrainedRegions();
try {
Monitor.Enter(m_Manager, ref tookLock);
// Make sure that the slot was not freed in the meantime
int slotIdx = slot.Slot;
if (slotIdx < 0)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SlotHasBeenFreed"));
if (slotIdx >= m_DataTable.Length)
{
int capacity = m_Manager.GetSlotTableLength();
// Validate that the specified capacity is larger than the current one.
Contract.Assert(capacity >= m_DataTable.Length, "LocalDataStore corrupted: capacity >= m_DataTable.Length");
// Allocate the new data table.
LocalDataStoreElement[] NewDataTable = new LocalDataStoreElement[capacity];
// Copy all the objects into the new table.
Array.Copy(m_DataTable, NewDataTable, m_DataTable.Length);
// Save the new table.
m_DataTable = NewDataTable;
}
// Validate that there is enough space in the local data store now
Contract.Assert(slotIdx < m_DataTable.Length, "LocalDataStore corrupted: slotIdx < m_DataTable.Length");
if (m_DataTable[slotIdx] == null)
m_DataTable[slotIdx] = new LocalDataStoreElement(slot.Cookie);
return m_DataTable[slotIdx];
}
finally {
if (tookLock)
Monitor.Exit(m_Manager);
}
}
}
}
// 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
- TwoPhaseCommit.cs
- TextBoxAutomationPeer.cs
- FlagsAttribute.cs
- WindowsMenu.cs
- TreeIterators.cs
- BaseConfigurationRecord.cs
- EmptyEnumerator.cs
- _ScatterGatherBuffers.cs
- MembershipSection.cs
- DrawTreeNodeEventArgs.cs
- XmlBinaryReader.cs
- CompensateDesigner.cs
- XamlFrame.cs
- CompositeCollectionView.cs
- StateChangeEvent.cs
- HttpVersion.cs
- SchemaNames.cs
- DataGridViewBand.cs
- Opcode.cs
- UITypeEditor.cs
- CompilerCollection.cs
- TableCell.cs
- StringSorter.cs
- InternalConfigSettingsFactory.cs
- ManifestResourceInfo.cs
- StickyNoteAnnotations.cs
- NamedPipeTransportManager.cs
- ParallelLoopState.cs
- TlsnegoTokenProvider.cs
- ClassicBorderDecorator.cs
- NamespaceList.cs
- ConditionalBranch.cs
- TimeSpanSecondsOrInfiniteConverter.cs
- DeclaredTypeValidatorAttribute.cs
- HttpRequest.cs
- VariableExpressionConverter.cs
- MessageFormatterConverter.cs
- ArgumentOutOfRangeException.cs
- _SpnDictionary.cs
- RtfNavigator.cs
- Mouse.cs
- MediaEntryAttribute.cs
- EmptyControlCollection.cs
- ProxyManager.cs
- RelationshipNavigation.cs
- ProcessStartInfo.cs
- MULTI_QI.cs
- ViewManager.cs
- GroupBoxRenderer.cs
- DataGridItemAttachedStorage.cs
- TextBoxLine.cs
- SizeLimitedCache.cs
- TextAutomationPeer.cs
- DBSqlParser.cs
- LoginCancelEventArgs.cs
- XMLDiffLoader.cs
- CodeCompiler.cs
- DataBindingExpressionBuilder.cs
- SizeAnimationUsingKeyFrames.cs
- DynamicRenderer.cs
- Attributes.cs
- BinaryObjectWriter.cs
- AssemblyBuilderData.cs
- UnsafeNativeMethodsTablet.cs
- EarlyBoundInfo.cs
- TCPClient.cs
- DynamicDocumentPaginator.cs
- SqlDataSourceStatusEventArgs.cs
- TableHeaderCell.cs
- SiteMapDataSourceView.cs
- IntranetCredentialPolicy.cs
- MenuItemAutomationPeer.cs
- OracleCommandBuilder.cs
- DoubleAnimationUsingPath.cs
- unsafenativemethodsother.cs
- DelegateBodyWriter.cs
- UpdateCommand.cs
- LocatorPart.cs
- DESCryptoServiceProvider.cs
- SocketPermission.cs
- FontStretch.cs
- SingleAnimation.cs
- cryptoapiTransform.cs
- BitmapEffectInput.cs
- AggregationMinMaxHelpers.cs
- FontDialog.cs
- SplitterEvent.cs
- DataControlImageButton.cs
- _ChunkParse.cs
- ChannelToken.cs
- HttpHandlerAction.cs
- ArrayTypeMismatchException.cs
- TypeReference.cs
- SiteIdentityPermission.cs
- ToolBarPanel.cs
- ImageMap.cs
- MultilineStringEditor.cs
- SchemaElementLookUpTableEnumerator.cs
- BamlTreeNode.cs
- TableAutomationPeer.cs