wasSharp

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 37  →  ?path2? @ 38
/Collections/Specialized/ConcurrentLazyList.cs
@@ -0,0 +1,176 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
 
// http://www.fallingcanbedeadly.com/posts/crazy-extention-methods-tolazylist/
 
namespace wasSharp.Collections.Specialized
{
public class ConcurrentLazyList<T> : IList<T>, IDisposable
{
public ConcurrentLazyList(IEnumerable<T> list)
{
syncRoot.EnterReadLock();
_enumerator = list.GetEnumerator();
syncRoot.ExitReadLock();
_isFinished = false;
_cached = new List<T>();
}
 
public T this[int index]
{
get
{
if (index < 0)
throw new ArgumentOutOfRangeException("index");
 
while (_cached.Count <= index && !_isFinished)
{
syncRoot.EnterReadLock();
GetNext();
syncRoot.ExitReadLock();
}
var cached = _cached[index];
return cached;
}
set
{
throw new NotSupportedException();
}
}
 
public int Count
{
get
{
syncRoot.EnterWriteLock();
Finish();
syncRoot.ExitWriteLock();
return _cached.Count;
}
}
 
public IEnumerator<T> GetEnumerator()
{
int current = 0;
 
while (current < _cached.Count || !_isFinished)
{
if (current == _cached.Count)
{
syncRoot.EnterReadLock();
GetNext();
syncRoot.ExitReadLock();
}
if (current != _cached.Count)
yield return _cached[current];
current++;
}
}
 
public void Dispose()
{
syncRoot.EnterWriteLock();
_enumerator.Dispose();
syncRoot.ExitWriteLock();
_isFinished = true;
}
 
public int IndexOf(T item)
{
int result = _cached.IndexOf(item);
while (result == -1 && !_isFinished)
{
syncRoot.EnterReadLock();
GetNext();
syncRoot.ExitReadLock();
if (_cached.Last().Equals(item))
result = _cached.Count - 1;
}
 
return result;
}
 
public void Insert(int index, T item)
{
throw new NotSupportedException();
}
 
public void RemoveAt(int index)
{
throw new NotSupportedException();
}
 
public void Add(T item)
{
throw new NotSupportedException();
}
 
public void Clear()
{
throw new NotSupportedException();
}
 
public bool Contains(T item)
{
syncRoot.EnterReadLock();
var contains = IndexOf(item) != -1;
syncRoot.ExitReadLock();
return contains;
}
 
public void CopyTo(T[] array, int arrayIndex)
{
syncRoot.EnterReadLock();
foreach (var item in this)
array[arrayIndex++] = item;
syncRoot.ExitReadLock();
}
 
public bool IsReadOnly => true;
 
public bool Remove(T item)
{
throw new NotSupportedException();
}
 
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
 
private void GetNext()
{
if (!_isFinished)
{
if (_enumerator.MoveNext())
{
_cached.Add(_enumerator.Current);
}
else
{
_isFinished = true;
_enumerator.Dispose();
}
}
}
 
private void Finish()
{
while (!_isFinished)
GetNext();
}
 
private readonly List<T> _cached;
private readonly IEnumerator<T> _enumerator;
private bool _isFinished;
private ReaderWriterLockSlim syncRoot = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
}
}
/Collections/Utilities/CollectionExtensions.cs
@@ -98,5 +98,10 @@
}
return dict;
}
 
public static IList<T> ToLazyList<T>(this IEnumerable<T> list)
{
return new ConcurrentLazyList<T>(list);
}
}
}