Use our AsyncMutex
MODIFY
WalletWasabi.Tests/StoreTests.cs
WalletWasabi.Tests/StoreTests.cs
@@ -188,10 +188,10 @@ namespace WalletWasabi.Tests
var myTask = Task.Run(async () =>
{
- await ioman1.WrapInMutexAsync(async () =>
+ using (await ioman1.Mutex.LockAsync())
{
await Task.Delay(3000);
- });
+ }
});
// Wait for the Task.Run to Acquire the Mutex.
@@ -201,10 +201,10 @@ namespace WalletWasabi.Tests
DateTime timeOfstart = DateTime.Now;
DateTime timeOfAcquired = default;
- await ioman1.WrapInMutexAsync(() =>
+ using (await ioman1.Mutex.LockAsync())
{
timeOfAcquired = DateTime.Now;
- });
+ }
Assert.True(myTask.IsCompletedSuccessfully);
@@ -250,17 +250,17 @@ namespace WalletWasabi.Tests
await Task.Run(async () =>
{
- await ioman1.WrapInMutexAsync(async () =>
+ using (await ioman1.Mutex.LockAsync())
{
// Should not be a problem because they using different Mutexes.
- await ioman2.WrapInMutexAsync(async () =>
+ using (await ioman2.Mutex.LockAsync())
{
await ioman1.WriteAllLinesAsync(lines);
await ioman2.WriteAllLinesAsync(lines);
ioman1.DeleteMe();
ioman2.DeleteMe();
- });
- });
+ }
+ }
});
// TryReplace test.

MODIFY
WalletWasabi/Stores/IndexStore.cs
WalletWasabi/Stores/IndexStore.cs
@@ -51,7 +51,7 @@ namespace WalletWasabi.Stores
using (await IndexLock.LockAsync())
{
- await IndexFileManager.WrapInMutexAsync(async () =>
+ using (await IndexFileManager.Mutex.LockAsync())
{
IoHelpers.EnsureDirectoryExists(WorkFolderPath);
@@ -83,7 +83,7 @@ namespace WalletWasabi.Stores
// Fix the currupted file.
await IndexFileManager.WriteAllLinesAsync(Index.Select(x => x.ToHeightlessLine()));
}
- });
+ }
}
}
@@ -137,10 +137,10 @@ namespace WalletWasabi.Stores
private async Task ToFileNoSemaphoreAsync()
{
- await IndexFileManager.WrapInMutexAsync(async () =>
+ using (await IndexFileManager.Mutex.LockAsync())
{
await IndexFileManager.WriteAllLinesAsync(Index.Select(x => x.ToHeightlessLine()));
- });
+ }
}
public async Task<FilterModel> GetBestKnownFilterAsync()

MODIFY
WalletWasabi/Stores/IoManager.cs
WalletWasabi/Stores/IoManager.cs
@@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Helpers;
using WalletWasabi.Logging;
+using WalletWasabi.Nito.AsyncEx;
namespace WalletWasabi.Stores
{
@@ -22,7 +23,7 @@ namespace WalletWasabi.Stores
public string FileName { get; }
public string FileNameWithoutExtension { get; }
- private string MutexName { get; }
+ public AsyncMutex Mutex { get; }
private const string OldExtension = ".old";
private const string NewExtension = ".new";
@@ -47,79 +48,9 @@ namespace WalletWasabi.Stores
// Within a terminal server session, two mutexes whose names differ only by their prefixes are separate mutexes,
// and both are visible to all processes in the terminal server session.
// That is, the prefix names "Global\" and "Local\" describe the scope of the mutex name relative to terminal server sessions, not relative to processes.
- MutexName = $"Global\\4AA0E5A2-A94F-4B92-B962-F2BBC7A68323-{FileNameWithoutExtension}";
+ Mutex = new AsyncMutex(FileNameWithoutExtension);
}
- #region Mutexes
-
- public async Task WrapInMutexAsync(Func<Task> todo)
- {
- using (var semaphore = new Semaphore(1, 1, MutexName))
- {
- await AcquireMutexAsync(semaphore);
-
- try
- {
- await todo();
- }
- finally
- {
- semaphore.Release();
- }
- }
- }
-
- private async Task AcquireMutexAsync(Semaphore semaphore)
- {
- bool semaphoreAcquired = false;
- try
- {
- // acquire the mutex (or timeout after 60 seconds)
- // will return false if it timed out
- var start = DateTime.Now;
- while (DateTime.Now - start < TimeSpan.FromSeconds(90))
- {
- semaphoreAcquired = semaphore.WaitOne(1);
-
- if (semaphoreAcquired)
- {
- break;
- }
- await Task.Delay(1000);
- }
- }
- catch (AbandonedMutexException)
- {
- // abandoned mutexes are still acquired, we just need
- // to handle the exception and treat it as acquisition
- semaphoreAcquired = true;
- }
-
- if (semaphoreAcquired == false)
- {
- throw new IOException("Couldn't acquire Semaphore on the file.");
- }
- }
-
- public async Task WrapInMutexAsync(Action todo)
- {
- using (var semaphore = new Semaphore(1, 1, MutexName))
- {
- await AcquireMutexAsync(semaphore);
-
- try
- {
- todo();
- }
- finally
- {
- semaphore.Release();
- }
- }
- }
-
- #endregion Mutexes
-
#region IoOperations
public void DeleteMe()

Use our AsyncMutex