You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
425
mcs/class/referencesource/System.Web/BufferAllocator.cs
Normal file
425
mcs/class/referencesource/System.Web/BufferAllocator.cs
Normal file
@@ -0,0 +1,425 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="BufferAllocator.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Buffer Allocators with recycling
|
||||
*
|
||||
* Copyright (c) 1999 Microsoft Corporation
|
||||
*/
|
||||
namespace System.Web {
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Globalization;
|
||||
|
||||
using System.Web.Util;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// 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 : IBufferAllocator {
|
||||
private int _maxFree;
|
||||
private int _numFree;
|
||||
private Stack _buffers;
|
||||
|
||||
private static int s_ProcsFudgeFactor;
|
||||
|
||||
static BufferAllocator() {
|
||||
s_ProcsFudgeFactor = SystemInfo.GetNumProcessCPUs();
|
||||
if (s_ProcsFudgeFactor < 1)
|
||||
s_ProcsFudgeFactor = 1;
|
||||
|
||||
if (s_ProcsFudgeFactor > 4)
|
||||
s_ProcsFudgeFactor = 4;
|
||||
}
|
||||
|
||||
|
||||
internal BufferAllocator(int maxFree) {
|
||||
_buffers = new Stack();
|
||||
_numFree = 0;
|
||||
_maxFree = maxFree * s_ProcsFudgeFactor;
|
||||
}
|
||||
|
||||
public void ReleaseAllBuffers() {
|
||||
if (_numFree > 0) {
|
||||
lock (this) {
|
||||
_buffers.Clear();
|
||||
_numFree = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public object GetBuffer() {
|
||||
Object buffer = null;
|
||||
|
||||
if (_numFree > 0) {
|
||||
lock(this) {
|
||||
if (_numFree > 0) {
|
||||
buffer = _buffers.Pop();
|
||||
_numFree--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer == null)
|
||||
buffer = AllocBuffer();
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void ReuseBuffer(object buffer) {
|
||||
if (_numFree < _maxFree) {
|
||||
lock(this) {
|
||||
if (_numFree < _maxFree) {
|
||||
_buffers.Push(buffer);
|
||||
_numFree++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To be implemented by a derived class
|
||||
*/
|
||||
abstract protected Object AllocBuffer();
|
||||
abstract public int BufferSize { get; }
|
||||
}
|
||||
|
||||
/*
|
||||
* Concrete allocator class for ubyte[] buffer recycling
|
||||
*/
|
||||
internal class UbyteBufferAllocator : BufferAllocator {
|
||||
private int _bufferSize;
|
||||
|
||||
internal UbyteBufferAllocator(int bufferSize, int maxFree) : base(maxFree) {
|
||||
_bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
protected override Object AllocBuffer() {
|
||||
return new byte[_bufferSize];
|
||||
}
|
||||
|
||||
public override int BufferSize {
|
||||
get {
|
||||
return _bufferSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Concrete allocator class for char[] buffer recycling
|
||||
*/
|
||||
internal class CharBufferAllocator : BufferAllocator {
|
||||
private int _bufferSize;
|
||||
|
||||
internal CharBufferAllocator(int bufferSize, int maxFree)
|
||||
|
||||
: base(maxFree) {
|
||||
_bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
protected override Object AllocBuffer() {
|
||||
return new char[_bufferSize];
|
||||
}
|
||||
|
||||
public override int BufferSize {
|
||||
get {
|
||||
return _bufferSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Concrete allocator class for int[] buffer recycling
|
||||
*/
|
||||
internal class IntegerArrayAllocator : BufferAllocator {
|
||||
private int _arraySize;
|
||||
|
||||
internal IntegerArrayAllocator(int arraySize, int maxFree)
|
||||
|
||||
: base(maxFree) {
|
||||
_arraySize = arraySize;
|
||||
}
|
||||
|
||||
protected override Object AllocBuffer() {
|
||||
return new int[_arraySize];
|
||||
}
|
||||
|
||||
public override int BufferSize {
|
||||
get {
|
||||
return _arraySize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Concrete allocator class for IntPtr[] buffer recycling
|
||||
*/
|
||||
internal class IntPtrArrayAllocator : BufferAllocator {
|
||||
private int _arraySize;
|
||||
|
||||
internal IntPtrArrayAllocator(int arraySize, int maxFree)
|
||||
|
||||
: base(maxFree) {
|
||||
_arraySize = arraySize;
|
||||
}
|
||||
|
||||
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