Skip to content

Commit

Permalink
Refactor AccessLock
Browse files Browse the repository at this point in the history
  • Loading branch information
cnshenj committed Jul 25, 2022
1 parent ad5b40a commit cbe9a73
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 20 deletions.
4 changes: 2 additions & 2 deletions Utilities/InterlockedDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ public class InterlockedDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
private static readonly IEqualityComparer<TValue> ValueComparer = EqualityComparer<TValue>.Default;

private readonly AccessLockFactory<TKey, Semaphore> lockFactory;
private readonly AccessLockFactory<TKey> lockFactory;

/// <summary>
/// Initializes a new instance of the <see cref="InterlockedDictionary{TKey, TValue}"/> class.
/// </summary>
/// <param name="lockTimeout">A <see cref="TimeSpan"/> that represents the time period to wait to acquire access locks.</param>
public InterlockedDictionary(TimeSpan? lockTimeout = default)
{
this.lockFactory = new AccessLockFactory<TKey, Semaphore>(() => new Semaphore(1, 1), lockTimeout);
this.lockFactory = new AccessLockFactory<TKey>(() => new LocalSemaphore(1, 1), lockTimeout);
}

/// <summary>
Expand Down
9 changes: 7 additions & 2 deletions Utilities/Synchronization/AccessLock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@ namespace SidekickNet.Utilities.Synchronization
{
/// <summary>
/// Provides a mechanism that synchronizes access to resources.
/// The lock will be automatically released when disposed synchronously or asynchronously.
/// </summary>
public class AccessLock : IDisposable, IAsyncDisposable
{
/// <summary>A <see cref="TimeSpan"/> to test lock state and return immediately.</summary>
public static readonly TimeSpan Immediate = TimeSpan.Zero;

/// <summary>A <see cref="TimeSpan"/> to wait indefinitely for lock acquisition.</summary>
public static readonly TimeSpan Indefinite = TimeSpan.FromMilliseconds(-1);
/// <summary>
/// A <see cref="TimeSpan"/> to wait indefinitely for lock acquisition.
/// Technically it should -1 ms.
/// In reality, 10 days can be considered indefinite for locking purpose, and is friendly to calculation.
/// </summary>
public static readonly TimeSpan Indefinite = TimeSpan.FromDays(10);

private bool disposed;

Expand Down
12 changes: 5 additions & 7 deletions Utilities/Synchronization/AccessLockFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,21 @@ namespace SidekickNet.Utilities.Synchronization
/// Provides a mechanism that synchronizes access to keys.
/// </summary>
/// <typeparam name="TKey">The type of keys.</typeparam>
/// <typeparam name="TPrimitive">The type of the synchronization primitive.</typeparam>
public class AccessLockFactory<TKey, TPrimitive>
public class AccessLockFactory<TKey>
where TKey : notnull
where TPrimitive : ISynchronizationPrimitive
{
private readonly ConcurrentDictionary<TKey, TPrimitive> primitives = new();
private readonly ConcurrentDictionary<TKey, ISynchronizationPrimitive> primitives = new();

private readonly Func<TPrimitive> primitiveFactory;
private readonly Func<ISynchronizationPrimitive> primitiveFactory;

private readonly TimeSpan timeout;

/// <summary>
/// Initializes a new instance of the <see cref="AccessLockFactory{TKey, TPrimitive}"/> class.
/// Initializes a new instance of the <see cref="AccessLockFactory{TKey}"/> class.
/// </summary>
/// <param name="primitiveFactory">The function that generate synchronization primitives.</param>
/// <param name="timeout">A <see cref="TimeSpan"/> that represents the default time period to wait to acquire access locks.</param>
public AccessLockFactory(Func<TPrimitive> primitiveFactory, TimeSpan? timeout = default)
public AccessLockFactory(Func<ISynchronizationPrimitive> primitiveFactory, TimeSpan? timeout = default)
{
this.primitiveFactory = primitiveFactory ?? throw new ArgumentNullException(nameof(primitiveFactory));
this.timeout = timeout ?? AccessLock.Indefinite;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
// <copyright file="Semaphore.cs" company="Zhang Shen">
// <copyright file="LocalSemaphore.cs" company="Zhang Shen">
// Copyright (c) Zhang Shen. All rights reserved.
// </copyright>

using System.Threading;

namespace SidekickNet.Utilities.Synchronization;

using System;
using System.Threading;
using System.Threading.Tasks;

/// <summary>
/// Synchronization primitive using <see cref="System.Threading.SemaphoreSlim"/>.
/// Synchronization primitive using <see cref="SemaphoreSlim"/>.
/// It can only be used for synchronization on a local machine.
/// </summary>
public class Semaphore : ISynchronizationPrimitive
public class LocalSemaphore : ISynchronizationPrimitive
{
private readonly SemaphoreSlim semaphoreSlim;

/// <summary>
/// Initializes a new instance of the <see cref="Semaphore"/> class, specifying
/// Initializes a new instance of the <see cref="LocalSemaphore"/> class, specifying
/// the initial and maximum number of requests that can be granted concurrently.
/// </summary>
/// <param name="initialCount">The initial number of requests for the semaphore that can be granted concurrently.</param>
public Semaphore(int initialCount)
public LocalSemaphore(int initialCount)
{
this.semaphoreSlim = new SemaphoreSlim(initialCount);
}

/// <summary>
/// Initializes a new instance of the <see cref="Semaphore"/> class, specifying
/// Initializes a new instance of the <see cref="LocalSemaphore"/> class, specifying
/// the initial and maximum number of requests that can be granted concurrently.
/// </summary>
/// <param name="initialCount">The initial number of requests for the semaphore that can be granted concurrently.</param>
/// <param name="maxCount">The maximum number of requests for the semaphore that can be granted concurrently.</param>
public Semaphore(int initialCount, int maxCount)
public LocalSemaphore(int initialCount, int maxCount)
{
this.semaphoreSlim = new SemaphoreSlim(initialCount, maxCount);
}
Expand Down

0 comments on commit cbe9a73

Please sign in to comment.