matthew-a-thomas / cs-reentrant-async-lock

A reentrant asynchronous lock
MIT License
12 stars 0 forks source link

Ergonomics could be better #1

Open matthew-a-thomas opened 2 years ago

matthew-a-thomas commented 2 years ago

As of 0.1.9, guarded side effects are allowed by any await within the guarded section (if the lock has been reentered), not just by the await on the task that reentered the lock.

For example, this program throws an exception when the casual observer might expect it to work:

namespace Example;

using System.Threading.Tasks;
using ReentrantAsyncLock;
using Xunit;

class Program
{
    static async Task Main()
    {
    var gate = new ReentrantAsyncLock();
    var state = 0;
    async Task ChangeGuardedStateAsync()
    {
        await using (await gate.LockAsync(default))
            {
                state++;
            }
        }
        await using (await gate.LockAsync(default))
        {
            var task = ChangeGuardedStateAsync();
            var stateBefore = state;
            await Task.Yield(); // Seemingly unrelated
            Assert.Equal(stateBefore, state); // ...but it allows side effects on the guarded state (this line throws)
            await task;
        }
    }
}

.NET Fiddle: https://dotnetfiddle.net/FzQ1qR

Thanks to Max Fedotov for patiently explaining this to me.

IvanGit commented 2 months ago

Hello! This implementation has no side effects: link .NET Fiddle: link 1, link 2

matthew-a-thomas commented 2 months ago

@IvanGit Very nice! I'm pretty busy with life these days but I hope to have time to study your implementation soon.