Skip to content

Instantly share code, notes, and snippets.

@alfeg
Last active May 22, 2020 07:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alfeg/e85d309759504ce4ccdd743beaf620cf to your computer and use it in GitHub Desktop.
Save alfeg/e85d309759504ce4ccdd743beaf620cf to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace WB.Core.GenericSubdomains.Portable
{
/// </remarks>
public class NamedLocker
{
private readonly ConcurrentDictionary<string, LockHolder>
locks = new ConcurrentDictionary<string, LockHolder>();
public NamedLocker()
{
Task.Factory.StartNew(async () =>
{
await Task.Delay(TimeSpan.FromMinutes(1));
cleanupLock.EnterWriteLock();
try
{
var currentTicks = DateTime.UtcNow.Ticks;
var threshold = TimeSpan.FromMinutes(1).Ticks;
foreach (var key in locks.Keys)
{
if (locks.TryGetValue(key, out var holder))
{
if (currentTicks - holder.Ticks > threshold)
{
locks.TryRemove(key, out _);
}
}
}
}
finally
{
cleanupLock.ExitWriteLock();
}
});
}
private readonly ReaderWriterLockSlim cleanupLock = new ReaderWriterLockSlim();
private class LockHolder
{
public long Ticks = 0;
}
public TResult RunWithLock<TResult>(string name, Func<TResult> body)
{
cleanupLock.EnterReadLock();
try
{
var l = this.locks.GetOrAdd(name, s => new LockHolder());
lock (l)
{
l.Ticks = DateTime.UtcNow.Ticks;
return body();
}
}
finally
{
cleanupLock.ExitReadLock();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment