namespace AcDream.App.Rendering;
///
/// Tracks shared resources by logical owner. Repeated use of the same key by
/// one owner is idempotent; a key is returned for destruction only after its
/// final owner leaves. Render-thread only.
///
internal sealed class OwnerScopedResourceRegistry where TKey : notnull
{
private readonly Dictionary> _keysByOwner = new();
private readonly Dictionary _ownerCountByKey = new();
public int OwnerCount => _keysByOwner.Count;
public int ResourceCount => _ownerCountByKey.Count;
public bool Acquire(uint ownerId, TKey key)
{
if (ownerId == 0)
throw new ArgumentOutOfRangeException(nameof(ownerId));
if (!_keysByOwner.TryGetValue(ownerId, out HashSet? keys))
{
keys = new HashSet();
_keysByOwner.Add(ownerId, keys);
}
if (!keys.Add(key))
return false;
_ownerCountByKey[key] = _ownerCountByKey.GetValueOrDefault(key) + 1;
return true;
}
public IReadOnlyList ReleaseOwner(uint ownerId)
{
if (!_keysByOwner.Remove(ownerId, out HashSet? keys))
return Array.Empty();
List? unowned = null;
foreach (TKey key in keys)
{
int remaining = _ownerCountByKey[key] - 1;
if (remaining > 0)
{
_ownerCountByKey[key] = remaining;
continue;
}
_ownerCountByKey.Remove(key);
(unowned ??= new List()).Add(key);
}
return unowned is null ? Array.Empty() : unowned;
}
public void Clear()
{
_keysByOwner.Clear();
_ownerCountByKey.Clear();
}
}