using System;
using System.Runtime;
using System.Collections.Generic;
using System.Threading;
namespace System.ServiceModel.Channels
{
internal class SynchronizedPool<T> where T : class
{
private struct Entry
{
public int threadID;
public T value;
}
private struct PendingEntry
{
public int returnCount;
public int threadID;
}
private static class SynchronizedPoolHelper
{
public static readonly int ProcessorCount = SynchronizedPool<T>.SynchronizedPoolHelper.GetProcessorCount();
private static int GetProcessorCount()
{
return Environment.ProcessorCount;
}
}
private class GlobalPool
{
private Stack<T> items;
private int maxCount;
public int MaxCount
{
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
get
{
return this.maxCount;
}
set
{
lock (this.ThisLock)
{
while (this.items.Count > value)
{
this.items.Pop();
}
this.maxCount = value;
}
}
}
private object ThisLock
{
get
{
return this;
}
}
public GlobalPool(int maxCount)
{
this.items = new Stack<T>();
this.maxCount = maxCount;
}
public void DecrementMaxCount()
{
lock (this.ThisLock)
{
if (this.items.Count == this.maxCount)
{
this.items.Pop();
}
this.maxCount--;
}
}
public T Take()
{
if (this.items.Count > 0)
{
lock (this.ThisLock)
{
if (this.items.Count > 0)
{
return this.items.Pop();
}
}
}
return default(T);
}
public bool Return(T value)
{
if (this.items.Count < this.MaxCount)
{
lock (this.ThisLock)
{
if (this.items.Count < this.MaxCount)
{
this.items.Push(value);
return true;
}
}
return false;
}
return false;
}
public void Clear()
{
lock (this.ThisLock)
{
this.items.Clear();
}
}
}
private SynchronizedPool<T>.Entry[] entries;
private SynchronizedPool<T>.GlobalPool globalPool;
private int maxCount;
private SynchronizedPool<T>.PendingEntry[] pending;
private int promotionFailures;
private const int maxPendingEntries = 128;
private const int maxPromotionFailures = 64;
private const int maxReturnsBeforePromotion = 64;
private const int maxThreadItemsPerProcessor = 16;
private object ThisLock
{
get
{
return this;
}
}
public SynchronizedPool(int maxCount)
{
int num = maxCount;
int num2 = 16 + SynchronizedPool<T>.SynchronizedPoolHelper.ProcessorCount;
if (num > num2)
{
num = num2;
}
this.maxCount = maxCount;
this.entries = new SynchronizedPool<T>.Entry[num];
this.pending = new SynchronizedPool<T>.PendingEntry[4];
this.globalPool = new SynchronizedPool<T>.GlobalPool(maxCount);
}
public void Clear()
{
SynchronizedPool<T>.Entry[] array = this.entries;
for (int i = 0; i < array.Length; i++)
{
array[i].value = default(T);
}
this.globalPool.Clear();
}
private void HandlePromotionFailure(int thisThreadID)
{
int num = this.promotionFailures + 1;
if (num >= 64)
{
lock (this.ThisLock)
{
this.entries = new SynchronizedPool<T>.Entry[this.entries.Length];
this.globalPool.MaxCount = this.maxCount;
}
this.PromoteThread(thisThreadID);
return;
}
this.promotionFailures = num;
}
private bool PromoteThread(int thisThreadID)
{
lock (this.ThisLock)
{
for (int i = 0; i < this.entries.Length; i++)
{
int threadID = this.entries[i].threadID;
if (threadID == thisThreadID)
{
bool result = true;
return result;
}
if (threadID == 0)
{
this.globalPool.DecrementMaxCount();
this.entries[i].threadID = thisThreadID;
bool result = true;
return result;
}
}
}
return false;
}
private void RecordReturnToGlobalPool(int thisThreadID)
{
SynchronizedPool<T>.PendingEntry[] array = this.pending;
int i = 0;
while (i < array.Length)
{
int threadID = array[i].threadID;
if (threadID == thisThreadID)
{
int num = array[i].returnCount + 1;
if (num < 64)
{
array[i].returnCount = num;
return;
}
array[i].returnCount = 0;
if (!this.PromoteThread(thisThreadID))
{
this.HandlePromotionFailure(thisThreadID);
return;
}
break;
}
else
{
if (threadID == 0)
{
return;
}
i++;
}
}
}
private void RecordTakeFromGlobalPool(int thisThreadID)
{
SynchronizedPool<T>.PendingEntry[] array = this.pending;
for (int i = 0; i < array.Length; i++)
{
int threadID = array[i].threadID;
if (threadID == thisThreadID)
{
return;
}
if (threadID == 0)
{
lock (array)
{
if (array[i].threadID == 0)
{
array[i].threadID = thisThreadID;
return;
}
}
}
}
if (array.Length >= 128)
{
this.pending = new SynchronizedPool<T>.PendingEntry[array.Length];
return;
}
SynchronizedPool<T>.PendingEntry[] destinationArray = new SynchronizedPool<T>.PendingEntry[array.Length * 2];
Array.Copy(array, destinationArray, array.Length);
this.pending = destinationArray;
}
public bool Return(T value)
{
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
return managedThreadId != 0 && (this.ReturnToPerThreadPool(managedThreadId, value) || this.ReturnToGlobalPool(managedThreadId, value));
}
private bool ReturnToPerThreadPool(int thisThreadID, T value)
{
SynchronizedPool<T>.Entry[] array = this.entries;
int i = 0;
while (i < array.Length)
{
int threadID = array[i].threadID;
if (threadID == thisThreadID)
{
if (array[i].value == null)
{
array[i].value = value;
return true;
}
return false;
}
else
{
if (threadID == 0)
{
break;
}
i++;
}
}
return false;
}
private bool ReturnToGlobalPool(int thisThreadID, T value)
{
this.RecordReturnToGlobalPool(thisThreadID);
return this.globalPool.Return(value);
}
public T Take()
{
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
if (managedThreadId == 0)
{
return default(T);
}
T t = this.TakeFromPerThreadPool(managedThreadId);
if (t != null)
{
return t;
}
return this.TakeFromGlobalPool(managedThreadId);
}
private T TakeFromPerThreadPool(int thisThreadID)
{
SynchronizedPool<T>.Entry[] array = this.entries;
int i = 0;
while (i < array.Length)
{
int threadID = array[i].threadID;
if (threadID == thisThreadID)
{
T value = array[i].value;
if (value != null)
{
array[i].value = default(T);
return value;
}
return default(T);
}
else
{
if (threadID == 0)
{
break;
}
i++;
}
}
return default(T);
}
private T TakeFromGlobalPool(int thisThreadID)
{
this.RecordTakeFromGlobalPool(thisThreadID);
return this.globalPool.Take();
}
}
internal abstract class InternalBufferManager
{
private class PooledBufferManager : InternalBufferManager
{
private abstract class BufferPool
{
private class SynchronizedBufferPool : InternalBufferManager.PooledBufferManager.BufferPool
{
private SynchronizedPool<byte[]> innerPool;
internal SynchronizedBufferPool(int bufferSize, int limit) : base(bufferSize, limit)
{
this.innerPool = new SynchronizedPool<byte[]>(limit);
}
internal override void OnClear()
{
this.innerPool.Clear();
}
internal override byte[] Take()
{
return this.innerPool.Take();
}
internal override bool Return(byte[] buffer)
{
return this.innerPool.Return(buffer);
}
}
private class LargeBufferPool : InternalBufferManager.PooledBufferManager.BufferPool
{
private Stack<byte[]> items;
private object ThisLock
{
get
{
return this.items;
}
}
internal LargeBufferPool(int bufferSize, int limit) : base(bufferSize, limit)
{
this.items = new Stack<byte[]>(limit);
}
internal override void OnClear()
{
lock (this.ThisLock)
{
this.items.Clear();
}
}
internal override byte[] Take()
{
lock (this.ThisLock)
{
if (this.items.Count > 0)
{
return this.items.Pop();
}
}
return null;
}
internal override bool Return(byte[] buffer)
{
lock (this.ThisLock)
{
if (this.items.Count < base.Limit)
{
this.items.Push(buffer);
return true;
}
}
return false;
}
}
private int bufferSize;
private int count;
private int limit;
private int misses;
private int peak;
public int BufferSize
{
get
{
return this.bufferSize;
}
}
public int Limit
{
get
{
return this.limit;
}
}
public int Misses
{
get
{
return this.misses;
}
set
{
this.misses = value;
}
}
public int Peak
{
get
{
return this.peak;
}
}
public BufferPool(int bufferSize, int limit)
{
this.bufferSize = bufferSize;
this.limit = limit;
}
public void Clear()
{
this.OnClear();
this.count = 0;
}
public void DecrementCount()
{
int num = this.count - 1;
if (num >= 0)
{
this.count = num;
}
}
public void IncrementCount()
{
int num = this.count + 1;
if (num <= this.limit)
{
this.count = num;
if (num > this.peak)
{
this.peak = num;
}
}
}
internal abstract byte[] Take();
internal abstract bool Return(byte[] buffer);
internal abstract void OnClear();
internal static InternalBufferManager.PooledBufferManager.BufferPool CreatePool(int bufferSize, int limit)
{
if (bufferSize < 85000)
{
return new InternalBufferManager.PooledBufferManager.BufferPool.SynchronizedBufferPool(bufferSize, limit);
}
return new InternalBufferManager.PooledBufferManager.BufferPool.LargeBufferPool(bufferSize, limit);
}
}
private const int minBufferSize = 128;
private const int maxMissesBeforeTuning = 8;
private const int initialBufferCount = 1;
private readonly object tuningLock;
private int[] bufferSizes;
private InternalBufferManager.PooledBufferManager.BufferPool[] bufferPools;
private long memoryLimit;
private long remainingMemory;
private bool areQuotasBeingTuned;
private int totalMisses;
public PooledBufferManager(long maxMemoryToPool, int maxBufferSize)
{
this.tuningLock = new object();
this.memoryLimit = maxMemoryToPool;
Lines 1–500 of 867. Load more
using System; using System.Runtime; using System.Collections.Generic; using System.Threading; namespace System.ServiceModel.Channels { internal class SynchronizedPool<T> where T : class { private struct Entry { public int threadID; public T value; } private struct PendingEntry { public int returnCount; public int threadID; } private static class SynchronizedPoolHelper { public static readonly int ProcessorCount = SynchronizedPool<T>.SynchronizedPoolHelper.GetProcessorCount(); private static int GetProcessorCount() { return Environment.ProcessorCount; } } private class GlobalPool { private Stack<T> items; private int maxCount; public int MaxCount { [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get { return this.maxCount; } set { lock (this.ThisLock) { while (this.items.Count > value) { this.items.Pop(); } this.maxCount = value; } } } private object ThisLock { get { return this; } } public GlobalPool(int maxCount) { this.items = new Stack<T>(); this.maxCount = maxCount; } public void DecrementMaxCount() { lock (this.ThisLock) { if (this.items.Count == this.maxCount) { this.items.Pop(); } this.maxCount--; } } public T Take() { if (this.items.Count > 0) { lock (this.ThisLock) { if (this.items.Count > 0) { return this.items.Pop(); } } } return default(T); } public bool Return(T value) { if (this.items.Count < this.MaxCount) { lock (this.ThisLock) { if (this.items.Count < this.MaxCount) { this.items.Push(value); return true; } } return false; } return false; } public void Clear() { lock (this.ThisLock) { this.items.Clear(); } } } private SynchronizedPool<T>.Entry[] entries; private SynchronizedPool<T>.GlobalPool globalPool; private int maxCount; private SynchronizedPool<T>.PendingEntry[] pending; private int promotionFailures; private const int maxPendingEntries = 128; private const int maxPromotionFailures = 64; private const int maxReturnsBeforePromotion = 64; private const int maxThreadItemsPerProcessor = 16; private object ThisLock { get { return this; } } public SynchronizedPool(int maxCount) { int num = maxCount; int num2 = 16 + SynchronizedPool<T>.SynchronizedPoolHelper.ProcessorCount; if (num > num2) { num = num2; } this.maxCount = maxCount; this.entries = new SynchronizedPool<T>.Entry[num]; this.pending = new SynchronizedPool<T>.PendingEntry[4]; this.globalPool = new SynchronizedPool<T>.GlobalPool(maxCount); } public void Clear() { SynchronizedPool<T>.Entry[] array = this.entries; for (int i = 0; i < array.Length; i++) { array[i].value = default(T); } this.globalPool.Clear(); } private void HandlePromotionFailure(int thisThreadID) { int num = this.promotionFailures + 1; if (num >= 64) { lock (this.ThisLock) { this.entries = new SynchronizedPool<T>.Entry[this.entries.Length]; this.globalPool.MaxCount = this.maxCount; } this.PromoteThread(thisThreadID); return; } this.promotionFailures = num; } private bool PromoteThread(int thisThreadID) { lock (this.ThisLock) { for (int i = 0; i < this.entries.Length; i++) { int threadID = this.entries[i].threadID; if (threadID == thisThreadID) { bool result = true; return result; } if (threadID == 0) { this.globalPool.DecrementMaxCount(); this.entries[i].threadID = thisThreadID; bool result = true; return result; } } } return false; } private void RecordReturnToGlobalPool(int thisThreadID) { SynchronizedPool<T>.PendingEntry[] array = this.pending; int i = 0; while (i < array.Length) { int threadID = array[i].threadID; if (threadID == thisThreadID) { int num = array[i].returnCount + 1; if (num < 64) { array[i].returnCount = num; return; } array[i].returnCount = 0; if (!this.PromoteThread(thisThreadID)) { this.HandlePromotionFailure(thisThreadID); return; } break; } else { if (threadID == 0) { return; } i++; } } } private void RecordTakeFromGlobalPool(int thisThreadID) { SynchronizedPool<T>.PendingEntry[] array = this.pending; for (int i = 0; i < array.Length; i++) { int threadID = array[i].threadID; if (threadID == thisThreadID) { return; } if (threadID == 0) { lock (array) { if (array[i].threadID == 0) { array[i].threadID = thisThreadID; return; } } } } if (array.Length >= 128) { this.pending = new SynchronizedPool<T>.PendingEntry[array.Length]; return; } SynchronizedPool<T>.PendingEntry[] destinationArray = new SynchronizedPool<T>.PendingEntry[array.Length * 2]; Array.Copy(array, destinationArray, array.Length); this.pending = destinationArray; } public bool Return(T value) { int managedThreadId = Thread.CurrentThread.ManagedThreadId; return managedThreadId != 0 && (this.ReturnToPerThreadPool(managedThreadId, value) || this.ReturnToGlobalPool(managedThreadId, value)); } private bool ReturnToPerThreadPool(int thisThreadID, T value) { SynchronizedPool<T>.Entry[] array = this.entries; int i = 0; while (i < array.Length) { int threadID = array[i].threadID; if (threadID == thisThreadID) { if (array[i].value == null) { array[i].value = value; return true; } return false; } else { if (threadID == 0) { break; } i++; } } return false; } private bool ReturnToGlobalPool(int thisThreadID, T value) { this.RecordReturnToGlobalPool(thisThreadID); return this.globalPool.Return(value); } public T Take() { int managedThreadId = Thread.CurrentThread.ManagedThreadId; if (managedThreadId == 0) { return default(T); } T t = this.TakeFromPerThreadPool(managedThreadId); if (t != null) { return t; } return this.TakeFromGlobalPool(managedThreadId); } private T TakeFromPerThreadPool(int thisThreadID) { SynchronizedPool<T>.Entry[] array = this.entries; int i = 0; while (i < array.Length) { int threadID = array[i].threadID; if (threadID == thisThreadID) { T value = array[i].value; if (value != null) { array[i].value = default(T); return value; } return default(T); } else { if (threadID == 0) { break; } i++; } } return default(T); } private T TakeFromGlobalPool(int thisThreadID) { this.RecordTakeFromGlobalPool(thisThreadID); return this.globalPool.Take(); } } internal abstract class InternalBufferManager { private class PooledBufferManager : InternalBufferManager { private abstract class BufferPool { private class SynchronizedBufferPool : InternalBufferManager.PooledBufferManager.BufferPool { private SynchronizedPool<byte[]> innerPool; internal SynchronizedBufferPool(int bufferSize, int limit) : base(bufferSize, limit) { this.innerPool = new SynchronizedPool<byte[]>(limit); } internal override void OnClear() { this.innerPool.Clear(); } internal override byte[] Take() { return this.innerPool.Take(); } internal override bool Return(byte[] buffer) { return this.innerPool.Return(buffer); } } private class LargeBufferPool : InternalBufferManager.PooledBufferManager.BufferPool { private Stack<byte[]> items; private object ThisLock { get { return this.items; } } internal LargeBufferPool(int bufferSize, int limit) : base(bufferSize, limit) { this.items = new Stack<byte[]>(limit); } internal override void OnClear() { lock (this.ThisLock) { this.items.Clear(); } } internal override byte[] Take() { lock (this.ThisLock) { if (this.items.Count > 0) { return this.items.Pop(); } } return null; } internal override bool Return(byte[] buffer) { lock (this.ThisLock) { if (this.items.Count < base.Limit) { this.items.Push(buffer); return true; } } return false; } } private int bufferSize; private int count; private int limit; private int misses; private int peak; public int BufferSize { get { return this.bufferSize; } } public int Limit { get { return this.limit; } } public int Misses { get { return this.misses; } set { this.misses = value; } } public int Peak { get { return this.peak; } } public BufferPool(int bufferSize, int limit) { this.bufferSize = bufferSize; this.limit = limit; } public void Clear() { this.OnClear(); this.count = 0; } public void DecrementCount() { int num = this.count - 1; if (num >= 0) { this.count = num; } } public void IncrementCount() { int num = this.count + 1; if (num <= this.limit) { this.count = num; if (num > this.peak) { this.peak = num; } } } internal abstract byte[] Take(); internal abstract bool Return(byte[] buffer); internal abstract void OnClear(); internal static InternalBufferManager.PooledBufferManager.BufferPool CreatePool(int bufferSize, int limit) { if (bufferSize < 85000) { return new InternalBufferManager.PooledBufferManager.BufferPool.SynchronizedBufferPool(bufferSize, limit); } return new InternalBufferManager.PooledBufferManager.BufferPool.LargeBufferPool(bufferSize, limit); } } private const int minBufferSize = 128; private const int maxMissesBeforeTuning = 8; private const int initialBufferCount = 1; private readonly object tuningLock; private int[] bufferSizes; private InternalBufferManager.PooledBufferManager.BufferPool[] bufferPools; private long memoryLimit; private long remainingMemory; private bool areQuotasBeingTuned; private int totalMisses; public PooledBufferManager(long maxMemoryToPool, int maxBufferSize) { this.tuningLock = new object(); this.memoryLimit = maxMemoryToPool;