add memory class isnt that cool
This commit is contained in:
parent
880f3e60ce
commit
f62c48396f
|
|
@ -0,0 +1,118 @@
|
||||||
|
using Qrakhen.Qamp.Core.Collections.Abstractions;
|
||||||
|
using Qrakhen.Qamp.Core.Values;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace Qrakhen.Qamp.Core.Collections;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Similar to a register with the caveat that the memory can free up or reserve blocks within itself, returning the next writeable address when storing data.
|
||||||
|
/// </summary>
|
||||||
|
public class Memory<TValue> :
|
||||||
|
IGetSet<Address, TValue>,
|
||||||
|
IToArray<TValue>,
|
||||||
|
IEnumerable<KeyValuePair<Address, TValue>>
|
||||||
|
{
|
||||||
|
private const int BLOCK_SIZE = sizeof(int);
|
||||||
|
private const uint BLOCK_FULL = (uint)((1UL << 32) - 1);
|
||||||
|
|
||||||
|
private readonly TValue[] _data;
|
||||||
|
|
||||||
|
private readonly uint[] _alloc;
|
||||||
|
|
||||||
|
public int Size { get; }
|
||||||
|
|
||||||
|
public TValue this[Address index]
|
||||||
|
{
|
||||||
|
get => _data[index];
|
||||||
|
set => _data[index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Memory(int size = 4096)
|
||||||
|
{
|
||||||
|
Size = size;
|
||||||
|
_data = new TValue[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetBlockIndex(Address address)
|
||||||
|
{
|
||||||
|
return (int)(address / BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetBitIndex(Address address)
|
||||||
|
{
|
||||||
|
return (int)(address % BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Address SeekFree(Address from = default)
|
||||||
|
{
|
||||||
|
Address cur = from - (from % BLOCK_SIZE);
|
||||||
|
while (cur < Size)
|
||||||
|
{
|
||||||
|
int block = GetBlockIndex(cur);
|
||||||
|
uint mask = _alloc[block];
|
||||||
|
if (mask < BLOCK_FULL)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
while ((mask & (1 << index)) > 0)
|
||||||
|
index++;
|
||||||
|
|
||||||
|
return (Address)((long)block * BLOCK_SIZE + index);
|
||||||
|
}
|
||||||
|
cur += BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
return Address.Void;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Free(Address address, int size = 1)
|
||||||
|
{
|
||||||
|
ArgumentOutOfRangeException.ThrowIfNotEqual(1, size); // only support single address freeing atm
|
||||||
|
int block = GetBlockIndex(address);
|
||||||
|
int index = GetBitIndex(address);
|
||||||
|
uint flags = _alloc[block];
|
||||||
|
_alloc[block] &= ~(1U << index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Allocate(int size = 1)
|
||||||
|
{
|
||||||
|
ArgumentOutOfRangeException.ThrowIfNotEqual(1, size); // only support single address allocation atm
|
||||||
|
Address address = SeekFree();
|
||||||
|
int block = GetBlockIndex(address);
|
||||||
|
int index = GetBitIndex(address);
|
||||||
|
_alloc[block] |= (1U << index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TValue[] ToArray()
|
||||||
|
{
|
||||||
|
return _data.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TValue Get(Address index)
|
||||||
|
{
|
||||||
|
return _data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Set(Address index, TValue value)
|
||||||
|
{
|
||||||
|
_data[index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address Add(TValue value)
|
||||||
|
{
|
||||||
|
Address free = SeekFree();
|
||||||
|
if (free == Address.Void)
|
||||||
|
throw new QampException($"Tried to add {value} to a memory block, but no free memory could be allocated.");
|
||||||
|
Set(free, value);
|
||||||
|
return free;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<Address, TValue>> GetEnumerator()
|
||||||
|
{
|
||||||
|
for (Address addr = 0; addr < Size; addr++)
|
||||||
|
yield return new KeyValuePair<Address, TValue>(addr, Get(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,9 @@ namespace Qrakhen.Qamp.Core.Values;
|
||||||
[StructLayout(LayoutKind.Sequential, Size = sizeof(long))]
|
[StructLayout(LayoutKind.Sequential, Size = sizeof(long))]
|
||||||
public readonly record struct Address(long Value)
|
public readonly record struct Address(long Value)
|
||||||
{
|
{
|
||||||
public override string ToString() => $"0x{Value:x8}";
|
public static readonly Address Void = new Address(-1);
|
||||||
|
|
||||||
|
public override string ToString() => $"&{Value:x8}";
|
||||||
|
|
||||||
public static implicit operator long(Address address) => address.Value;
|
public static implicit operator long(Address address) => address.Value;
|
||||||
public static implicit operator Address(long value) => new(value);
|
public static implicit operator Address(long value) => new(value);
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ public readonly struct Ptr
|
||||||
{
|
{
|
||||||
private static readonly PushStack<Obj> _register = new();
|
private static readonly PushStack<Obj> _register = new();
|
||||||
|
|
||||||
|
private static readonly Collections.Memory<Obj> _memory = [];
|
||||||
|
|
||||||
[Serialized] public readonly Address Address;
|
[Serialized] public readonly Address Address;
|
||||||
|
|
||||||
//private readonly IntPtr _pointer;
|
//private readonly IntPtr _pointer;
|
||||||
|
|
@ -27,6 +29,7 @@ public readonly struct Ptr
|
||||||
|
|
||||||
private Ptr(Address address)
|
private Ptr(Address address)
|
||||||
{
|
{
|
||||||
|
|
||||||
//_pointer = GCHandle.ToIntPtr(GCHandle.Alloc(obj, GCHandleType.Normal));
|
//_pointer = GCHandle.ToIntPtr(GCHandle.Alloc(obj, GCHandleType.Normal));
|
||||||
Address = address;
|
Address = address;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security.AccessControl;
|
||||||
using Qrakhen.Qamp.Core.Abstractions;
|
using Qrakhen.Qamp.Core.Abstractions;
|
||||||
using Qrakhen.Qamp.Core.Values.Objects;
|
using Qrakhen.Qamp.Core.Values.Objects;
|
||||||
using String = Qrakhen.Qamp.Core.Values.Objects.String;
|
using String = Qrakhen.Qamp.Core.Values.Objects.String;
|
||||||
|
|
@ -7,6 +8,27 @@ using T = Qrakhen.Qamp.Core.Values.ValueType;
|
||||||
|
|
||||||
namespace Qrakhen.Qamp.Core.Values;
|
namespace Qrakhen.Qamp.Core.Values;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// HEY. IDEA.
|
||||||
|
// have custom structs for types. this way we can handle many more thing and also more clean no????
|
||||||
|
|
||||||
|
public interface IPrimitive
|
||||||
|
{
|
||||||
|
public static abstract string Name { get; }
|
||||||
|
public static abstract int SizeOf { get; }
|
||||||
|
|
||||||
|
public ulong Raw { get; }
|
||||||
|
|
||||||
|
public string Print();
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly record struct Signed(long Value)// : IPrimitive
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface IValue<T>
|
public interface IValue<T>
|
||||||
{
|
{
|
||||||
T Data { get; }
|
T Data { get; }
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ public enum ValueType
|
||||||
Integer = Unsigned | Signed | Char,
|
Integer = Unsigned | Signed | Char,
|
||||||
Primitive = Integer | Decimal | Bool,
|
Primitive = Integer | Decimal | Bool,
|
||||||
|
|
||||||
Address = 0x0020, // coded with : symbol
|
Address = 0x0020,
|
||||||
|
|
||||||
// classes etc. here?
|
// classes etc. here?
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue