diff --git a/src/Flecs.NET.Codegen/Helpers/Type.cs b/src/Flecs.NET.Codegen/Helpers/Type.cs index 8fdf9a5..ae9d0bc 100644 --- a/src/Flecs.NET.Codegen/Helpers/Type.cs +++ b/src/Flecs.NET.Codegen/Helpers/Type.cs @@ -1,4 +1,3 @@ - using System.Diagnostics.CodeAnalysis; namespace Flecs.NET.Codegen.Helpers; diff --git a/src/Flecs.NET/Core/BindingContext/Functions.cs b/src/Flecs.NET/Core/BindingContext/Functions.cs index 586218a..0656a51 100644 --- a/src/Flecs.NET/Core/BindingContext/Functions.cs +++ b/src/Flecs.NET/Core/BindingContext/Functions.cs @@ -12,48 +12,54 @@ namespace Flecs.NET.Core.BindingContext; /// internal static unsafe class Functions { - #region Context Free + #region Context Free [UnmanagedCallersOnly] internal static void WorldContextFree(WorldContext* context) { - context->Dispose(); - Memory.Free(context); + WorldContext.Free(context); } [UnmanagedCallersOnly] internal static void IteratorContextFree(IteratorContext* context) { - context->Dispose(); - Memory.Free(context); + IteratorContext.Free(context); } [UnmanagedCallersOnly] internal static void RunContextFree(RunContext* context) { - context->Dispose(); - Memory.Free(context); + RunContext.Free(context); } [UnmanagedCallersOnly] internal static void QueryContextFree(QueryContext* context) { - context->Dispose(); - Memory.Free(context); + QueryContext.Free(context); } [UnmanagedCallersOnly] internal static void GroupByContextFree(GroupByContext* context) { - context->Dispose(); - Memory.Free(context); + GroupByContext.Free(context); + } + + [UnmanagedCallersOnly] + internal static void SystemContextFree(SystemContext* context) + { + SystemContext.Free(context); + } + + [UnmanagedCallersOnly] + internal static void ObserverContextFree(ObserverContext* context) + { + ObserverContext.Free(context); } [UnmanagedCallersOnly] internal static void TypeHooksContextFree(TypeHooksContext* context) { - context->Dispose(); - Memory.Free(context); + TypeHooksContext.Free(context); } internal static void UserContextFinishDelegate(ref UserContext context) diff --git a/src/Flecs.NET/Core/BindingContext/GroupByContext.cs b/src/Flecs.NET/Core/BindingContext/GroupByContext.cs index b8a78d7..4673a36 100644 --- a/src/Flecs.NET/Core/BindingContext/GroupByContext.cs +++ b/src/Flecs.NET/Core/BindingContext/GroupByContext.cs @@ -1,8 +1,9 @@ using System; +using Flecs.NET.Utilities; namespace Flecs.NET.Core.BindingContext; -internal struct GroupByContext : IDisposable +internal unsafe struct GroupByContext : IDisposable { public Callback GroupBy; public Callback GroupCreate; @@ -16,4 +17,18 @@ public void Dispose() GroupDelete.Dispose(); GroupByUserContext.Dispose(); } + + public static void Free(GroupByContext* context) + { + if (context == null) + return; + context->Dispose(); + Memory.Free(context); + } + + public static void Free(ref GroupByContext context) + { + fixed (GroupByContext* ptr = &context) + Free(ptr); + } } diff --git a/src/Flecs.NET/Core/BindingContext/IteratorContext.cs b/src/Flecs.NET/Core/BindingContext/IteratorContext.cs index 3c0b246..9a79289 100644 --- a/src/Flecs.NET/Core/BindingContext/IteratorContext.cs +++ b/src/Flecs.NET/Core/BindingContext/IteratorContext.cs @@ -1,8 +1,9 @@ using System; +using Flecs.NET.Utilities; namespace Flecs.NET.Core.BindingContext; -internal struct IteratorContext : IDisposable +internal unsafe struct IteratorContext : IDisposable { public Callback Callback; @@ -10,4 +11,18 @@ public void Dispose() { Callback.Dispose(); } + + public static void Free(IteratorContext* context) + { + if (context == null) + return; + context->Dispose(); + Memory.Free(context); + } + + public static void Free(ref IteratorContext context) + { + fixed (IteratorContext* ptr = &context) + Free(ptr); + } } diff --git a/src/Flecs.NET/Core/BindingContext/ObserverContext.cs b/src/Flecs.NET/Core/BindingContext/ObserverContext.cs new file mode 100644 index 0000000..7e4742d --- /dev/null +++ b/src/Flecs.NET/Core/BindingContext/ObserverContext.cs @@ -0,0 +1,28 @@ +using System; +using Flecs.NET.Utilities; + +namespace Flecs.NET.Core.BindingContext; + +internal unsafe struct ObserverContext : IDisposable +{ + public UserContext UserContext; + + public void Dispose() + { + UserContext.Dispose(); + } + + public static void Free(ObserverContext* context) + { + if (context == null) + return; + context->Dispose(); + Memory.Free(context); + } + + public static void Free(ref ObserverContext context) + { + fixed (ObserverContext* ptr = &context) + Free(ptr); + } +} diff --git a/src/Flecs.NET/Core/BindingContext/OsApiContext.cs b/src/Flecs.NET/Core/BindingContext/OsApiContext.cs index 05b62ee..3963332 100644 --- a/src/Flecs.NET/Core/BindingContext/OsApiContext.cs +++ b/src/Flecs.NET/Core/BindingContext/OsApiContext.cs @@ -1,8 +1,9 @@ using System; +using Flecs.NET.Utilities; namespace Flecs.NET.Core.BindingContext; -internal struct OsApiContext : IDisposable +internal unsafe struct OsApiContext : IDisposable { public Callback Abort; public Callback Log; @@ -12,4 +13,18 @@ public void Dispose() Abort.Dispose(); Log.Dispose(); } + + public static void Free(OsApiContext* context) + { + if (context == null) + return; + context->Dispose(); + Memory.Free(context); + } + + public static void Free(ref OsApiContext context) + { + fixed (OsApiContext* ptr = &context) + Free(ptr); + } } diff --git a/src/Flecs.NET/Core/BindingContext/Pointers.cs b/src/Flecs.NET/Core/BindingContext/Pointers.cs index ffaf3b9..85f692c 100644 --- a/src/Flecs.NET/Core/BindingContext/Pointers.cs +++ b/src/Flecs.NET/Core/BindingContext/Pointers.cs @@ -33,6 +33,8 @@ static Pointers() internal static readonly nint RunContextFree = (nint)(delegate* unmanaged)&Functions.RunContextFree; internal static readonly nint QueryContextFree = (nint)(delegate* unmanaged)&Functions.QueryContextFree; internal static readonly nint GroupByContextFree = (nint)(delegate* unmanaged)&Functions.GroupByContextFree; + internal static readonly nint SystemContextFree = (nint)(delegate* unmanaged)&Functions.SystemContextFree; + internal static readonly nint ObserverContextFree = (nint)(delegate* unmanaged)&Functions.ObserverContextFree; internal static readonly nint TypeHooksContextFree = (nint)(delegate* unmanaged)&Functions.TypeHooksContextFree; #endregion diff --git a/src/Flecs.NET/Core/BindingContext/PostFrameContext.cs b/src/Flecs.NET/Core/BindingContext/PostFrameContext.cs index d28b295..574c668 100644 --- a/src/Flecs.NET/Core/BindingContext/PostFrameContext.cs +++ b/src/Flecs.NET/Core/BindingContext/PostFrameContext.cs @@ -1,8 +1,9 @@ using System; +using Flecs.NET.Utilities; namespace Flecs.NET.Core.BindingContext; -internal struct PostFrameContext : IDisposable +internal unsafe struct PostFrameContext : IDisposable { public Callback Callback; @@ -10,4 +11,18 @@ public void Dispose() { Callback.Dispose(); } + + public static void Free(PostFrameContext* context) + { + if (context == null) + return; + context->Dispose(); + Memory.Free(context); + } + + public static void Free(ref PostFrameContext context) + { + fixed (PostFrameContext* ptr = &context) + Free(ptr); + } } diff --git a/src/Flecs.NET/Core/BindingContext/QueryContext.cs b/src/Flecs.NET/Core/BindingContext/QueryContext.cs index 039cdaa..067e3b9 100644 --- a/src/Flecs.NET/Core/BindingContext/QueryContext.cs +++ b/src/Flecs.NET/Core/BindingContext/QueryContext.cs @@ -4,7 +4,7 @@ namespace Flecs.NET.Core.BindingContext; -internal struct QueryContext : IDisposable +internal unsafe struct QueryContext : IDisposable { public Callback OrderBy; public Callback ContextFree; @@ -24,4 +24,18 @@ public void Dispose() Strings.Dispose(); } + + public static void Free(QueryContext* context) + { + if (context == null) + return; + context->Dispose(); + Memory.Free(context); + } + + public static void Free(ref QueryContext context) + { + fixed (QueryContext* ptr = &context) + Free(ptr); + } } diff --git a/src/Flecs.NET/Core/BindingContext/RunContext.cs b/src/Flecs.NET/Core/BindingContext/RunContext.cs index 34df7ed..fac5c52 100644 --- a/src/Flecs.NET/Core/BindingContext/RunContext.cs +++ b/src/Flecs.NET/Core/BindingContext/RunContext.cs @@ -1,8 +1,9 @@ using System; +using Flecs.NET.Utilities; namespace Flecs.NET.Core.BindingContext; -internal struct RunContext : IDisposable +internal unsafe struct RunContext : IDisposable { public Callback Callback; @@ -10,4 +11,18 @@ public void Dispose() { Callback.Dispose(); } + + public static void Free(RunContext* context) + { + if (context == null) + return; + context->Dispose(); + Memory.Free(context); + } + + public static void Free(ref RunContext context) + { + fixed (RunContext* ptr = &context) + Free(ptr); + } } diff --git a/src/Flecs.NET/Core/BindingContext/SystemContext.cs b/src/Flecs.NET/Core/BindingContext/SystemContext.cs new file mode 100644 index 0000000..89be70d --- /dev/null +++ b/src/Flecs.NET/Core/BindingContext/SystemContext.cs @@ -0,0 +1,28 @@ +using System; +using Flecs.NET.Utilities; + +namespace Flecs.NET.Core.BindingContext; + +internal unsafe struct SystemContext : IDisposable +{ + public UserContext UserContext; + + public void Dispose() + { + UserContext.Dispose(); + } + + public static void Free(SystemContext* context) + { + if (context == null) + return; + context->Dispose(); + Memory.Free(context); + } + + public static void Free(ref SystemContext context) + { + fixed (SystemContext* ptr = &context) + Free(ptr); + } +} diff --git a/src/Flecs.NET/Core/BindingContext/TypeHooksContext.cs b/src/Flecs.NET/Core/BindingContext/TypeHooksContext.cs index 1415a65..3739ebe 100644 --- a/src/Flecs.NET/Core/BindingContext/TypeHooksContext.cs +++ b/src/Flecs.NET/Core/BindingContext/TypeHooksContext.cs @@ -1,8 +1,9 @@ using System; +using Flecs.NET.Utilities; namespace Flecs.NET.Core.BindingContext; -internal struct TypeHooksContext : IDisposable +internal unsafe struct TypeHooksContext : IDisposable { public int Header; @@ -28,4 +29,18 @@ public void Dispose() OnRemove.Dispose(); ContextFree.Dispose(); } + + public static void Free(TypeHooksContext* context) + { + if (context == null) + return; + context->Dispose(); + Memory.Free(context); + } + + public static void Free(ref TypeHooksContext context) + { + fixed (TypeHooksContext* ptr = &context) + Free(ptr); + } } diff --git a/src/Flecs.NET/Core/BindingContext/WorldContext.cs b/src/Flecs.NET/Core/BindingContext/WorldContext.cs index a81f0a5..4c108cf 100644 --- a/src/Flecs.NET/Core/BindingContext/WorldContext.cs +++ b/src/Flecs.NET/Core/BindingContext/WorldContext.cs @@ -26,4 +26,18 @@ public void Dispose() foreach (nint ptr in WorldFinishContexts) Memory.Free((WorldFinishContext*)ptr); } + + public static void Free(WorldContext* context) + { + if (context == null) + return; + context->Dispose(); + Memory.Free(context); + } + + public static void Free(ref WorldContext context) + { + fixed (WorldContext* ptr = &context) + Free(ptr); + } } diff --git a/src/Flecs.NET/Core/BindingContext/WorldFinishContext.cs b/src/Flecs.NET/Core/BindingContext/WorldFinishContext.cs index 36420e6..ae9ff43 100644 --- a/src/Flecs.NET/Core/BindingContext/WorldFinishContext.cs +++ b/src/Flecs.NET/Core/BindingContext/WorldFinishContext.cs @@ -1,8 +1,9 @@ using System; +using Flecs.NET.Utilities; namespace Flecs.NET.Core.BindingContext; -internal struct WorldFinishContext : IDisposable +internal unsafe struct WorldFinishContext : IDisposable { public Callback Callback; @@ -10,4 +11,18 @@ public void Dispose() { Callback.Dispose(); } + + public static void Free(WorldFinishContext* context) + { + if (context == null) + return; + context->Dispose(); + Memory.Free(context); + } + + public static void Free(ref WorldFinishContext context) + { + fixed (WorldFinishContext* ptr = &context) + Free(ptr); + } } diff --git a/src/Flecs.NET/Core/ObserverBuilder.cs b/src/Flecs.NET/Core/ObserverBuilder.cs index fa99379..27e962f 100644 --- a/src/Flecs.NET/Core/ObserverBuilder.cs +++ b/src/Flecs.NET/Core/ObserverBuilder.cs @@ -30,6 +30,10 @@ public unsafe partial struct ObserverBuilder : IDisposable, IEquatable public ref QueryBuilder QueryBuilder => ref _queryBuilder; + internal ref ObserverContext ObserverContext => ref *EnsureObserverContext(); + internal ref IteratorContext IteratorContext => ref *EnsureIteratorContext(); + internal ref RunContext RunContext => ref *EnsureRunContext(); + /// /// Creates an observer builder for the provided world. /// @@ -66,8 +70,10 @@ public ObserverBuilder(ecs_world_t* world, string name) : this(world) public void Dispose() { QueryBuilder.Dispose(); - FreeRun(); - FreeCallback(); + ObserverContext.Free(ref ObserverContext); + IteratorContext.Free(ref IteratorContext); + RunContext.Free(ref RunContext); + this = default; } /// @@ -309,45 +315,25 @@ public Observer Each(delegate* callback) internal ref ObserverBuilder SetCallback(T callback, nint invoker) where T : Delegate { - FreeCallback(); - IteratorContext context = default; - context.Callback.Set(callback, invoker); - Desc.callback = Pointers.IteratorCallback; - Desc.callback_ctx = Memory.Alloc(context); - Desc.callback_ctx_free = Pointers.IteratorContextFree; + IteratorContext.Callback.Set(callback, invoker); return ref this; } internal ref ObserverBuilder SetCallback(nint callback, nint invoker) { - FreeCallback(); - IteratorContext context = default; - context.Callback.Set(callback, invoker); - Desc.callback = Pointers.IteratorCallback; - Desc.callback_ctx = Memory.Alloc(context); - Desc.callback_ctx_free = Pointers.IteratorContextFree; + IteratorContext.Callback.Set(callback, invoker); return ref this; } internal ref ObserverBuilder SetRun(T callback, nint invoker) where T : Delegate { - FreeRun(); - RunContext context = default; - context.Callback.Set(callback, invoker); - Desc.run = Pointers.RunCallback; - Desc.run_ctx = Memory.Alloc(context); - Desc.run_ctx_free = Pointers.RunContextFree; + RunContext.Callback.Set(callback, invoker); return ref this; } internal ref ObserverBuilder SetRun(nint callback, nint invoker) { - FreeRun(); - RunContext context = default; - context.Callback.Set(callback, invoker); - Desc.run = Pointers.RunCallback; - Desc.run_ctx = Memory.Alloc(context); - Desc.run_ctx_free = Pointers.RunContextFree; + RunContext.Callback.Set(callback, invoker); return ref this; } @@ -368,20 +354,36 @@ Observer IQueryBuilder.Build() return Build(); } - private void FreeRun() + private ObserverContext* EnsureObserverContext() { - if (Desc.run == default) - return; + if (Desc.ctx != null) + return (ObserverContext*)Desc.ctx; - ((delegate*)Desc.run_ctx_free)(Desc.run_ctx); + Desc.ctx = Memory.AllocZeroed(1); + Desc.ctx_free = Pointers.ObserverContextFree; + return (ObserverContext*)Desc.ctx; } - private void FreeCallback() + private IteratorContext* EnsureIteratorContext() { - if (Desc.callback == default) - return; + if (Desc.callback_ctx != null) + return (IteratorContext*)Desc.callback_ctx; - ((delegate*)Desc.callback_ctx_free)(Desc.callback_ctx); + Desc.callback = Pointers.IteratorCallback; + Desc.callback_ctx = Memory.AllocZeroed(1); + Desc.callback_ctx_free = Pointers.IteratorContextFree; + return (IteratorContext*)Desc.callback_ctx; + } + + private RunContext* EnsureRunContext() + { + if (Desc.run_ctx != null) + return (RunContext*)Desc.run_ctx; + + Desc.run = Pointers.RunCallback; + Desc.run_ctx = Memory.AllocZeroed(1); + Desc.run_ctx_free = Pointers.RunContextFree; + return (RunContext*)Desc.run_ctx; } /// diff --git a/src/Flecs.NET/Core/QueryBuilder.cs b/src/Flecs.NET/Core/QueryBuilder.cs index 1e6650e..c4843d9 100644 --- a/src/Flecs.NET/Core/QueryBuilder.cs +++ b/src/Flecs.NET/Core/QueryBuilder.cs @@ -102,7 +102,9 @@ public QueryBuilder(ecs_world_t* world, string name) : this(world) /// public void Dispose() { - QueryContext.Dispose(); + QueryContext.Free(ref QueryContext); + GroupByContext.Free(ref GroupByContext); + this = default; } /// diff --git a/src/Flecs.NET/Core/SystemBuilder.cs b/src/Flecs.NET/Core/SystemBuilder.cs index 2a72d84..21f44c1 100644 --- a/src/Flecs.NET/Core/SystemBuilder.cs +++ b/src/Flecs.NET/Core/SystemBuilder.cs @@ -29,6 +29,10 @@ public unsafe partial struct SystemBuilder : IDisposable, IEquatable public ref QueryBuilder QueryBuilder => ref _queryBuilder; + internal ref SystemContext SystemContext => ref *EnsureSystemContext(); + internal ref IteratorContext IteratorContext => ref *EnsureIteratorContext(); + internal ref RunContext RunContext => ref *EnsureRunContext(); + /// /// Creates a system builder for the provided world. /// @@ -75,8 +79,10 @@ public SystemBuilder(ecs_world_t* world, string name) public void Dispose() { QueryBuilder.Dispose(); - FreeRun(); - FreeCallback(); + SystemContext.Free(ref SystemContext); + IteratorContext.Free(ref IteratorContext); + RunContext.Free(ref RunContext); + this = default; } /// @@ -396,46 +402,25 @@ public System_ Each(delegate* callback) internal ref SystemBuilder SetCallback(T callback, nint invoker) where T : Delegate { - FreeCallback(); - IteratorContext context = default; - context.Callback.Set(callback, invoker); - Desc.callback = Pointers.IteratorCallback; - Desc.callback_ctx = Memory.Alloc(context); - Desc.callback_ctx_free = Pointers.IteratorContextFree; + IteratorContext.Callback.Set(callback, invoker); return ref this; } internal ref SystemBuilder SetCallback(nint callback, nint invoker) { - FreeCallback(); - IteratorContext context = default; - context.Callback.Set(callback, invoker); - Desc.callback = Pointers.IteratorCallback; - Desc.callback_ctx = Memory.Alloc(context); - Desc.callback_ctx_free = Pointers.IteratorContextFree; - + IteratorContext.Callback.Set(callback, invoker); return ref this; } internal ref SystemBuilder SetRun(T callback, nint invoker) where T : Delegate { - FreeRun(); - RunContext context = default; - context.Callback.Set(callback, invoker); - Desc.run = Pointers.RunCallback; - Desc.run_ctx = Memory.Alloc(context); - Desc.run_ctx_free = Pointers.RunContextFree; + RunContext.Callback.Set(callback, invoker); return ref this; } internal ref SystemBuilder SetRun(nint callback, nint invoker) { - FreeRun(); - RunContext context = default; - context.Callback.Set(callback, invoker); - Desc.run = Pointers.RunCallback; - Desc.run_ctx = Memory.Alloc(context); - Desc.run_ctx_free = Pointers.RunContextFree; + RunContext.Callback.Set(callback, invoker); return ref this; } @@ -452,20 +437,36 @@ System_ IQueryBuilder.Build() return Build(); } - private void FreeRun() + private SystemContext* EnsureSystemContext() { - if (Desc.run == default) - return; + if (Desc.ctx != null) + return (SystemContext*)Desc.ctx; - ((delegate*)Desc.run_ctx_free)(Desc.run_ctx); + Desc.ctx = Memory.AllocZeroed(1); + Desc.ctx_free = Pointers.SystemContextFree; + return (SystemContext*)Desc.ctx; } - private void FreeCallback() + private IteratorContext* EnsureIteratorContext() { - if (Desc.callback == default) - return; + if (Desc.callback_ctx != null) + return (IteratorContext*)Desc.callback_ctx; + + Desc.callback = Pointers.IteratorCallback; + Desc.callback_ctx = Memory.AllocZeroed(1); + Desc.callback_ctx_free = Pointers.IteratorContextFree; + return (IteratorContext*)Desc.callback_ctx; + } - ((delegate*)Desc.callback_ctx_free)(Desc.callback_ctx); + private RunContext* EnsureRunContext() + { + if (Desc.run_ctx != null) + return (RunContext*)Desc.run_ctx; + + Desc.run = Pointers.RunCallback; + Desc.run_ctx = Memory.AllocZeroed(1); + Desc.run_ctx_free = Pointers.RunContextFree; + return (RunContext*)Desc.run_ctx; } ///