c# - 如何正确确定循环池中的活动实例?
问题描述
我有一个循环池实现
public class CircularPool<T> where T : class, new()
{
private readonly Queue<T> instances;
public CircularPool(int size)
{
instances = new Queue<T>(size);
for (var i = 0; i < size; ++i)
{
instances.Enqueue(new T());
}
}
public T GetInstance()
{
var instance = instances.Dequeue();
instances.Enqueue(instance); // Circular pool
return instance;
}
public void ReturnInstance(T instance)
{
// What does returning look like?
// Could use IsActive flag?
}
public IEnumerable<T> GetActiveInstances()
{
return instances; // TODO: Only want the active ones
}
}
我希望能够跟踪池中当前正在使用的实例,以便可以迭代它们并执行各种操作
var pool = new CircularPool<Foo>(5);
var fooInstanceA = pool.GetInstance();
var fooInstanceB = pool.GetInstance();
var fooInstanceC = pool.GetInstance();
pool.ReturnInstance(fooInstanceB);
foreach (var activeInstance in pool.GetActiveInstances())
{
// Do stuff with active instances (fooInstanceA then fooInstanceC)
}
如何按年龄顺序正确获取活动实例?
鉴于这是一个循环池,那么如果调用 GetInstance 的次数超过了池的大小而没有调用 ReturnInstance,则返回最旧的活动实例并成为最年轻的活动实例。这应该相应地反映在 GetActiveInstances 中。
此外,在循环池的上下文中 ReturnInstance 应该是什么样子?
解决方案
好吧,我们可以T[]
对所有实例和HashSet<T>
活动实例使用数组:
public class CircularPool<T> where T : class, new() {
private readonly T[] m_All;
private readonly HashSet<T> m_InUse;
private int m_Index; // Index to start looking for a free instance
public CircularPool(int size) {
if (size <= 0)
throw new ArgumentOutOfRangeException(nameof(size));
m_InUse = new HashSet<T>(size);
m_All = Enumerable.Range(0, size).Select(_ => new T()).ToArray();
}
public bool TryGetInstance(out T availableInstance) {
for (int i = 0; i < m_All.Length; ++i) {
int index = (i + m_Index) % m_All.Length;
if (m_InUse.Add(m_All[index])) {
availableInstance = m_All[index];
m_Index = index + 1;
return true;
}
}
availableInstance = default(T); // no available instances found
return false;
}
public T GetInstance() => TryGetInstance(out var result)
? result
: throw new InvalidOperationException("There are no available instances.");
public bool ReturnInstance(T instance) => m_InUse.Remove(instance);
public IEnumerable<T> GetActiveInstances() => m_InUse;
public IEnumerable<T> GetAvailableInstances() =>
m_All.Where(item => !m_All.Contains(item));
}
推荐阅读
- python - Python - 根据另一个单元格条件选择行单元格
- javascript - 在多级对象数组上使用过滤器?
- database - Microsoft Access:如何在连续表单上添加一个按钮,该按钮将更新与该按钮在同一行中的特定字段的值?
- python - 替换数据框中的某个值
- javascript - Javascript从xml中删除节点
- c++ - 允许用户在我的类中定义数组大小而不是使用固定变量的最佳方法是什么,在这种情况下为 8
- javascript - 使用路由器调用另一个组件上的方法
- c - 是否可以在 Flex/Lex 中定义多个“名称”?
- php - 购物车内只有虚拟商品不收取手续费
- r - 为什么此数据框变量采用未明确分配给它的属性?(dplyr-R)