The Labs \ Source Viewer \ SSCLI \ System \ LocalDataStore

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*=============================================================================
  16. **
  17. ** Class: LocalDataStore
  18. **
  19. **
  20. ** Purpose: Class that stores local data. This class is used in cooperation
  21. **          with the _LocalDataStoreMgr class.
  22. **
  23. **
  24. =============================================================================*/
  25. namespace System
  26. {
  27.    
  28.     using System;
  29.     using System.Threading;
  30.     using System.Runtime.CompilerServices;
  31.    
  32.     // This class will not be marked serializable
  33.     internal class LocalDataStore
  34.     {
  35. /*=========================================================================
  36.         ** DON'T CHANGE THESE UNLESS YOU MODIFY LocalDataStoreBaseObject in vm\object.h
  37.         =========================================================================*/       
  38.         private object[] m_DataTable;
  39.         private LocalDataStoreMgr m_Manager;
  40.         #pragma warning disable 414 // Field is not used from managed.
  41.         private int DONT_USE_InternalStore = 0;
  42.         // pointer
  43.         #pragma warning restore 414
  44. /*=========================================================================
  45.         ** Initialize the data store.
  46.         =========================================================================*/       
  47.         public LocalDataStore(LocalDataStoreMgr mgr, int InitialCapacity)
  48.         {
  49.             if (null == mgr)
  50.                 throw new ArgumentNullException("mgr");
  51.            
  52.             // Store the manager of the local data store.
  53.             m_Manager = mgr;
  54.            
  55.             // Allocate the array that will contain the data.
  56.             m_DataTable = new object[InitialCapacity];
  57.         }
  58.        
  59. /*=========================================================================
  60.         ** Retrieves the value from the specified slot.
  61.         =========================================================================*/       
  62.         public object GetData(LocalDataStoreSlot slot)
  63.         {
  64.             object o = null;
  65.            
  66.             // Validate the slot.
  67.             m_Manager.ValidateSlot(slot);
  68.            
  69.             // Cache the slot index to avoid synchronization issues.
  70.             int slotIdx = slot.Slot;
  71.            
  72.             if (slotIdx >= 0) {
  73.                 // Delay expansion of m_DataTable if we can
  74.                 if (slotIdx >= m_DataTable.Length)
  75.                     return null;
  76.                
  77.                 // Retrieve the data from the given slot.
  78.                 o = m_DataTable[slotIdx];
  79.             }
  80.            
  81.             // Check if the slot has become invalid.
  82.             if (!slot.IsValid())
  83.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SlotHasBeenFreed"));
  84.             return o;
  85.         }
  86.        
  87. /*=========================================================================
  88.         ** Sets the data in the specified slot.
  89.         =========================================================================*/       
  90.         public void SetData(LocalDataStoreSlot slot, object data)
  91.         {
  92.             // Validate the slot.
  93.             m_Manager.ValidateSlot(slot);
  94.            
  95.             // I can't think of a way to avoid the race described in the
  96.             // LocalDataStoreSlot finalizer method without a lock.
  97.             bool tookLock = false;
  98.             RuntimeHelpers.PrepareConstrainedRegions();
  99.             try {
  100.                 Monitor.ReliableEnter(m_Manager, ref tookLock);
  101.                 if (!slot.IsValid())
  102.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SlotHasBeenFreed"));
  103.                
  104.                 // Do the actual set operation.
  105.                     /*bAlloc*/                SetDataInternal(slot.Slot, data, true);
  106.             }
  107.             finally {
  108.                 if (tookLock)
  109.                     Monitor.Exit(m_Manager);
  110.             }
  111.            
  112.         }
  113.        
  114. /*=========================================================================
  115.         ** This method does the actual work of setting the data.
  116.         =========================================================================*/       
  117.         internal void SetDataInternal(int slot, object data, bool bAlloc)
  118.         {
  119.             // We try to delay allocate the dataTable (in cases like the manager clearing a
  120.             // just-freed slot in all stores
  121.             if (slot >= m_DataTable.Length) {
  122.                 if (!bAlloc)
  123.                     return;
  124.                 SetCapacity(m_Manager.GetSlotTableLength());
  125.             }
  126.            
  127.             // Set the data on the given slot.
  128.             m_DataTable[slot] = data;
  129.         }
  130.        
  131. /*=========================================================================
  132. ** Method used to set the capacity of the local data store.
  133. =========================================================================*/       
  134.         private void SetCapacity(int capacity)
  135.         {
  136.             // Validate that the specified capacity is larger than the current one.
  137.             if (capacity < m_DataTable.Length)
  138.                 throw new ArgumentException(Environment.GetResourceString("Argument_ALSInvalidCapacity"));
  139.            
  140.             // Allocate the new data table.
  141.             object[] NewDataTable = new object[capacity];
  142.            
  143.             // Copy all the objects into the new table.
  144.             Array.Copy(m_DataTable, NewDataTable, m_DataTable.Length);
  145.            
  146.             // Save the new table.
  147.             m_DataTable = NewDataTable;
  148.         }
  149.     }
  150. }

Developer Fusion