You've already forked linux-packaging-mono
Imported Upstream version 4.3.2.467
Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user