var objectPool = new ObjectPool<MyObject>(poolSize: 10);
MyObject obj = objectPool.Rent();
objectPool.Return(obj);
| using System; | |
| using System.Collections.Generic; | |
| using System.Diagnostics; | |
| using System.Threading; | |
| namespace GameServ | |
| { | |
| public class ObjectPool<TObject> | |
| { | |
| private int maxPoolSize; | |
| private Stack<TObject> poolCache; | |
| private Func<TObject> factory; | |
| public ObjectPool(int poolSize) | |
| { | |
| this.maxPoolSize = poolSize; | |
| this.poolCache = new Stack<TObject>(); | |
| } | |
| public ObjectPool(int poolSize, Func<TObject> factory) : this(poolSize) | |
| { | |
| this.factory = factory; | |
| } | |
| public TObject Rent() | |
| { | |
| TObject instance = default(TObject); | |
| Monitor.Enter(this.poolCache); | |
| if (this.poolCache.Count > 0) | |
| { | |
| instance = this.poolCache.Pop(); | |
| } | |
| Monitor.Exit(this.poolCache); | |
| if (instance != null) | |
| { | |
| return instance; | |
| } | |
| // New instances don't need to be prepared for re-use, so we just return it. | |
| if (this.factory == null) | |
| { | |
| return (TObject)Activator.CreateInstance(typeof(TObject)); | |
| } | |
| else | |
| { | |
| return this.factory(); | |
| } | |
| } | |
| public void Return(TObject instanceObject) | |
| { | |
| Monitor.Enter(poolCache); | |
| if (this.poolCache.Count >= this.maxPoolSize) | |
| { | |
| return; | |
| } | |
| // TODO: Convert Stack into an array. | |
| // We'll track the current index by decrementing the index in Rent, and incrementing in Return | |
| // Upon Renting, we'll set pool[index] to null, then reduce index by 1. This lets us manage an | |
| // array and have zero lookup costs. | |
| this.poolCache.Push(instanceObject); | |
| Monitor.Exit(poolCache); | |
| } | |
| } | |
| } |