_LocalDataStore.cs source code in C# .NET

Source code for the .NET framework in C#

                        

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

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