_LocalDataStoreMgr.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / _LocalDataStoreMgr.cs / 1 / _LocalDataStoreMgr.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*==============================================================================
** 
** Class: LocalDataStoreMgr 
**
** 
** Purpose: Class that manages stores of local data. This class is used in
**          cooperation with the LocalDataStore class.
**
** 
=============================================================================*/
namespace System { 
 
    using System;
    using System.Collections; 
    using System.Threading;
    using System.Runtime.CompilerServices;

 	// This is a cheesy internal helper class that is used to make sure memory 
	// is actually being accessed and not some cached copy of a field in a
	// register. 
	// WARNING: If we every do type analysis to eliminate virtual functions, 
 	// this will break.
	// This class will not be marked serializable 
 	internal class LdsSyncHelper
 	{
		internal virtual int Get(ref int slot)
 		{ 
			return slot;
		} 
	} 

 	// This class is an encapsulation of a slot so that it is managed in a secure fashion. 
	// It is constructed by the LocalDataStoreManager, holds the slot and the manager
 	// and cleans up when it is finalized.
 	// This class will not be marked serializable
[System.Runtime.InteropServices.ComVisible(true)] 
	public sealed class LocalDataStoreSlot
 	{ 
		private static LdsSyncHelper m_helper = new LdsSyncHelper(); 

		private LocalDataStoreMgr m_mgr; 
		private int m_slot;

 		// Construct the object to encapsulate the slot.
		internal LocalDataStoreSlot(LocalDataStoreMgr mgr, int slot) 
 		{
 			m_mgr = mgr; 
			m_slot = slot; 
 		}
 
		// Accessors for the two fields of this class.
		internal LocalDataStoreMgr Manager
		{
 			get 
			{
 				return m_mgr; 
 			} 
		}
 		internal int Slot 
		{
			get
			{
 				return m_slot; 
			}
 		} 
 
 		// This is used to make sure we are actually reading and writing to
		// memory to fetch the slot (rather than possibly using a value 
 		// cached in a register).
		internal bool IsValid()
		{
			return m_helper.Get(ref m_slot) != -1; 
 		}
 
