Last active
February 25, 2017 21:03
-
-
Save scionwest/d64f7822be28d72f7006e63677ea196c to your computer and use it in GitHub Desktop.
ObjectPool<T>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ObjectPool<TObject> where TObject : class, new() | |
{ | |
private int maxPoolSize; | |
private Stack<TObject> poolCache; | |
private Action<TObject> objectReset; | |
private Func<TObject> factory; | |
private bool isObjectResettable; | |
public ObjectPool(int poolSize) | |
{ | |
this.maxPoolSize = poolSize; | |
this.poolCache = new Stack<TObject>(); | |
this.isObjectResettable = typeof(IReusable).GetTypeInfo().IsAssignableFrom(typeof(TObject).GetTypeInfo()); | |
} | |
public ObjectPool(int poolSize, Action<TObject> objectReset) : this(poolSize) | |
=> this.objectReset = objectReset; | |
public ObjectPool(int poolSize, Func<TObject> factory) : this(poolSize) | |
=> this.factory = factory; | |
public ObjectPool(int poolSize, Func<TObject> factory, Action<TObject> objectReset) : this(poolSize, objectReset) | |
=> this.factory = factory; | |
public TObject Rent() | |
{ | |
Monitor.Enter(this.poolCache); | |
if (this.poolCache.Count == 0) | |
{ | |
Monitor.Exit(this.poolCache); | |
// New instances don't need to be prepared for re-use, so we just return it. | |
return this.CreateNewInstance(); | |
} | |
TObject instance = this.poolCache.Pop(); | |
Monitor.Exit(this.poolCache); | |
this.TryResettingInstance(instance); | |
return instance; | |
} | |
public void Return(TObject instanceObject) | |
{ | |
Monitor.Enter(poolCache); | |
if (this.poolCache.Count >= this.maxPoolSize) | |
{ | |
Monitor.Exit(poolCache); | |
return; | |
} | |
this.poolCache.Push(instanceObject); | |
Monitor.Exit(poolCache); | |
} | |
private TObject CreateNewInstance() => this.factory == null | |
? new TObject() | |
: this.factory(); | |
private void TryResettingInstance(TObject instance) | |
{ | |
if (this.objectReset != null) | |
{ | |
this.objectReset(instance); | |
return; | |
} | |
if (this.isObjectResettable) | |
{ | |
IReusable resettableInstance = (IReusable)instance; | |
resettableInstance.PrepareForReuse(); | |
return; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment