Skip to content

Commit

Permalink
Implemented ValueQueue<T>. Renamed some interface.
Browse files Browse the repository at this point in the history
  • Loading branch information
fryderykhuang committed Jan 21, 2024
1 parent 2c3b482 commit ca4b9be
Show file tree
Hide file tree
Showing 21 changed files with 774 additions and 159 deletions.
29 changes: 15 additions & 14 deletions src/NullGC.Abstractions/Allocators/AllocatorContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,24 @@ namespace NullGC.Allocators;

public static class AllocatorContext
{
public static IAllocatorContextImpl Impl = null!;
private static IAllocatorContextImpl _impl = null!;
public static IAllocatorContextImpl Impl => _impl;

public static void SetImplementation(IAllocatorContextImpl impl)
{
Impl.TryDispose();
Impl = impl;
_impl.TryDispose();
_impl = impl;
}

internal static bool ResetImplementation(IAllocatorContextImpl? impl)
{
if (Impl != null)
if (_impl != null)
{
Impl.TryDispose();
Impl = impl!;
_impl.TryDispose();
_impl = impl!;
return true;
}
Impl = impl!;
_impl = impl!;
return false;
}

Expand All @@ -35,7 +36,7 @@ internal static bool ResetImplementation(IAllocatorContextImpl? impl)
public static void FreeAllocations(int allocatorProviderId)
{
GuardImpl();
Impl.FreeAllocations(allocatorProviderId);
_impl.FreeAllocations(allocatorProviderId);
}

/// <summary>
Expand All @@ -47,33 +48,33 @@ public static void FreeAllocations(int allocatorProviderId)
public static void SetAllocatorProvider(IAllocatorProvider provider, int allocatorProviderId, bool scoped)
{
GuardImpl();
Impl.SetAllocatorProvider(provider, allocatorProviderId, scoped);
_impl.SetAllocatorProvider(provider, allocatorProviderId, scoped);
}

public static void FinalizeConfiguration()
{
GuardImpl();
Impl.FinalizeConfiguration();
_impl.FinalizeConfiguration();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void GuardImpl()
{
if (Impl is null)
if (_impl is null)
ThrowHelper.ThrowInvalidOperationException(
$"Implementation is not set, call {nameof(SetImplementation)} first.");
}

public static void ClearProvidersAndAllocations()
{
GuardImpl();
Impl.ClearProvidersAndAllocations();
_impl.ClearProvidersAndAllocations();
}

public static IMemoryAllocator GetAllocator(int allocatorProviderId = (int) AllocatorTypes.Default)
{
GuardImpl();
return Impl.GetAllocator(allocatorProviderId);
return _impl.GetAllocator(allocatorProviderId);
}

/// <summary>
Expand All @@ -84,6 +85,6 @@ public static IMemoryAllocator GetAllocator(int allocatorProviderId = (int) Allo
public static IDisposable BeginAllocationScope(int allocatorProviderId = (int) AllocatorTypes.Default)
{
GuardImpl();
return Impl.BeginAllocationScope(allocatorProviderId);
return _impl.BeginAllocationScope(allocatorProviderId);
}
}
6 changes: 6 additions & 0 deletions src/NullGC.Abstractions/Collections/IHasUnmanagedResource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace NullGC.Collections;

public interface IHasUnmanagedResource
{
bool IsAllocated { get; }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace NullGC.Collections;

public interface IUnsafeArray<T>
public interface IUnmanagedArray<T> : IHasUnmanagedResource
{
/// <summary>
///
Expand All @@ -12,5 +12,4 @@ public interface IUnsafeArray<T>
unsafe T* Items { get; }
#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
int Length { get; }
bool IsInitialized { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@
public static class DefaultAllocatorContextImplExtensions
{
public static IAllocatorContextImpl ConfigureDefault(this IAllocatorContextImpl ac,
int defaultArenaAllocationCacheRetentionTimeMs = 10000)
int defaultMemCacheTtlMs = 10000)
{
return ConfigureDefault(ac, out _, out _, defaultArenaAllocationCacheRetentionTimeMs);
return ConfigureDefault(ac, out _, out _, defaultMemCacheTtlMs);
}

public static IAllocatorContextImpl ConfigureDefaultUnscoped(this IAllocatorContextImpl ac,
int cacheTtlMs = 10000, int cacheLostObserveWindowSize = 100, UIntPtr cleanupTh = 8 * 1024 * 1024)
int defaultMemCacheTtlMs = 10000, int cacheLostObserveWindowSize = 100, UIntPtr cleanupTh = 8 * 1024 * 1024)
{
return ConfigureDefaultUnscoped(ac, out _, out _, cleanupTh: cleanupTh, cacheTtl: cacheTtlMs,
return ConfigureDefaultUnscoped(ac, out _, out _, cleanupTh: cleanupTh, cacheTtl: defaultMemCacheTtlMs,
cacheLostObserveWindowSize: cacheLostObserveWindowSize);
}

public static IAllocatorContextImpl ConfigureDefault(this IAllocatorContextImpl ac,
out IMemoryAllocationTrackable frontStats, out IMemoryAllocationTrackable? cacheAllocStats,
int defaultTtlMs = 10000, int cacheLostObserveWindowSize = 100, nuint cleanupTh = 8 * 1024 * 1024)
int defaultMemCacheTtlMs = 10000, int cacheLostObserveWindowSize = 100, nuint cleanupTh = 8 * 1024 * 1024)
{
var memPoolerUnscoped = new DefaultAllocationPooler(new DefaultAlignedNativeMemoryAllocator(),
defaultTtlMs);
defaultMemCacheTtlMs);
ac.SetAllocatorProvider(memPoolerUnscoped, (int) AllocatorTypes.DefaultUnscoped, false);
var cache = new DefaultAllocationPooler(new DefaultAlignedNativeMemoryAllocator(),
defaultTtlMs, cleanupTh, cacheLostObserveWindowSize: cacheLostObserveWindowSize);
defaultMemCacheTtlMs, cleanupTh, cacheLostObserveWindowSize: cacheLostObserveWindowSize);
cacheAllocStats = cache;
var allocatorPooler = new AllocatorPool<ArenaAllocator>(p => new ArenaAllocator(p, p, cache));
frontStats = allocatorPooler;
Expand Down
10 changes: 9 additions & 1 deletion src/NullGC.Collections.Tests/ValueArrayTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using NullGC.Allocators;
using NullGC.Allocators.Extensions;
using NullGC.TestCommons;
using Xunit.Abstractions;

Expand All @@ -13,7 +15,7 @@ public ValueArrayTests(ITestOutputHelper logger) : base(logger, false)
public void DefaultArrayFacts()
{
ValueArray<int> defaultArr = default;
Assert.False(defaultArr.IsInitialized);
Assert.False(defaultArr.IsAllocated);
Assert.True(EqualityComparer<ValueArray<int>>.Default.Equals(ValueArray<int>.Empty, defaultArr));
Assert.Empty(defaultArr);
foreach (ref var item in defaultArr) Assert.Fail("Should be empty.");
Expand All @@ -39,6 +41,12 @@ public void SpecificLengthArrayCanBeConstructed()
arr.Dispose();
}

// TODO hard to mock
// [Fact]
// public void ValueArrayMaxLengthFacts()
// {
// }

[Fact]
public void ValueSetShouldBePreserved()
{
Expand Down
2 changes: 1 addition & 1 deletion src/NullGC.Collections.Tests/ValueListTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public ValueListTests(ITestOutputHelper logger) : base(logger, false, true)
public void DefaultListIsEmptyList()
{
ValueList<int> defaultList = default;
Assert.False(defaultList.IsInitialized);
Assert.False(defaultList.IsAllocated);
Assert.True(EqualityComparer<ValueList<int>>.Default.Equals(ValueList<int>.Empty, defaultList));
Assert.Empty(defaultList);
foreach (ref var _ in defaultList) Assert.Fail("Should be empty.");
Expand Down
57 changes: 57 additions & 0 deletions src/NullGC.Collections.Tests/ValueQueueTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using NullGC.TestCommons;
using Xunit.Abstractions;

namespace NullGC.Collections.Tests;

public class ValueQueueTests :AssertMemoryAllFreedBase
{
public ValueQueueTests(ITestOutputHelper logger) : base(logger, false)
{
}

[Fact]
public void EmptyQueueFacts()
{
var queue = new ValueQueue<int>();
Assert.False(queue.IsAllocated);
Assert.Equal(0, queue.Count);
Assert.Empty(queue);
Assert.Throws<InvalidOperationException>(() => queue.Peek());
Assert.Throws<InvalidOperationException>(() => queue.Dequeue());
queue.Dispose();
Assert.True(AllocTracker.ClientIsAllFreed);
queue.Dispose();
}

[Fact]
public void EnqueueDequeueFacts()
{
var queue = new ValueQueue<int>();
queue.Enqueue(1);
Assert.Equal(1, queue.Dequeue());
Assert.Equal(0, queue.Count);
Assert.Empty(queue);
Assert.Throws<InvalidOperationException>(() => queue.Dequeue());
queue.Enqueue(1);
Assert.Single(queue);
queue.Enqueue(2);
queue.Enqueue(3);
queue.Enqueue(4);
queue.Enqueue(5);
queue.Enqueue(6);
Assert.Equal(6, queue.Count);
Assert.Equal(6, queue.Count());
Assert.Equal(1, queue.Dequeue());
queue.Enqueue(7);
Assert.Equal(2, queue.Dequeue());
Assert.Equal(3, queue.Dequeue());
Assert.Equal(4, queue.Dequeue());
Assert.Equal(5, queue.Dequeue());
Assert.Equal(6, queue.Dequeue());
Assert.Equal(7, queue.Dequeue());

queue.Dispose();
Assert.True(AllocTracker.ClientIsAllFreed);
queue.Dispose();
}
}
26 changes: 13 additions & 13 deletions src/NullGC.Collections/Extensions/IUnsafeArrayExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public static ReadOnlySpan<T> AsReadOnlySpan<T>(this ValueList<T> src, int index

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T, TCollection>(this TCollection src)
where TCollection : IUnsafeArray<T> where T : unmanaged
where TCollection : IUnmanagedArray<T> where T : unmanaged
{
unsafe
{
Expand All @@ -93,7 +93,7 @@ public static Span<T> AsSpan<T, TCollection>(this TCollection src)

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<T> AsReadOnlySpan<T, TCollection>(this TCollection src)
where TCollection : IUnsafeArray<T> where T : unmanaged
where TCollection : IUnmanagedArray<T> where T : unmanaged
{
unsafe
{
Expand All @@ -103,7 +103,7 @@ public static ReadOnlySpan<T> AsReadOnlySpan<T, TCollection>(this TCollection sr

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<T> AsReadOnlySpan<T, TCollection>(this TCollection src, int index)
where TCollection : IUnsafeArray<T> where T : unmanaged
where TCollection : IUnmanagedArray<T> where T : unmanaged
{
Guard.IsLessThan(index, src.Length, nameof(index));
unsafe
Expand All @@ -114,7 +114,7 @@ public static ReadOnlySpan<T> AsReadOnlySpan<T, TCollection>(this TCollection sr

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<T> AsReadOnlySpan<T, TCollection>(this TCollection src, int index, int count)
where TCollection : IUnsafeArray<T> where T : unmanaged
where TCollection : IUnmanagedArray<T> where T : unmanaged
{
Guard.IsLessThanOrEqualTo(count - index, src.Length, nameof(count));
unsafe
Expand All @@ -125,7 +125,7 @@ public static ReadOnlySpan<T> AsReadOnlySpan<T, TCollection>(this TCollection sr

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T, TCollection>(this TCollection src, int index)
where TCollection : IUnsafeArray<T> where T : unmanaged
where TCollection : IUnmanagedArray<T> where T : unmanaged
{
Guard.IsLessThan(index, src.Length, nameof(index));
unsafe
Expand All @@ -136,7 +136,7 @@ public static Span<T> AsSpan<T, TCollection>(this TCollection src, int index)

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T, TCollection>(this TCollection src, int index, int count)
where TCollection : IUnsafeArray<T> where T : unmanaged
where TCollection : IUnmanagedArray<T> where T : unmanaged
{
Guard.IsLessThanOrEqualTo(count - index, src.Length, nameof(count));
unsafe
Expand Down Expand Up @@ -195,7 +195,7 @@ public static bool Contains<T>(this ValueArray<T> src, T key) where T : unmanage
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo<T, TCollection1, TCollection2>(this TCollection1 src, TCollection2 dest, int srcIndex,
int destIndex, int srcCountToCopy)
where TCollection1 : IUnsafeArray<T> where TCollection2 : IUnsafeArray<T> where T : unmanaged
where TCollection1 : IUnmanagedArray<T> where TCollection2 : IUnmanagedArray<T> where T : unmanaged
{
Guard.IsLessThanOrEqualTo(srcCountToCopy, dest.Length - destIndex);
unsafe
Expand All @@ -208,7 +208,7 @@ public static void CopyTo<T, TCollection1, TCollection2>(this TCollection1 src,
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo<T, TCollection1>(this TCollection1 src, IList<T> dest, int srcIndex,
int destIndex, int srcCountToCopy)
where TCollection1 : IUnsafeArray<T> where T : unmanaged
where TCollection1 : IUnmanagedArray<T> where T : unmanaged
{
Guard.IsLessThanOrEqualTo(srcCountToCopy, dest.Count - destIndex);

Expand All @@ -223,7 +223,7 @@ public static void CopyTo<T, TCollection1>(this TCollection1 src, IList<T> dest,

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo<T, TCollection1, TCollection2>(this TCollection1 src, TCollection2 dest)
where TCollection1 : IUnsafeArray<T> where TCollection2 : IUnsafeArray<T> where T : unmanaged
where TCollection1 : IUnmanagedArray<T> where TCollection2 : IUnmanagedArray<T> where T : unmanaged
{
Guard.IsGreaterThanOrEqualTo(dest.Length, src.Length, nameof(dest));
unsafe
Expand All @@ -234,7 +234,7 @@ public static void CopyTo<T, TCollection1, TCollection2>(this TCollection1 src,

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clear<T, TCollection>(this TCollection src)
where TCollection : IUnsafeArray<T> where T : unmanaged
where TCollection : IUnmanagedArray<T> where T : unmanaged
{
unsafe
{
Expand Down Expand Up @@ -269,7 +269,7 @@ public static void Clear<T>(this ValueArray<T> src, int index, int count) where

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clear<T, TCollection>(this TCollection src, int index, int count)
where TCollection : IUnsafeArray<T> where T : unmanaged
where TCollection : IUnmanagedArray<T> where T : unmanaged
{
unsafe
{
Expand All @@ -281,7 +281,7 @@ public static void Clear<T, TCollection>(this TCollection src, int index, int co
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ValueList<T> ToValueList<T, TCollection>(this TCollection src,
int allocatorProviderId = (int) AllocatorTypes.Default)
where TCollection : IUnsafeArray<T> where T : unmanaged
where TCollection : IUnmanagedArray<T> where T : unmanaged
{
var ret = new ValueList<T>(src.Length, allocatorProviderId);
src.CopyTo<T, TCollection, ValueList<T>>(ret);
Expand All @@ -305,7 +305,7 @@ public static ValueList<T> ToValueList<T>(this ValueArray<T> src,
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ValueArray<T> ToValueArray<T, TCollection>(this TCollection src,
int allocatorProviderId = (int) AllocatorTypes.Default)
where TCollection : IUnsafeArray<T> where T : unmanaged
where TCollection : IUnmanagedArray<T> where T : unmanaged
{
var ret = new ValueArray<T>(src.Length, allocatorProviderId);
src.CopyTo<T, TCollection, ValueArray<T>>(ret);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

namespace NullGC.Collections;

public struct UnsafeArrayEnumerator<T> : ILinqRefEnumerator<T>, ILinqValueEnumerator<T>, IUnsafeArray<T>, IAddressFixed where T : unmanaged
public struct UnmanagedArrayEnumerator<T> : ILinqRefEnumerator<T>, ILinqValueEnumerator<T>, IUnmanagedArray<T>, IAddressFixed where T : unmanaged
{
private readonly unsafe T* _items;
private readonly int _length;
private int _index;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe UnsafeArrayEnumerator(T* items, int length)
public unsafe UnmanagedArrayEnumerator(T* items, int length)
{
_items = items;
_length = length;
Expand Down Expand Up @@ -78,7 +78,7 @@ public void Dispose()
public unsafe T* Items => _items;
public int Length => _length;

public bool IsInitialized
public bool IsAllocated
{
get
{
Expand Down
Loading

0 comments on commit ca4b9be

Please sign in to comment.