867 lines · 31.3 KB · C#
RawDownload
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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t