Я создаю структуру данных, предназначенную только для добавления, которая находится в памяти и добавляет в эту память записи, сериализованные в массивы байтов. Мне нужно, чтобы это было потокобезопасным и чрезвычайно быстрым, поэтому я придумал следующий код, который до сих пор работает отлично (это псевдокод, реальная версия более сложна и делает некоторые другие вещи, но просто для понимания)
public sealed class MemoryList : IDisposable
{
private int nextOffset = 0;
private readonly MemoryMappedFile file;
private readonly MemoryMappedViewAccessor va;
public MemoryList(uint capacity)
{
// Some checks on capacity here
var mapName = Guid.NewGuid().ToString("N");
this.file = MemoryMappedFile.CreateNew(mapName, capacity);
this.va = file.CreateViewAccessor(0, capacity);
}
public void AppendMessage(byte[] messagePayload)
{
if (messagePayload == null)
throw new ArgumentNullException(nameof(messagePayload));
if (messagePayload.Length == 0)
throw new ArgumentOutOfRangeException(nameof(messagePayload));
if (TryReserveCapacity(messagePayload.Length, out var offsetToWriteTo))
{
this.va.Write(offsetToWriteTo, messagePayload.Length);
this.va.WriteArray(offsetToWriteTo + sizeof(int), messagePayload, 0, messagePayload.Length);
}
}
private bool TryReserveCapacity(int dataLength, out long reservedOffset)
{
// reserve enough room to store data + its size
var packetSize = sizeof(int) + dataLength;
reservedOffset = Interlocked.Add(ref this.nextOffset, packetSize) - packetSize;
if (this.nextOffset
Подробнее здесь: [url]https://stackoverflow.com/questions/56807807/atomically-change-two-numbers-without-using-locks[/url]
Я создаю структуру данных, предназначенную только для добавления, которая находится в памяти и добавляет в эту память записи, сериализованные в массивы байтов. Мне нужно, чтобы это было потокобезопасным и чрезвычайно быстрым, поэтому я придумал следующий код, который до сих пор работает отлично (это псевдокод, реальная версия более сложна и делает некоторые другие вещи, но просто для понимания)
[code]public sealed class MemoryList : IDisposable { private int nextOffset = 0; private readonly MemoryMappedFile file; private readonly MemoryMappedViewAccessor va;
public MemoryList(uint capacity) { // Some checks on capacity here var mapName = Guid.NewGuid().ToString("N"); this.file = MemoryMappedFile.CreateNew(mapName, capacity); this.va = file.CreateViewAccessor(0, capacity); }
public void AppendMessage(byte[] messagePayload) { if (messagePayload == null) throw new ArgumentNullException(nameof(messagePayload)); if (messagePayload.Length == 0) throw new ArgumentOutOfRangeException(nameof(messagePayload));
if (TryReserveCapacity(messagePayload.Length, out var offsetToWriteTo)) { this.va.Write(offsetToWriteTo, messagePayload.Length); this.va.WriteArray(offsetToWriteTo + sizeof(int), messagePayload, 0, messagePayload.Length); } }
private bool TryReserveCapacity(int dataLength, out long reservedOffset) { // reserve enough room to store data + its size var packetSize = sizeof(int) + dataLength; reservedOffset = Interlocked.Add(ref this.nextOffset, packetSize) - packetSize;