Skip to content

Commit 8fbb9ad

Browse files
authored
Use NeoSmart.AsyncLock in NGitLab.Mock.Clients.ClientContext (#947)
After a few attempts at fixing the SemaphoreSlim-based ClientContext, use something that is said to be an async/await-friendly replacement for the `lock` implementation. This means it supports reentrancy.
1 parent d61ca21 commit 8fbb9ad

File tree

2 files changed

+6
-42
lines changed

2 files changed

+6
-42
lines changed
Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,21 @@
11
using System;
2-
using System.Diagnostics;
3-
using System.Runtime.CompilerServices;
4-
using System.Threading;
2+
using NeoSmart.AsyncLock;
53

64
namespace NGitLab.Mock.Clients;
75

86
internal sealed class ClientContext(GitLabServer server, User user)
97
{
10-
private readonly SemaphoreSlim _operationLock = new(1, 1);
8+
private readonly AsyncLock _operationLock = new();
119

1210
public GitLabServer Server { get; } = server;
1311

1412
public User User { get; } = user;
1513

16-
public bool IsAuthenticated => User != null;
14+
public bool IsAuthenticated => User is not null;
1715

18-
public IDisposable BeginOperationScope(
19-
[CallerMemberName] string callingMethod = null,
20-
[CallerFilePath] string callingFilePath = null,
21-
[CallerLineNumber] int callingLineNumber = -1)
16+
public IDisposable BeginOperationScope()
2217
{
2318
Server.RaiseOnClientOperation();
24-
var releaser = new Releaser(_operationLock);
25-
26-
// Store caller info for debugging purposes
27-
Releaser.MethodWhereLockWasTaken = callingMethod;
28-
Releaser.FilePathWhereLockWasTaken = callingFilePath;
29-
Releaser.LineNumberWhereLockWasTaken = callingLineNumber;
30-
31-
return releaser;
32-
}
33-
34-
private sealed class Releaser : IDisposable
35-
{
36-
private readonly SemaphoreSlim _operationLock;
37-
38-
public Releaser(SemaphoreSlim operationLock)
39-
{
40-
_operationLock = operationLock;
41-
if (_operationLock.CurrentCount == 0 && Debugger.IsAttached)
42-
Debugger.Break();
43-
_operationLock.Wait();
44-
}
45-
46-
// The following is for debugging purposes only. It stores info about where the active lock was taken.
47-
public static string MethodWhereLockWasTaken { get; set; }
48-
49-
public static string FilePathWhereLockWasTaken { get; set; }
50-
51-
public static int LineNumberWhereLockWasTaken { get; set; }
52-
53-
public void Dispose()
54-
{
55-
_operationLock.Release();
56-
}
19+
return _operationLock.Lock();
5720
}
5821
}

NGitLab.Mock/NGitLab.Mock.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<PrivateAssets>all</PrivateAssets>
1313
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1414
</PackageReference>
15+
<PackageReference Include="NeoSmart.AsyncLock" Version="3.2.1" />
1516
<PackageReference Include="YamlDotNet" Version="16.3.0" />
1617
</ItemGroup>
1718

0 commit comments

Comments
 (0)