csharp/0xFireball/PenguinUpload/src/PenguinUpload/Infrastructure/Concurrency/UserLock.cs

UserLock.cs
using System;
using System.Threading;
using System.Threading.Tasks;

namespace PenguinUpload.Infrastructure.Concurrency
{
    public clast UserLock
    {
        private readonly AutoResetEvent _readFree = new AutoResetEvent(true);
        private readonly AutoResetEvent _writeFree = new AutoResetEvent(true);

        #region Basic Functionality

        public void ObtainExclusiveWrite()
        {
            // Wait for exclusive read and write
            _writeFree.WaitOne();
            _readFree.WaitOne();
        }

        public async Task ObtainExclusiveWriteAsync()
        {
            await Task.Run(() => ObtainExclusiveWrite());
        }

        public void ReleaseExclusiveWrite()
        {
            // Release exclusive read and write
            _writeFree.Set();
            _readFree.Set();
        }

        public void ObtainExclusiveRead()
        {
            _readFree.WaitOne();
        }

        public async Task ObtainExclusiveReadAsync()
        {
            await Task.Run(() => ObtainExclusiveRead());
        }

        public void ReleaseExclusiveRead()
        {
            _readFree.Set();
        }

        public void ObtainConcurrentRead()
        {
            // Lock writing, and allow multiple concurrent reads
            _writeFree.WaitOne();
        }

        public async Task ObtainConcurrentReadAsync()
        {
            await Task.Run(() => ObtainConcurrentRead());
        }

        public void ReleaseConcurrentRead()
        {
            // Allow writing again
            _writeFree.Set();
        }

        #endregion Basic Functionality

        #region Nicer API

        public async Task WithExclusiveWriteAsync(Task action)
        {
            await ObtainExclusiveWriteAsync();
            await action;
            ReleaseExclusiveWrite();
        }

        public async Task WithExclusiveWriteAsync(Func action)
        {
            await ObtainExclusiveWriteAsync();
            await action();
            ReleaseExclusiveWrite();
        }

        public async Task WithExclusiveReadAsync(Task action)
        {
            await ObtainExclusiveReadAsync();
            await action;
            ReleaseExclusiveRead();
        }

        public async Task WithExclusiveReadAsync(Func action)
        {
            await ObtainExclusiveReadAsync();
            await action();
            ReleaseExclusiveRead();
        }

        public async Task WithConcurrentReadAsync(Task action)
        {
            await ObtainConcurrentReadAsync();
            await action;
            ReleaseConcurrentRead();
        }

        public async Task WithConcurrentReadAsync(Func action)
        {
            await ObtainConcurrentReadAsync();
            await action();
            ReleaseConcurrentRead();
        }

        #endregion Nicer API
    }
}