using System; using System.Collections.Generic; using io.github.hatayama.uLoopMCP.Factory; namespace io.github.hatayama.uLoopMCP { internal sealed class DynamicCodeExecutorPool : IDynamicCodeExecutorPool { private readonly IDynamicCodeExecutorProvider _executorProvider; private readonly Dictionary _executorsBySecurityLevel = new(); private readonly object _executorsLock = new(); private bool _disposed; public DynamicCodeExecutorPool(IDynamicCodeExecutorProvider executorProvider) { _executorProvider = executorProvider ?? throw new ArgumentNullException(nameof(executorProvider)); } public IDynamicCodeExecutor GetOrCreate(DynamicCodeSecurityLevel securityLevel) { lock (_executorsLock) { ThrowIfDisposed(); if (_executorsBySecurityLevel.TryGetValue(securityLevel, out IDynamicCodeExecutor executor)) { return executor; } IDynamicCodeExecutor createdExecutor = _executorProvider.Create(securityLevel); if (createdExecutor is DynamicCodeExecutorStub) { return createdExecutor; } _executorsBySecurityLevel.Add(securityLevel, createdExecutor); return createdExecutor; } } public void Dispose() { lock (_executorsLock) { if (_disposed) { return; } _disposed = true; foreach (IDynamicCodeExecutor executor in _executorsBySecurityLevel.Values) { executor.Dispose(); } _executorsBySecurityLevel.Clear(); } } private void ThrowIfDisposed() { if (_disposed) { throw new ObjectDisposedException(nameof(DynamicCodeExecutorPool)); } } } }