mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-18 16:10:26 +02:00
Improvements to Queue, to bring it more inline with List
This commit is contained in:
parent
69cb6d0208
commit
96c53d4a9e
5 changed files with 238 additions and 88 deletions
|
@ -111,6 +111,12 @@ namespace System
|
||||||
arr[i] = default(T);
|
arr[i] = default(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Clear<T>(T* arr, int length)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
arr[i] = default(T);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Copy<T, T2>(T[] arrayFrom, int srcOffset, T2[] arrayTo, int dstOffset, int length) where T : var where T2 : var
|
public static void Copy<T, T2>(T[] arrayFrom, int srcOffset, T2[] arrayTo, int dstOffset, int length) where T : var where T2 : var
|
||||||
{
|
{
|
||||||
if (((Object)arrayTo == (Object)arrayFrom) && (dstOffset > srcOffset))
|
if (((Object)arrayTo == (Object)arrayFrom) && (dstOffset > srcOffset))
|
||||||
|
|
|
@ -35,16 +35,6 @@ namespace System.Collections.Generic
|
||||||
const int_cosize DynAllocFlag = (int_cosize)0x80000000;
|
const int_cosize DynAllocFlag = (int_cosize)0x80000000;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
|
||||||
static DbgRawAllocData sRawAllocData;
|
|
||||||
public static this()
|
|
||||||
{
|
|
||||||
sRawAllocData.mMarkFunc = null;
|
|
||||||
sRawAllocData.mMaxStackTrace = 1;
|
|
||||||
sRawAllocData.mType = typeof(T);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private T* mItems;
|
private T* mItems;
|
||||||
private int_cosize mSize;
|
private int_cosize mSize;
|
||||||
private int_cosize mAllocSizeAndFlags;
|
private int_cosize mAllocSizeAndFlags;
|
||||||
|
@ -262,13 +252,7 @@ namespace System.Collections.Generic
|
||||||
|
|
||||||
protected T* Alloc(int size)
|
protected T* Alloc(int size)
|
||||||
{
|
{
|
||||||
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
return Internal.AllocRawArrayUnmarked<T>(size);
|
||||||
// We don't want to use the default mark function because the GC will mark the entire array,
|
|
||||||
// whereas we have a custom marking routine because we only want to mark up to mSize
|
|
||||||
return (T*)Internal.Dbg_RawAlloc(size * strideof(T), &sRawAllocData);
|
|
||||||
#else
|
|
||||||
return new T[size]*(?);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Free(T* val)
|
protected void Free(T* val)
|
||||||
|
|
|
@ -10,12 +10,22 @@ namespace System.Collections.Generic
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
/// A simple Queue of generic items. Internally it is implemented as a
|
/// A simple Queue of generic items. Internally it is implemented as a
|
||||||
/// circular buffer, so Enqueue can be O(n). Dequeue is O(1).
|
/// circular buffer, so Enqueue can be O(n). Dequeue is O(1).
|
||||||
public class Queue<T> : IEnumerable<T> //, System.Collections.ICollection, IReadOnlyCollection<T>
|
public class Queue<T> : IEnumerable<T> //, System.Collections.ICollection, IReadOnlyCollection<T>
|
||||||
{
|
{
|
||||||
private T[] mArray;
|
#if BF_LARGE_COLLECTIONS
|
||||||
|
const int_cosize SizeFlags = 0x7FFFFFFF'FFFFFFFF;
|
||||||
|
const int_cosize DynAllocFlag = (int_cosize)0x80000000'00000000;
|
||||||
|
#else
|
||||||
|
const int_cosize SizeFlags = 0x7FFFFFFF;
|
||||||
|
const int_cosize DynAllocFlag = (int_cosize)0x80000000;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private T* mItems;
|
||||||
|
private int_cosize mAllocSizeAndFlags;
|
||||||
private int_cosize mHead; // First valid element in the queue
|
private int_cosize mHead; // First valid element in the queue
|
||||||
private int_cosize mTail; // Last valid element in the queue
|
private int_cosize mTail; // Last valid element in the queue
|
||||||
private int_cosize mSize; // Number of elements.
|
private int_cosize mSize; // Number of elements.
|
||||||
|
@ -29,24 +39,42 @@ namespace System.Collections.Generic
|
||||||
private const int32 cShrinkThreshold = 32;
|
private const int32 cShrinkThreshold = 32;
|
||||||
private const int32 cGrowFactor = 200; // double each time
|
private const int32 cGrowFactor = 200; // double each time
|
||||||
private const int32 cDefaultCapacity = 4;
|
private const int32 cDefaultCapacity = 4;
|
||||||
static T[] sEmptyArray = new T[0] ~ delete _;
|
|
||||||
|
|
||||||
/// Creates a queue with room for capacity objects. The default initial
|
/// Creates a queue with room for capacity objects. The default initial
|
||||||
/// capacity and grow factor are used.
|
/// capacity and grow factor are used.
|
||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
mArray = sEmptyArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a queue with room for capacity objects. The default grow factor
|
/// Creates a queue with room for capacity objects. The default grow factor
|
||||||
/// is used.
|
/// is used.
|
||||||
|
[AllowAppend]
|
||||||
public this(int capacity)
|
public this(int capacity)
|
||||||
{
|
{
|
||||||
|
T* items = append T[capacity]* (?);
|
||||||
Debug.Assert(capacity >= 0);
|
Debug.Assert(capacity >= 0);
|
||||||
mArray = new T[capacity];
|
mItems = items;
|
||||||
mHead = 0;
|
mHead = 0;
|
||||||
mTail = 0;
|
mTail = 0;
|
||||||
mSize = 0;
|
mSize = 0;
|
||||||
|
if (capacity > 0)
|
||||||
|
{
|
||||||
|
mItems = items;
|
||||||
|
mAllocSizeAndFlags = (int_cosize)(capacity & SizeFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
if (IsDynAlloc)
|
||||||
|
{
|
||||||
|
var items = mItems;
|
||||||
|
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
||||||
|
mItems= null;
|
||||||
|
Interlocked.Fence();
|
||||||
|
#endif
|
||||||
|
Free(items);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fills a Queue with the elements of an ICollection. Uses the enumerator
|
// Fills a Queue with the elements of an ICollection. Uses the enumerator
|
||||||
|
@ -72,24 +100,42 @@ namespace System.Collections.Generic
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
public int AllocSize
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mAllocSizeAndFlags & SizeFlags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDynAlloc
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (mAllocSizeAndFlags & DynAllocFlag) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int Count
|
public int Count
|
||||||
{
|
{
|
||||||
get { return mSize; }
|
get { return mSize; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected T* Alloc(int size)
|
||||||
|
{
|
||||||
|
return Internal.AllocRawArrayUnmarked<T>(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Free(T* val)
|
||||||
|
{
|
||||||
|
delete (void*)val;
|
||||||
|
}
|
||||||
|
|
||||||
/// Removes all items from the queue.
|
/// Removes all items from the queue.
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
|
||||||
if (mHead < mTail)
|
|
||||||
Array.Clear(mArray, mHead, mSize);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Array.Clear(mArray, mHead, mArray.Count - mHead);
|
|
||||||
Array.Clear(mArray, 0, mTail);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
mHead = 0;
|
mHead = 0;
|
||||||
mTail = 0;
|
mTail = 0;
|
||||||
mSize = 0;
|
mSize = 0;
|
||||||
|
@ -109,12 +155,15 @@ namespace System.Collections.Generic
|
||||||
int numToCopy = (arrayLen - arrayIndex < mSize) ? (arrayLen - arrayIndex) : mSize;
|
int numToCopy = (arrayLen - arrayIndex < mSize) ? (arrayLen - arrayIndex) : mSize;
|
||||||
if (numToCopy == 0) return;
|
if (numToCopy == 0) return;
|
||||||
|
|
||||||
int firstPart = (mArray.Count - mHead < numToCopy) ? mArray.Count - mHead : numToCopy;
|
int firstPart = (AllocSize - mHead < numToCopy) ? AllocSize - mHead : numToCopy;
|
||||||
Array.Copy(mArray, mHead, array, arrayIndex, firstPart);
|
//Array.Copy(mArray, mHead, array, arrayIndex, firstPart);
|
||||||
|
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 + mArray.Count - mHead, numToCopy);
|
//Array.Copy(mArray, 0, array, arrayIndex + AllocSize - mHead, numToCopy);
|
||||||
|
Internal.MemCpy(&array.[Friend]GetRef(arrayIndex + AllocSize - mHead), mItems, numToCopy * strideof(T), alignof(T));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,18 +171,18 @@ namespace System.Collections.Generic
|
||||||
/// Adds item to the tail of the queue.
|
/// Adds item to the tail of the queue.
|
||||||
public void Enqueue(T item)
|
public void Enqueue(T item)
|
||||||
{
|
{
|
||||||
if (mSize == mArray.Count)
|
if (mSize == AllocSize)
|
||||||
{
|
{
|
||||||
int newcapacity = (int)((int64)mArray.Count * (int64)cGrowFactor / 100);
|
int newcapacity = (int)((int64)AllocSize * (int64)cGrowFactor / 100);
|
||||||
if (newcapacity < mArray.Count + cMinimumGrow)
|
if (newcapacity < AllocSize + cMinimumGrow)
|
||||||
{
|
{
|
||||||
newcapacity = mArray.Count + cMinimumGrow;
|
newcapacity = AllocSize + cMinimumGrow;
|
||||||
}
|
}
|
||||||
SetCapacity(newcapacity);
|
SetCapacity(newcapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
mArray[mTail] = item;
|
mItems[mTail] = item;
|
||||||
mTail = (mTail + 1) % (int_cosize)mArray.Count;
|
mTail = (mTail + 1) % (int_cosize)AllocSize;
|
||||||
mSize++;
|
mSize++;
|
||||||
#if VERSION_QUEUE
|
#if VERSION_QUEUE
|
||||||
mVersion++;
|
mVersion++;
|
||||||
|
@ -155,9 +204,8 @@ namespace System.Collections.Generic
|
||||||
//ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyQueue);
|
//ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyQueue);
|
||||||
Runtime.FatalError();
|
Runtime.FatalError();
|
||||||
|
|
||||||
T removed = mArray[mHead];
|
T removed = mItems[mHead];
|
||||||
mArray[mHead] = default(T);
|
mHead = (mHead + 1) % (int_cosize)AllocSize;
|
||||||
mHead = (mHead + 1) % (int_cosize)mArray.Count;
|
|
||||||
mSize--;
|
mSize--;
|
||||||
#if VERSION_QUEUE
|
#if VERSION_QUEUE
|
||||||
mVersion++;
|
mVersion++;
|
||||||
|
@ -171,7 +219,7 @@ namespace System.Collections.Generic
|
||||||
public T Peek()
|
public T Peek()
|
||||||
{
|
{
|
||||||
Debug.Assert(mSize != 0);
|
Debug.Assert(mSize != 0);
|
||||||
return mArray[mHead];
|
return mItems[mHead];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the queue contains at least one object equal to item.
|
/// Returns true if the queue contains at least one object equal to item.
|
||||||
|
@ -184,51 +232,33 @@ namespace System.Collections.Generic
|
||||||
{
|
{
|
||||||
if (((Object)item) == null)
|
if (((Object)item) == null)
|
||||||
{
|
{
|
||||||
if (((Object)mArray[index]) == null)
|
if (((Object)mItems[index]) == null)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (mArray[index] != null && mArray[index] == item)
|
else if (mItems[index] != null && mItems[index] == item)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
index = (index + 1) % mArray.Count;
|
index = (index + 1) % AllocSize;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
T GetElement(int i)
|
T GetElement(int i)
|
||||||
{
|
{
|
||||||
return mArray[(mHead + i) % mArray.Count];
|
return mItems[(mHead + i) % AllocSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates over the objects in the queue, returning an array of the
|
ref T GetElementRef(int i)
|
||||||
/// objects in the Queue, or an empty array if the queue is empty.
|
|
||||||
/// The order of elements in the array is first in to last in, the same
|
|
||||||
/// order produced by successive calls to Dequeue.
|
|
||||||
public T[] ToArray()
|
|
||||||
{
|
{
|
||||||
T[] arr = new T[mSize];
|
return ref mItems[(mHead + i) % AllocSize];
|
||||||
if (mSize == 0)
|
|
||||||
return arr;
|
|
||||||
|
|
||||||
if (mHead < mTail)
|
|
||||||
{
|
|
||||||
Array.Copy(mArray, mHead, arr, 0, mSize);
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
Array.Copy(mArray, mHead, arr, 0, mArray.Count - mHead);
|
|
||||||
Array.Copy(mArray, 0, arr, mArray.Count - mHead, mTail);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// PRIVATE Grows or shrinks the buffer to hold capacity objects. Capacity
|
// PRIVATE Grows or shrinks the buffer to hold capacity objects. Capacity
|
||||||
// must be >= _size.
|
// must be >= _size.
|
||||||
private void SetCapacity(int capacity)
|
private void SetCapacity(int value)
|
||||||
{
|
{
|
||||||
T[] newarray = new T[capacity];
|
/*T* newarray = new T[capacity]*;
|
||||||
if (mSize > 0)
|
if (mSize > 0)
|
||||||
{
|
{
|
||||||
if (mHead < mTail)
|
if (mHead < mTail)
|
||||||
|
@ -236,22 +266,82 @@ namespace System.Collections.Generic
|
||||||
Array.Copy(mArray, mHead, newarray, 0, mSize);
|
Array.Copy(mArray, mHead, newarray, 0, mSize);
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
Array.Copy(mArray, mHead, newarray, 0, mArray.Count - mHead);
|
Array.Copy(mArray, mHead, newarray, 0, AllocSize - mHead);
|
||||||
Array.Copy(mArray, 0, newarray, mArray.Count - mHead, mTail);
|
Array.Copy(mArray, 0, newarray, AllocSize - mHead, mTail);
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (value > 0)
|
||||||
|
{
|
||||||
|
T* newItems = Alloc(value);
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
int typeId = typeof(T).GetTypeId();
|
||||||
|
if (typeId == sDebugTypeId)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Alloc {0} {1} {2}", scope Object[] { this, newItems, sDebugIdx } );
|
||||||
|
sDebugIdx++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (mSize > 0)
|
||||||
|
{
|
||||||
|
if (mHead < mTail)
|
||||||
|
{
|
||||||
|
Internal.MemCpy(newItems, mItems + mHead, mSize * strideof(T), alignof(T));
|
||||||
|
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
Internal.MemCpy(newItems, mItems + mHead, (AllocSize - mHead) * strideof(T), alignof(T));
|
||||||
|
Internal.MemCpy(newItems + (AllocSize - mHead), mItems, mTail * strideof(T), alignof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldItems = mItems;
|
||||||
|
mItems = newItems;
|
||||||
|
if (IsDynAlloc)
|
||||||
|
{
|
||||||
|
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
||||||
|
// We need to avoid scanning a deleted mItems
|
||||||
|
Interlocked.Fence();
|
||||||
|
#endif
|
||||||
|
Free(oldItems);
|
||||||
|
}
|
||||||
|
mAllocSizeAndFlags = (.)(value | DynAllocFlag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IsDynAlloc)
|
||||||
|
Free(mItems);
|
||||||
|
mItems = null;
|
||||||
|
mAllocSizeAndFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mArray = newarray;
|
|
||||||
mHead = 0;
|
mHead = 0;
|
||||||
mTail = (mSize == capacity) ? 0 : mSize;
|
mTail = (mSize == value) ? 0 : mSize;
|
||||||
#if VERSION_QUEUE
|
#if VERSION_QUEUE
|
||||||
mVersion++;
|
mVersion++;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GCMarkMembers()
|
||||||
|
{
|
||||||
|
if (mItems == null)
|
||||||
|
return;
|
||||||
|
let type = typeof(T);
|
||||||
|
if ((type.[Friend]mTypeFlags & .WantsMark) == 0)
|
||||||
|
return;
|
||||||
|
int allocSize = AllocSize;
|
||||||
|
for (int i < mSize)
|
||||||
|
{
|
||||||
|
GC.Mark_Unbound(mItems[(i + mHead) % allocSize]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void TrimExcess()
|
public void TrimExcess()
|
||||||
{
|
{
|
||||||
int32 threshold = (int32)(((double)mArray.Count) * 0.9);
|
int32 threshold = (int32)(((double)AllocSize) * 0.9);
|
||||||
if (mSize < threshold)
|
if (mSize < threshold)
|
||||||
{
|
{
|
||||||
SetCapacity(mSize);
|
SetCapacity(mSize);
|
||||||
|
@ -261,14 +351,14 @@ namespace System.Collections.Generic
|
||||||
/// Implements an enumerator for a Queue. The enumerator uses the
|
/// Implements an enumerator for a Queue. The enumerator uses the
|
||||||
/// internal version number of the list to ensure that no modifications are
|
/// internal version number of the list to ensure that no modifications are
|
||||||
/// made to the list while an enumeration is in progress.
|
/// made to the list while an enumeration is in progress.
|
||||||
public struct Enumerator : IEnumerator<T>
|
public struct Enumerator : IRefEnumerator<T>
|
||||||
{
|
{
|
||||||
private Queue<T> mQueue;
|
private Queue<T> mQueue;
|
||||||
private int32 mIndex; // -1 = not started, -2 = ended/disposed
|
private int32 mIndex; // -1 = not started, -2 = ended/disposed
|
||||||
#if VERSION_QUEUE
|
#if VERSION_QUEUE
|
||||||
private int32 mVersion;
|
private int32 mVersion;
|
||||||
#endif
|
#endif
|
||||||
private T mCurrentElement;
|
private T* mCurrentElement;
|
||||||
|
|
||||||
public this(Queue<T> q)
|
public this(Queue<T> q)
|
||||||
{
|
{
|
||||||
|
@ -277,7 +367,7 @@ namespace System.Collections.Generic
|
||||||
mVersion = mQueue.mVersion;
|
mVersion = mQueue.mVersion;
|
||||||
#endif
|
#endif
|
||||||
mIndex = -1;
|
mIndex = -1;
|
||||||
mCurrentElement = default(T);
|
mCurrentElement = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if VERSION_QUEUE
|
#if VERSION_QUEUE
|
||||||
|
@ -291,7 +381,7 @@ namespace System.Collections.Generic
|
||||||
public void Dispose() mut
|
public void Dispose() mut
|
||||||
{
|
{
|
||||||
mIndex = -2;
|
mIndex = -2;
|
||||||
mCurrentElement = default(T);
|
mCurrentElement = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MoveNext() mut
|
public bool MoveNext() mut
|
||||||
|
@ -307,11 +397,11 @@ namespace System.Collections.Generic
|
||||||
if (mIndex == mQueue.mSize)
|
if (mIndex == mQueue.mSize)
|
||||||
{
|
{
|
||||||
mIndex = -2;
|
mIndex = -2;
|
||||||
mCurrentElement = default(T);
|
mCurrentElement = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentElement = mQueue.GetElement(mIndex);
|
mCurrentElement = &mQueue.GetElementRef(mIndex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +416,22 @@ namespace System.Collections.Generic
|
||||||
else
|
else
|
||||||
Runtime.FatalError("Enumeration ended");
|
Runtime.FatalError("Enumeration ended");
|
||||||
}
|
}
|
||||||
return mCurrentElement;
|
return *mCurrentElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref T CurrentRef
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (mIndex < 0)
|
||||||
|
{
|
||||||
|
if (mIndex == -1)
|
||||||
|
Runtime.FatalError("Enumeration not started");
|
||||||
|
else
|
||||||
|
Runtime.FatalError("Enumeration ended");
|
||||||
|
}
|
||||||
|
return ref *mCurrentElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,6 +450,13 @@ namespace System.Collections.Generic
|
||||||
return .Err;
|
return .Err;
|
||||||
return Current;
|
return Current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Result<T*> GetNextRef() mut
|
||||||
|
{
|
||||||
|
if (!MoveNext())
|
||||||
|
return .Err;
|
||||||
|
return &CurrentRef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,17 @@ namespace System
|
||||||
public Type mType;
|
public Type mType;
|
||||||
public void* mMarkFunc;
|
public void* mMarkFunc;
|
||||||
public int32 mMaxStackTrace;
|
public int32 mMaxStackTrace;
|
||||||
|
|
||||||
|
public struct Unmarked<T>
|
||||||
|
{
|
||||||
|
public static DbgRawAllocData sRawAllocData;
|
||||||
|
public static this()
|
||||||
|
{
|
||||||
|
sRawAllocData.mMarkFunc = null;
|
||||||
|
sRawAllocData.mMaxStackTrace = 1;
|
||||||
|
sRawAllocData.mType = typeof(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[AlwaysInclude]
|
[AlwaysInclude]
|
||||||
|
@ -81,6 +92,17 @@ namespace System
|
||||||
sModuleHandle = handle;
|
sModuleHandle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static T* AllocRawArrayUnmarked<T>(int size)
|
||||||
|
{
|
||||||
|
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
||||||
|
// We don't want to use the default mark function because the GC will mark the entire array,
|
||||||
|
// whereas we have a custom marking routine because we only want to mark up to mSize
|
||||||
|
return (T*)Internal.Dbg_RawAlloc(size * strideof(T), &DbgRawAllocData.Unmarked<T>.sRawAllocData);
|
||||||
|
#else
|
||||||
|
return new T[size]*(?);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
public static Object ObjectAlloc(TypeInstance typeInst, int size)
|
public static Object ObjectAlloc(TypeInstance typeInst, int size)
|
||||||
{
|
{
|
||||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||||
|
|
26
IDE/dist/BeefDbgVis.toml
vendored
26
IDE/dist/BeefDbgVis.toml
vendored
|
@ -219,10 +219,36 @@ DisplayString = "{{ count={mSize} }}"
|
||||||
[[Type.Expand.Item]]
|
[[Type.Expand.Item]]
|
||||||
Name = "[Count]"
|
Name = "[Count]"
|
||||||
Value = "mSize"
|
Value = "mSize"
|
||||||
|
[[Type.Expand.Item]]
|
||||||
|
Condition = "__getHighBits(mAllocSizeAndFlags, 1) == 1"
|
||||||
|
Name = "[AllocSize]"
|
||||||
|
Value = "__clearHighBits(mAllocSizeAndFlags, 1)"
|
||||||
|
[[Type.Expand.Item]]
|
||||||
|
Condition = "__getHighBits(mAllocSizeAndFlags, 1) == 0"
|
||||||
|
Name = "[InternalSize]"
|
||||||
|
Value = "__clearHighBits(mAllocSizeAndFlags, 1)"
|
||||||
[Type.Expand.ArrayItems]
|
[Type.Expand.ArrayItems]
|
||||||
Size = "mSize"
|
Size = "mSize"
|
||||||
ValuePointer = "mItems"
|
ValuePointer = "mItems"
|
||||||
|
|
||||||
|
[[Type]]
|
||||||
|
Name = "System.Collections.Generic.Queue<*>"
|
||||||
|
DisplayString = "{{ count={mSize} }}"
|
||||||
|
[[Type.Expand.Item]]
|
||||||
|
Name = "[Count]"
|
||||||
|
Value = "mSize"
|
||||||
|
[[Type.Expand.Item]]
|
||||||
|
Condition = "__getHighBits(mAllocSizeAndFlags, 1) == 1"
|
||||||
|
Name = "[AllocSize]"
|
||||||
|
Value = "__clearHighBits(mAllocSizeAndFlags, 1)"
|
||||||
|
[[Type.Expand.Item]]
|
||||||
|
Condition = "__getHighBits(mAllocSizeAndFlags, 1) == 0"
|
||||||
|
Name = "[InternalSize]"
|
||||||
|
Value = "__clearHighBits(mAllocSizeAndFlags, 1)"
|
||||||
|
[Type.Expand.IndexListItems]
|
||||||
|
Size = "mSize"
|
||||||
|
ValueNode = "mItems[($i + mHead) % __clearHighBits(mAllocSizeAndFlags, 2)]"
|
||||||
|
|
||||||
[[Type]]
|
[[Type]]
|
||||||
Name = "System.Collections.Generic.Dictionary<*, *>"
|
Name = "System.Collections.Generic.Dictionary<*, *>"
|
||||||
DisplayString = "{{ count={mCount - mFreeCount} }}"
|
DisplayString = "{{ count={mCount - mFreeCount} }}"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue