Skip to content

Commit

Permalink
Cleaning pooling and aggressively inlining locking methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkCiliaVincenti committed Jan 1, 2024
1 parent 010d3aa commit 79b1216
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 13 deletions.
10 changes: 5 additions & 5 deletions AsyncKeyedLock/AsyncKeyedLock.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
<PackageProjectUrl>https://github.com/MarkCiliaVincenti/AsyncKeyedLock</PackageProjectUrl>
<Copyright>MIT</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Version>6.2.5</Version>
<Version>6.2.6</Version>
<PackageIcon>logo.png</PackageIcon>
<PackageReleaseNotes>Minor optimization.</PackageReleaseNotes>
<PackageReleaseNotes>Cleaning pooling and aggressively inlining locking methods.</PackageReleaseNotes>
<Description>An asynchronous .NET Standard 2.0 library that allows you to lock based on a key (keyed semaphores), limiting concurrent threads sharing the same key to a specified number, with optional pooling for reducing memory allocations.</Description>
<Copyright2023 Mark Cilia Vincenti</Copyright>
<Copyright2024 Mark Cilia Vincenti</Copyright>
<PackageTags>async,lock,key,keyed,semaphore,striped,dictionary,concurrentdictionary,pooling,duplicate,synchronization</PackageTags>
<RepositoryType>git</RepositoryType>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<AssemblyVersion>6.2.5.0</AssemblyVersion>
<FileVersion>6.2.5.0</FileVersion>
<AssemblyVersion>6.2.6.0</AssemblyVersion>
<FileVersion>6.2.6.0</FileVersion>
<PackageReadmeFile>README.md</PackageReadmeFile>
<IsPackable>true</IsPackable>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
Expand Down
8 changes: 4 additions & 4 deletions AsyncKeyedLock/AsyncKeyedLockDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public AsyncKeyedLockDictionary(AsyncKeyedLockOptions options) : base()
if (options.PoolSize > 0)
{
PoolingEnabled = true;
_pool = new AsyncKeyedLockPool<TKey>((key) => new AsyncKeyedLockReleaser<TKey>(key, new SemaphoreSlim(MaxCount, MaxCount), this), options.PoolSize, options.PoolInitialFill);
_pool = new AsyncKeyedLockPool<TKey>(this, options.PoolSize, options.PoolInitialFill);
}
}

Expand All @@ -40,7 +40,7 @@ public AsyncKeyedLockDictionary(AsyncKeyedLockOptions options, IEqualityComparer
if (options.PoolSize > 0)
{
PoolingEnabled = true;
_pool = new AsyncKeyedLockPool<TKey>((key) => new AsyncKeyedLockReleaser<TKey>(key, new SemaphoreSlim(MaxCount, MaxCount), this), options.PoolSize, options.PoolInitialFill);
_pool = new AsyncKeyedLockPool<TKey>(this, options.PoolSize, options.PoolInitialFill);
}
}

Expand All @@ -56,7 +56,7 @@ public AsyncKeyedLockDictionary(AsyncKeyedLockOptions options, int concurrencyLe
if (options.PoolSize > 0)
{
PoolingEnabled = true;
_pool = new AsyncKeyedLockPool<TKey>((key) => new AsyncKeyedLockReleaser<TKey>(key, new SemaphoreSlim(MaxCount, MaxCount), this), options.PoolSize, options.PoolInitialFill);
_pool = new AsyncKeyedLockPool<TKey>(this, options.PoolSize, options.PoolInitialFill);
}
}

Expand All @@ -72,7 +72,7 @@ public AsyncKeyedLockDictionary(AsyncKeyedLockOptions options, int concurrencyLe
if (options.PoolSize > 0)
{
PoolingEnabled = true;
_pool = new AsyncKeyedLockPool<TKey>((key) => new AsyncKeyedLockReleaser<TKey>(key, new SemaphoreSlim(MaxCount, MaxCount), this), options.PoolSize, options.PoolInitialFill);
_pool = new AsyncKeyedLockPool<TKey>(this, options.PoolSize, options.PoolInitialFill);
}
}

Expand Down
8 changes: 6 additions & 2 deletions AsyncKeyedLock/AsyncKeyedLockOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ public sealed class AsyncKeyedLockOptions
public int MaxCount { get; set; } = 1;

/// <summary>
/// The size of the pool to use in order for generated objects to be reused. Defaults to 0 (disabled).
/// The size of the pool to use in order for generated objects to be reused. This is NOT a concurrency limit,
/// but if the pool is empty then a new object will be created rather than waiting for an object to return to
/// the pool. Defaults to 0 (disabled) but strongly recommended to use.
/// </summary>
public int PoolSize { get; set; } = 0;

Expand All @@ -24,7 +26,9 @@ public sealed class AsyncKeyedLockOptions
/// Initializes options for the <see cref="AsyncKeyedLocker"/> constructors
/// </summary>
/// <param name="maxCount">The maximum number of requests for the semaphore that can be granted concurrently. Defaults to 1.</param>
/// <param name="poolSize">The size of the pool to use in order for generated objects to be reused. Defaults to 0 (disabled).</param>
/// <param name="poolSize">The size of the pool to use in order for generated objects to be reused. This is NOT a concurrency limit,
/// but if the pool is empty then a new object will be created rather than waiting for an object to return to
/// the pool. Defaults to 0 (disabled) but strongly recommended to use.</param>
/// <param name="poolInitialFill">The number of items to fill the pool with during initialization. Defaults to -1 (fill up to pool size).</param>
public AsyncKeyedLockOptions(int maxCount = 1, int poolSize = 0, int poolInitialFill = -1)
{
Expand Down
9 changes: 7 additions & 2 deletions AsyncKeyedLock/AsyncKeyedLockPool.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Threading;

namespace AsyncKeyedLock
{
Expand All @@ -9,10 +10,14 @@ internal sealed class AsyncKeyedLockPool<TKey> : IDisposable
private readonly BlockingCollection<AsyncKeyedLockReleaser<TKey>> _objects;
private readonly Func<TKey, AsyncKeyedLockReleaser<TKey>> _objectGenerator;

public AsyncKeyedLockPool(Func<TKey, AsyncKeyedLockReleaser<TKey>> objectGenerator, int capacity, int initialFill = -1)
public AsyncKeyedLockPool(AsyncKeyedLockDictionary<TKey> asyncKeyedLockDictionary, int capacity, int initialFill = -1)
{
_objects = new BlockingCollection<AsyncKeyedLockReleaser<TKey>>(new ConcurrentBag<AsyncKeyedLockReleaser<TKey>>(), capacity);
_objectGenerator = objectGenerator;
_objectGenerator = (key) => new AsyncKeyedLockReleaser<TKey>(
key,
new SemaphoreSlim(asyncKeyedLockDictionary.MaxCount, asyncKeyedLockDictionary.MaxCount),
asyncKeyedLockDictionary);

if (initialFill < 0)
{
for (int i = 0; i < capacity; ++i)
Expand Down
Loading

0 comments on commit 79b1216

Please sign in to comment.