using System;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using FxResources.System.Buffers;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyTitle("System.Buffers")]
[assembly: AssemblyDescription("System.Buffers")]
[assembly: AssemblyDefaultAlias("System.Buffers")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyProduct("Microsoft® .NET Framework")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyFileVersion("4.6.28619.01")]
[assembly: AssemblyInformationalVersion("4.6.28619.01 @BuiltBy: dlab14-DDVSOWINAGE069 @Branch: release/2.1 @SrcCode: https://github.com/dotnet/corefx/tree/7601f4f6225089ffb291dc7d58293c7bbf5c5d4f")]
[assembly: CLSCompliant(true)]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("4.0.3.0")]
[module: UnverifiableCode]
namespace FxResources.System.Buffers
{
internal static class SR
{
}
}
namespace System
{
internal static class SR
{
private static ResourceManager s_resourceManager;
private static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(ResourceType));
internal static Type ResourceType { get; } = typeof(SR);
internal static string ArgumentException_BufferNotFromPool => GetResourceString("ArgumentException_BufferNotFromPool", null);
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool UsingResourceKeys()
{
return false;
}
internal static string GetResourceString(string resourceKey, string defaultString)
{
string text = null;
try
{
text = ResourceManager.GetString(resourceKey);
}
catch (MissingManifestResourceException)
{
}
if (defaultString != null && resourceKey.Equals(text, StringComparison.Ordinal))
{
return defaultString;
}
return text;
}
internal static string Format(string resourceFormat, params object[] args)
{
if (args != null)
{
if (UsingResourceKeys())
{
return resourceFormat + string.Join(", ", args);
}
return string.Format(resourceFormat, args);
}
return resourceFormat;
}
internal static string Format(string resourceFormat, object p1)
{
if (UsingResourceKeys())
{
return string.Join(", ", resourceFormat, p1);
}
return string.Format(resourceFormat, p1);
}
internal static string Format(string resourceFormat, object p1, object p2)
{
if (UsingResourceKeys())
{
return string.Join(", ", resourceFormat, p1, p2);
}
return string.Format(resourceFormat, p1, p2);
}
internal static string Format(string resourceFormat, object p1, object p2, object p3)
{
if (UsingResourceKeys())
{
return string.Join(", ", resourceFormat, p1, p2, p3);
}
return string.Format(resourceFormat, p1, p2, p3);
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.All)]
internal class __BlockReflectionAttribute : Attribute
{
}
}
namespace System.Buffers
{
public abstract class ArrayPool<T>
{
private static ArrayPool<T> s_sharedInstance;
public static ArrayPool<T> Shared
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return Volatile.Read(ref s_sharedInstance) ?? EnsureSharedCreated();
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static ArrayPool<T> EnsureSharedCreated()
{
Interlocked.CompareExchange(ref s_sharedInstance, Create(), null);
return s_sharedInstance;
}
public static ArrayPool<T> Create()
{
return new DefaultArrayPool<T>();
}
public static ArrayPool<T> Create(int maxArrayLength, int maxArraysPerBucket)
{
return new DefaultArrayPool<T>(maxArrayLength, maxArraysPerBucket);
}
public abstract T[] Rent(int minimumLength);
public abstract void Return(T[] array, bool clearArray = false);
}
[EventSource(Name = "System.Buffers.ArrayPoolEventSource")]
internal sealed class ArrayPoolEventSource : EventSource
{
internal enum BufferAllocatedReason
{
Pooled,
OverMaximumSize,
PoolExhausted
}
internal static readonly System.Buffers.ArrayPoolEventSource Log = new System.Buffers.ArrayPoolEventSource();
[Event(1, Level = EventLevel.Verbose)]
internal unsafe void BufferRented(int bufferId, int bufferSize, int poolId, int bucketId)
{
EventData* ptr = stackalloc EventData[4];
*ptr = new EventData
{
Size = 4,
DataPointer = (IntPtr)(&bufferId)
};
ptr[1] = new EventData
{
Size = 4,
DataPointer = (IntPtr)(&bufferSize)
};
ptr[2] = new EventData
{
Size = 4,
DataPointer = (IntPtr)(&poolId)
};
ptr[3] = new EventData
{
Size = 4,
DataPointer = (IntPtr)(&bucketId)
};
WriteEventCore(1, 4, ptr);
}
[Event(2, Level = EventLevel.Informational)]
internal unsafe void BufferAllocated(int bufferId, int bufferSize, int poolId, int bucketId, BufferAllocatedReason reason)
{
EventData* ptr = stackalloc EventData[5];
*ptr = new EventData
{
Size = 4,
DataPointer = (IntPtr)(&bufferId)
};
ptr[1] = new EventData
{
Size = 4,
DataPointer = (IntPtr)(&bufferSize)
};
ptr[2] = new EventData
{
Size = 4,
DataPointer = (IntPtr)(&poolId)
};
ptr[3] = new EventData
{
Size = 4,
DataPointer = (IntPtr)(&bucketId)
};
ptr[4] = new EventData
{
Size = 4,
DataPointer = (IntPtr)(&reason)
};
WriteEventCore(2, 5, ptr);
}
[Event(3, Level = EventLevel.Verbose)]
internal void BufferReturned(int bufferId, int bufferSize, int poolId)
{
WriteEvent(3, bufferId, bufferSize, poolId);
}
}
internal sealed class DefaultArrayPool<T> : ArrayPool<T>
{
private sealed class Bucket
{
internal readonly int _bufferLength;
private readonly T[][] _buffers;
private readonly int _poolId;
private SpinLock _lock;
private int _index;
internal int Id => GetHashCode();
internal Bucket(int bufferLength, int numberOfBuffers, int poolId)
{
_lock = new SpinLock(Debugger.IsAttached);
_buffers = new T[numberOfBuffers][];
_bufferLength = bufferLength;
_poolId = poolId;
}
internal T[] Rent()
{
T[][] buffers = _buffers;
T[] array = null;
bool lockTaken = false;
bool flag = false;
try
{
_lock.Enter(ref lockTaken);
if (_index < buffers.Length)
{
array = buffers[_index];
buffers[_index++] = null;
flag = array == null;
}
}
finally
{
if (lockTaken)
{
_lock.Exit(useMemoryBarrier: false);
}
}
if (flag)
{
array = new T[_bufferLength];
System.Buffers.ArrayPoolEventSource log = System.Buffers.ArrayPoolEventSource.Log;
if (log.IsEnabled())
{
log.BufferAllocated(array.GetHashCode(), _bufferLength, _poolId, Id, System.Buffers.ArrayPoolEventSource.BufferAllocatedReason.Pooled);
}
}
return array;
}
internal void Return(T[] array)
{
if (array.Length != _bufferLength)
{
throw new ArgumentException(System.SR.ArgumentException_BufferNotFromPool, "array");
}
bool lockTaken = false;
try
{
_lock.Enter(ref lockTaken);
if (_index != 0)
{
_buffers[--_index] = array;
}
}
finally
{
if (lockTaken)
{
_lock.Exit(useMemoryBarrier: false);
}
}
}
}
private const int DefaultMaxArrayLength = 1048576;
private const int DefaultMaxNumberOfArraysPerBucket = 50;
private static T[] s_emptyArray;
private readonly Bucket[] _buckets;
private int Id => GetHashCode();
internal DefaultArrayPool()
: this(1048576, 50)
{
}
internal DefaultArrayPool(int maxArrayLength, int maxArraysPerBucket)
{
if (maxArrayLength <= 0)
{
throw new ArgumentOutOfRangeException("maxArrayLength");
}
if (maxArraysPerBucket <= 0)
{
throw new ArgumentOutOfRangeException("maxArraysPerBucket");
}
if (maxArrayLength > 1073741824)
{
maxArrayLength = 1073741824;
}
else if (maxArrayLength < 16)
{
maxArrayLength = 16;
}
int id = Id;
int num = System.Buffers.Utilities.SelectBucketIndex(maxArrayLength);
Bucket[] array = new Bucket[num + 1];
for (int i = 0; i < array.Length; i++)
{
array[i] = new Bucket(System.Buffers.Utilities.GetMaxSizeForBucket(i), maxArraysPerBucket, id);
}
_buckets = array;
}
public override T[] Rent(int minimumLength)
{
if (minimumLength < 0)
{
throw new ArgumentOutOfRangeException("minimumLength");
}
if (minimumLength == 0)
{
return s_emptyArray ?? (s_emptyArray = new T[0]);
}
System.Buffers.ArrayPoolEventSource log = System.Buffers.ArrayPoolEventSource.Log;
T[] array = null;
int num = System.Buffers.Utilities.SelectBucketIndex(minimumLength);
if (num < _buckets.Length)
{
int num2 = num;
do
{
array = _buckets[num2].Rent();
if (array != null)
{
if (log.IsEnabled())
{
log.BufferRented(array.GetHashCode(), array.Length, Id, _buckets[num2].Id);
}
return array;
}
}
while (++num2 < _buckets.Length && num2 != num + 2);
array = new T[_buckets[num]._bufferLength];
}
else
{
array = new T[minimumLength];
}
if (log.IsEnabled())
{
int hashCode = array.GetHashCode();
int bucketId = -1;
log.BufferRented(hashCode, array.Length, Id, bucketId);
log.BufferAllocated(hashCode, array.Length, Id, bucketId, (num >= _buckets.Length) ? System.Buffers.ArrayPoolEventSource.BufferAllocatedReason.OverMaximumSize : System.Buffers.ArrayPoolEventSource.BufferAllocatedReason.PoolExhausted);
}
return array;
}
public override void Return(T[] array, bool clearArray = false)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
if (array.Length == 0)
{
return;
}
int num = System.Buffers.Utilities.SelectBucketIndex(array.Length);
if (num < _buckets.Length)
{
if (clearArray)
{
Array.Clear(array, 0, array.Length);
}
_buckets[num].Return(array);
}
System.Buffers.ArrayPoolEventSource log = System.Buffers.ArrayPoolEventSource.Log;
if (log.IsEnabled())
{
log.BufferReturned(array.GetHashCode(), array.Length, Id);
}
}
}
internal static class Utilities
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int SelectBucketIndex(int bufferSize)
{
uint num = (uint)(bufferSize - 1) >> 4;
int num2 = 0;
if (num > 65535)
{
num >>= 16;
num2 = 16;
}
if (num > 255)
{
num >>= 8;
num2 += 8;
}
if (num > 15)
{
num >>= 4;
num2 += 4;
}
if (num > 3)
{
num >>= 2;
num2 += 2;
}
if (num > 1)
{
num >>= 1;
num2++;
}
return num2 + (int)num;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int GetMaxSizeForBucket(int binIndex)
{
return 16 << binIndex;
}
}
}