Created
May 4, 2018 18:44
-
-
Save JustinPealing/472389e2f0c7a5f9176bb1fae7d8e6fe to your computer and use it in GitHub Desktop.
Awaitable pool of objects of type T
This file contains 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<T> | |
{ | |
private readonly Queue<T> _items = new Queue<T>(); | |
private readonly Queue<TaskCompletionSource<T>> _waits = new Queue<TaskCompletionSource<T>>(); | |
public void Add(T value) | |
{ | |
lock (_waits) | |
{ | |
if (_waits.TryDequeue(out var wait)) | |
wait.SetResult(value); | |
else | |
_items.Enqueue(value); | |
} | |
} | |
public Task<T> TakeAsync() | |
{ | |
lock (_waits) | |
{ | |
if (_items.TryDequeue(out var result)) | |
return Task.FromResult(result); | |
else | |
{ | |
var tcs = new TaskCompletionSource<T>(); | |
_waits.Enqueue(tcs); | |
return tcs.Task; | |
} | |
} | |
} | |
} | |
[TestClass] | |
public class ObjectPoolTest | |
{ | |
private readonly ObjectPool<string> _pool = new ObjectPool<string>(); | |
/// <summary> | |
/// ObjectPool is a pool of object of type T. Add is used to add an item to the pool, and TakeAsync is | |
/// used to get an item from the pool. | |
/// </summary> | |
[TestMethod] | |
public async Task Take() | |
{ | |
_pool.Add("test"); | |
Assert.AreEqual("test", await _pool.TakeAsync()); | |
} | |
/// <summary> | |
/// TakeAsync will wait until an object is added if there are no objects available in the pool. | |
/// </summary> | |
[TestMethod] | |
public void WaitForObject() | |
{ | |
var task = _pool.TakeAsync(); | |
Assert.IsFalse(task.IsCompleted); | |
_pool.Add("test"); | |
Assert.IsTrue(task.IsCompleted); | |
Assert.IsFalse(_pool.TakeAsync().IsCompleted); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment