您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

89 行
2.8 KiB

using System;
using System.Threading;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
namespace Unity.Networking.Transport.Utilities.LowLevel.Unsafe
{
internal unsafe struct UnsafeAtomicFreeList : IDisposable
{
// used count
// free list size
// free indices...
[NativeDisableUnsafePtrRestriction]
private int* m_Buffer;
private int m_Length;
private Allocator m_Allocator;
public int Capacity => m_Length;
public int InUse => m_Buffer[0] - m_Buffer[1];
public bool IsCreated => m_Buffer != null;
/// <summary>
/// Initializes a new instance of the AtomicFreeList struct.
/// </summary>
/// <param name="capacity">The number of elements the free list can store.</param>
/// <param name="allocator">The <see cref="Allocator"/> used to allocate the memory.</param>
public UnsafeAtomicFreeList(int capacity, Allocator allocator)
{
m_Allocator = allocator;
m_Length = capacity;
var size = UnsafeUtility.SizeOf<int>() * (capacity + 2);
m_Buffer = (int*)UnsafeUtility.Malloc(size, UnsafeUtility.AlignOf<int>(), allocator);
UnsafeUtility.MemClear(m_Buffer, size);
}
public void Dispose()
{
if (IsCreated)
UnsafeUtility.Free(m_Buffer, m_Allocator);
}
/// <summary>
/// Inserts an item on top of the stack.
/// </summary>
/// <param name="item">The item to push onto the stack.</param>
public unsafe void Push(int item)
{
int* buffer = m_Buffer;
int idx = Interlocked.Increment(ref buffer[1]) - 1;
while (Interlocked.CompareExchange(ref buffer[idx + 2], item + 1, 0) != 0)
{
}
}
/// <summary>
/// Remove and return a value from the top of the stack
/// </summary>
/// <remarks>
/// <value>The removed value from the top of the stack.</value>
public unsafe int Pop()
{
int* buffer = m_Buffer;
int idx = buffer[1] - 1;
while (idx >= 0 && Interlocked.CompareExchange(ref buffer[1], idx, idx + 1) != idx + 1)
idx = buffer[1] - 1;
if (idx >= 0)
{
int val = 0;
while (val == 0)
{
val = Interlocked.Exchange(ref buffer[2 + idx], 0);
}
return val - 1;
}
idx = Interlocked.Increment(ref buffer[0]) - 1;
if (idx >= Capacity)
{
Interlocked.Decrement(ref buffer[0]);
return -1;
}
return idx;
}
}
}