first commit
This commit is contained in:
175
NitroxModel/DataStructures/ThreadSafeQueue.cs
Normal file
175
NitroxModel/DataStructures/ThreadSafeQueue.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
using ProtoBufNet;
|
||||
|
||||
namespace NitroxModel.DataStructures;
|
||||
|
||||
[DebuggerDisplay($"Items = {{{nameof(queue)}}}")]
|
||||
[ProtoContract, JsonObject(MemberSerialization.OptIn)]
|
||||
[Serializable]
|
||||
public class ThreadSafeQueue<T> : IReadOnlyCollection<T>, ICollection
|
||||
{
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
[IgnoreDataMember]
|
||||
private readonly object locker = new();
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
[JsonProperty, ProtoIgnore]
|
||||
private Queue<T> queue;
|
||||
|
||||
// Protobuf serialization workaround, see: https://stackoverflow.com/a/31021014
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
[ProtoMember(1), JsonIgnore]
|
||||
private T[] Items
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
return queue.ToArray();
|
||||
}
|
||||
}
|
||||
init
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
queue = new Queue<T>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
return queue.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public object SyncRoot => locker;
|
||||
|
||||
public bool IsSynchronized => true;
|
||||
|
||||
public ThreadSafeQueue()
|
||||
{
|
||||
queue = new Queue<T>();
|
||||
}
|
||||
|
||||
public ThreadSafeQueue(int initialCapacity)
|
||||
{
|
||||
queue = new Queue<T>(initialCapacity);
|
||||
}
|
||||
|
||||
public ThreadSafeQueue(IEnumerable<T> values)
|
||||
{
|
||||
queue = new Queue<T>(values);
|
||||
}
|
||||
|
||||
public ThreadSafeQueue(Queue<T> queue, bool createCopy = true)
|
||||
{
|
||||
this.queue = createCopy ? CreateCopy(queue) : queue;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
queue.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
return queue.Contains(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyTo(Array array, int arrayIndex)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
T[] tmpArray = ToArray();
|
||||
tmpArray.CopyTo(array, arrayIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
queue.CopyTo(array, arrayIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public T Dequeue()
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
return queue.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
queue.Enqueue(item);
|
||||
}
|
||||
}
|
||||
|
||||
public T Peek()
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
return queue.Peek();
|
||||
}
|
||||
}
|
||||
|
||||
public T[] ToArray()
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
return queue.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public void TrimExcess()
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
queue.TrimExcess();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<T> Clone()
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
return CreateCopy(queue);
|
||||
}
|
||||
}
|
||||
|
||||
private Queue<T> CreateCopy(IEnumerable<T> data)
|
||||
{
|
||||
return new Queue<T>(data);
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
return CreateCopy(queue).GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
Reference in New Issue
Block a user