1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-12 05:14:10 +02:00

Make Queue methods more similar to List

This commit is contained in:
Brian Fiete 2022-02-22 07:13:00 -08:00
parent 0ce67cecc2
commit 168d47a865
3 changed files with 282 additions and 40 deletions

View file

@ -362,6 +362,12 @@ namespace System.Collections
#endif #endif
} }
/// Adds an item to the front of the list.
public void AddFront(T item)
{
Insert(0, item);
}
/// Adds an item to the back of the list. /// Adds an item to the back of the list.
public void AddRange(Span<T> addSpan) public void AddRange(Span<T> addSpan)
{ {
@ -386,6 +392,12 @@ namespace System.Collections
Add(item); Add(item);
} }
public void AddRange<TEnumable>(TEnumable items) where TEnumable : IEnumerable<T>
{
for (let item in items.GetEnumerator())
Add(item);
}
public Span<T> GetRange(int offset) public Span<T> GetRange(int offset)
{ {
Debug.Assert((uint)offset <= (uint)mSize); Debug.Assert((uint)offset <= (uint)mSize);

View file

@ -63,6 +63,12 @@ namespace System.Collections
} }
} }
public this(IEnumerator<T> enumerator)
{
for (var item in enumerator)
Add(item);
}
public ~this() public ~this()
{ {
if (IsDynAlloc) if (IsDynAlloc)
@ -99,6 +105,110 @@ namespace System.Collections
} }
}*/ }*/
public ref T this[int index]
{
[Checked]
get
{
Runtime.Assert((uint)index < (uint)mSize);
return ref mItems[(mHead + index) % AllocSize];
}
[Unchecked, Inline]
get
{
return ref mItems[(mHead + index) % AllocSize];
}
[Checked]
set
{
Runtime.Assert((uint)index < (uint)mSize);
mItems[(mHead + index) % AllocSize] = value;
#if VERSION_LIST
mVersion++;
#endif
}
[Unchecked, Inline]
set
{
mItems[(mHead + index) % AllocSize] = value;
#if VERSION_LIST
mVersion++;
#endif
}
}
public ref T this[Index index]
{
[Checked]
get
{
int idx = index.Get(mSize);
Runtime.Assert((uint)idx < (uint)mSize);
return ref mItems[(mHead + idx) % AllocSize];
}
[Unchecked, Inline]
get
{
return ref mItems[(mHead + index.Get(mSize)) % AllocSize];
}
[Checked]
set
{
int idx = index.Get(mSize);
Runtime.Assert((uint)idx < (uint)mSize);
mItems[(mHead + idx) % AllocSize] = value;
#if VERSION_LIST
mVersion++;
#endif
}
[Unchecked, Inline]
set
{
mItems[(mHead + index.Get(mSize)) % AllocSize] = value;
#if VERSION_LIST
mVersion++;
#endif
}
}
public ref T Front
{
[Checked]
get
{
Runtime.Assert(mSize != 0);
return ref mItems[mHead % AllocSize];
}
[Unchecked, Inline]
get
{
return ref mItems[mHead % AllocSize];
}
}
public ref T Back
{
[Checked]
get
{
Runtime.Assert(mSize != 0);
return ref mItems[(mHead + mSize - 1) % AllocSize];
}
[Unchecked, Inline]
get
{
return ref mItems[(mHead + mSize - 1) % AllocSize];
}
}
public int AllocSize public int AllocSize
{ {
[Inline] [Inline]
@ -122,6 +232,14 @@ namespace System.Collections
get { return mSize; } get { return mSize; }
} }
public bool IsEmpty
{
get
{
return mSize == 0;
}
}
protected virtual T* Alloc(int size) protected virtual T* Alloc(int size)
{ {
return Internal.AllocRawArrayUnmarked<T>(size); return Internal.AllocRawArrayUnmarked<T>(size);
@ -145,30 +263,33 @@ namespace System.Collections
/// CopyTo copies a collection into an Array, starting at a particular /// CopyTo copies a collection into an Array, starting at a particular
/// index into the array. /// index into the array.
public void CopyTo(T[] array, int arrayIndex) public void CopyTo(Span<T> span)
{ {
Debug.Assert((uint)arrayIndex <= (uint)array.Count); int arrayLen = span.Length;
int arrayLen = array.Count;
Debug.Assert(arrayLen >= mSize); Debug.Assert(arrayLen >= mSize);
int numToCopy = (arrayLen - arrayIndex < mSize) ? (arrayLen - arrayIndex) : mSize; int numToCopy = Math.Min(arrayLen, mSize);
if (numToCopy == 0) return; if (numToCopy == 0) return;
int firstPart = (AllocSize - mHead < numToCopy) ? AllocSize - mHead : numToCopy; int firstPart = (AllocSize - mHead < numToCopy) ? AllocSize - mHead : numToCopy;
//Array.Copy(mArray, mHead, array, arrayIndex, firstPart); Internal.MemCpy(span.Ptr, mItems + mHead, firstPart * strideof(T), alignof(T));
Internal.MemCpy(&array.[Friend]GetRef(arrayIndex), mItems + mHead, firstPart * strideof(T), alignof(T));
numToCopy -= firstPart; numToCopy -= firstPart;
if (numToCopy > 0) if (numToCopy > 0)
{ {
//Array.Copy(mArray, 0, array, arrayIndex + AllocSize - mHead, numToCopy); Internal.MemCpy(span.Ptr + AllocSize - mHead, mItems, numToCopy * strideof(T), alignof(T));
Internal.MemCpy(&array.[Friend]GetRef(arrayIndex + AllocSize - mHead), mItems, numToCopy * strideof(T), alignof(T));
} }
} }
/// Adds item to the tail of the queue. /// Adds item to the tail of the queue.
[Obsolete("Replaced with Add", false)]
public void Enqueue(T item) public void Enqueue(T item)
{
Add(item);
}
/// Adds item to the tail of the queue.
public void Add(T item)
{ {
if (mSize == AllocSize) if (mSize == AllocSize)
{ {
@ -187,21 +308,65 @@ namespace System.Collections
mVersion++; mVersion++;
#endif #endif
} }
/// Adds item to the head of the queue.
public void AddFront(T item)
{
if (mSize == AllocSize)
{
int newcapacity = (int)((int64)AllocSize * (int64)cGrowFactor / 100);
if (newcapacity < AllocSize + cMinimumGrow)
{
newcapacity = AllocSize + cMinimumGrow;
}
SetCapacity(newcapacity);
}
int allocSize = AllocSize;
mHead = (.)((mHead + allocSize - 1) % allocSize);
mItems[mHead] = item;
mSize++;
#if VERSION_QUEUE
mVersion++;
#endif
}
/// GetEnumerator returns an IEnumerator over this Queue. This /// GetEnumerator returns an enumerator over this Queue which supports removing
/// Enumerator will support removing.
public Enumerator GetEnumerator() public Enumerator GetEnumerator()
{ {
return Enumerator(this); return Enumerator(this);
} }
/// Removes the object at the head of the queue and returns it. If the queue /// Removes the object at the head of the queue and returns it. If the queue
/// is empty, this method simply returns null. /// is empty, this method returns an error
[Obsolete("Replaced with PopFront", false)]
public T Dequeue() public T Dequeue()
{
return PopFront();
}
/// Removes the object at the head of the queue and returns it. If the queue
/// is empty, this method returns an error
public Result<T> TryPopFront()
{ {
if (mSize == 0) if (mSize == 0)
//ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyQueue); return .Err;
Runtime.FatalError();
T removed = mItems[mHead];
mHead = (mHead + 1) % (int_cosize)AllocSize;
mSize--;
#if VERSION_QUEUE
mVersion++;
#endif
return .Ok(removed);
}
/// Removes the object at the head of the queue and returns it. If the queue
/// is empty, this method fails
public T PopFront()
{
if (mSize == 0)
Runtime.FatalError("Queue empty");
T removed = mItems[mHead]; T removed = mItems[mHead];
mHead = (mHead + 1) % (int_cosize)AllocSize; mHead = (mHead + 1) % (int_cosize)AllocSize;
@ -211,46 +376,102 @@ namespace System.Collections
#endif #endif
return removed; return removed;
} }
/// Returns the object at the head of the queue. The object remains in the /// Removes the object at the tail of the queue and returns it. If the queue
/// queue. If the queue is empty, this method throws an /// is empty, this method returns an error
/// InvalidOperationException. public Result<T> TryPopBack()
public T Peek()
{ {
Debug.Assert(mSize != 0); if (mSize == 0)
return mItems[mHead]; return .Err;
int_cosize allocSize = (.)AllocSize;
mTail = (mTail + allocSize - 1) % allocSize;
T removed = mItems[mTail];
mSize--;
#if VERSION_QUEUE
mVersion++;
#endif
return .Ok(removed);
}
/// Removes the object at the tail of the queue and returns it. If the queue
/// is empty, this method fails
public T PopBack()
{
if (mSize == 0)
Runtime.FatalError("Queue empty");
int_cosize allocSize = (.)AllocSize;
mTail = (mTail + allocSize - 1) % allocSize;
T removed = mItems[mTail];
mSize--;
#if VERSION_QUEUE
mVersion++;
#endif
return removed;
} }
/// Returns true if the queue contains at least one object equal to item. /// Returns the object at the head of the queue. The object remains in the
/// Equality is determined using item.Equals(). /// queue. If the queue is empty, this method returns an error
public Result<T> Peek()
{
if (mSize == 0)
return .Err;
return .Ok(mItems[mHead]);
}
/// Returns true if the queue contains at least one object equal to 'item'.
public bool Contains(T item) public bool Contains(T item)
{ {
int index = mHead; int index = mHead;
int count = mSize; int count = mSize;
while (count-- > 0) while (count-- > 0)
{ {
if (((Object)item) == null) if (mItems[index] == item)
{
if (((Object)mItems[index]) == null)
return true;
}
else if (mItems[index] != null && mItems[index] == item)
{
return true; return true;
}
index = (index + 1) % AllocSize; index = (index + 1) % AllocSize;
} }
return false; return false;
} }
T GetElement(int i) /// Returns true if the queue contains at least one object equal to 'item'.
public bool ContainsStrict(T item)
{ {
return mItems[(mHead + i) % AllocSize]; int index = mHead;
int count = mSize;
while (count-- > 0)
{
if (mItems[index] === item)
return true;
index = (index + 1) % AllocSize;
}
return false;
} }
ref T GetElementRef(int i) T GetElement(int index)
{ {
return ref mItems[(mHead + i) % AllocSize]; Debug.Assert((uint)index < (uint)mSize);
return mItems[(mHead + index) % AllocSize];
}
ref T GetElementRef(int index)
{
Debug.Assert((uint)index < (uint)mSize);
return ref mItems[(mHead + index) % AllocSize];
}
public void RemoveAt(int index)
{
Debug.Assert((uint)index < (uint)mSize);
int absIndex = (mHead + index) % AllocSize;
if (absIndex < mSize - 1)
{
Internal.MemMove(mItems + absIndex, mItems + absIndex + 1, (mSize - absIndex - 1) * strideof(T), alignof(T));
}
mSize--;
#if VERSION_LIST
mVersion++;
#endif
} }
// PRIVATE Grows or shrinks the buffer to hold capacity objects. Capacity // PRIVATE Grows or shrinks the buffer to hold capacity objects. Capacity
@ -353,7 +574,7 @@ namespace System.Collections
public struct Enumerator : IRefEnumerator<T*>, IEnumerator<T> public struct Enumerator : IRefEnumerator<T*>, IEnumerator<T>
{ {
private Queue<T> mQueue; private Queue<T> mQueue;
private int32 mIndex; // -1 = not started, -2 = ended/disposed private int_cosize mIndex; // -1 = not started, -2 = ended/disposed
#if VERSION_QUEUE #if VERSION_QUEUE
private int32 mVersion; private int32 mVersion;
#endif #endif
@ -434,6 +655,15 @@ namespace System.Collections
} }
} }
public void Remove() mut
{
mQueue.RemoveAt(mIndex);
#if VERSION_QUEUE
mVersion = mList.mVersion;
#endif
mIndex--;
}
public void Reset() mut public void Reset() mut
{ {
#if VERSION_QUEUE #if VERSION_QUEUE

View file

@ -159,10 +159,10 @@ namespace System.Diagnostics
{ {
if (sb.Length != 0) if (sb.Length != 0)
{ {
messageQueue.Enqueue(new String(sb)); messageQueue.Add(new String(sb));
sb.Clear(); sb.Clear();
} }
messageQueue.Enqueue(null); messageQueue.Add(null);
} }
// UserCallback could throw, we should still set the eofEvent // UserCallback could throw, we should still set the eofEvent
@ -223,7 +223,7 @@ namespace System.Diagnostics
using (mMonitor.Enter()) using (mMonitor.Enter())
{ {
messageQueue.Enqueue(s); messageQueue.Add(s);
} }
} }
currentIndex++; currentIndex++;
@ -269,7 +269,7 @@ namespace System.Diagnostics
{ {
if (messageQueue.Count > 0) if (messageQueue.Count > 0)
{ {
String s = messageQueue.Dequeue(); String s = messageQueue.PopFront();
// skip if the read is the read is cancelled // skip if the read is the read is cancelled
// this might happen inside UserCallBack // this might happen inside UserCallBack
// However, continue to drain the queue // However, continue to drain the queue