		// Release the slot reserved by this object when this object goes away. 
 		// There is  a race condition that can happen in the face of
 		// resurrection where another thread is fetching values or assigning 
		// while the finalizer thread is here.  We are counting on the fact
 		// that code that fetches values calls IsValid after fetching a value
		// and before giving it to anyone.  See LocalDataStore for the other
		// half of this.  We are also counting on code that sets values locks 
		// the manager.
        ~LocalDataStoreSlot() 
 		{ 
			int slot = m_slot;
 
 			// This lock fixes synchronization with the assignment of values.
            bool tookLock = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                Monitor.ReliableEnter(m_mgr, ref tookLock);
 				// Mark the slot as free. 
				m_slot = -1; 

 				m_mgr.FreeDataSlot(slot); 
			}
            finally {
                if (tookLock)
                    Monitor.Exit(m_mgr); 
            }
		} 
	} 

 	// This class will not be marked serializable 
    internal class LocalDataStoreMgr
    {
    	private const byte DataSlotOccupied				= 0x01;
 
    	private const int InitialSlotTableSize			= 64;
    	private const int SlotTableDoubleThreshold		= 512; 
    	private const int LargeSlotTableSizeIncrease	= 128; 

        /*========================================================================= 
        ** Create a data store to be managed by this manager and add it to the
		** list. The initial size of the new store matches the number of slots
 		** allocated in this manager.
        =========================================================================*/ 
    	public LocalDataStore CreateLocalDataStore()
    	{ 
        	// Create a new local data store. 
        	LocalDataStore Store = new LocalDataStore(this, m_SlotInfoTable.Length);
        		 
            bool tookLock = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                Monitor.ReliableEnter(this, ref tookLock); 
        		// Add the store to the array list and return it.
        		m_ManagedLocalDataStores.Add(Store); 
        	} 
            finally {
                if (tookLock) 
                    Monitor.Exit(this);
            }
       		return Store;
 	    } 

        /*========================================================================= 
		 * Remove the specified store from the list of managed stores.. 
        =========================================================================*/
    	public void DeleteLocalDataStore(LocalDataStore store) 
 		{
            bool tookLock = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                Monitor.ReliableEnter(this, ref tookLock);
        		// Remove the store to the array list and return it. 
        		m_ManagedLocalDataStores.Remove(store); 
        	}
            finally { 
                if (tookLock)
                    Monitor.Exit(this);
            }
		} 

        /*========================================================================= 
        ** Allocates a data slot by finding an available index and wrapping it 
		** an object to prevent clients from manipulating it directly, allowing us
		** to make assumptions its integrity. 
        =========================================================================*/
    	public LocalDataStoreSlot AllocateDataSlot()
    	{
            bool tookLock = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                Monitor.ReliableEnter(this, ref tookLock); 
        		int i;		
        		LocalDataStoreSlot slot; 

        		// Retrieve the current size of the table.
        		int SlotTableSize = m_SlotInfoTable.Length;
 
 				// Check if there are any slots left.
				if (m_FirstAvailableSlot < SlotTableSize) 
 				{ 
 					// Save the first available slot.
					slot = new LocalDataStoreSlot(this, m_FirstAvailableSlot); 
       				m_SlotInfoTable[m_FirstAvailableSlot] = DataSlotOccupied;

 					// Find the next available slot.
					for (i=m_FirstAvailableSlot+1; i < SlotTableSize; ++i) 
	        			if (0 == (m_SlotInfoTable[i] & DataSlotOccupied))
							break; 
 
 					// Save the new "first available slot".
					m_FirstAvailableSlot = i; 

 					// Return the slot index.
 					return slot;
				} 

        		// The table is full so we need to increase its size. 
        		int NewSlotTableSize; 
        		if (SlotTableSize < SlotTableDoubleThreshold)
        		{ 
        			// The table is still relatively small so double it.
        			NewSlotTableSize = SlotTableSize * 2;
        		}
        		else 
        		{
        			// The table is relatively large so simply increase its size by a given amount. 
        			NewSlotTableSize = SlotTableSize + LargeSlotTableSizeIncrease; 
        		}
 
        		// Allocate the new slot info table.
        		byte[] NewSlotInfoTable = new byte[NewSlotTableSize];

        		// Copy the old array into the new one. 
        		Array.Copy(m_SlotInfoTable, NewSlotInfoTable, SlotTableSize);
        		m_SlotInfoTable = NewSlotInfoTable; 
 
        		// SlotTableSize is the index of the first empty slot in the expanded table.
 				slot = new LocalDataStoreSlot(this, SlotTableSize); 
        		m_SlotInfoTable[SlotTableSize] = DataSlotOccupied;
				m_FirstAvailableSlot = SlotTableSize + 1;

        		// Return the selected slot 
        		return slot;			
        	} 
            finally { 
                if (tookLock)
                    Monitor.Exit(this); 
            }
	    }
    	
        /*========================================================================== 
		** Allocate a slot and associate a name with it.
        =========================================================================*/ 
    	public LocalDataStoreSlot AllocateNamedDataSlot(String name) 
    	{
            bool tookLock = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                Monitor.ReliableEnter(this, ref tookLock);
        		// Allocate a normal data slot. 
 				LocalDataStoreSlot slot = AllocateDataSlot();
 
        		// Insert the association between the name and the data slot number 
				// in the hash table.
        		m_KeyToSlotMap.Add(name, slot); 
        		return slot;
        	}
            finally {
                if (tookLock) 
                    Monitor.Exit(this);
            } 
 		} 

        /*========================================================================= 
 		** Retrieve the slot associated with a name, allocating it if no such
		** association has been defined.
        =========================================================================*/
    	public LocalDataStoreSlot GetNamedDataSlot(String name) 
    	{
            bool tookLock = false; 
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                Monitor.ReliableEnter(this, ref tookLock); 
        		// Lookup in the hashtable to try find a slot for the name.
        		LocalDataStoreSlot slot = (LocalDataStoreSlot) m_KeyToSlotMap[name];
        		
        		// If the name is not yet in the hashtable then add it. 
        		if (null == slot)
        			return AllocateNamedDataSlot(name); 
        		 
        		// The name was in the hashtable so return the associated slot.
        		return slot; 
        	}
            finally {
                if (tookLock)
                    Monitor.Exit(this); 
            }
 		} 
 
        /*==========================================================================
		** Eliminate the association of a name with a slot.  The actual slot will 
		** be reclaimed when the finalizer for the slot object runs.
        =========================================================================*/
    	public void FreeNamedDataSlot(String name)
    	{ 
            bool tookLock = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try { 
                Monitor.ReliableEnter(this, ref tookLock);
        		// Remove the name slot association from the hashtable. 
        		m_KeyToSlotMap.Remove(name);
        	}
            finally {
                if (tookLock) 
                    Monitor.Exit(this);
            } 
		} 

        /*========================================================================== 
        ** Free's a previously allocated data slot on ALL the managed data stores.
        =========================================================================*/
    	internal void FreeDataSlot(int slot)
    	{ 
            bool tookLock = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try { 
                Monitor.ReliableEnter(this, ref tookLock);
        		// Go thru all the managed stores and set the data on the specified slot to 0. 
        		for (int i=0; i < m_ManagedLocalDataStores.Count; i++)
        		{
        			((LocalDataStore)m_ManagedLocalDataStores[i]).SetDataInternal(
        			                                                  slot, 
        			                                                  null,
        			                                                  false); 
                }        			 
    			        		
        		// Mark the slot as being no longer occupied. 
        		m_SlotInfoTable[slot] = 0;
 				if (slot < m_FirstAvailableSlot)
					m_FirstAvailableSlot = slot;
        	} 
            finally {
                if (tookLock) 
                    Monitor.Exit(this); 
            }
 	    } 

        /*=========================================================================
        ** Return the number of allocated slots in this manager.
        =========================================================================*/ 
 	    public void ValidateSlot(LocalDataStoreSlot slot)
	    { 
            // Make sure the slot was allocated for this store. 
 	        if (slot==null || slot.Manager != this)
                throw new ArgumentException(Environment.GetResourceString("Argument_ALSInvalidSlot")); 
        }

        /*==========================================================================
        ** Return the number of allocated slots in this manager. 
        =========================================================================*/
	    internal int GetSlotTableLength() 
	    { 
	            return m_SlotInfoTable.Length;
        } 

    	private byte[] m_SlotInfoTable = new byte[InitialSlotTableSize];
 		private int m_FirstAvailableSlot = 0;
    	private ArrayList m_ManagedLocalDataStores = new ArrayList(); 
    	private Hashtable m_KeyToSlotMap = new Hashtable();
    } 
}
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK