Skip to content

Commit 86fc06c

Browse files
author
LoneWandererProductions
committed
add some more stuff.
1 parent 579a797 commit 86fc06c

4 files changed

Lines changed: 168 additions & 3 deletions

File tree

CommonExtendedObjectsTests/IntArrayTests.cs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public void CompareIntArrayvsIntArrayDotNetPerformance()
117117
var customTime = stopwatch.ElapsedMilliseconds;
118118
intArray.Dispose();
119119

120-
Console.WriteLine($"IntArray (unmanaged) time: {customTime} ms");
120+
Trace.WriteLine($"IntArray (unmanaged) time: {customTime} ms");
121121

122122
// === Native int[] Test ===
123123
var nativeArray = new int[Size];
@@ -133,7 +133,7 @@ public void CompareIntArrayvsIntArrayDotNetPerformance()
133133
stopwatch.Stop();
134134
var nativeTime = stopwatch.ElapsedMilliseconds;
135135

136-
Console.WriteLine($"int[] (managed) time: {nativeTime} ms");
136+
Trace.WriteLine($"int[] (managed) time: {nativeTime} ms");
137137

138138
// === Sanity Check ===
139139
var expected = (long)(Size - 1) * Size / 2;
@@ -143,6 +143,52 @@ public void CompareIntArrayvsIntArrayDotNetPerformance()
143143
// Optional performance sanity check (loose threshold)
144144
Assert.IsTrue(customTime < 2000, $"IntArray took too long: {customTime}ms");
145145
Assert.IsTrue(nativeTime < 2000, $"int[] took too long: {nativeTime}ms");
146+
147+
// === UnmanagedArray<T> Test ===
148+
var genericArray = new UnmanagedArray<int>(Size);
149+
stopwatch.Restart();
150+
151+
for (int i = 0; i < Size; i++)
152+
genericArray[i] = i;
153+
154+
long genericSum = 0;
155+
for (int i = 0; i < Size; i++)
156+
genericSum += genericArray[i];
157+
158+
stopwatch.Stop();
159+
var genericTime = stopwatch.ElapsedMilliseconds;
160+
genericArray.Dispose();
161+
162+
Trace.WriteLine($"UnmanagedArray<int> time: {genericTime} ms");
163+
Assert.AreEqual(expected, genericSum, "UnmanagedArray sum mismatch");
164+
165+
}
166+
167+
/// <summary>
168+
/// Indexings the should work for int array.
169+
/// </summary>
170+
[TestMethod]
171+
public void IndexingShouldWorkForIntArray() => RunIndexingTest(new IntArray(5));
172+
173+
/// <summary>
174+
/// Indexings the should work for unmanaged array.
175+
/// </summary>
176+
[TestMethod]
177+
public void IndexingShouldWorkForUnmanagedArray() => RunIndexingTest(new UnmanagedArray<int>(5));
178+
179+
/// <summary>
180+
/// Runs the indexing test.
181+
/// </summary>
182+
/// <param name="arr">The arr.</param>
183+
private static void RunIndexingTest(IUnmanagedArray<int> arr)
184+
{
185+
for (int i = 0; i < arr.Length; i++)
186+
arr[i] = i * 10;
187+
188+
for (int i = 0; i < arr.Length; i++)
189+
Assert.AreEqual(i * 10, arr[i]);
190+
191+
arr.Dispose();
146192
}
147193
}
148194
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* COPYRIGHT: See COPYING in the top level directory
3+
* PROJECT: ExtendedSystemObjects
4+
* FILE: ExtendedSystemObjects/IUnmanagedArray.cs
5+
* PURPOSE: An Abstraction for UnmanagedArray and IntArray to make both exchangeable.
6+
* PROGRAMMER: Peter Geinitz (Wayfarer)
7+
*/
8+
9+
using System;
10+
11+
namespace ExtendedSystemObjects
12+
{
13+
/// <summary>
14+
/// Interface to make unmanaged arrays interchangeable.
15+
/// </summary>
16+
/// <typeparam name="T">Generic Type</typeparam>
17+
/// <seealso cref="System.IDisposable" />
18+
public interface IUnmanagedArray<T> : IDisposable
19+
{
20+
int Length { get; }
21+
T this[int index] { get; set; }
22+
void Resize(int newSize);
23+
void Clear();
24+
}
25+
26+
}

