diff --git a/src/EasyCaching.Core/DistributedLock/MemoryLock.cs b/src/EasyCaching.Core/DistributedLock/MemoryLock.cs index b88147df..c1d01f57 100644 --- a/src/EasyCaching.Core/DistributedLock/MemoryLock.cs +++ b/src/EasyCaching.Core/DistributedLock/MemoryLock.cs @@ -1,4 +1,6 @@ -using System; +using AsyncKeyedLock; +using System; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -6,8 +8,11 @@ namespace EasyCaching.Core.DistributedLock { public class MemoryLock : IDistributedLock { - private static readonly RefCounterPool SemaphoreSlims - = new RefCounterPool(); + private static readonly AsyncKeyedLocker _locker = new AsyncKeyedLocker(o => + { + o.PoolSize = 20; + o.PoolInitialFill = 1; + }); public string Key { get; } @@ -15,26 +20,27 @@ private static readonly RefCounterPool SemaphoreSlims public MemoryLock(string key) => Key = key; - private SemaphoreSlim _semaphore; + private AsyncKeyedLockReleaser _releaser; - private SemaphoreSlim GetOrCreate() + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private AsyncKeyedLockReleaser GetOrCreate() { - if (Volatile.Read(ref _semaphore) != null) throw new DistributedLockException(); + if (Volatile.Read(ref _releaser) != null) throw new DistributedLockException(); lock (_syncObj) { - if (Volatile.Read(ref _semaphore) != null) throw new DistributedLockException(); + if (Volatile.Read(ref _releaser) != null) throw new DistributedLockException(); - var semaphore = SemaphoreSlims.GetOrAdd(Key, _ => new SemaphoreSlim(1, 1)); + var releaser = _locker.GetOrAdd(Key); - Volatile.Write(ref _semaphore, semaphore); + Volatile.Write(ref _releaser, releaser); - return semaphore; + return releaser; } } #region Dispose - + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { Dispose(true); @@ -42,6 +48,7 @@ public void Dispose() GC.SuppressFinalize(this); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual async ValueTask DisposeAsync() { await ReleaseAsync(); @@ -49,26 +56,29 @@ public virtual async ValueTask DisposeAsync() GC.SuppressFinalize(this); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] protected virtual void Dispose(bool disposing) => Release(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] ~MemoryLock() => Dispose(false); #endregion Dispose #region Release + [MethodImpl(MethodImplOptions.AggressiveInlining)] private void InternalRelease() { - var semaphore = Interlocked.Exchange(ref _semaphore, null); + var semaphore = Interlocked.Exchange(ref _releaser, null); if (semaphore == null) return; - semaphore.Release(); - - SemaphoreSlims.TryRemove(Key)?.Dispose(); + semaphore.Dispose(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void Release() => InternalRelease(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual ValueTask ReleaseAsync() { InternalRelease(); @@ -77,23 +87,25 @@ public virtual ValueTask ReleaseAsync() } #endregion + [MethodImpl(MethodImplOptions.AggressiveInlining)] private void LockFail() { - var semaphore = Interlocked.Exchange(ref _semaphore, null); + var semaphore = Interlocked.Exchange(ref _releaser, null); if (semaphore == null) return; - SemaphoreSlims.TryRemove(Key)?.Dispose(); + new AsyncKeyedLockTimeoutReleaser(false, semaphore).Dispose(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual bool Lock(int millisecondsTimeout, CancellationToken cancellationToken) { var semaphore = GetOrCreate(); - var locked = false; + bool locked = false; try { - locked = semaphore.Wait(millisecondsTimeout, cancellationToken); + locked = semaphore.SemaphoreSlim.Wait(millisecondsTimeout, cancellationToken); } finally { @@ -103,14 +115,15 @@ public virtual bool Lock(int millisecondsTimeout, CancellationToken cancellation return locked; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual async ValueTask LockAsync(int millisecondsTimeout, CancellationToken cancellationToken) { var semaphore = GetOrCreate(); - var locked = false; + bool locked = false; try { - locked = await semaphore.WaitAsync(millisecondsTimeout, cancellationToken); + locked = await semaphore.SemaphoreSlim.WaitAsync(millisecondsTimeout, cancellationToken).ConfigureAwait(false); } finally { diff --git a/src/EasyCaching.Core/EasyCaching.Core.csproj b/src/EasyCaching.Core/EasyCaching.Core.csproj index 3368a3e7..33f26dfe 100644 --- a/src/EasyCaching.Core/EasyCaching.Core.csproj +++ b/src/EasyCaching.Core/EasyCaching.Core.csproj @@ -44,4 +44,8 @@ + + + +