Decompiled source of Agrona v1.40.0
BepInEx/core/Agrona/netstandard2.0/Adaptive.Agrona.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.MemoryMappedFiles; using System.Linq; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using Adaptive.Agrona.Collections; using Adaptive.Agrona.Concurrent; using Adaptive.Agrona.Concurrent.Status; using Adaptive.Agrona.Util; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("Adaptive Financial Consulting Ltd.")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright 2023")] [assembly: AssemblyDescription("Agrona provides a library of data structures and utility methods that are a common need when building high-performance applications in .NET")] [assembly: AssemblyFileVersion("1.40.0.0")] [assembly: AssemblyInformationalVersion("1.40.0")] [assembly: AssemblyProduct("Agrona libraries initially included in Aeron Client")] [assembly: AssemblyTitle("Adaptive.Agrona")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.40.0.0")] [module: UnverifiableCode] namespace Adaptive.Agrona { public class BitUtil { public const int SIZE_OF_BYTE = 1; public const int SIZE_OF_BOOLEAN = 1; public const int SIZE_OF_CHAR = 2; public const int SIZE_OF_SHORT = 2; public const int SIZE_OF_INT = 4; public const int SIZE_OF_FLOAT = 4; public const int SIZE_OF_LONG = 8; public const int SIZE_OF_DOUBLE = 8; public const int CACHE_LINE_LENGTH = 64; private static readonly byte[] HexDigitTable; private static readonly byte[] FromHexDigitTable; private const int LastDigitMask = 1; private static readonly Encoding Utf8Encoding; static BitUtil() { HexDigitTable = new byte[16] { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102 }; Utf8Encoding = Encoding.UTF8; FromHexDigitTable = new byte[128]; FromHexDigitTable[48] = 0; FromHexDigitTable[49] = 1; FromHexDigitTable[50] = 2; FromHexDigitTable[51] = 3; FromHexDigitTable[52] = 4; FromHexDigitTable[53] = 5; FromHexDigitTable[54] = 6; FromHexDigitTable[55] = 7; FromHexDigitTable[56] = 8; FromHexDigitTable[57] = 9; FromHexDigitTable[97] = 10; FromHexDigitTable[65] = 10; FromHexDigitTable[98] = 11; FromHexDigitTable[66] = 11; FromHexDigitTable[99] = 12; FromHexDigitTable[67] = 12; FromHexDigitTable[100] = 13; FromHexDigitTable[68] = 13; FromHexDigitTable[101] = 14; FromHexDigitTable[69] = 14; FromHexDigitTable[102] = 15; FromHexDigitTable[70] = 15; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int FindNextPositivePowerOfTwo(int value) { return 1 << 32 - IntUtil.NumberOfLeadingZeros(value - 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Align(int value, int alignment) { return (value + (alignment - 1)) & ~(alignment - 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] FromHexByteArray(byte[] buffer) { byte[] array = new byte[buffer.Length >> 1]; for (int i = 0; i < buffer.Length; i += 2) { array[i >> 1] = (byte)((FromHexDigitTable[buffer[i]] << 4) | FromHexDigitTable[buffer[i + 1]]); } return array; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] ToHexByteArray(byte[] buffer) { return ToHexByteArray(buffer, 0, buffer.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] ToHexByteArray(byte[] buffer, int offset, int length) { byte[] array = new byte[length << 1]; for (int i = 0; i < length << 1; i += 2) { byte b = buffer[offset + (i >> 1)]; array[i] = HexDigitTable[(b >> 4) & 0xF]; array[i + 1] = HexDigitTable[b & 0xF]; } return array; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] FromHex(string value) { return FromHexByteArray(Utf8Encoding.GetBytes(value)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string ToHex(byte[] buffer, int offset, int length) { byte[] array = ToHexByteArray(buffer, offset, length); return Utf8Encoding.GetString(array, 0, array.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string ToHex(byte[] buffer) { byte[] array = ToHexByteArray(buffer); return Utf8Encoding.GetString(array, 0, array.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsEven(int value) { return (value & 1) == 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsPowerOfTwo(int value) { if (value > 0) { return (value & (~value + 1)) == value; } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Next(int current, int max) { int num = current + 1; if (num == max) { num = 0; } return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Previous(int current, int max) { if (current == 0) { return max - 1; } return current - 1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsAligned(long address, int alignment) { if (!IsPowerOfTwo(alignment)) { ThrowHelper.ThrowArgumentException("Alignment must be a power of 2: alignment=" + alignment); } return (address & (alignment - 1)) == 0; } } public class BufferUtil { public static readonly byte[] NullBytes = Encoding.UTF8.GetBytes("null"); public static void BoundsCheck(byte[] buffer, long index, int length) { int num = buffer.Length; long num2 = index + length; if (index < 0 || num2 > num) { ThrowHelper.ThrowIndexOutOfRangeException($"index={index:D}, length={length:D}, capacity={num:D}"); } } public static ByteBuffer AllocateDirectAligned(int capacity, int alignment) { return new ByteBuffer(capacity, alignment); } public static ByteBuffer AllocateDirect(int capacity) { return new ByteBuffer(capacity, 8); } } public class ByteBuffer : IDisposable { private GCHandle _bufferHandle; private bool _disposed; public IntPtr BufferPointer { get; } public int Capacity { get; } public ByteBuffer(int capacity, int byteAlignment) { Capacity = capacity; byte[] value = new byte[capacity + byteAlignment]; _bufferHandle = GCHandle.Alloc(value, GCHandleType.Pinned); long num = _bufferHandle.AddrOfPinnedObject().ToInt64(); num = (num + byteAlignment - 1) & ~(byteAlignment - 1); BufferPointer = new IntPtr(num); } ~ByteBuffer() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); } private void Dispose(bool disposing) { if (!_disposed) { _bufferHandle.Free(); _disposed = true; } } } public enum ByteOrder { BigEndian, LittleEndian } public struct CacheLinePadding { private long p1; private long p2; private long p3; private long p4; private long p5; private long p6; private long p7; private long p8; private long p9; private long p10; private long p11; private long p12; private long p13; private long p14; private long p15; public override string ToString() { return string.Format("{0}: {1}, {2}: {3}, {4}: {5}, {6}: {7}, {8}: {9}, {10}: {11}, {12}: {13}, {14}: {15}, {16}: {17}, {18}: {19}, {20}: {21}, {22}: {23}, {24}: {25}, {26}: {27}, {28}: {29}", "p1", p1, "p2", p2, "p3", p3, "p4", p4, "p5", p5, "p6", p6, "p7", p7, "p8", p8, "p9", p9, "p10", p10, "p11", p11, "p12", p12, "p13", p13, "p14", p14, "p15", p15); } } public static class CloseHelper { public static void QuietDispose(IDisposable disposable) { try { disposable?.Dispose(); } catch { } } public static void QuietDispose(Action disposable) { try { disposable?.Invoke(); } catch { } } public static void Dispose(ErrorHandler errorHandler, IDisposable disposable) { try { disposable?.Dispose(); } catch (Exception exception) { errorHandler(exception); } } public static void Dispose(IErrorHandler errorHandler, IDisposable disposable) { try { disposable?.Dispose(); } catch (Exception exception) { errorHandler.OnError(exception); } } public static void Dispose(ErrorHandler errorHandler, Action disposable) { try { disposable?.Invoke(); } catch (Exception exception) { errorHandler(exception); } } public static void CloseAll(IEnumerable<IDisposable> disposables) { if (disposables == null || !disposables.Any()) { return; } Exception ex = null; foreach (IDisposable disposable in disposables) { if (disposable != null) { try { disposable.Dispose(); } catch (Exception ex2) { ex = ((ex != null) ? new Exception(null, ex2) : ex2); } } } if (ex == null) { return; } throw ex; } } public interface DelegatingErrorHandler { void Next(ErrorHandler errorHandler); void OnError(Exception exception); } public static class EndianessConverter { private static readonly ByteOrder NativeByteOrder = (BitConverter.IsLittleEndian ? ByteOrder.LittleEndian : ByteOrder.BigEndian); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short ApplyInt16(ByteOrder byteOrder, short value) { if (byteOrder == NativeByteOrder) { return value; } return (short)((long)(((ulong)value & 0xFFuL) << 8) | ((long)((ulong)value & 0xFF00uL) >> 8)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ushort ApplyUint16(ByteOrder byteOrder, ushort value) { if (byteOrder == NativeByteOrder) { return value; } return (ushort)((uint)((value & 0xFF) << 8) | ((uint)(value & 0xFF00) >> 8)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ApplyInt32(ByteOrder byteOrder, int value) { if (byteOrder == NativeByteOrder) { return value; } return (int)((long)((((ulong)value & 0xFFuL) << 24) | (((ulong)value & 0xFF00uL) << 8)) | ((long)((ulong)value & 0xFF0000uL) >> 8) | ((value & 0xFF000000u) >> 24)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint ApplyUint32(ByteOrder byteOrder, uint value) { if (byteOrder == NativeByteOrder) { return value; } return ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) | ((value & 0xFF0000) >> 8) | ((value & 0xFF000000u) >> 24); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong ApplyUint64(ByteOrder byteOrder, ulong value) { if (byteOrder == NativeByteOrder) { return value; } return ((value & 0xFF) << 56) | ((value & 0xFF00) << 40) | ((value & 0xFF0000) << 24) | ((value & 0xFF000000u) << 8) | ((value & 0xFF00000000L) >> 8) | ((value & 0xFF0000000000L) >> 24) | ((value & 0xFF000000000000L) >> 40) | ((value & 0xFF00000000000000uL) >> 56); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long ApplyInt64(ByteOrder byteOrder, long value) { if (byteOrder == NativeByteOrder) { return value; } return IPAddress.HostToNetworkOrder(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double ApplyDouble(ByteOrder byteOrder, double value) { if (byteOrder == NativeByteOrder) { return value; } return BitConverter.Int64BitsToDouble(IPAddress.HostToNetworkOrder(BitConverter.DoubleToInt64Bits(value))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static float ApplyFloat(ByteOrder byteOrder, float value) { if (byteOrder == NativeByteOrder) { return value; } int value2 = *(int*)(&value); int num = ApplyInt32(byteOrder, value2); return *(float*)(&num); } } public delegate void ErrorHandler(Exception exception); public class ExpandableArrayBuffer : IMutableDirectBuffer, IDirectBuffer, IComparable<IDirectBuffer> { public static readonly int MAX_ARRAY_LENGTH = 2147483639; public const int INITIAL_CAPACITY = 128; private byte[] _byteArray; private GCHandle _pinnedGcHandle; private unsafe byte* _pBuffer; public unsafe IntPtr BufferPointer => new IntPtr(_pBuffer); public byte[] ByteArray => _byteArray; public ByteBuffer ByteBuffer => null; public int Capacity => _byteArray.Length; public bool IsExpandable => true; public ExpandableArrayBuffer() : this(128) { } public ExpandableArrayBuffer(int initialCapacity) { AllocateAndPinArray(initialCapacity); } private unsafe void AllocateAndPinArray(int capacity) { _byteArray = new byte[capacity]; _pinnedGcHandle = GCHandle.Alloc(_byteArray, GCHandleType.Pinned); _pBuffer = (byte*)_pinnedGcHandle.AddrOfPinnedObject().ToPointer(); } ~ExpandableArrayBuffer() { if (_pinnedGcHandle.IsAllocated) { _pinnedGcHandle.Free(); } } public void Wrap(byte[] buffer) { throw new NotSupportedException(); } public void Wrap(byte[] buffer, int offset, int length) { throw new NotSupportedException(); } public void Wrap(IDirectBuffer buffer) { throw new NotSupportedException(); } public void Wrap(IDirectBuffer buffer, int offset, int length) { throw new NotSupportedException(); } public void Wrap(IntPtr pointer, int length) { throw new NotSupportedException(); } public void Wrap(IntPtr pointer, int offset, int length) { throw new NotSupportedException(); } public int CompareTo(IDirectBuffer other) { throw new NotSupportedException(); } public void CheckLimit(int limit) { EnsureCapacity(limit, 1); } public unsafe long GetLong(int index, ByteOrder byteOrder) { BoundsCheck0(index, 8); long value = *(long*)(_pBuffer + index); return EndianessConverter.ApplyInt64(byteOrder, value); } public unsafe long GetLong(int index) { BoundsCheck0(index, 8); return *(long*)(_pBuffer + index); } public unsafe int GetInt(int index, ByteOrder byteOrder) { BoundsCheck0(index, 4); int value = *(int*)(_pBuffer + index); return EndianessConverter.ApplyInt32(byteOrder, value); } public unsafe int GetInt(int index) { BoundsCheck0(index, 4); return *(int*)(_pBuffer + index); } public unsafe double GetDouble(int index) { BoundsCheck0(index, 8); return *(double*)(_pBuffer + index); } public unsafe float GetFloat(int index) { BoundsCheck0(index, 4); return *(float*)(_pBuffer + index); } public unsafe short GetShort(int index, ByteOrder byteOrder) { BoundsCheck0(index, 2); short value = *(short*)(_pBuffer + index); return EndianessConverter.ApplyInt16(byteOrder, value); } public unsafe short GetShort(int index) { BoundsCheck0(index, 2); return *(short*)(_pBuffer + index); } public unsafe char GetChar(int index) { BoundsCheck0(index, 2); return *(char*)(_pBuffer + index); } public byte GetByte(int index) { return _byteArray[index]; } public void GetBytes(int index, byte[] dst) { Array.Copy(_byteArray, index, dst, 0, dst.Length); } public void GetBytes(int index, byte[] dst, int offset, int length) { Array.Copy(_byteArray, index, dst, offset, length); } public void GetBytes(int index, IMutableDirectBuffer dstBuffer, int dstIndex, int length) { dstBuffer.PutBytes(dstIndex, _byteArray, index, length); } public string GetStringUtf8(int index) { int @int = GetInt(index); return GetStringUtf8(index, @int); } public string GetStringAscii(int index) { int @int = GetInt(index); return GetStringAscii(index, @int); } public int GetStringAscii(int index, StringBuilder appendable) { int @int = GetInt(index); return GetStringAscii(index, @int, appendable); } public unsafe int GetStringAscii(int index, int length, StringBuilder appendable) { int i = index + 4; for (int num = index + 4 + length; i < num; i++) { char c = *(char*)(_pBuffer + index); appendable.Append((c > '\u007f') ? '?' : c); } return length; } public string GetStringUtf8(int index, int length) { byte[] array = new byte[length]; GetBytes(index + 4, array); return Encoding.UTF8.GetString(array); } public string GetStringAscii(int index, int length) { byte[] array = new byte[length]; GetBytes(index + 4, array); return Encoding.ASCII.GetString(array); } public string GetStringWithoutLengthUtf8(int index, int length) { byte[] array = new byte[length]; GetBytes(index, array); return Encoding.UTF8.GetString(array); } public string GetStringWithoutLengthAscii(int index, int length) { byte[] array = new byte[length]; GetBytes(index, array); return Encoding.ASCII.GetString(array); } public void BoundsCheck(int index, int length) { BoundsCheck0(index, length); } public unsafe void SetMemory(int index, int length, byte value) { EnsureCapacity(index, length); Unsafe.InitBlock(_pBuffer + index, value, (uint)length); } public unsafe void PutLong(int index, long value, ByteOrder byteOrder) { EnsureCapacity(index, 8); value = EndianessConverter.ApplyInt64(byteOrder, value); *(long*)(_pBuffer + index) = value; } public unsafe void PutLong(int index, long value) { EnsureCapacity(index, 8); BoundsCheck0(index, 8); *(long*)(_pBuffer + index) = value; } public unsafe void PutInt(int index, int value, ByteOrder byteOrder) { EnsureCapacity(index, 4); value = EndianessConverter.ApplyInt32(byteOrder, value); *(int*)(_pBuffer + index) = value; } public unsafe void PutInt(int index, int value) { EnsureCapacity(index, 4); *(int*)(_pBuffer + index) = value; } public unsafe void PutDouble(int index, double value) { EnsureCapacity(index, 8); *(double*)(_pBuffer + index) = value; } public unsafe void PutFloat(int index, float value) { EnsureCapacity(index, 4); *(float*)(_pBuffer + index) = value; } public unsafe void PutShort(int index, short value, ByteOrder byteOrder) { EnsureCapacity(index, 2); value = EndianessConverter.ApplyInt16(byteOrder, value); *(short*)(_pBuffer + index) = value; } public unsafe void PutShort(int index, short value) { EnsureCapacity(index, 2); *(short*)(_pBuffer + index) = value; } public unsafe void PutChar(int index, char value) { EnsureCapacity(index, 2); *(char*)(_pBuffer + index) = value; } public unsafe void PutByte(int index, byte value) { EnsureCapacity(index, 1); _pBuffer[index] = value; } public void PutBytes(int index, byte[] src) { PutBytes(index, src, 0, src.Length); } public void PutBytes(int index, byte[] src, int offset, int length) { EnsureCapacity(index, length); Array.Copy(src, offset, _byteArray, index, length); } public unsafe void PutBytes(int index, IDirectBuffer srcBuffer, int srcIndex, int length) { if (length != 0) { EnsureCapacity(index, length); srcBuffer.BoundsCheck(srcIndex, length); byte* destination = _pBuffer + index; byte* source = (byte*)srcBuffer.BufferPointer.ToPointer() + srcIndex; ByteUtil.MemoryCopy(destination, source, (uint)length); } } public int PutStringUtf8(int index, string value) { return PutStringUtf8(index, value, int.MaxValue); } public int PutStringAscii(int index, string value) { return PutStringAscii(index, value, int.MaxValue); } public int PutStringAscii(int index, string value, int maxEncodedSize) { byte[] array = ((value == null) ? BufferUtil.NullBytes : Encoding.ASCII.GetBytes(value)); if (array.Length > maxEncodedSize) { ThrowHelper.ThrowArgumentException("Encoded string larger than maximum size: " + maxEncodedSize); } EnsureCapacity(index, 4 + array.Length); PutInt(index, array.Length); PutBytes(index + 4, array); return 4 + array.Length; } public unsafe int PutStringWithoutLengthAscii(int index, string value) { int num = value?.Length ?? 0; EnsureCapacity(index, num); for (int i = 0; i < num; i++) { char c = value[i]; if (c > '\u007f') { c = '?'; } *(char*)(_pBuffer + index + i) = c; } return num; } public unsafe int PutStringWithoutLengthAscii(int index, string value, int valueOffset, int length) { int num = ((value != null) ? Math.Min(value.Length - valueOffset, length) : 0); EnsureCapacity(index, num); for (int i = 0; i < num; i++) { char c = value[valueOffset + i]; if (c > '\u007f') { c = '?'; } *(char*)(_pBuffer + index + i) = c; } return num; } public int PutStringUtf8(int index, string value, int maxEncodedSize) { byte[] array = ((value == null) ? BufferUtil.NullBytes : Encoding.UTF8.GetBytes(value)); if (array.Length > maxEncodedSize) { ThrowHelper.ThrowArgumentException("Encoded string larger than maximum size: " + maxEncodedSize); } EnsureCapacity(index, 4 + array.Length); PutInt(index, array.Length); PutBytes(index + 4, array); return 4 + array.Length; } public int PutStringWithoutLengthUtf8(int index, string value) { byte[] array = ((value == null) ? BufferUtil.NullBytes : Encoding.UTF8.GetBytes(value)); EnsureCapacity(index, array.Length); PutBytes(index, array); return array.Length; } private void EnsureCapacity(int index, int length) { if (index < 0 || length < 0) { throw new IndexOutOfRangeException("negative value: index=" + index + " length=" + length); } long num = (long)index + (long)length; int num2 = _byteArray.Length; if (num > num2) { if (num > MAX_ARRAY_LENGTH) { string[] obj = new string[6] { "index=", index.ToString(), " length=", length.ToString(), " maxCapacity=", null }; int mAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH; obj[5] = mAX_ARRAY_LENGTH.ToString(); throw new IndexOutOfRangeException(string.Concat(obj)); } int capacity = CalculateExpansion(num2, num); byte[] byteArray = _byteArray; _pinnedGcHandle.Free(); AllocateAndPinArray(capacity); Array.Copy(byteArray, _byteArray, byteArray.Length); } } private int CalculateExpansion(int currentLength, long requiredLength) { long num = Math.Max(currentLength, 128); while (num < requiredLength) { num += num >> 1; if (num > MAX_ARRAY_LENGTH) { num = MAX_ARRAY_LENGTH; } } return (int)num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void BoundsCheck0(int index, int length) { int num = _byteArray.Length; long num2 = (long)index + (long)length; if (index < 0 || length < 0 || num2 > num) { ThrowHelper.ThrowIndexOutOfRangeException($"index={index:D}, length={length:D}, capacity={Capacity:D}"); } } } public interface IDirectBuffer : IComparable<IDirectBuffer> { IntPtr BufferPointer { get; } byte[] ByteArray { get; } ByteBuffer ByteBuffer { get; } int Capacity { get; } void Wrap(byte[] buffer); void Wrap(byte[] buffer, int offset, int length); void Wrap(IDirectBuffer buffer); void Wrap(IDirectBuffer buffer, int offset, int length); void Wrap(IntPtr pointer, int length); void Wrap(IntPtr pointer, int offset, int length); void CheckLimit(int limit); long GetLong(int index, ByteOrder byteOrder); long GetLong(int index); int GetInt(int index, ByteOrder byteOrder); int GetInt(int index); double GetDouble(int index); float GetFloat(int index); short GetShort(int index, ByteOrder byteOrder); short GetShort(int index); char GetChar(int index); byte GetByte(int index); void GetBytes(int index, byte[] dst); void GetBytes(int index, byte[] dst, int offset, int length); void GetBytes(int index, IMutableDirectBuffer dstBuffer, int dstIndex, int length); string GetStringUtf8(int index); string GetStringAscii(int index); int GetStringAscii(int index, StringBuilder appendable); int GetStringAscii(int index, int length, StringBuilder appendable); string GetStringUtf8(int index, int length); string GetStringAscii(int index, int length); string GetStringWithoutLengthUtf8(int index, int length); string GetStringWithoutLengthAscii(int index, int length); void BoundsCheck(int index, int length); } public interface IErrorHandler { void OnError(Exception exception); } public interface IManagedResource { void TimeOfLastStateChange(long time); long TimeOfLastStateChange(); void Delete(); } public interface IMutableDirectBuffer : IDirectBuffer, IComparable<IDirectBuffer> { bool IsExpandable { get; } void SetMemory(int index, int length, byte value); void PutLong(int index, long value, ByteOrder byteOrder); void PutLong(int index, long value); void PutInt(int index, int value, ByteOrder byteOrder); void PutInt(int index, int value); void PutDouble(int index, double value); void PutFloat(int index, float value); void PutShort(int index, short value, ByteOrder byteOrder); void PutShort(int index, short value); void PutChar(int index, char value); void PutByte(int index, byte value); void PutBytes(int index, byte[] src); void PutBytes(int index, byte[] src, int offset, int length); void PutBytes(int index, IDirectBuffer srcBuffer, int srcIndex, int length); int PutStringUtf8(int index, string value); int PutStringAscii(int index, string value); int PutStringWithoutLengthAscii(int index, string value); int PutStringWithoutLengthAscii(int index, string value, int valueOffset, int length); int PutStringUtf8(int index, string value, int maxEncodedSize); int PutStringWithoutLengthUtf8(int index, string value); } public enum MapMode { ReadOnly, ReadWrite } public class IoUtil { public static MappedByteBuffer MapExistingFile(string path, MapMode mapMode) { return new MappedByteBuffer(OpenMemoryMappedFile(path)); } public static MappedByteBuffer MapExistingFile(FileInfo path, long offset, long length) { return new MappedByteBuffer(OpenMemoryMappedFile(path.FullName), offset, length); } public static MappedByteBuffer MapNewFile(FileInfo cncFile, long length, bool fillWithZeros = true) { FileAccess access = FileAccess.ReadWrite; FileShare share = FileShare.ReadWrite | FileShare.Delete; MemoryMappedFileAccess access2 = MemoryMappedFileAccess.ReadWrite; MappedByteBuffer mappedByteBuffer = new MappedByteBuffer(MemoryMappedFile.CreateFromFile(new FileStream(cncFile.FullName, FileMode.CreateNew, access, share), null, length, access2, HandleInheritability.None, leaveOpen: false), 0L, length); if (fillWithZeros) { mappedByteBuffer.FillWithZeros(); } return mappedByteBuffer; } public static MappedByteBuffer MapNewOrExistingFile(FileInfo cncFile, long length) { FileAccess access = FileAccess.ReadWrite; FileShare share = FileShare.ReadWrite | FileShare.Delete; MemoryMappedFileAccess access2 = MemoryMappedFileAccess.ReadWrite; return new MappedByteBuffer(MemoryMappedFile.CreateFromFile(new FileStream(cncFile.FullName, FileMode.OpenOrCreate, access, share), null, length, access2, HandleInheritability.None, leaveOpen: false), 0L, length); } public static MemoryMappedFile OpenMemoryMappedFile(string path) { CheckFileExists(path); FileAccess access = FileAccess.ReadWrite; FileShare share = FileShare.ReadWrite | FileShare.Delete; return OpenMemoryMappedFile(new FileStream(path, FileMode.Open, access, share)); } private static MemoryMappedFile OpenMemoryMappedFile(FileStream f) { MemoryMappedFileAccess access = MemoryMappedFileAccess.ReadWrite; return MemoryMappedFile.CreateFromFile(f, null, 0L, access, HandleInheritability.None, leaveOpen: false); } public static MappedByteBuffer MapExistingFile(FileStream fileStream) { return new MappedByteBuffer(OpenMemoryMappedFile(fileStream)); } public static MappedByteBuffer MapExistingFile(FileInfo location, string descriptionLabel) { CheckFileExists(location, descriptionLabel); return new MappedByteBuffer(OpenMemoryMappedFile(location.FullName)); } public static void Unmap(MappedByteBuffer wrapper) { wrapper?.Dispose(); } public static void CheckFileExists(FileInfo file, string name) { if (!file.Exists) { throw new InvalidOperationException("Missing file for " + name + " : " + file.FullName); } } public static void CheckFileExists(string path) { if (!File.Exists(path)) { throw new InvalidOperationException("Missing file " + path); } } public static void Delete(DirectoryInfo directory, bool b) { if (directory.Exists) { directory.Delete(recursive: true); } } public static void EnsureDirectoryExists(DirectoryInfo directory, string descriptionLabel) { if (!directory.Exists) { directory.Create(); if (!directory.Exists) { throw new ArgumentException("could not create " + descriptionLabel + " directory: " + directory.FullName); } } } } public class MarkFile : IDisposable { private readonly int versionFieldOffset; private readonly int timestampFieldOffset; private readonly DirectoryInfo parentDir; private readonly FileInfo markFile; private readonly MappedByteBuffer mappedBuffer; private readonly UnsafeBuffer buffer; private volatile bool isClosed; public MarkFile(DirectoryInfo directory, string filename, bool warnIfDirectoryExists, bool dirDeleteOnStart, int versionFieldOffset, int timestampFieldOffset, int totalFileLength, long timeoutMs, IEpochClock epochClock, Action<int> versionCheck, Action<string> logger) { ValidateOffsets(versionFieldOffset, timestampFieldOffset); EnsureDirectoryExists(directory, filename, warnIfDirectoryExists, dirDeleteOnStart, versionFieldOffset, timestampFieldOffset, timeoutMs, epochClock, versionCheck, logger); parentDir = directory; markFile = new FileInfo(Path.Combine(directory.Name, filename)); mappedBuffer = MapNewFile(markFile, totalFileLength); buffer = new UnsafeBuffer(mappedBuffer.Pointer, totalFileLength); this.versionFieldOffset = versionFieldOffset; this.timestampFieldOffset = timestampFieldOffset; } public MarkFile(FileInfo markFile, bool shouldPreExist, int versionFieldOffset, int timestampFieldOffset, int totalFileLength, long timeoutMs, IEpochClock epochClock, Action<int> versionCheck, Action<string> logger) { ValidateOffsets(versionFieldOffset, timestampFieldOffset); parentDir = markFile.Directory; this.markFile = markFile; mappedBuffer = mapNewOrExistingMarkFile(markFile, shouldPreExist, versionFieldOffset, timestampFieldOffset, totalFileLength, timeoutMs, epochClock, versionCheck, logger); buffer = new UnsafeBuffer(mappedBuffer.Pointer, totalFileLength); this.versionFieldOffset = versionFieldOffset; this.timestampFieldOffset = timestampFieldOffset; } public MarkFile(DirectoryInfo directory, string filename, int versionFieldOffset, int timestampFieldOffset, long timeoutMs, IEpochClock epochClock, Action<int> versionCheck, Action<string> logger) { ValidateOffsets(versionFieldOffset, timestampFieldOffset); parentDir = directory; markFile = new FileInfo(Path.Combine(directory.FullName, filename)); mappedBuffer = MapExistingMarkFile(markFile, versionFieldOffset, timestampFieldOffset, timeoutMs, epochClock, versionCheck, logger); buffer = new UnsafeBuffer(mappedBuffer); this.versionFieldOffset = versionFieldOffset; this.timestampFieldOffset = timestampFieldOffset; } public MarkFile(MappedByteBuffer mappedBuffer, int versionFieldOffset, int timestampFieldOffset) { ValidateOffsets(versionFieldOffset, timestampFieldOffset); parentDir = null; markFile = null; this.mappedBuffer = mappedBuffer; buffer = new UnsafeBuffer(mappedBuffer); this.versionFieldOffset = versionFieldOffset; this.timestampFieldOffset = timestampFieldOffset; } public MarkFile(UnsafeBuffer buffer, int versionFieldOffset, int timestampFieldOffset) { ValidateOffsets(versionFieldOffset, timestampFieldOffset); parentDir = null; markFile = null; mappedBuffer = null; this.buffer = buffer; this.versionFieldOffset = versionFieldOffset; this.timestampFieldOffset = timestampFieldOffset; } public bool IsClosed() { return isClosed; } public void Dispose() { if (!isClosed) { if (mappedBuffer != null) { IoUtil.Unmap(mappedBuffer); } isClosed = true; } } public void SignalReady(int version) { buffer.PutIntOrdered(versionFieldOffset, version); } public int VersionVolatile() { return buffer.GetIntVolatile(versionFieldOffset); } public int VersionWeak() { return buffer.GetInt(versionFieldOffset); } public void TimestampOrdered(long timestamp) { buffer.PutLongOrdered(timestampFieldOffset, timestamp); } public long TimestampVolatile() { return buffer.GetLongVolatile(timestampFieldOffset); } public long TimestampWeak() { return buffer.GetLong(timestampFieldOffset); } public void DeleteDirectory(bool ignoreFailures) { IoUtil.Delete(parentDir, ignoreFailures); } public DirectoryInfo CncDirectory() { return parentDir; } public FileInfo FileName() { return markFile; } public MappedByteBuffer MappedByteBuffer() { return mappedBuffer; } public UnsafeBuffer Buffer() { return buffer; } public static void EnsureDirectoryExists(DirectoryInfo directory, string filename, bool warnIfDirectoryExists, bool dirDeleteOnStart, int versionFieldOffset, int timestampFieldOffset, long timeoutMs, IEpochClock epochClock, Action<int> versionCheck, Action<string> logger) { FileInfo cncFile = new FileInfo(Path.Combine(directory.FullName, filename)); if (directory.Exists) { if (warnIfDirectoryExists) { logger?.Invoke("WARNING: " + directory?.ToString() + " already exists."); } if (!dirDeleteOnStart) { int num = Math.Min(versionFieldOffset, timestampFieldOffset); int num2 = Math.Max(versionFieldOffset, timestampFieldOffset) + 8 - num; MappedByteBuffer mappedByteBuffer = MapExistingFile(cncFile, logger, num, num2); try { if (IsActive(mappedByteBuffer, epochClock, timeoutMs, versionFieldOffset, timestampFieldOffset, versionCheck, logger)) { throw new InvalidOperationException("active mark file detected"); } } finally { IoUtil.Unmap(mappedByteBuffer); } } IoUtil.Delete(directory, b: false); } IoUtil.EnsureDirectoryExists(directory, directory.ToString()); } public static MappedByteBuffer MapExistingMarkFile(FileInfo markFile, int versionFieldOffset, int timestampFieldOffset, long timeoutMs, IEpochClock epochClock, Action<int> versionCheck, Action<string> logger) { long num = epochClock.Time(); while (!markFile.Exists) { if (epochClock.Time() > num + timeoutMs) { throw new InvalidOperationException("CnC file not found: " + markFile.FullName); } Sleep(16); } MappedByteBuffer result = MapExistingFile(markFile, logger); UnsafeBuffer unsafeBuffer = new UnsafeBuffer(result); int intVolatile; while ((intVolatile = unsafeBuffer.GetIntVolatile(versionFieldOffset)) == 0) { if (epochClock.Time() > num + timeoutMs) { throw new InvalidOperationException("CnC file is created but not initialised."); } Sleep(1); } versionCheck(intVolatile); while (unsafeBuffer.GetLongVolatile(timestampFieldOffset) == 0L) { if (epochClock.Time() > num + timeoutMs) { throw new InvalidOperationException("No non-0 timestamp detected."); } Sleep(1); } return result; } public static MappedByteBuffer mapNewOrExistingMarkFile(FileInfo markFile, bool shouldPreExist, int versionFieldOffset, int timestampFieldOffset, long totalFileLength, long timeoutMs, IEpochClock epochClock, Action<int> versionCheck, Action<string> logger) { MappedByteBuffer mappedByteBuffer = null; try { mappedByteBuffer = IoUtil.MapNewOrExistingFile(markFile, totalFileLength); UnsafeBuffer unsafeBuffer = new UnsafeBuffer(mappedByteBuffer); if (shouldPreExist) { int intVolatile = unsafeBuffer.GetIntVolatile(versionFieldOffset); logger?.Invoke("INFO: Mark file exists: " + markFile); versionCheck(intVolatile); long longVolatile = unsafeBuffer.GetLongVolatile(timestampFieldOffset); long num = epochClock.Time() - longVolatile; logger?.Invoke("INFO: heartbeat is (ms): " + num); if (num < timeoutMs) { throw new InvalidOperationException("Active mark file detected"); } } } catch (Exception) { if (mappedByteBuffer != null) { IoUtil.Unmap(mappedByteBuffer); } throw; } return mappedByteBuffer; } public static MappedByteBuffer MapExistingFile(FileInfo cncFile, Action<string> logger, long offset, long length) { if (cncFile.Exists) { logger?.Invoke("INFO: Mark file exists: " + cncFile); return IoUtil.MapExistingFile(cncFile, offset, length); } return null; } public static MappedByteBuffer MapExistingFile(FileInfo cncFile, Action<string> logger) { if (cncFile.Exists) { logger?.Invoke("INFO: Mark file exists: " + cncFile); return IoUtil.MapExistingFile(cncFile, cncFile.ToString()); } return null; } public static MappedByteBuffer MapNewFile(FileInfo cncFile, long length) { return IoUtil.MapNewFile(cncFile, length); } public static bool IsActive(MappedByteBuffer cncByteBuffer, IEpochClock epochClock, long timeoutMs, int versionFieldOffset, int timestampFieldOffset, Action<int> versionCheck, Action<string> logger) { if (cncByteBuffer == null) { return false; } UnsafeBuffer unsafeBuffer = new UnsafeBuffer(cncByteBuffer); long num = epochClock.Time(); int intVolatile; while ((intVolatile = unsafeBuffer.GetIntVolatile(versionFieldOffset)) == 0) { if (epochClock.Time() > num + timeoutMs) { throw new InvalidOperationException("Mark file is created but not initialised."); } Sleep(1); } versionCheck(intVolatile); long longVolatile = unsafeBuffer.GetLongVolatile(timestampFieldOffset); long num2 = epochClock.Time() - longVolatile; logger?.Invoke("INFO: heartbeat is (ms): " + num2); return num2 <= timeoutMs; } private static void ValidateOffsets(int versionFieldOffset, int timestampFieldOffset) { if (versionFieldOffset + 4 > timestampFieldOffset) { throw new ArgumentException("version field must precede the timestamp field"); } } internal static void Sleep(int durationMs) { try { Thread.Sleep(durationMs); } catch (ThreadInterruptedException) { Thread.CurrentThread.Interrupt(); } } } public static class Objects { public static T RequireNonNull<T>(T obj, string name) { if (obj == null) { throw new NullReferenceException(name); } return obj; } } public class SemanticVersion { public static int Compose(int major, int minor, int patch) { if (major < 0 || major > 255) { throw new ArgumentException("major must be 0-255: " + major); } if (minor < 0 || minor > 255) { throw new ArgumentException("minor must be 0-255: " + minor); } if (patch < 0 || patch > 255) { throw new ArgumentException("patch must be 0-255: " + patch); } if (major + minor + patch == 0) { throw new ArgumentException("all parts cannot be zero"); } return (major << 16) | (minor << 8) | patch; } public static int Major(int version) { return (version >> 16) & 0xFF; } public static int Minor(int version) { return (version >> 8) & 0xFF; } public static int Patch(int version) { return version & 0xFF; } public static string ToString(int version) { return Major(version) + "." + Minor(version) + "." + Patch(version); } } public class SystemUtil { private const long MAX_G_VALUE = 8589934591L; private const long MAX_M_VALUE = 8796093022207L; private const long MAX_K_VALUE = 9007199254739968L; private const long SECONDS_TO_NANOS = 1000000000L; private const long MILLS_TO_NANOS = 1000000L; private const long MICROS_TO_NANOS = 1000L; public static long ParseSize(string propertyName, string propertyValue) { int num = propertyValue.Length - 1; char c = propertyValue[num]; if (char.IsDigit(c)) { return long.Parse(propertyValue); } long num2 = Convert.ToInt64(propertyValue.Substring(0, num)); switch (c) { case 'K': case 'k': if (num2 > 9007199254739968L) { throw new FormatException(propertyName + " would overflow long: " + propertyValue); } return num2 * 1024; case 'M': case 'm': if (num2 > 8796093022207L) { throw new FormatException(propertyName + " would overflow long: " + propertyValue); } return num2 * 1024 * 1024; case 'G': case 'g': if (num2 > 8589934591L) { throw new FormatException(propertyName + " would overflow long: " + propertyValue); } return num2 * 1024 * 1024 * 1024; default: throw new FormatException(propertyName + ": " + propertyValue + " should end with: k, m, or g."); } } public static long ParseDuration(string propertyName, string propertyValue) { char c = propertyValue[propertyValue.Length - 1]; if (char.IsDigit(c)) { return long.Parse(propertyValue); } if (c != 's' && c != 'S') { throw new FormatException(propertyName + ": " + propertyValue + " should end with: s, ms, us, or ns."); } char c2 = propertyValue[propertyValue.Length - 2]; if (char.IsDigit(c2)) { long num = Convert.ToInt64(propertyValue.Substring(0, propertyValue.Length - 1)); return 1000000000 * num; } long num2 = Convert.ToInt64(propertyValue.Substring(0, propertyValue.Length - 2)); switch (c2) { case 'N': case 'n': return num2; case 'U': case 'u': return 1000 * num2; case 'M': case 'm': return 1000000 * num2; default: throw new FormatException(propertyName + ": " + propertyValue + " should end with: s, ms, us, or ns."); } } } public class TimeUnit { public static readonly TimeUnit NANOSECONDS = new TimeUnit(); public static readonly TimeUnit MILLIS = new TimeUnit(); private TimeUnit() { } public long Convert(long sourceValue, TimeUnit destinationTimeUnit) { if (destinationTimeUnit == NANOSECONDS) { if (this == MILLIS) { return sourceValue * 1000000; } if (this == NANOSECONDS) { return sourceValue; } } if (destinationTimeUnit == MILLIS) { if (this == MILLIS) { return sourceValue; } if (this == NANOSECONDS) { return sourceValue / 1000000; } } throw new ArgumentException(); } public long ToMillis(long value) { return Convert(value, MILLIS); } public long ToNanos(long value) { return Convert(value, NANOSECONDS); } } } namespace Adaptive.Agrona.Util { public class ByteUtil { [StructLayout(LayoutKind.Sequential, Pack = 32, Size = 32)] internal struct CopyChunk32 { private readonly long _l1; private readonly long _l2; private readonly long _l3; private readonly long _l4; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void MemoryCopy(byte* destination, byte* source, uint length) { int i = 0; for (int j = i + 32; j <= length; j += 32) { *(CopyChunk32*)(destination + i) = *(CopyChunk32*)(source + i); i = j; } for (int j = i + 8; j <= length; j += 8) { *(long*)(destination + i) = *(long*)(source + i); i = j; } for (; i < length; i++) { destination[i] = source[i]; } } } public static class IntUtil { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int NumberOfTrailingZeros(int i) { if (i == 0) { return 32; } int num = 31; int num2 = i << 16; if (num2 != 0) { num -= 16; i = num2; } num2 = i << 8; if (num2 != 0) { num -= 8; i = num2; } num2 = i << 4; if (num2 != 0) { num -= 4; i = num2; } num2 = i << 2; if (num2 != 0) { num -= 2; i = num2; } return num - (i << 1 >>> 31); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int NumberOfLeadingZeros(int i) { if (i == 0) { return 32; } int num = 1; if (i >>> 16 == 0) { num += 16; i <<= 16; } if (i >>> 24 == 0) { num += 8; i <<= 8; } if (i >>> 28 == 0) { num += 4; i <<= 4; } if (i >>> 30 == 0) { num += 2; i <<= 2; } return num - (i >>> 31); } } public static class LockSupport { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ParkNanos(long nanos) { Thread.SpinWait((int)(15 * nanos / 1000)); } } public class MappedByteBuffer : IDisposable { private readonly MemoryMappedFile _memoryMappedFile; private readonly MemoryMappedViewAccessor _view; private bool _disposed; public IntPtr Pointer { get; } public long Capacity { get; } public unsafe MappedByteBuffer(MemoryMappedFile memoryMappedFile) { _memoryMappedFile = memoryMappedFile; byte* pointer = null; _view = memoryMappedFile.CreateViewAccessor(); _view.SafeMemoryMappedViewHandle.AcquirePointer(ref pointer); Pointer = new IntPtr(pointer); Capacity = _view.Capacity; } public unsafe MappedByteBuffer(MemoryMappedFile memoryMappedFile, long offset, long length) { _memoryMappedFile = memoryMappedFile; byte* pointer = null; _view = memoryMappedFile.CreateViewAccessor(offset, length); _view.SafeMemoryMappedViewHandle.AcquirePointer(ref pointer); Pointer = new IntPtr(pointer); Capacity = length; } public void FillWithZeros() { for (int i = 0; i < Capacity; i++) { _view.Write((long)i, (byte)0); } } public void Flush() { _view.Flush(); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } ~MappedByteBuffer() { Dispose(disposing: false); } private void Dispose(bool disposing) { if (!_disposed) { if (_view != null) { _view.SafeMemoryMappedViewHandle.ReleasePointer(); _view.Dispose(); } _memoryMappedFile?.Dispose(); _disposed = true; } } } public static class NanoUtil { public static long FromSeconds(long seconds) { return seconds * 1000 * 1000 * 1000; } public static long FromMilliseconds(long milliseconds) { return milliseconds * 1000 * 1000; } public static int ToMillis(long resourceLingerDurationNs) { return (int)(resourceLingerDurationNs / 1000000); } } public static class ThrowHelper { [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowArgumentException() { throw GetArgumentException(); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowArgumentException(string message) { throw GetArgumentException(message); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowArgumentOutOfRangeException() { throw GetArgumentOutOfRangeException(); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowArgumentOutOfRangeException(string argument) { throw GetArgumentOutOfRangeException(argument); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowIndexOutOfRangeException(string message) { throw GetIndexOutOfRangeException(message); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowInvalidOperationException() { throw GetInvalidOperationException(); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowInvalidCastException() { throw GetInvalidCastException(); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowInvalidOperationException(string message) { throw GetInvalidOperationException(message); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowInvalidOperationException_ForVariantTypeMissmatch() { throw GetInvalidOperationException_ForVariantTypeMissmatch(); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowNotImplementedException() { throw GetNotImplementedException(); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowNotImplementedException(string message) { throw GetNotImplementedException(message); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowNotSupportedException() { throw GetNotSupportedException(); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowKeyNotFoundException(string message) { throw GetKeyNotFoundException(message); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowArgumentNullException(string argument) { throw new ArgumentNullException(argument); } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowObjectDisposedException(string objectName) { throw GetObjectDisposedException(objectName); } [MethodImpl(MethodImplOptions.NoInlining)] private static ArgumentException GetArgumentException() { return new ArgumentException(); } [MethodImpl(MethodImplOptions.NoInlining)] private static ArgumentException GetArgumentException(string message) { return new ArgumentException(message); } [MethodImpl(MethodImplOptions.NoInlining)] private static ArgumentOutOfRangeException GetArgumentOutOfRangeException() { return new ArgumentOutOfRangeException(); } [MethodImpl(MethodImplOptions.NoInlining)] private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(string argument) { return new ArgumentOutOfRangeException(argument); } [MethodImpl(MethodImplOptions.NoInlining)] private static IndexOutOfRangeException GetIndexOutOfRangeException(string message) { return new IndexOutOfRangeException(message); } [MethodImpl(MethodImplOptions.NoInlining)] private static InvalidOperationException GetInvalidOperationException() { return new InvalidOperationException(); } [MethodImpl(MethodImplOptions.NoInlining)] private static InvalidCastException GetInvalidCastException() { return new InvalidCastException(); } [MethodImpl(MethodImplOptions.NoInlining)] private static InvalidOperationException GetInvalidOperationException(string message) { return new InvalidOperationException(message); } [MethodImpl(MethodImplOptions.NoInlining)] private static InvalidOperationException GetInvalidOperationException_ForVariantTypeMissmatch() { return new InvalidOperationException("Variant type doesn't match typeof(T)"); } [MethodImpl(MethodImplOptions.NoInlining)] private static NotImplementedException GetNotImplementedException() { return new NotImplementedException(); } [MethodImpl(MethodImplOptions.NoInlining)] private static NotImplementedException GetNotImplementedException(string message) { return new NotImplementedException(message); } [MethodImpl(MethodImplOptions.NoInlining)] private static NotSupportedException GetNotSupportedException() { return new NotSupportedException(); } [MethodImpl(MethodImplOptions.NoInlining)] private static KeyNotFoundException GetKeyNotFoundException(string message) { return new KeyNotFoundException(message); } [MethodImpl(MethodImplOptions.NoInlining)] private static ObjectDisposedException GetObjectDisposedException(string objectName) { return new ObjectDisposedException(objectName); } } public static class UnixTimeConverter { private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long CurrentUnixTimeMillis() { return (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static DateTime FromUnixTimeMillis(long epoch) { DateTime jan1st = Jan1st1970; return jan1st.AddMilliseconds(epoch); } } } namespace Adaptive.Agrona.SBE { public interface ICompositeDecoderFlyweight : IDecoderFlyweight, IFlyweight { ICompositeDecoderFlyweight Wrap(IDirectBuffer buffer, int offset); } public interface ICompositeEncoderFlyweight : IEncoderFlyweight, IFlyweight { } public interface IDecoderFlyweight : IFlyweight { } public interface IEncoderFlyweight : IFlyweight { IEncoderFlyweight Wrap(IMutableDirectBuffer buffer, int offset); } public interface IFlyweight { int EncodedLength(); } public interface IMessageDecoderFlyweight : IMessageFlyweight, IFlyweight, IDecoderFlyweight { IMessageDecoderFlyweight Wrap(IDirectBuffer buffer, int offset, int actingBlockLength, int actingVersion); } public interface IMessageEncoderFlyweight : IMessageFlyweight, IFlyweight, IEncoderFlyweight { } public interface IMessageFlyweight : IFlyweight { int SbeBlockLength(); int SbeTemplateId(); int SbeSchemaId(); int SbeSchemaVersion(); string SbeSemanticType(); int Offset(); } } namespace Adaptive.Agrona.Concurrent { public class AgentInvoker : IDisposable { private readonly AtomicCounter _errorCounter; private readonly ErrorHandler _errorHandler; private readonly IAgent _agent; public bool IsClosed { get; private set; } public bool IsStarted { get; private set; } public bool IsRunning { get; private set; } public AgentInvoker(ErrorHandler errorHandler, AtomicCounter errorCounter, IAgent agent) { Objects.RequireNonNull(errorHandler, "errorHandler"); Objects.RequireNonNull(agent, "agent"); _errorHandler = errorHandler; _errorCounter = errorCounter; _agent = agent; } public IAgent Agent() { return _agent; } public void Start() { try { if (!IsStarted) { IsStarted = true; _agent.OnStart(); IsRunning = true; } } catch (Exception exception) { HandleError(exception); Dispose(); } } public int Invoke() { int result = 0; if (IsRunning) { try { result = _agent.DoWork(); } catch (ThreadInterruptedException) { Dispose(); Thread.CurrentThread.Interrupt(); } catch (AgentTerminationException exception) { HandleError(exception); Dispose(); } catch (Exception exception2) { if (_errorCounter != null) { _errorCounter.Increment(); } _errorHandler(exception2); } } return result; } public void Dispose() { try { if (!IsClosed) { IsRunning = false; IsClosed = true; _agent.OnClose(); } } catch (Exception exception) { HandleError(exception); } } private void HandleError(Exception exception) { if (_errorCounter != null) { _errorCounter.Increment(); } _errorHandler(exception); } } public class AgentRunner : IDisposable { private static readonly Thread TOMBSTONE = new Thread((ThreadStart)delegate { }); public static readonly int RETRY_CLOSE_TIMEOUT_MS = 3000; private volatile bool _isRunning = true; private readonly AtomicCounter _errorCounter; private readonly ErrorHandler _errorHandler; private readonly IIdleStrategy _idleStrategy; private readonly IAgent _agent; private readonly AtomicReference<Thread> _thread = new AtomicReference<Thread>(); public bool IsClosed { get; private set; } public AgentRunner(IIdleStrategy idleStrategy, ErrorHandler errorHandler, AtomicCounter errorCounter, IAgent agent) { if (idleStrategy == null) { throw new ArgumentNullException("idleStrategy"); } if (errorHandler == null) { throw new ArgumentNullException("errorHandler"); } if (agent == null) { throw new ArgumentNullException("agent"); } _idleStrategy = idleStrategy; _errorHandler = errorHandler; _errorCounter = errorCounter; _agent = agent; } public static Thread StartOnThread(AgentRunner runner) { Thread thread = new Thread(runner.Run); ConfigureThread(thread, runner); thread.Start(); return thread; } public static Thread StartOnThread(AgentRunner runner, IThreadFactory threadFactory) { Thread thread = threadFactory.NewThread(runner.Run); ConfigureThread(thread, runner); thread.Start(); return thread; } private static void ConfigureThread(Thread thread, AgentRunner runner) { thread.Name = runner.Agent().RoleName(); thread.IsBackground = true; } public IAgent Agent() { return _agent; } public Thread Thread() { return _thread.Get(); } public void Run() { try { if (!_thread.CompareAndSet(null, System.Threading.Thread.CurrentThread)) { return; } IIdleStrategy idleStrategy = _idleStrategy; IAgent agent = _agent; try { agent.OnStart(); } catch (Exception exception) { HandleError(exception); _isRunning = false; } while (_isRunning && !DoDutyCycle(idleStrategy, agent)) { } try { agent.OnClose(); } catch (Exception exception2) { HandleError(exception2); } } finally { IsClosed = true; } } public void Dispose() { _isRunning = false; Thread andSet = _thread.GetAndSet(TOMBSTONE); if (andSet == null) { try { IsClosed = true; _agent.OnClose(); } catch (Exception exception) { _errorHandler(exception); } } if (TOMBSTONE == andSet) { return; } while (true) { try { andSet.Join(RETRY_CLOSE_TIMEOUT_MS); if (!andSet.IsAlive || IsClosed) { break; } Console.Error.WriteLine("Timeout waiting for agent '" + _agent.RoleName() + "' to close, Retrying..."); andSet.Interrupt(); } catch (ThreadInterruptedException) { System.Threading.Thread.CurrentThread.Interrupt(); break; } } } private bool DoDutyCycle(IIdleStrategy idleStrategy, IAgent agent) { try { idleStrategy.Idle(agent.DoWork()); } catch (ThreadInterruptedException) { System.Threading.Thread.CurrentThread.Interrupt(); return true; } catch (AgentTerminationException exception) { HandleError(exception); return true; } catch (Exception exception2) { HandleError(exception2); } return false; } private void HandleError(Exception exception) { if (_isRunning) { _errorCounter?.Increment(); _errorHandler(exception); } } } public class AgentTerminationException : Exception { public AgentTerminationException() { } public AgentTerminationException(string message) : base(message) { } } public class AtomicBoolean { private int _value; private const int TRUE = 1; private const int FALSE = 0; public AtomicBoolean(bool initialValue) { Interlocked.Exchange(ref _value, initialValue ? 1 : 0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool CompareAndSet(bool comparand, bool newValue) { int value = ToInt(newValue); int num = ToInt(comparand); return Interlocked.CompareExchange(ref _value, value, num) == num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Get() { return ToBool(Volatile.Read(ref _value)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator bool(AtomicBoolean value) { return value.Get(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool ToBool(int value) { if (value != 0 && value != 1) { ThrowHelper.ThrowArgumentOutOfRangeException("value"); } return value == 1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int ToInt(bool value) { if (!value) { return 0; } return 1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Set(bool value) { Volatile.Write(ref _value, ToInt(value)); } } public class AtomicLong { private long _long; public long Get() { return Interlocked.Read(ref _long); } public void LazySet(long newValue) { Interlocked.Exchange(ref _long, newValue); } public void Set(long value) { Interlocked.Exchange(ref _long, value); } public void Add(long add) { Interlocked.Add(ref _long, add); } public long IncrementAndGet() { return Interlocked.Increment(ref _long); } } public class AtomicReference<T> where T : class { private T _value; public T Get() { return Volatile.Read(ref _value); } public void LazySet(T newValue) { Volatile.Write(ref _value, newValue); } public T GetAndSet(T value) { return Interlocked.Exchange(ref _value, value); } public bool CompareAndSet(T compareValue, T newValue) { return Interlocked.CompareExchange(ref _value, newValue, compareValue) == compareValue; } } public class BackgroundThreadFactory : IThreadFactory { public static readonly BackgroundThreadFactory Instance = new BackgroundThreadFactory(); public Thread NewThread(ThreadStart runner) { return new Thread(runner) { IsBackground = true }; } } public class BackoffIdleStrategy : IIdleStrategy { private enum State { NOT_IDLE, SPINNING, YIELDING, PARKING } private readonly long _maxSpins; private readonly long _maxYields; private readonly int _minParkPeriodMs; private readonly int _maxParkPeriodMs; private State _state; private long _spins; private long _yields; private int _parkPeriodMs; public BackoffIdleStrategy(long maxSpins, long maxYields, long minParkPeriodMs, long maxParkPeriodMs) { _maxSpins = maxSpins; _maxYields = maxYields; _minParkPeriodMs = (int)minParkPeriodMs; _maxParkPeriodMs = (int)maxParkPeriodMs; _state = State.NOT_IDLE; } public void Idle(int workCount) { if (workCount > 0) { Reset(); } else { Idle(); } } public void Idle() { switch (_state) { case State.NOT_IDLE: _state = State.SPINNING; _spins++; break; case State.SPINNING: if (++_spins > _maxSpins) { _state = State.YIELDING; _yields = 0L; } break; case State.YIELDING: if (++_yields > _maxYields) { _state = State.PARKING; _parkPeriodMs = _minParkPeriodMs; } else { Thread.Yield(); } break; case State.PARKING: Thread.Sleep(_parkPeriodMs); _parkPeriodMs = Math.Min(_parkPeriodMs << 1, _maxParkPeriodMs); break; } } public void Reset() { _spins = 0L; _yields = 0L; _state = State.NOT_IDLE; } } public sealed class BusySpinIdleStrategy : IIdleStrategy { public void Idle(int workCount) { if (workCount <= 0) { Thread.SpinWait(0); } } public void Idle() { Thread.SpinWait(0); } public void Reset() { } } public class CachedEpochClock : IEpochClock { private long timeMs; public long Time() { return timeMs; } public void Update(long timeMs) { this.timeMs = timeMs; } } public class CompositeAgent : IAgent { private readonly IAgent[] _agents; private readonly string _roleName; private int _workIndex; public CompositeAgent(List<IAgent> agents) : this(agents.ToArray()) { } public CompositeAgent(params IAgent[] agents) { if (agents.Length == 0) { throw new ArgumentException("CompsiteAgent requires at least one sub-agent"); } _agents = agents; StringBuilder stringBuilder = new StringBuilder(agents.Length * 16); stringBuilder.Append('['); foreach (IAgent agent in agents) { Objects.RequireNonNull(agent, "Agent cannot be null"); stringBuilder.Append(agent.RoleName()).Append(','); } stringBuilder[stringBuilder.Length - 1] = ']'; _roleName = stringBuilder.ToString(); } public string RoleName() { return _roleName; } public void OnStart() { Exception ex = null; IAgent[] agents = _agents; foreach (IAgent agent in agents) { try { agent.OnStart(); } catch (Exception innerException) { if (ex == null) { ex = new Exception("CompositeAgent: underlying agent error on start", innerException); } } } if (ex != null) { throw ex; } } public int DoWork() { int num = 0; IAgent[] agents = _agents; while (_workIndex < agents.Length) { IAgent agent = agents[_workIndex++]; num += agent.DoWork(); } _workIndex = 0; return num; } public void OnClose() { Exception ex = null; IAgent[] agents = _agents; foreach (IAgent agent in agents) { try { agent.OnClose(); } catch (Exception innerException) { if (ex == null) { ex = new Exception("CompositeAgent: underlying agent error on close", innerException); } } } if (ex != null) { throw ex; } } } public class Configuration { public const long IDLE_MAX_SPINS = 10L; public const long IDLE_MAX_YIELDS = 40L; public const long IDLE_MIN_PARK_MS = 1L; public static readonly long IDLE_MAX_PARK_MS = 16L; } public class ControllableIdleStrategy : IIdleStrategy { public const int NOT_CONTROLLED = 0; public const int NOOP = 1; public const int BUSY_SPIN = 2; public const int YIELD = 3; public const int PARK = 4; private const long PARK_PERIOD_NANOSECONDS = 1000L; private readonly StatusIndicatorReader statusIndicatorReader; public ControllableIdleStrategy(StatusIndicatorReader statusIndicatorReader) { this.statusIndicatorReader = statusIndicatorReader; } public void Idle(int workCount) { if (workCount <= 0) { Idle(); } } public void Idle() { switch ((int)statusIndicatorReader.GetVolatile()) { case 2: Thread.SpinWait(0); break; case 3: Thread.Yield(); break; default: LockSupport.ParkNanos(1000L); break; case 1: break; } } public void Reset() { } public override string ToString() { return "ControllableIdleStrategy{statusIndicatorReader=" + statusIndicatorReader?.ToString() + "}"; } } public class CountedErrorHandler : IErrorHandler { private readonly ErrorHandler _errorHandler; private readonly AtomicCounter _errorCounter; public readonly ErrorHandler AsErrorHandler; public CountedErrorHandler(ErrorHandler errorHandler, AtomicCounter errorCounter) { Objects.RequireNonNull(errorHandler, "errorHandler"); Objects.RequireNonNull(errorCounter, "errorCounter"); _errorHandler = errorHandler; _errorCounter = errorCounter; AsErrorHandler = OnError; } public void OnError(Exception throwable) { _errorCounter.Increment(); _errorHandler(throwable); } } public class DefaultThreadFactory : IThreadFactory { public Thread NewThread(ThreadStart runner) { return new Thread(runner); } } public interface IAgent { void OnStart(); int DoWork(); void OnClose(); string RoleName(); } public interface IAtomicBuffer : IMutableDirectBuffer, IDirectBuffer, IComparable<IDirectBuffer> { void VerifyAlignment(); long GetLongVolatile(int index); void PutLongVolatile(int index, long value); void PutLongOrdered(int index, long value); long AddLongOrdered(int index, long increment); bool CompareAndSetLong(int index, long expectedValue, long updateValue); long GetAndAddLong(int index, long delta); int GetIntVolatile(int index); void PutIntVolatile(int index, int value); void PutIntOrdered(int index, int value); int AddIntOrdered(int index, int increment); bool CompareAndSetInt(int index, int expectedValue, int updateValue); int GetAndAddInt(int index, int delta); short GetShortVolatile(int index); void PutShortVolatile(int index, short value); byte GetByteVolatile(int index); void PutByteVolatile(int index, byte value); } public static class IdleStrategyFactory { public static IIdleStrategy Create(string strategyName, StatusIndicator controllableStatus) { switch (strategyName) { case "ControllableIdleStrategy": { ControllableIdleStrategy result = new ControllableIdleStrategy(controllableStatus); controllableStatus.SetOrdered(4L); return result; } case "YieldingIdleStrategy": return new YieldingIdleStrategy(); case "SleepingIdleStrategy": return new SleepingIdleStrategy(1); case "BusySpinIdleStrategy": return new BusySpinIdleStrategy(); case "NoOpIdleStrategy": return new NoOpIdleStrategy(); default: return new BackoffIdleStrategy(10L, 40L, 1L, Configuration.IDLE_MAX_PARK_MS); } } } public interface IEpochClock { long Time(); } public interface IIdleStrategy { void Idle(int workCount); void Idle(); void Reset(); } public interface ILock { void Lock(); void Unlock(); bool TryLock(); } public interface INanoClock { long NanoTime(); } public interface IThreadFactory { Thread NewThread(ThreadStart runner); } public delegate void MessageHandler(int msgTypeId, IMutableDirectBuffer buffer, int index, int length); public sealed class NoOpIdleStrategy : IIdleStrategy { public void Idle(int workCount) { } public void Idle() { } public void Reset() { } } public class NoOpLock : ILock { public static readonly NoOpLock Instance = new NoOpLock(); public void Lock() { } public void Unlock() { } public bool TryLock() { return true; } } public class NullEpochClock : IEpochClock { public long Time() { return 0L; } } public class ReentrantLock : ILock { private readonly object _lockObj = new object(); public void Lock() { Monitor.Enter(_lockObj); } public void Unlock() { Monitor.Exit(_lockObj); } public bool TryLock() { return Monitor.TryEnter(_lockObj); } } public class ShutdownSignalBarrier { private readonly ManualResetEventSlim _latch = new ManualResetEventSlim(initialState: false); public void Signal() { _latch.Set(); } public void Await() { try { _latch.Wait(); } catch (ThreadInterruptedException) { Thread.CurrentThread.Interrupt(); } } } public sealed class SleepingIdleStrategy : IIdleStrategy { private readonly int _sleepPeriodMs; public SleepingIdleStrategy(int sleepPeriodMs) { _sleepPeriodMs = sleepPeriodMs; } public void Idle(int workCount) { if (workCount <= 0) { Thread.Sleep(_sleepPeriodMs); } } public void Idle() { Thread.Sleep(_sleepPeriodMs); } public void Reset() { } } public class SpinWaitIdleStrategy : IIdleStrategy { private SpinWait _spinWait; public void Idle(int workCount) { if (workCount <= 0) { _spinWait.SpinOnce(); } } public void Idle() { _spinWait.SpinOnce(); } public void Reset() { _spinWait.Reset(); } } public abstract class StatusIndicator : StatusIndicatorReader { public abstract void SetOrdered(long value); } public abstract class StatusIndicatorReader { public abstract int Id { get; } public abstract long GetVolatile(); } public class StopwatchClock : INanoClock { private readonly Stopwatch _stopwatch; public StopwatchClock() { _stopwatch = Stopwatch.StartNew(); } public long NanoTime() { return _stopwatch.ElapsedTicks / Stopwatch.Frequency * 1000000000; } } public class SystemEpochClock : IEpochClock { public static readonly SystemEpochClock INSTANCE = new SystemEpochClock(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public long Time() { return UnixTimeConverter.CurrentUnixTimeMillis(); } } public class SystemNanoClock : INanoClock { public static readonly SystemNanoClock INSTANCE = new SystemNanoClock(); private readonly Stopwatch _stopwatch; public SystemNanoClock() { _stopwatch = Stopwatch.StartNew(); } public long NanoTime() { return _stopwatch.ElapsedMilliseconds * 1000 * 1000; } } public class UnsafeBuffer : IAtomicBuffer, IMutableDirectBuffer, IDirectBuffer, IComparable<IDirectBuffer>, IDisposable { public const int ALIGNMENT = 8; public static readonly string DISABLE_BOUNDS_CHECKS_PROP_NAME = "AGRONA_DISABLE_BOUNDS_CHECKS"; private static readonly bool SHOULD_BOUNDS_CHECK = !bool.Parse(Environment.GetEnvironmentVariable(DISABLE_BOUNDS_CHECKS_PROP_NAME) ?? "false"); private unsafe byte* _pBuffer; private bool _disposed; private GCHandle _pinnedGcHandle; private bool _needToFreeGcHandle; public unsafe IntPtr BufferPointer { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new IntPtr(_pBuffer); } } public byte[] ByteArray { get; private set; } public ByteBuffer ByteBuffer { get; private set; } public int Capacity { get; private set; } public bool IsExpandable => false; public UnsafeBuffer(byte[] buffer) { Wrap(buffer); } public UnsafeBuffer() { Capacity = -1; } public UnsafeBuffer(byte[] buffer, int offset, int length) { Wrap(buffer, offset, length); } public UnsafeBuffer(ByteBuffer buffer) { Wrap(buffer); } public UnsafeBuffer(IDirectBuffer buffer) { Wrap(buffer); } public UnsafeBuffer(IDirectBuffer buffer, int offset, int length) { Wrap(buffer, offset, length); } public UnsafeBuffer(IntPtr address, int length) { Wrap(address, length); } public UnsafeBuffer(IntPtr address, int offset, int length) { Wrap(address, offset, length); } public UnsafeBuffer(MappedByteBuffer buffer) { Wrap(buffer.Pointer, 0, (int)buffer.Capacity); } public unsafe void Wrap(byte[] buffer) { if (buffer == null) { ThrowHelper.ThrowArgumentNullException("buffer"); } FreeGcHandle(); _pinnedGcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned); _needToFreeGcHandle = true; _pBuffer = (byte*)_pinnedGcHandle.AddrOfPinnedObject().ToPointer(); Capacity = buffer.Length; ByteArray = buffer; ByteBuffer = null; } public unsafe void Wrap(byte[] buffer, int offset, int length) { if (buffer == null) { ThrowHelper.ThrowArgumentException("buffer"); } if (SHOULD_BOUNDS_CHECK) { int num = buffer.Length; if (offset != 0 && (offset < 0 || offset > num - 1)) { ThrowHelper.ThrowArgumentException("offset=" + offset + " not valid for capacity=" + num); } if (length < 0 || length > num - offset) { ThrowHelper.ThrowArgumentException("offset=" + offset + " length=" + length + " not valid for capacity=" + num); } } FreeGcHandle(); _pinnedGcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned); _needToFreeGcHandle = true; _pBuffer = (byte*)_pinnedGcHandle.AddrOfPinnedObject().ToPointer() + offset; Capacity = length; ByteArray = buffer; ByteBuffer = null; } public unsafe void Wrap(IDirectBuffer buffer) { FreeGcHandle(); _needToFreeGcHandle = false; _pBuffer = (byte*)buffer.BufferPointer.ToPointer(); Capacity = buffer.Capacity; ByteArray = buffer.ByteArray; ByteBuffer = buffer.ByteBuffer; } public unsafe void Wrap(ByteBuffer buffer) { FreeGcHandle(); _needToFreeGcHandle = false; _pBuffer = (byte*)buffer.BufferPointer.ToPointer(); Capacity = buffer.Capacity; ByteArray = null; ByteBuffer = buffer; } public unsafe void Wrap(IDirectBuffer buffer, int offset, int length) { if (SHOULD_BOUNDS_CHECK) { int capacity = buffer.Capacity; if (offset != 0 && (offset < 0 || offset > capacity - 1)) { ThrowHelper.ThrowArgumentException("offset=" + offset + " not valid for capacity=" + capacity); } if (length < 0 || length > capacity - offset) { ThrowHelper.ThrowArgumentException("offset=" + offset + " length=" + length + " not valid for capacity=" + capacity); } } FreeGcHandle(); _needToFreeGcHandle = false; _pBuffer = (byte*)buffer.BufferPointer.ToPointer() + offset; Capacity = length; ByteArray = buffer.ByteArray; ByteBuffer = buffer.ByteBuffer; } public unsafe void Wrap(IntPtr pointer, int length) { FreeGcHandle(); _needToFreeGcHandle = false; _pBuffer = (byte*)pointer.ToPointer(); Capacity = length; ByteBuffer = null; ByteArray = null; } public void Wrap(int memoryAddress, int length) { } public unsafe void Wrap(IntPtr pointer, int offset, int length) { FreeGcHandle(); _needToFreeGcHandle = false; _pBuffer = (byte*)pointer.ToPointer() + offset; Capacity = length; ByteBuffer = null; ByteArray = null; } public unsafe void Wrap(byte* pointer, int length) { FreeGcHandle(); _needToFreeGcHandle = false; _pBuffer = pointer; Capacity = length; ByteBuffer = null; ByteArray = null; } public unsafe void Wrap(byte* pointer, int offset, int length) { FreeGcHandle(); _needToFreeGcHandle = false; _pBuffer = pointer + offset; Capacity = length; ByteBuffer = null; ByteArray = null; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void SetMemory(int index, int length, byte value) { BoundsCheck0(index, length); Unsafe.InitBlock(_pBuffer + index, value, (uint)length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CheckLimit(int limit) { if (limit > Capacity) { ThrowHelper.ThrowIndexOutOfRangeException($"limit={limit:D} is beyond capacity={Capacity:D}"); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void VerifyAlignment() { long num = new IntPtr(_pBuffer).ToInt64(); if ((num & 7) != 0L) { ThrowHelper.ThrowInvalidOperationException($"AtomicBuffer is not correctly aligned: addressOffset={num:D} in not divisible by {8:D}"); } } public unsafe long GetLong(int index, ByteOrder byteOrder) { BoundsCheck0(index, 8); long value = *(long*)(_pBuffer + index); return EndianessConverter.ApplyInt64(byteOrder, value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe long GetLong(int index) { BoundsCheck0(index, 8); return *(long*)(_pBuffer + index); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutLong(int index, long value) { BoundsCheck0(index, 8); *(long*)(_pBuffer + index) = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutLong(int index, long value, ByteOrder byteOrder) { BoundsCheck0(index, 8); value = EndianessConverter.ApplyInt64(byteOrder, value); *(long*)(_pBuffer + index) = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe long GetLongVolatile(int index) { BoundsCheck0(index, 8); return Volatile.Read(ref *(long*)(_pBuffer + index)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutLongVolatile(int index, long value) { BoundsCheck0(index, 8); Interlocked.Exchange(ref *(long*)(_pBuffer + index), value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutLongOrdered(int index, long value) { BoundsCheck0(index, 8); Volatile.Write(ref *(long*)(_pBuffer + index), value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public long AddLongOrdered(int index, long increment) { BoundsCheck0(index, 8); long @long = GetLong(index); PutLongOrdered(index, @long + increment); return @long; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe bool CompareAndSetLong(int index, long expectedValue, long updateValue) { BoundsCheck0(index, 8); return Interlocked.CompareExchange(ref *(long*)(_pBuffer + index), updateValue, expectedValue) == expectedValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe long GetAndAddLong(int index, long delta) { BoundsCheck0(index, 8); return Interlocked.Add(ref *(long*)(_pBuffer + index), delta) - delta; } public unsafe void PutInt(int index, int value, ByteOrder byteOrder) { BoundsCheck0(index, 4); value = EndianessConverter.ApplyInt32(byteOrder, value); *(int*)(_pBuffer + index) = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe int GetInt(int index) { BoundsCheck0(index, 4); return *(int*)(_pBuffer + index); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe int GetInt(int index, ByteOrder byteOrder) { BoundsCheck0(index, 4); int value = *(int*)(_pBuffer + index); return EndianessConverter.ApplyInt32(byteOrder, value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutInt(int index, int value) { BoundsCheck0(index, 4); *(int*)(_pBuffer + index) = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe int GetIntVolatile(int index) { BoundsCheck0(index, 4); return Volatile.Read(ref *(int*)(_pBuffer + index)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutIntVolatile(int index, int value) { BoundsCheck0(index, 4); Interlocked.Exchange(ref *(int*)(_pBuffer + index), value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutIntOrdered(int index, int value) { BoundsCheck0(index, 4); Volatile.Write(ref *(int*)(_pBuffer + index), value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int AddIntOrdered(int index, int increment) { BoundsCheck0(index, 4); int @int = GetInt(index); PutIntOrdered(index, @int + increment); return @int; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe bool CompareAndSetInt(int index, int expectedValue, int updateValue) { BoundsCheck0(index, 4); return Interlocked.CompareExchange(ref *(int*)(_pBuffer + index), updateValue, expectedValue) == expectedValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe int GetAndAddInt(int index, int delta) { BoundsCheck0(index, 4); return Interlocked.Add(ref *(int*)(_pBuffer + index), delta) - delta; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe double GetDouble(int index, ByteOrder byteOrder) { BoundsCheck0(index, 8); return EndianessConverter.ApplyDouble(byteOrder, *(double*)(_pBuffer + index)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutDouble(int index, double value, ByteOrder byteOrder) { BoundsCheck0(index, 8); value = EndianessConverter.ApplyDouble(byteOrder, value); *(double*)(_pBuffer + index) = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe double GetDouble(int index) { BoundsCheck0(index, 8); return *(double*)(_pBuffer + index); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutDouble(int index, double value) { BoundsCheck0(index, 8); *(double*)(_pBuffer + index) = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe float GetFloat(int index, ByteOrder byteOrder) { BoundsCheck0(index, 4); return EndianessConverter.ApplyFloat(byteOrder, *(float*)(_pBuffer + index)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutFloat(int index, float value, ByteOrder byteOrder) { BoundsCheck0(index, 4); value = EndianessConverter.ApplyFloat(byteOrder, value); *(float*)(_pBuffer + index) = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe float GetFloat(int index) { BoundsCheck0(index, 4); return *(float*)(_pBuffer + index); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutFloat(int index, float value) { BoundsCheck0(index, 4); *(float*)(_pBuffer + index) = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe short GetShort(int index) { BoundsCheck0(index, 2); return *(short*)(_pBuffer + index); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe short GetShort(int index, ByteOrder byteOrder) { BoundsCheck0(index, 2); short value = *(short*)(_pBuffer + index); return EndianessConverter.ApplyInt16(byteOrder, value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutShort(int index, short value) { BoundsCheck0(index, 2); *(short*)(_pBuffer + index) = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutShort(int index, short value, ByteOrder byteOrder) { BoundsCheck0(index, 2); value = EndianessConverter.ApplyInt16(byteOrder, value); *(short*)(_pBuffer + index) = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe short GetShortVolatile(int index) { BoundsCheck0(index, 2); return Volatile.Read(ref *(short*)(_pBuffer + index)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutShortVolatile(int index, short value) { BoundsCheck0(index, 2); Volatile.Write(ref *(short*)(_pBuffer + index), value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe byte GetByte(int index) { BoundsCheck(index); return _pBuffer[index]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutByte(int index, byte value) { BoundsCheck(index); _pBuffer[index] = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe byte GetByteVolatile(int index) { BoundsCheck(index); return Volatile.Read(ref _pBuffer[index]); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutByteVolatile(int index, byte value) { BoundsCheck(index); Volatile.Write(ref _pBuffer[index], value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void GetBytes(int index, byte[] dst) { GetBytes(index, dst, 0, dst.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void GetBytes(int index, byte[] dst, int offset, int length) { if (length != 0) { BoundsCheck0(index, length); if (SHOULD_BOUNDS_CHECK) { BufferUtil.BoundsCheck(dst, offset, length); } byte* source = _pBuffer + index; fixed (byte* destination = &dst[offset]) { ByteUtil.MemoryCopy(destination, source, (uint)length); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void GetBytes(int index, IMutableDirectBuffer dstBuffer, int dstIndex, int length) { dstBuffer.PutBytes(dstIndex, this, index, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PutBytes(int index, byte[] src) { PutBytes(index, src, 0, src.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutBytes(int index, byte[] src, int offset, int length) { if (length != 0) { BoundsCheck0(index, length); if (SHOULD_BOUNDS_CHECK) { BufferUtil.BoundsCheck(src, offset, length); } byte* destination = _pBuffer + index; fixed (byte* source = &src[offset]) { ByteUtil.MemoryCopy(destination, source, (uint)length); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutBytes(int index, IDirectBuffer srcBuffer, int srcIndex, int length) { if (length != 0) { BoundsCheck0(index, length); srcBuffer.BoundsCheck(srcIndex, length); byte* destination = _pBuffer + index; byte* source = (byte*)srcBuffer.BufferPointer.ToPointer() + srcIndex; ByteUtil.MemoryCopy(destination, source, (uint)length); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe char GetChar(int index) { BoundsCheck0(index, 2); return *(char*)(_pBuffer + index); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void PutChar(int index, char value) { BoundsCheck0(index, 2); *(char*)(_pBuffer + index) = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public string GetStringUtf8(int index) { int @int = GetInt(index); return GetStringUtf8(index, @int); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public string GetStringAscii(int index) { int @int = GetInt(index); return GetStringAscii(index, @int); } public int GetStringAscii(int index, StringBuilder appendable) { int @int = GetInt(index); return GetStringAscii(index, @int, appendable); } public unsafe int GetStringAscii(int index, int length, StringBuilder appendable) { int i = index + 4; for (int num = index + 4 + length; i < num; i++) { char c = *(char*)(_pBuffer + index); appendable.Append((c > '\u007f') ? '?' : c); } return length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public string GetStringUtf8(int index, int length) { byte[] array = new byte[length]; GetBytes(index + 4, array); return Encoding.UTF8.GetString(array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public string GetStringAscii(int index, int length) { byte[] array = new byte[length]; GetBytes(index + 4, array); return Encoding.ASCII.GetString(array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int PutStringUtf8(int index, string value) { return PutStringUtf8(index, value, int.MaxValue); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int PutStringAscii(int index, string value) { return PutStringAscii(index, value, int.MaxValue); } public unsafe int PutStringWithoutLengthAscii(int index, string value) { int num = value?.Length ?? 0; BoundsCheck0(index, num); for (int i = 0; i < num; i++) { char c = value[i]; if (c > '\u007f') { c = '?'; } *(char*)(_pBuffer + index + i) = c; } return num; } public unsafe int PutStringWithoutLengthAscii(int index, string value, int valueOffset, int length) { int num = ((value != null) ? Math.Min(value.Length - valueOffset, length) : 0); BoundsCheck0(index, num); for (int i = 0; i < num; i++) { char c = value[valueOffset + i]; if (c > '\u007f') { c = '?'; } *(char*)(_pBuffer + index + i) = c; } return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int PutStringUtf8(int index, string value, int maxEncodedSize) { byte[] array = ((value == null) ? BufferUtil.NullBytes : Encoding.UTF8.GetBytes(value)); if (array.Length > maxEncodedSize) { ThrowHelper.ThrowArgumentException("Encoded string larger than maximum size: " + maxEncodedSize); } PutInt(index, array.Length); PutBytes(index + 4, array); return 4 + array.Length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int PutStringAscii(int index, string value, int maxEncodedSize) { byte[] array = ((value == null) ? BufferUtil.NullBytes : Encoding.ASCII.GetBytes(value)); if (array.Length > maxEncodedSize) { ThrowHelper.ThrowArgumentException("Encoded string larger than maximum size: " + maxEncodedSize); } PutInt(index, array.Length); PutBytes(index + 4, array); return 4 + array.Length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public string GetStringWithoutLengthUtf8(int index, int length) { byte[] array = new byte[length]; GetBytes(index, array); return Encoding.UTF8.GetString(array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public string GetStringWithoutLengthAscii(int index, int length) { byte[] array = new byte[length]; GetBytes(index, array); return Encoding.ASCII.GetString(array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int PutStringWithoutLengthUtf8(int index, string value) { byte[] array = ((value == null) ? BufferUtil.NullBytes : Encoding.UTF8.GetBytes(value)); PutBytes(index, array); return array.Length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void BoundsCheck(int index) { if (SHOULD_BOUNDS_CHECK && (index < 0 || index >= Capacity)) { ThrowHelper.ThrowIndexOutOfRangeException($"index={index:D}, capacity={Capacity:D}"); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void BoundsCheck0(int index, int length) { if (SHOULD_BOUNDS_CHECK) { long num = (long)index + (long)length; if (index < 0 || num > Capacity) { ThrowHelper.ThrowIndexOutOfRangeException($"index={index:D}, length={length:D}, capacity={Capacity:D}"); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void BoundsCheck(int index, int length) { BoundsCheck0(index, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe int CompareTo(IDirectBuffer that) { int capacity = Capacity; int capacity2 = that.Capacity; byte* pBuffer = _pBuffer; byte* ptr = (byte*)that.BufferPointer.ToPointer(); int i = 0; for (int num = Math.Min(capacity, capacity2); i < num; i++) { int num2 = pBuffer[i] - ptr[i]; if (num2 != 0) { return num2; } } if (capacity != capacity2) { return capacity - capacity2; } return 0; } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } ~UnsafeBuffer() { Dispose(disposing: false); } private void Dispose(bool disposing) { if (!_disposed) { FreeGcHandle(); ByteArray = null; ByteBuffer = null; _disposed = true; } } private void FreeGcHandle() { if (_needToFreeGcHandle) { _pinnedGcHandle.Free(); _needToFreeGcHandle = false; } } } public sealed class YieldingIdleStrategy : IIdleStrategy { public static readonly YieldingIdleStrategy INSTANCE = new YieldingIdleStrategy(); public void Idle(int workCount) { if (workCount <= 0) { Thread.Yield(); } } public void Idle() { Thread.Yield(); } public void Reset() { } } } namespace Adaptive.Agrona.Concurrent.Status { public class AtomicCounter : IDisposable { private readonly int _offset; private readonly IAtomicBuffer _buffer; private readonly CountersManager _countersManager; public int Id { get; } public virtual bool IsClosed { get; private set; } public AtomicCounter(IAtomicBuffer buffer, int counterId) : this(buffer, counterId, null) { } public AtomicCounter(IAtomicBuffer buffer, int counterId, CountersManager countersManager) { _buffer = buffer; Id = counterId; _countersManager = countersManager; _offset = CountersReader.CounterOffset(counterId); buffer.BoundsCheck(_offset, 8); } public long Increment() { return _buffer.GetAndAddLong(_offset, 1L); } public long IncrementOrdered() { return _buffer.AddLongOrdered(_offset, 1L); } public void Set(long value) { _buffer.PutLongVolatile(_offset, value); } public void SetOrdered(long value) { _buffer.PutLongOrdered(_offset, value); } public long GetAndAdd(long increment) { return _buffer.GetAndAddLong(_offset, increment); } public long GetAndAddOrdered(long increment) { return _buffer.AddLongOrdered(_offset, increment); } public bool CompareAndSet(long expectedValue, long updateValue) { return _buffer.CompareAndSetLong(_offset, expectedValue, updateValue); } public long Get() { return _buffer.GetLongVolatile(_offset); } public long GetWeak() { return _buffer.GetLong(_offset); } public bool ProposeMaxOrdered(long proposedValue) { bool result = false; if (_buffer.GetLong(_offset) < proposedValue) { _buffer.PutLongOrdered(_offset, proposedValue); result = true; } return result; } public virtual void Dispose() { if (!IsClosed) { IsClosed = true; _countersManager?.Free(Id); } } } public class AtomicLongPosition : IPosition, IReadablePosition, IDisposable { private readonly AtomicLong _value = new AtomicLong(); public int Id => 0; public void Dispose() { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public long GetVolatile() { return _value.Get(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public long Get() { return _value.Get(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Set(long value) { _value.Set(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetOrdered(long value) { _value.Set(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetVolatile(long value) { _value.Set(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool ProposeMax(long proposedValue) { return ProposeMaxOrdered(proposedValue); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool ProposeMaxOrdered(long proposedValue) { bool result = false; if (Get() < proposedValue) { SetOrdered(proposedValue); result = true; } return result; } } public class CountersManager : CountersReader { private readonly long _freeToReuseTimeoutMs; private int _idHighWaterMark = -1; private readonly List<int> _freeList = new List<int>(); private readonly IEpochClock _epochClock; public CountersManager(IAtomicBuffer metaDataBuffer, IAtomicBuffer valuesBuffer, Encoding labelCharset, IEpochClock epochClock, long freeToReuseTimeoutMs) : base(metaDataBuffer, valuesBuffer, labelCharset) { valuesBuffer.VerifyAlignment(); _epochClock = epochClock; _freeToReuseTimeoutMs = freeToReuseTimeoutMs; if (metaDataBuffer.Capacity < valuesBuffer.Capacity * 2) { throw new ArgumentException("Meta data buffer not sufficiently large"); } } public CountersManager(IAtomicBuffer metaDataBuffer, IAtomicBuffer valuesBuffer) : base(metaDataBuffer, valuesBuffer) { valuesBuffer.VerifyAlignment(); _epochClock = new NullEpochClock(); if (metaDataBuffer.Capacity < valuesBuffer.Capacity * 2) { throw new ArgumentException("Meta data buffer not sufficiently large"); } } public CountersManager(IAtomicBuffer metaDataBuffer, IAtomicBuffer valuesBuffer, Encoding labelCharset) : this(metaDataBuffer, valuesBuffer, labelCharset, new NullEpochClock(), 0L) { valuesBuffer.VerifyAlignment(); if (metaDataBuffer.Capacity < valuesBuffer.Capacity * 2) { throw new ArgumentException("Meta data buffer not sufficiently large"); } } public int Allocate(string label, int typeId = 0) { int num = NextCounterId(); CheckCountersCapacity(num); int num2 = CountersReader.MetaDataOffset(num); CheckMetaDataCapacity(num2); try { base.MetaDataBuffer.PutInt(num2 + CountersReader.TYPE_ID_OFFSET, typeId); base.MetaDataBuffer.PutLong(num2 + CountersReader.FREE_FOR_REUSE_DEADLINE_OFFSET, CountersReader.NOT_FREE_TO_REUSE); PutLabel(num2, label); base.MetaDataBuffer.PutIntOrdered(num2, 1); return num; } catch (Exception) { _freeList.Add(num); throw; } } public int Allocate(string label, int typeId, Action<IMutableDirectBuffer> keyFunc) { int num = NextCounterId(); CheckCountersCapacity(num); int num2 = CountersReader.MetaDataOffset(num); CheckMetaDataCapacity(num2); try { base.MetaDataBuffer.PutInt(num2 + CountersReader.TYPE_ID_OFFSET, typeId); keyFunc(new UnsafeBuffer(base.MetaDataBuffer, num2 + CountersReader.KEY_OFFSET, CountersReader.MAX_KEY_LENGTH)); base.MetaDataBuffer.PutLong(num2 + CountersReader.FREE_FOR_REUSE_DEADLINE_OFFSET, CountersReader.NOT_FREE_TO_REUSE); PutLabel(num2, label); base.MetaDataBuffer.PutIntOrdered(num2, 1); return num; } catch (Exception) { _freeList.Add(num); throw; } } public int Allocate(int typeId, IDirectBuffer keyBuffer, int keyOffset, int keyLength, IDirectBuffer labelBuffer, int labelOffset, int labelLength) { int num = NextCounterId(); CheckCountersCapacity(num); int num2 = CountersReader.MetaDataOffset(num); CheckMetaDataCapacity(num2); try { base.MetaDataBuffer.PutInt(num2 + CountersReader.TYPE_ID_OFFSET, typeId); base.MetaDataBuffer.PutLong(num2 + CountersReader.FREE_FOR_REUSE_DEADLINE_OFFSET, CountersReader.NOT_FREE_TO_REUSE); int length; if (keyBuffer != null) { length = Math.Min(keyLength, CountersReader.MAX_KEY_LENGTH); base.MetaDataBuffer.PutBytes(num2 + CountersReader.KEY_OFFSET, keyBuffer, keyOffset, length); } length = Math.Min(labelLength, CountersReader.MAX_LABEL_LENGTH); base.MetaDataBuffer.PutInt(num2 + CountersReader.LABEL_OFFSET, length); base.MetaDataBuffer.PutBytes(num2 + CountersReader.LABEL_OFFSET + 4, labelBuffer, labelOffset, length); base.MetaDataBuffer.PutIntOrdered(num2, 1); return num; } catch (Exception) { _freeList.Add(num); throw; } } public AtomicCounter NewCounter(string label) { return new AtomicCounter(base.ValuesBuffer, Allocate(label), this); } public AtomicCounter NewCounter(string label, int typeId) { return new AtomicCounter(base.ValuesBuffer, Allocate(label, typeId), this); } public AtomicCounter NewCounter(string label, int typeId, Action<IMutableDirectBuffer> keyFunc) { return new AtomicCounter(base.ValuesBuffer, Allocate(label, typeId, keyFu