ExtendedSystemObjects/IntArray.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ namespace ExtendedSystemObjects
1717
/// backed by unmanaged memory. Designed for performance-critical
1818
/// scenarios where garbage collection overhead must be avoided.
1919
/// </summary>
20+
/// <seealso cref="ExtendedSystemObjects.IUnmanagedArray" />
2021
/// <seealso cref="System.IDisposable" />
21-
public unsafe class IntArray : IDisposable
22+
public unsafe class IntArray : IUnmanagedArray<int>, IDisposable
2223
{
2324
/// <summary>
2425
/// The buffer
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace ExtendedSystemObjects
5+
{
6+
/// <summary>
7+
/// Unsafe array
8+
/// </summary>
9+
/// <typeparam name="T">Generic Type, must be unmanaged</typeparam>
10+
/// <seealso cref="System.IDisposable" />
11+
public unsafe class UnmanagedArray<T> : IUnmanagedArray<T>, IDisposable where T : unmanaged
12+
{
13+
private IntPtr _buffer;
14+
private T* _ptr;
15+
private int _length;
16+
17+
public int Length => _length;
18+
19+
/// <summary>
20+
/// Initializes a new instance of the <see cref="UnmanagedArray{T}"/> class.
21+
/// </summary>
22+
/// <param name="size">The size.</param>
23+
public UnmanagedArray(int size)
24+
{
25+
_length = size;
26+
_buffer = Marshal.AllocHGlobal(size * sizeof(T));
27+
_ptr = (T*)_buffer;
28+
}
29+
30+
/// <summary>
31+
/// Gets or sets the <see cref="T"/> at the specified index.
32+
/// </summary>
33+
/// <value>
34+
/// The <see cref="T"/>.
35+
/// </value>
36+
/// <param name="index">The index.</param>
37+
/// <returns>The value at the specified index.</returns>
38+
/// <exception cref="System.IndexOutOfRangeException"></exception>
39+
public T this[int index]
40+
{
41+
get
42+
{
43+
#if DEBUG
44+
if (index < 0 || index >= _length) throw new IndexOutOfRangeException();
45+
#endif
46+
return _ptr[index];
47+
}
48+
set
49+
{
50+
#if DEBUG
51+
if (index < 0 || index >= _length) throw new IndexOutOfRangeException();
52+
#endif
53+
_ptr[index] = value;
54+
}
55+
}
56+
57+
58+
/// <summary>
59+
/// Resizes the internal array to the specified new size.
60+
/// Contents will be preserved up to the minimum of old and new size.
61+
/// </summary>
62+
/// <param name="newSize">The new size of the array.</param>
63+
public void Resize(int newSize)
64+
{
65+
_buffer = Marshal.ReAllocHGlobal(_buffer, (IntPtr)(newSize * sizeof(T)));
66+
_ptr = (T*)_buffer;
67+
_length = newSize;
68+
}
69+
70+
/// <summary>
71+
/// Clears the array by setting all elements to zero.
72+
/// </summary>
73+
public void Clear()
74+
{
75+
// Use Span<T>.Clear for safety and type correctness
76+
AsSpan().Clear();
77+
}
78+
79+
public Span<T> AsSpan() => new Span<T>(_ptr, _length);
80+
81+
public void Dispose()
82+
{
83+
if (_buffer != IntPtr.Zero)
84+
{
85+
Marshal.FreeHGlobal(_buffer);
86+
_buffer = IntPtr.Zero;
87+
_ptr = null;
88+
_length = 0;
89+
}
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)