using System;
using System.Collections;
using System.Collections.Concurrent;
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 = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Adaptive Financial Consulting Ltd.")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright Adaptive Financial Consulting Ltd.")]
[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.49.0.0")]
[assembly: AssemblyInformationalVersion("1.49.0+9179232fd342a742df7b8c88046b0306e4a0fc2e")]
[assembly: AssemblyProduct("Agrona libraries initially included in Aeron Client")]
[assembly: AssemblyTitle("Adaptive.Agrona")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.49.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;
private static readonly ThreadLocal<Random> threadLocalRandom;
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;
threadLocalRandom = new ThreadLocal<Random>(() => new Random());
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;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long Align(long value, long alignment)
{
return (value + (alignment - 1)) & -alignment;
}
[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 static int GenerateRandomisedId()
{
return threadLocalRandom.Value.Next();
}
}
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 static ByteBuffer Allocate(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 unsafe byte Get(int index)
{
return ((byte*)BufferPointer.ToPointer())[index];
}
}
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 Dispose(IDisposable disposable)
{
disposable?.Dispose();
}
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 static void CloseAll<T>(IErrorHandler errorHandler, ICollection<T> disposables) where T : IDisposable
{
if (disposables == null)
{
return;
}
NullReferenceException ex = null;
List<Exception> list = null;
foreach (T disposable in disposables)
{
if (disposable == null)
{
continue;
}
try
{
disposable.Dispose();
}
catch (Exception ex2)
{
if (errorHandler == null)
{
if (ex == null)
{
ex = new NullReferenceException("errorHandler is null");
}
if (list == null)
{
list = new List<Exception>();
}
list.Add(ex2);
}
else
{
errorHandler.OnError(ex2);
}
}
}
if (ex == null)
{
return;
}
if (list.Count > 0)
{
List<Exception> list2 = new List<Exception>(1 + list.Count);
list2.Add(ex);
list2.AddRange(list);
throw new AggregateException("One or more errors occurred while disposing.", list2);
}
throw ex;
}
}
public interface DelegatingErrorHandler : IErrorHandler
{
void Next(IErrorHandler errorHandler);
}
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 void TimestampRelease(long timestamp)
{
buffer.PutLongRelease(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 ParentDirectory()
{
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");
}
}
public static void EnsureMarkFileLink(DirectoryInfo serviceDir, FileInfo actualFile, string linkFilename)
{
string fullName;
try
{
fullName = serviceDir.FullName;
}
catch (Exception)
{
throw new ArgumentException("Failed to resolve canonical path for serviceDir=" + serviceDir);
}
string fullName2;
try
{
fullName2 = actualFile.Directory.FullName;
}
catch (Exception)
{
throw new ArgumentException("Failed to resolve canonical path for markFile parent dir of " + actualFile);
}
string path = Path.Combine(fullName, linkFilename);
if (fullName.Equals(fullName2, StringComparison.OrdinalIgnoreCase))
{
try
{
if (File.Exists(path))
{
File.Delete(path);
}
return;
}
catch (IOException innerException)
{
throw new Exception("Failed to remove old link file", innerException);
}
}
try
{
File.WriteAllText(path, fullName2, Encoding.ASCII);
}
catch (IOException innerException2)
{
throw new Exception("Failed to create link for mark file directory", innerException2);
}
}
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 static T RequireNonNull<T>(T obj)
{
if (obj == null)
{
throw new NullReferenceException();
}
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 Force()
{
_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 IErrorHandler _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(IErrorHandler 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.OnError(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.OnError(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 IErrorHandler _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, IErrorHandler 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.OnError(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.OnError(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)
{
return value ? 1 : 0;
}
[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 IErrorHandler _errorHandler;
private readonly AtomicCounter _errorCounter;
public readonly ErrorHandler AsErrorHandler;
public CountedErrorHandler(IErrorHandler 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.OnError(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);
void PutLongRelease(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);
void PutIntRelease(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 sealed class ShutdownSignalBarrier : IDisposable
{
public delegate void SignalHandler();
private static readonly SignalHandler NO_OP_SIGNAL_HANDLER;
private static readonly ConcurrentDictionary<ShutdownSignalBarrier, byte> BARRIERS;
private readonly ManualResetEventSlim _waitEvent = new ManualResetEventSlim(initialState: false);
private readonly ManualResetEventSlim _closeEvent = new ManualResetEventSlim(initialState: false);
private int _signaled;
private readonly SignalHandler _signalHandler;
static ShutdownSignalBarrier()
{
NO_OP_SIGNAL_HANDLER = delegate
{
};
BARRIERS = new ConcurrentDictionary<ShutdownSignalBarrier, byte>();
AppDomain.CurrentDomain.ProcessExit += delegate
{
AwaitTermination(SignalAndClearAll(), TimeSpan.FromSeconds(10.0), Console.Out);
};
Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
{
AwaitTermination(SignalAndClearAll(), TimeSpan.FromSeconds(10.0), Console.Out);
e.Cancel = false;
};
}
public ShutdownSignalBarrier()
: this(NO_OP_SIGNAL_HANDLER)
{
}
public ShutdownSignalBarrier(SignalHandler signalHandler)
{
if (signalHandler == null)
{
throw new ArgumentNullException("signalHandler");
}
_signalHandler = signalHandler;
BARRIERS.TryAdd(this, 0);
}
public void Signal()
{
if (Interlocked.CompareExchange(ref _signaled, 1, 0) == 0)
{
BARRIERS.TryRemove(this, out var _);
_waitEvent.Set();
_signalHandler();
}
}
public void SignalAll()
{
SignalAndClearAll();
}
public void Remove()
{
BARRIERS.TryRemove(this, out var _);
}
public void Await()
{
try
{
_waitEvent.Wait();
}
catch (ThreadInterruptedException)
{
try
{
Signal();
}
finally
{
Thread.CurrentThread.Interrupt();
}
}
}
public void Close()
{
try
{
Signal();
}
finally
{
_closeEvent.Set();
}
}
public void Dispose()
{
Close();
}
public override string ToString()
{
return "ShutdownSignalBarrier{waitEvent=" + _waitEvent.IsSet + ", closeEvent=" + _closeEvent.IsSet + ", signaled=" + (_signaled == 1) + "}";
}
private static ShutdownSignalBarrier[] SignalAndClearAll()
{
ShutdownSignalBarrier[] array = new ShutdownSignalBarrier[BARRIERS.Count];
BARRIERS.Keys.CopyTo(array, 0);
BARRIERS.Clear();
List<Exception> list = null;
for (int i = 0; i < array.Length; i++)
{
try
{
array[i].Signal();
}
catch (Exception item)
{
if (list == null)
{
list = new List<Exception>(4);
}
list.Add(item);
}
}
if (list != null && list.Count > 0)
{
throw new AggregateException("One or more barriers threw during Signal()", list);
}
return array;
}
private static void AwaitTermination(ShutdownSignalBarrier[] barriers, TimeSpan timeoutPerBarrier, TextWriter output)
{
if (barriers == null || barriers.Length == 0)
{
return;
}
bool flag = false;
try
{
ShutdownSignalBarrier[] array = (ShutdownSignalBarrier[])barriers.Clone();
int num = 0;
do
{
for (int i = 0; i < array.Length; i++)
{
ShutdownSignalBarrier shutdownSignalBarrier = array[i];
if (shutdownSignalBarrier == null)
{
continue;
}
try
{
if (shutdownSignalBarrier._closeEvent.Wait(timeoutPerBarrier))
{
num++;
array[i] = null;
}
else
{
output.WriteLine("WARN: ShutdownSignalBarrier hasn't terminated in " + timeoutPerBarrier.TotalSeconds.ToString("N0") + " seconds! Did you forget to call Close()/Dispose() on it?");
}
}
catch (ThreadInterruptedException)
{
flag = true;
break;
}
}
}
while (num < array.Length);
}
finally
{
if (flag)
{
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)
{
Reset();
}
else
{
_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()
{
Wrap(Array.Empty<byte>());
}
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 UnsafeBuffer(MappedByteBuffer buffer, int offset, int length)
{
Wrap(buffer.Pointer, offset, length);
}
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 unsafe void PutLongRelease(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 unsafe void PutIntRelease(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.Yiel