refactor(lifetime): own render resource prefixes
Give terrain, sky, retained UI, portal preparation, and the update/render frame pair explicit single owners. Make shader, texture, text, bindless, and GL construction prefixes checked and retryable so partial failure cannot lose or replay resource ownership. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
fec0d94148
commit
c87b15303d
41 changed files with 3768 additions and 355 deletions
63
src/AcDream.App/Rendering/ResourceCleanupGroup.cs
Normal file
63
src/AcDream.App/Rendering/ResourceCleanupGroup.cs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
namespace AcDream.App.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Reverse-order, all-attempted cleanup owner used while a composite resource
|
||||
/// is still under construction and after it becomes the aggregate owner.
|
||||
/// </summary>
|
||||
internal sealed class ResourceCleanupGroup : IRetryableResourceCleanup
|
||||
{
|
||||
private sealed record Entry(string Name, Action Release)
|
||||
{
|
||||
public bool Complete { get; set; }
|
||||
}
|
||||
|
||||
private readonly List<Entry> _entries = [];
|
||||
private bool _running;
|
||||
|
||||
public bool IsCleanupComplete => _entries.All(static entry => entry.Complete);
|
||||
|
||||
public void Add(string name, Action release)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(name);
|
||||
ArgumentNullException.ThrowIfNull(release);
|
||||
if (_running || IsCleanupComplete && _entries.Count != 0)
|
||||
throw new InvalidOperationException("The resource cleanup group is no longer accepting ownership.");
|
||||
_entries.Add(new Entry(name, release));
|
||||
}
|
||||
|
||||
public void RetryCleanup()
|
||||
{
|
||||
if (_running || IsCleanupComplete)
|
||||
return;
|
||||
|
||||
_running = true;
|
||||
List<Exception>? failures = null;
|
||||
try
|
||||
{
|
||||
for (int i = _entries.Count - 1; i >= 0; i--)
|
||||
{
|
||||
Entry entry = _entries[i];
|
||||
if (entry.Complete)
|
||||
continue;
|
||||
try
|
||||
{
|
||||
entry.Release();
|
||||
entry.Complete = true;
|
||||
}
|
||||
catch (Exception failure)
|
||||
{
|
||||
(failures ??= []).Add(new InvalidOperationException(
|
||||
$"Resource cleanup operation '{entry.Name}' failed.",
|
||||
failure));
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_running = false;
|
||||
}
|
||||
|
||||
if (failures is not null)
|
||||
throw new AggregateException("Composite resource cleanup remains incomplete.", failures);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue