You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Zero/ZeroLevel/Services/Collections/RoundRobinCollection.cs

210 lines
5.3 KiB

6 years ago
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace ZeroLevel.Services.Collections
{
/// <summary>
/// Collection return new seq every iteration
/// Sample. Original: [1,2,3]. Iteration #1: [1, 2, 3]. Iteration #2: [2, 3, 1]. Iteration #3: [3, 1, 2]. Iteration #4: [1, 2, 3]
/// </summary>
/// <typeparam name="T"></typeparam>
6 years ago
public sealed class RoundRobinCollection<T> :
IDisposable
{
private readonly List<T> _collection =
new List<T>();
6 years ago
private int _index = -1;
6 years ago
private readonly ReaderWriterLockSlim _lock =
new ReaderWriterLockSlim();
public int Count { get { return _collection.Count; } }
public RoundRobinCollection() { }
public RoundRobinCollection(IEnumerable<T> items)
{
if (items != null && items.Any())
{
_collection.AddRange(items);
_index = 0;
}
}
6 years ago
public void Add(T item)
{
_lock.EnterWriteLock();
try
{
if (!_collection.Contains(item))
{
_collection.Add(item);
if (_index == -1) _index = 0;
}
6 years ago
}
finally
{
_lock.ExitWriteLock();
}
}
public void Remove(T item)
{
_lock.EnterWriteLock();
try
{
_collection.Remove(item);
if (_index >= _collection.Count)
{
if (_collection.Count == 0) _index = -1;
else _index = 0;
}
}
finally
{
_lock.ExitWriteLock();
}
}
public bool Contains(T item)
{
_lock.EnterReadLock();
try
{
return _collection.Contains(item);
}
finally
{
_lock.ExitReadLock();
}
}
public bool MoveNext()
{
_lock.EnterReadLock();
try
{
if (_collection.Count > 0)
{
_index = Interlocked.Increment(ref _index) % _collection.Count;
return true;
}
}
finally
{
_lock.ExitReadLock();
}
return false;
}
4 years ago
public IEnumerable<T> MoveNextSeq()
{
_lock.EnterReadLock();
try
{
if (_collection.Count > 0)
{
_index = Interlocked.Increment(ref _index) % _collection.Count;
int p = 0;
for (int i = _index; i < _collection.Count; i++, p++)
{
yield return _collection[i];
}
for (int i = 0; i < _index; i++, p++)
{
yield return _collection[i];
}
}
}
finally
{
_lock.ExitReadLock();
}
}
5 years ago
public bool MoveNextAndHandle(Action<T> handler)
{
_lock.EnterReadLock();
try
{
if (_collection.Count > 0)
{
_index = Interlocked.Increment(ref _index) % _collection.Count;
handler.Invoke(Current);
return true;
}
}
finally
{
_lock.ExitReadLock();
}
return false;
}
6 years ago
public T Current
{
get
{
7 months ago
return (_index == -1 ? default(T) : _collection[_index])!;
6 years ago
}
}
public IEnumerable<T> Source { get { return _collection; } }
public IEnumerable<T> GetCurrentSeq()
{
_lock.EnterReadLock();
try
{
int p = 0;
for (int i = _index; i < _collection.Count; i++, p++)
{
4 years ago
yield return _collection[i];
6 years ago
}
for (int i = 0; i < _index; i++, p++)
{
4 years ago
yield return _collection[i];
6 years ago
}
}
finally
{
_lock.ExitReadLock();
}
}
public IEnumerable<T> Find(Func<T, bool> selector)
{
_lock.EnterReadLock();
try
{
var arr = new List<T>(_collection.Count);
for (int i = _index; i < _collection.Count; i++)
{
if (selector(_collection[i]))
{
arr.Add(_collection[i]);
}
}
return arr;
}
finally
{
_lock.ExitReadLock();
}
6 years ago
}
public void Clear()
{
_collection.Clear();
_index = -1;
}
public void Dispose()
{
_collection.Clear();
_lock.Dispose();
}
}
}

Powered by TurnKey Linux.