namespace Dashboard.Drawing.OpenGL { public class ContextResourcePoolManager { private readonly Dictionary _unique = new Dictionary(); private readonly Dictionary _shared = new Dictionary(); public ContextResourcePool Get(IGLContext context) { if (context.ContextGroup == -1) { if (!_unique.TryGetValue(context, out ContextResourcePool? pool)) { pool = new ContextResourcePool(this, context); _unique.Add(context, pool); } return pool; } else { if (!_shared.TryGetValue(context.ContextGroup, out ContextResourcePool? pool)) { pool = new ContextResourcePool(this, context.ContextGroup); _shared.Add(context.ContextGroup, pool); } return pool; } } internal void Disposed(ContextResourcePool pool) { // TODO: } } public class ContextResourcePool : IGLDisposable, IArc { private int _references = 0; private bool _isDisposed = false; private readonly Dictionary _managers = new Dictionary(); public ContextResourcePoolManager Manager { get; } public IGLContext? Context { get; private set; } = null; public int ContextGroup { get; private set; } = -1; public int References => _references; public ContextCollector Collector { get; } = new ContextCollector(); internal ContextResourcePool(ContextResourcePoolManager manager, int contextGroup) { Manager = manager; ContextGroup = contextGroup; } internal ContextResourcePool(ContextResourcePoolManager manager, IGLContext context) { Manager = manager; Context = context; } public T GetResourceManager(bool init = true) where T : IResourceManager, new() { int index = ManagerAtom.Atom; if (!_managers.TryGetValue(index, out IResourceManager? resourceClass)) { _managers[index] = resourceClass = new T(); } if (init && resourceClass is IInitializer initializer) { initializer.Initialize(); } return (T)resourceClass; } ~ContextResourcePool() { Dispose(true, false); } public void Dispose() => Dispose(true, false); public void Dispose(bool safeExit) => Dispose(safeExit, true); private void Dispose(bool safeExit, bool disposing) { if (_isDisposed) return; _isDisposed = true; Manager.Disposed(this); if (disposing) { foreach ((int _, IResourceManager manager) in _managers) { if (manager is IGLDisposable glDisposable) glDisposable.Dispose(safeExit); else if (manager is IDisposable disposable) disposable.Dispose(); } GC.SuppressFinalize(this); } } public void IncrementReference() { Interlocked.Increment(ref _references); } public bool DecrementReference() { return Interlocked.Decrement(ref _references) == 0; } private class ManagerAtom { private static int _counter = -1; protected static int Acquire() => Interlocked.Increment(ref _counter); } private class ManagerAtom : ManagerAtom where T : IResourceManager { public static int Atom { get; } = Acquire(); } } }