1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
|
// ==++==
//
// 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.Generic;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Diagnostics.Contracts;
// 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 LocalDataStoreMgr m_mgr;
private int m_slot;
private long m_cookie;
// Construct the object to encapsulate the slot.
internal LocalDataStoreSlot(LocalDataStoreMgr mgr, int slot, long cookie)
{
m_mgr = mgr;
m_slot = slot;
m_cookie = cookie;
}
// Accessors for the two fields of this class.
internal LocalDataStoreMgr Manager
{
get
{
return m_mgr;
}
}
internal int Slot
{
get
{
return m_slot;
}
}
internal long Cookie
{
get
{
return m_cookie;
}
}
// Release the slot reserved by this object when this object goes away.
~LocalDataStoreSlot()
{
LocalDataStoreMgr mgr = m_mgr;
if (mgr == null)
return;
int slot = m_slot;
// Mark the slot as free.
m_slot = -1;
mgr.FreeDataSlot(slot, m_cookie);
}
}
// This class will not be marked serializable
sealed internal class LocalDataStoreMgr
{
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.
=========================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
public LocalDataStoreHolder CreateLocalDataStore()
{
// Create a new local data store.
LocalDataStore store = new LocalDataStore(this, m_SlotInfoTable.Length);
LocalDataStoreHolder holder = new LocalDataStoreHolder(store);
bool tookLock = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
Monitor.Enter(this, ref tookLock);
// Add the store to the array list and return it.
m_ManagedLocalDataStores.Add(store);
}
finally
{
if (tookLock)
Monitor.Exit(this);
}
return holder;
}
/*=========================================================================
* Remove the specified store from the list of managed stores..
=========================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
public void DeleteLocalDataStore(LocalDataStore store)
{
bool tookLock = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
Monitor.Enter(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.
=========================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
public LocalDataStoreSlot AllocateDataSlot()
{
bool tookLock = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
Monitor.Enter(this, ref tookLock);
LocalDataStoreSlot slot;
int slotTableSize = m_SlotInfoTable.Length;
// In case FreeDataSlot has moved the pointer back, the next slot may not be available.
// Find the first actually available slot.
int availableSlot = m_FirstAvailableSlot;
while (availableSlot < slotTableSize)
{
if (!m_SlotInfoTable[availableSlot])
break;
availableSlot++;
}
// Check if there are any slots left.
if (availableSlot >= slotTableSize)
{
// 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.
bool[] newSlotInfoTable = new bool[newSlotTableSize];
// Copy the old array into the new one.
Array.Copy(m_SlotInfoTable, newSlotInfoTable, slotTableSize);
m_SlotInfoTable = newSlotInfoTable;
}
// availableSlot is the index of the empty slot.
m_SlotInfoTable[availableSlot] = true;
// We do not need to worry about overflowing m_CookieGenerator. It would take centuries
// of intensive slot allocations on current machines to get the 2^64 counter to overflow.
// We will perform the increment with overflow check just to play it on the safe side.
slot = new LocalDataStoreSlot(this, availableSlot, checked(m_CookieGenerator++));
// Save the new "first available slot".hint
m_FirstAvailableSlot = availableSlot + 1;
// Return the selected slot
return slot;
}
finally
{
if (tookLock)
Monitor.Exit(this);
}
}
/*=========================================================================
** Allocate a slot and associate a name with it.
=========================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
public LocalDataStoreSlot AllocateNamedDataSlot(String name)
{
bool tookLock = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
Monitor.Enter(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.
=========================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
public LocalDataStoreSlot GetNamedDataSlot(String name)
{
bool tookLock = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
Monitor.Enter(this, ref tookLock);
// Lookup in the hashtable to try find a slot for the name.
LocalDataStoreSlot slot = m_KeyToSlotMap.GetValueOrDefault(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.
=========================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
public void FreeNamedDataSlot(String name)
{
bool tookLock = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
Monitor.Enter(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.
=========================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
internal void FreeDataSlot(int slot, long cookie)
{
bool tookLock = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
Monitor.Enter(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]).FreeData(slot, cookie);
}
// Mark the slot as being no longer occupied.
m_SlotInfoTable[slot] = false;
if (slot < m_FirstAvailableSlot)
m_FirstAvailableSlot = slot;
}
finally
{
if (tookLock)
Monitor.Exit(this);
}
}
/*=========================================================================
** Check that this is a valid slot for this store
=========================================================================*/
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"));
Contract.EndContractBlock();
}
/*=========================================================================
** Return the number of allocated slots in this manager.
=========================================================================*/
internal int GetSlotTableLength()
{
return m_SlotInfoTable.Length;
}
private bool[] m_SlotInfoTable = new bool[InitialSlotTableSize];
private int m_FirstAvailableSlot;
private List<LocalDataStore> m_ManagedLocalDataStores = new List<LocalDataStore>();
private Dictionary<String, LocalDataStoreSlot> m_KeyToSlotMap = new Dictionary<String, LocalDataStoreSlot>();
private long m_CookieGenerator;
}
}
|