As of 0.1.9, guarded side effects are allowed by anyawait 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;
}
}
}
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 theawait
on the task that reentered the lock.For example, this program throws an exception when the casual observer might expect it to work:
.NET Fiddle: https://dotnetfiddle.net/FzQ1qR
Thanks to Max Fedotov for patiently explaining this to me.