개발/C#

[C#] ConcurrentList

min1119 2023. 12. 6. 02:40
  • thread-safe하게 read, write가 가능하고 인덱서 사용이 가능한 List가 필요하여 생성한 자료구조 클래스
  • ReaderWriterLockSlim을 사용하여 필요 자원 잠금
  • try문의 finally를 이용하여 작업 진행 후 Lock 해제
  • 코드 재사용성을 위해 일괄적으로 내부에서 lock 사용 및 대리자를 호출하는 함수 사용
public class ConcurrentList<T>
{
    ~ConcurrentList()
    {
        _lockSlim?.Dispose();
    }

    public T? this[int index]
    {
        get
        {
            if (index < 0 || _values.Count <= index)
            {
                return default;
            }

            return (T?)ReadExecute(() => _values[index]);
        }

        set
        {
            if (index < 0 || _values.Count <= index)
            {
                return;
            }

            WriteExecute(() => _values[index] = value);
        }
    }

    public int Count => (int)ReadExecute(() => _values.Count)!;

    public bool Contains(T obj) => (bool)ReadExecute(() => _values.Contains(obj))!;

    public void Add(T obj, int timeout = 0) => WriteExecute(() => _values.Add(obj), timeout);

    public void Remove(T obj, int timeout = 0) => WriteExecute(() => _values.Remove(obj), timeout);

    public void Clear(int timeout = 0) => WriteExecute(() => _values.Clear(), timeout);

    private void WriteExecute(Delegate @delegate, int timeout = 0, params object?[]? args)
    {
        if (timeout <= 0)
        {
            _lockSlim.EnterWriteLock();
        }
        else
        {
            _lockSlim.TryEnterWriteLock(timeout);
        }

        try
        {
            @delegate.DynamicInvoke(args);
        }
        finally
        {
            _lockSlim.ExitWriteLock();
        }
    }

    private object? ReadExecute(Delegate @delegate, int timeout = 0, params object?[]? args)
    {
        if (timeout <= 0)
        {
            _lockSlim.EnterReadLock();
        }
        else
        {
            _lockSlim.TryEnterReadLock(timeout);
        }

        try
        {
            return @delegate.DynamicInvoke(args);
        }
        finally
        {
            _lockSlim.ExitReadLock();
        }
    }

    private ReaderWriterLockSlim _lockSlim = new();

    private List<T?> _values = new();
}

Git : https://github.com/ChoiMingyeong/Devoram.git

 

GitHub - ChoiMingyeong/Devoram: Devoram Engine Repository

Devoram Engine Repository. Contribute to ChoiMingyeong/Devoram development by creating an account on GitHub.

github.com

Permalink : https://github.com/ChoiMingyeong/Devoram/blob/34f03a5917bd164fad8dd4b7957957777e5706bf/Devoram/DevoramUtility/ConcurrentList.cs