Skip to content

Commit 6d1af88

Browse files
committed
feat: rework
1 parent ce27ee7 commit 6d1af88

File tree

2 files changed

+113
-15
lines changed

2 files changed

+113
-15
lines changed

managed/CounterStrikeSharp.API/Modules/Memory/DisposableMemory.cs

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,17 @@
1414
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
1515
*/
1616

17+
using System;
18+
19+
using CounterStrikeSharp.API.Core;
20+
using CounterStrikeSharp.API.Modules.Utils;
21+
1722
namespace CounterStrikeSharp.API.Modules.Memory
1823
{
1924
public abstract class DisposableMemory : NativeObject, IDisposableMemory
2025
{
26+
internal static Type DisposableType = typeof(DisposableMemory);
27+
2128
internal static int _instances;
2229

2330
internal static int Instances
@@ -82,14 +89,111 @@ public virtual void ReleaseUnmanaged()
8289
MemAlloc.Free(Handle);
8390
}
8491

92+
/// <summary>
93+
/// Recursively checks if the given type is (or contains) a <see cref="DisposableMemory"/>
94+
/// </summary>
95+
/// <param name="type"></param>
96+
/// <returns></returns>
97+
internal static bool IsDisposableType(Type type)
98+
{
99+
/* This part will be only needed if we have a correct implementation for `NetworkedVector<>` or any class that has any `DisposableMemory` as generic.
100+
* Until that, this would be overkill
101+
if (type == DisposableType || DisposableType.IsAssignableFrom(type))
102+
return true;
103+
104+
if (type.IsGenericType)
105+
{
106+
foreach (Type arg in type.GetGenericArguments())
107+
{
108+
if (DisposableType.IsAssignableFrom(arg))
109+
{
110+
return true;
111+
}
112+
113+
if (IsDisposableType(arg))
114+
{
115+
return true;
116+
}
117+
}
118+
}
119+
120+
return type.BaseType != null && type.BaseType.Namespace!.StartsWith("CounterStrikeSharp") && IsDisposableType(type.BaseType);
121+
*/
122+
123+
return type == DisposableType || DisposableType.IsAssignableFrom(type);
124+
}
125+
126+
internal static void MarkAsPure(DisposableMemory disposable)
127+
{
128+
disposable.PurePointer = true;
129+
130+
// we should not count these as they are not handled by us.
131+
Instances--;
132+
}
133+
134+
/*
135+
internal static void MarkCollectionAsPure<T>(IEnumerable<T> collection) where T: DisposableMemory
136+
{
137+
foreach (DisposableMemory disposable in collection)
138+
{
139+
MarkAsPure(disposable);
140+
}
141+
}
142+
*/
143+
144+
/* Span<T> where T has pointer or reference: Only value types without pointers or references are supported.
145+
internal static void MarkSpanAsPure<T>(Span<T> collection)
146+
{
147+
foreach (T instance in collection)
148+
{
149+
if (instance is DisposableMemory disposable)
150+
{
151+
MarkAsPure(disposable);
152+
}
153+
}
154+
}
155+
*/
156+
85157
internal static void MarkAsPure(object? instance)
86158
{
87-
if (instance != null && instance is DisposableMemory disposable)
159+
if (instance == null)
160+
return;
161+
162+
switch (instance)
88163
{
89-
disposable.PurePointer = true;
164+
case DisposableMemory disposable:
165+
MarkAsPure(disposable);
166+
break;
90167

91-
// we should not count these as they are not handled by us.
92-
Instances--;
168+
/* since 'Networked vectors currently only support CHandle<T>' lets stab ourselves in the back in the future
169+
case NetworkedVector<Vector> vectors:
170+
MarkCollectionAsPure<Vector>(vectors);
171+
break;
172+
173+
case NetworkedVector<Vector2D> vector2ds:
174+
MarkCollectionAsPure<Vector2D>(vector2ds);
175+
break;
176+
177+
case NetworkedVector<Vector4D> vector4ds:
178+
MarkCollectionAsPure<Vector4D>(vector4ds);
179+
break;
180+
181+
// 'Angle' is only referenced inside the 'Vector' class
182+
case NetworkedVector<QAngle> angles:
183+
MarkCollectionAsPure<QAngle>(angles);
184+
break;
185+
186+
case NetworkedVector<Quaternion> quaternions:
187+
MarkCollectionAsPure<Quaternion>(quaternions);
188+
break;
189+
190+
case NetworkedVector<matrix3x4_t> matrixes:
191+
MarkCollectionAsPure<matrix3x4_t>(matrixes);
192+
break;
193+
194+
default: throw new NotSupportedException($"'MarkAsPure': type '{instance.GetType().Name}' is not supported.");
195+
*/
196+
default: return;
93197
}
94198
}
95199
}

managed/CounterStrikeSharp.API/Modules/Memory/Schema.cs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,14 @@ public static T GetDeclaredClass<T>(IntPtr pointer, string className, string mem
100100
{
101101
if (pointer == IntPtr.Zero) throw new ArgumentNullException(nameof(pointer), "Schema target points to null.");
102102

103-
if (typeof(DisposableMemory).IsAssignableFrom(typeof(T)) || (typeof(T).IsGenericType && typeof(DisposableMemory).IsAssignableFrom(typeof(T).GetGenericTypeDefinition())))
103+
object? instance = Activator.CreateInstance(typeof(T), pointer + GetSchemaOffset(className, memberName));
104+
105+
if (DisposableMemory.IsDisposableType(typeof(T)))
104106
{
105-
object? instance = Activator.CreateInstance(typeof(T), pointer + GetSchemaOffset(className, memberName));
106107
DisposableMemory.MarkAsPure(instance);
107-
return (T)instance;
108108
}
109109

110-
return (T)Activator.CreateInstance(typeof(T), pointer + GetSchemaOffset(className, memberName));
110+
return (T)instance;
111111
}
112112

113113
public static unsafe ref T GetRef<T>(IntPtr pointer, string className, string memberName)
@@ -147,13 +147,7 @@ public static unsafe Span<T> GetFixedArray<T>(IntPtr pointer, string className,
147147

148148
Span<T> span = new((void*)(pointer + GetSchemaOffset(className, memberName)), count);
149149

150-
if (typeof(DisposableMemory).IsAssignableFrom(typeof(T)) || (typeof(T).IsGenericType && typeof(DisposableMemory).IsAssignableFrom(typeof(T).GetGenericTypeDefinition())))
151-
{
152-
foreach (T instance in span)
153-
{
154-
DisposableMemory.MarkAsPure(instance);
155-
}
156-
}
150+
// TODO: once we get a correct implementation for this method check for `DisposableMemory` instances and mark them as pure
157151

158152
return span;
159153
}

0 commit comments

Comments
 (0)