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); | |
} | |
} | |
} |