From 66fde6db42710aa1ced42a79742a627adf9a7f2e Mon Sep 17 00:00:00 2001 From: Albie Date: Tue, 8 Dec 2020 19:45:44 +0000 Subject: [PATCH] simplify locking and don't lock inside of a try-catch block --- DragonFruit.Common.Data/ApiClient.cs | 34 +++++++++++----------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/DragonFruit.Common.Data/ApiClient.cs b/DragonFruit.Common.Data/ApiClient.cs index 0b0353a..734a5f0 100644 --- a/DragonFruit.Common.Data/ApiClient.cs +++ b/DragonFruit.Common.Data/ApiClient.cs @@ -109,11 +109,10 @@ public string Authorization #region Clients, Hashes and Locks - private bool _clientAdjustmentInProgress; + private int _clientAdjustmentSignal; private string _lastHandlerHash = string.Empty; private string _lastHash = string.Empty; - private readonly object _clientAdjustmentLock = new object(); private long _currentRequests; private HttpMessageHandler _handler; @@ -129,13 +128,7 @@ public string Authorization /// protected HttpClient GetClient() { - // if we're waiting, then don't cause a crash from the monitor below or from getting the wrong client - just wait. - while (_clientAdjustmentInProgress) - { - Thread.Sleep(AdjustmentTimeout / 2); - } - - //if there's no edits return the current client (perform the check once instead of a potential twice) + // if there's no edits return the current client (perform the check once instead of a potential twice) var changeHeaders = Headers.ChangesAvailable; if (_lastHash == ClientHash && !changeHeaders) @@ -143,20 +136,18 @@ protected HttpClient GetClient() return Client; } - try + // if we're waiting, then don't cause a crash from the monitor below or from getting the wrong client - just wait. + while (Interlocked.CompareExchange(ref _clientAdjustmentSignal, 1, 0) == 1) { - _clientAdjustmentInProgress = true; - - //lock for modification - if (!Monitor.TryEnter(_clientAdjustmentLock, AdjustmentTimeout)) - { - throw new TimeoutException($"The {nameof(ApiClient)} is being overloaded with reconstruction requests. Consider creating a separate {nameof(ApiClient)} and delegating clients to specific types of requests"); - } + Timeout(); + } - //wait for all ongoing requests to end + try + { + // wait for all ongoing requests to end while (_currentRequests > 0) { - Thread.Sleep(AdjustmentTimeout / 2); + Timeout(); } var handlerHash = Handler.ItemHashCode(); @@ -189,8 +180,7 @@ protected HttpClient GetClient() } finally { - _clientAdjustmentInProgress = false; - Monitor.Exit(_clientAdjustmentLock); + Interlocked.Decrement(ref _clientAdjustmentSignal); } } @@ -375,5 +365,7 @@ protected virtual void ValidateRequest(ApiRequest request) } } } + + private void Timeout() => Thread.Sleep(AdjustmentTimeout / 2); } }