namespace SimpleObjectPool { using System; using System.Collections.Concurrent; using System.Collections.Generic; internal class MixedObjectPool : IMixedObjectPool where T : class { private const int DEFAULT_MAX_SIZE_PER_TYPE = 10; private readonly ConcurrentDictionary> entries; private readonly ConcurrentDictionary typeSize; private readonly IMixedObjectFactory factory; private int defaultMaxSizePerType; public MixedObjectPool(IMixedObjectFactory factory) : this(factory, DEFAULT_MAX_SIZE_PER_TYPE) { } public MixedObjectPool(IMixedObjectFactory factory, int defaultMaxSizePerType) { this.factory = factory; this.defaultMaxSizePerType = defaultMaxSizePerType; if (defaultMaxSizePerType <= 0) { throw new ArgumentException("The maxSize must be greater than 0."); } entries = new ConcurrentDictionary>(); typeSize = new ConcurrentDictionary(); } public T Allocate(string typeName) { if (entries.TryGetValue(typeName, out List list) && list.Count > 0) { T obj = list[0]; list.RemoveAt(0); return obj; } return factory.Create(typeName); } public void Free(string typeName, T obj) { if (obj == null) return; if (!factory.Validate(typeName, obj)) { factory.Destroy(typeName, obj); return; } int maxSize = GetMaxSize(typeName); List list = entries.GetOrAdd(typeName, n => new List()); if (list.Count >= maxSize) { factory.Destroy(typeName, obj); return; } factory.Reset(typeName, obj); list.Add(obj); } public int GetMaxSize(string typeName) { if (typeSize.TryGetValue(typeName, out int size)) { return size; } return defaultMaxSizePerType; } public void SetMaxSize(string typeName, int value) { typeSize.AddOrUpdate(typeName, value, (key, oldValue) => value); } protected virtual void Clear() { foreach (var kv in entries) { string typeName = kv.Key; List list = kv.Value; if (list == null || list.Count <= 0) continue; list.ForEach(e => factory.Destroy(typeName, e)); list.Clear(); } entries.Clear(); typeSize.Clear(); } public void Dispose() { Clear(); GC.SuppressFinalize(this); } } }