using System; using System.Collections.Generic; using System.Linq; using System.Threading; namespace ZeroLevel.Services.Collections { /// /// 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] /// /// public sealed class RoundRobinCollection : IDisposable { private readonly List _collection = new List(); private int _index = -1; private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); public int Count { get { return _collection.Count; } } public RoundRobinCollection() { } public RoundRobinCollection(IEnumerable items) { if (items != null && items.Any()) { _collection.AddRange(items); _index = 0; } } public void Add(T item) { _lock.EnterWriteLock(); try { if (!_collection.Contains(item)) { _collection.Add(item); if (_index == -1) _index = 0; } } 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; } public bool MoveNextAndHandle(Action 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; } public T Current { get { return _index == -1 ? default(T) : _collection[_index]; } } public IEnumerable Source { get { return _collection; } } public IEnumerable GetCurrentSeq() { _lock.EnterReadLock(); try { var arr = new T[_collection.Count]; int p = 0; for (int i = _index; i < _collection.Count; i++, p++) { arr[p] = _collection[i]; } for (int i = 0; i < _index; i++, p++) { arr[p] = _collection[i]; } return arr; } finally { _lock.ExitReadLock(); } } public IEnumerable Find(Func selector) { _lock.EnterReadLock(); try { var arr = new List(_collection.Count); for (int i = _index; i < _collection.Count; i++) { if (selector(_collection[i])) { arr.Add(_collection[i]); } } return arr; } finally { _lock.ExitReadLock(); } } public void Clear() { _collection.Clear(); _index = -1; } public void Dispose() { _collection.Clear(); _lock.Dispose(); } } }