Imported Upstream version 4.3.2.467

Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
Xamarin Public Jenkins
2016-02-22 11:00:01 -05:00
parent f302175246
commit f3e3aab35a
4097 changed files with 122406 additions and 82300 deletions

View File

@@ -12,6 +12,7 @@
namespace System.Web {
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Globalization;
@@ -20,10 +21,31 @@ namespace System.Web {
//////////////////////////////////////////////////////////////////////////////
// Generic buffer recycling
internal interface IBufferAllocator {
object GetBuffer();
void ReuseBuffer(object buffer);
void ReleaseAllBuffers();
int BufferSize { get; }
}
internal interface IBufferAllocator<T> : IBufferAllocator {
new T[] GetBuffer();
T[] GetBuffer(int minSize);
void ReuseBuffer(T[] buffer);
}
internal interface IAllocatorProvider {
IBufferAllocator<char> CharBufferAllocator { get; }
IBufferAllocator<int> IntBufferAllocator { get; }
IBufferAllocator<IntPtr> IntPtrBufferAllocator { get; }
void TrimMemory();
}
/*
* Base class for allocator doing buffer recycling
*/
internal abstract class BufferAllocator {
internal abstract class BufferAllocator : IBufferAllocator {
private int _maxFree;
private int _numFree;
private Stack _buffers;
@@ -46,7 +68,7 @@ namespace System.Web {
_maxFree = maxFree * s_ProcsFudgeFactor;
}
internal void ReleaseAllBuffers() {
public void ReleaseAllBuffers() {
if (_numFree > 0) {
lock (this) {
_buffers.Clear();
@@ -55,7 +77,7 @@ namespace System.Web {
}
}
internal /*public*/ Object GetBuffer() {
public object GetBuffer() {
Object buffer = null;
if (_numFree > 0) {
@@ -73,7 +95,7 @@ namespace System.Web {
return buffer;
}
internal void ReuseBuffer(Object buffer) {
public void ReuseBuffer(object buffer) {
if (_numFree < _maxFree) {
lock(this) {
if (_numFree < _maxFree) {
@@ -88,6 +110,7 @@ namespace System.Web {
* To be implemented by a derived class
*/
abstract protected Object AllocBuffer();
abstract public int BufferSize { get; }
}
/*
@@ -103,6 +126,12 @@ namespace System.Web {
protected override Object AllocBuffer() {
return new byte[_bufferSize];
}
public override int BufferSize {
get {
return _bufferSize;
}
}
}
/*
@@ -120,6 +149,12 @@ namespace System.Web {
protected override Object AllocBuffer() {
return new char[_bufferSize];
}
public override int BufferSize {
get {
return _bufferSize;
}
}
}
/*
@@ -137,6 +172,12 @@ namespace System.Web {
protected override Object AllocBuffer() {
return new int[_arraySize];
}
public override int BufferSize {
get {
return _arraySize;
}
}
}
/*
@@ -154,6 +195,231 @@ namespace System.Web {
protected override Object AllocBuffer() {
return new IntPtr[_arraySize];
}
public override int BufferSize {
get {
return _arraySize;
}
}
}
/*
* Simple Buffer Allocator - Reusable buffers pool
* Thread UNSAFE! Lock free. Caller must guarantee non-concurent access.
* Use as member of already pooled instances (like HttpApplication) that prohibit concurent access to avoid taking locks
*/
internal class SimpleBufferAllocator<T> : IBufferAllocator<T> {
private Stack<T[]> _buffers;
private readonly int _bufferSize;
public SimpleBufferAllocator(int bufferSize) {
if (bufferSize <= 0) {
throw new ArgumentOutOfRangeException("bufferSize");
}
_buffers = new Stack<T[]>();
_bufferSize = bufferSize;
}
public T[] GetBuffer() {
return GetBufferImpl();
}
public T[] GetBuffer(int minSize) {
if (minSize < 0) {
throw new ArgumentOutOfRangeException("minSize");
}
T[] buffer = null;
if (minSize <= BufferSize) {
// Get from the pool
buffer = GetBufferImpl();
}
else {
// Allocate a new buffer. It will not be reused later
buffer = AllocBuffer(minSize);
}
return buffer;
}
object IBufferAllocator.GetBuffer() {
return GetBufferImpl();
}
public void ReuseBuffer(T[] buffer) {
ReuseBufferImpl(buffer);
}
void IBufferAllocator.ReuseBuffer(object buffer) {
ReuseBufferImpl((T[]) buffer);
}
public void ReleaseAllBuffers() {
_buffers.Clear();
}
public int BufferSize {
get {
return _bufferSize;
}
}
private T[] GetBufferImpl() {
T[] buffer = null;
if (_buffers.Count > 0) {
// Get an exisitng buffer
buffer = _buffers.Pop();
}
else {
// Create a new buffer
buffer = AllocBuffer(BufferSize);
}
return buffer;
}
private void ReuseBufferImpl(T[] buffer) {
// Accept back only buffers that match the orirignal buffer size
if (buffer != null && buffer.Length == BufferSize) {
_buffers.Push(buffer);
}
}
private static T[] AllocBuffer(int size) {
return new T[size];
}
}
/*
* Adapter to convert IBufferAllocator to generic IBufferAllocator<>
*/
class BufferAllocatorWrapper<T> : IBufferAllocator<T> {
private IBufferAllocator _allocator;
public BufferAllocatorWrapper(IBufferAllocator allocator) {
Debug.Assert(allocator != null);
_allocator = allocator;
}
public T[] GetBuffer() {
return (T[])_allocator.GetBuffer();
}
public T[] GetBuffer(int minSize) {
if (minSize < 0) {
throw new ArgumentOutOfRangeException("minSize");
}
T[] buffer = null;
if (minSize <= BufferSize) {
// Get from the allocator
buffer = (T[])_allocator.GetBuffer();
}
else {
// Allocate a new buffer. It will not be reused later
buffer = new T[minSize];
}
return buffer;
}
public void ReuseBuffer(T[] buffer) {
// Accept back only buffers that match the orirignal buffer size
if (buffer != null && buffer.Length == BufferSize) {
_allocator.ReuseBuffer(buffer);
}
}
object IBufferAllocator.GetBuffer() {
return _allocator.GetBuffer();
}
void IBufferAllocator.ReuseBuffer(object buffer) {
ReuseBuffer((T[])buffer);
}
public void ReleaseAllBuffers() {
_allocator.ReleaseAllBuffers();
}
public int BufferSize {
get {
return _allocator.BufferSize;
}
}
}
/*
* Provider for different buffer allocators
*/
internal class AllocatorProvider : IAllocatorProvider {
private IBufferAllocator<char> _charAllocator = null;
private IBufferAllocator<int> _intAllocator = null;
private IBufferAllocator<IntPtr> _intPtrAllocator = null;
public IBufferAllocator<char> CharBufferAllocator {
get {
return _charAllocator;
}
set {
if (value == null) {
throw new ArgumentNullException("value");
}
_charAllocator = value;
}
}
public IBufferAllocator<int> IntBufferAllocator {
get {
return _intAllocator;
}
set {
if (value == null) {
throw new ArgumentNullException("value");
}
_intAllocator = value;
}
}
public IBufferAllocator<IntPtr> IntPtrBufferAllocator {
get {
return _intPtrAllocator;
}
set {
if (value == null) {
throw new ArgumentNullException("value");
}
_intPtrAllocator = value;
}
}
public void TrimMemory() {
if (_charAllocator != null) {
_charAllocator.ReleaseAllBuffers();
}
if (_intAllocator != null) {
_intAllocator.ReleaseAllBuffers();
}
if (_intPtrAllocator != null) {
_intPtrAllocator.ReleaseAllBuffers();
}
}
}
}