ReaderWriterLockSlimActionFuncWrapper.cs

ReaderWriterLockSlim Wrapper See: MonitorActionFuncWrapper.cs

using System;
using System.Threading;
public class ReaderWriterLockSlimActionFuncWrapper : ConcurrencyCheck, IDisposable
{
    private bool                 _deadLock;
    private bool                 _disposed;
    private ReaderWriterLockSlim _rwl;
    public ReaderWriterLockSlimActionFuncWrapper(LockRecursionPolicy recursionPolicy = LockRecursionPolicy.NoRecursion)
    {
        _rwl = new ReaderWriterLockSlim(recursionPolicy);
        GC.SuppressFinalize(this);
    }
    public void Dispose()
    {
        Dispose(true);
    }
    public void Read(Action action)
    {
        if (action == null)
            throw new Exception("Action argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterReadLock();
                action();
            }
            finally
            {
                _rwl.ExitReadLock();
            }
        else
            action();
    }
    public TResult Read<TResult>(Func<TResult> func)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterReadLock();
                return func();
            }
            finally
            {
                _rwl.ExitReadLock();
            }
        return func();
    }
    public (TResult1, TResult2) Read<TResult1, TResult2>(Func<(TResult1, TResult2)> func)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterReadLock();
                return func();
            }
            finally
            {
                _rwl.ExitReadLock();
            }
        return func();
    }
    public (TResult1, TResult2) Read<TArg, TResult1, TResult2>(Func<TArg, (TResult1, TResult2)> func, TArg arg)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterReadLock();
                return func(arg);
            }
            finally
            {
                _rwl.ExitReadLock();
            }
        return func(arg);
    }
    public TResult Read<TArg, TResult>(Func<TArg, TResult> func, TArg arg)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterReadLock();
                return func(arg);
            }
            finally
            {
                _rwl.ExitReadLock();
            }
        return func(arg);
    }
    public void Read<TArg>(Action<TArg> action, TArg arg)
    {
        if (action == null)
            throw new Exception("Action argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterReadLock();
                action(arg);
            }
            finally
            {
                _rwl.ExitReadLock();
            }
        else
            action(arg);
    }
    public void Write(Action action)
    {
        if (action == null)
            throw new Exception("Action argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterWriteLock();
                action();
            }
            finally
            {
                _rwl.ExitWriteLock();
            }
        else
            action();
    }
    public TResult Write<TResult>(Func<TResult> func)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterWriteLock();
                return func();
            }
            finally
            {
                _rwl.ExitWriteLock();
            }
        return func();
    }
    public (TResult1, TResult2) Write<TResult1, TResult2>(Func<(TResult1, TResult2)> func)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterWriteLock();
                return func();
            }
            finally
            {
                _rwl.ExitWriteLock();
            }
        return func();
    }
    public (TResult1, TResult2) Write<TArg, TResult1, TResult2>(Func<TArg, (TResult1, TResult2)> func, TArg arg)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterWriteLock();
                return func(arg);
            }
            finally
            {
                _rwl.ExitWriteLock();
            }
        return func(arg);
    }
    public TResult Write<TArg, TResult>(Func<TArg, TResult> func, TArg arg)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterWriteLock();
                return func(arg);
            }
            finally
            {
                _rwl.ExitWriteLock();
            }
        return func(arg);
    }
    public void Write<TArg>(Action<TArg> action, TArg arg)
    {
        if (action == null)
            throw new Exception("Action argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterWriteLock();
                action(arg);
            }
            finally
            {
                _rwl.ExitWriteLock();
            }
        else
            action(arg);
    }
    public void ReadUpdate(Action action)
    {
        if (action == null)
            throw new Exception("Action argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterUpgradeableReadLock();
                try
                {
                    _rwl.EnterWriteLock();
                    action();
                }
                finally
                {
                    _rwl.ExitWriteLock();
                }
            }
            finally
            {
                _rwl.ExitUpgradeableReadLock();
            }
        else
            action();
    }
    public TResult ReadUpdate<TResult>(Func<TResult> func)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterUpgradeableReadLock();
                try
                {
                    _rwl.EnterWriteLock();
                    return func();
                }
                finally
                {
                    _rwl.ExitWriteLock();
                }
            }
            finally
            {
                _rwl.ExitUpgradeableReadLock();
            }
        return func();
    }
    public (TResult1, TResult2) ReadUpdate<TResult1, TResult2>(Func<(TResult1, TResult2)> func)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterUpgradeableReadLock();
                try
                {
                    _rwl.EnterWriteLock();
                    return func();
                }
                finally
                {
                    _rwl.ExitWriteLock();
                }
            }
            finally
            {
                _rwl.ExitUpgradeableReadLock();
            }
        return func();
    }
    public (TResult1, TResult2) ReadUpdate<TArg, TResult1, TResult2>(Func<TArg, (TResult1, TResult2)> func, TArg arg)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterUpgradeableReadLock();
                try
                {
                    _rwl.EnterWriteLock();
                    return func(arg);
                }
                finally
                {
                    _rwl.ExitWriteLock();
                }
            }
            finally
            {
                _rwl.ExitUpgradeableReadLock();
            }
        return func(arg);
    }
    public TResult ReadUpdate<TArg, TResult>(Func<TArg, TResult> func, TArg arg)
    {
        if (func == null)
            throw new Exception("Func argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterUpgradeableReadLock();
                try
                {
                    _rwl.EnterWriteLock();
                    return func(arg);
                }
                finally
                {
                    _rwl.ExitWriteLock();
                }
            }
            finally
            {
                _rwl.ExitUpgradeableReadLock();
            }
        return func(arg);
    }
    public void ReadUpdate<TArg>(Action<TArg> action, TArg arg)
    {
        if (action == null)
            throw new Exception("Action argument cannot be null");
        if (CheckState())
            try
            {
                _rwl.EnterUpgradeableReadLock();
                try
                {
                    _rwl.EnterWriteLock();
                    action(arg);
                }
                finally
                {
                    _rwl.ExitWriteLock();
                }
            }
            finally
            {
                _rwl.ExitUpgradeableReadLock();
            }
        else
            action(arg);
    }
    ~ReaderWriterLockSlimActionFuncWrapper()
    {
        if (_rwl != null)
            _rwl.Dispose();
    }
    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
            throw new Exception("Already Disposed");
        try
        {
            _rwl.Dispose();
            _disposed = true;
            _rwl      = null;
        }
        catch (SynchronizationLockException) when (disposing)
        {
            _deadLock = true;
        }
        finally
        {
            if (!_disposed && disposing)
                GC.ReRegisterForFinalize(this);
        }
    }
}