Skip to content

Instantly share code, notes, and snippets.

@Ariex
Last active June 9, 2016 23:37
Show Gist options
  • Select an option

  • Save Ariex/288f28a5ef3168fa9b5e to your computer and use it in GitHub Desktop.

Select an option

Save Ariex/288f28a5ef3168fa9b5e to your computer and use it in GitHub Desktop.
An implementation for helping to solve concurrent issue when multiple client write to multiple file
using System;
using System.Collections.Generic;
/// <summary>
/// Create a lock block against a string
/// </summary>
public class StringLocker
{
/// <summary>
/// Store map from string to lockable object
/// </summary>
private static Dictionary<string, Tuple<object, int>> lockers = new Dictionary<string, Tuple<object, int>>();
/// <summary>
/// Locker for "lockers" operation
/// </summary>
private static object lockersLocker = new object();
private StringLocker() { }
/// <summary>
/// Create a lock block with given locker name, and action that will be executed in the lock block.
/// </summary>
/// <param name="lockerName">Name of lockable object</param>
/// <param name="act">Action to execute in lock block</param>
public static void Lock(string lockerName, Action act)
{
object locker = null;
// check if lockable object already exist
lock (lockersLocker)
{
if (lockers.ContainsKey(lockerName))
{
// grab the existing lockable object then update its reference counter
var tp = lockers[lockerName];
lockers[lockerName] = new Tuple<object, int>(tp.Item1, tp.Item2 + 1);
locker = tp.Item1;
}
else
{
// create a new lockable object against the key, set its reference counter to 1
var l = new object();
lockers.Add(lockerName, new Tuple<object, int>(l, 1));
locker = l;
}
}
lock (locker)
{
try
{
act();
}
catch
{
throw;
}
finally
{
// update lockable object reference
lock (lockersLocker)
{
if (lockers.ContainsKey(lockerName))
{
var tp = lockers[lockerName];
lockers[lockerName] = new Tuple<object, int>(tp.Item1, tp.Item2 - 1);
if (tp.Item2 - 1 < 1)
{
// remove the lockable object if there is no reference to it
lockers.Remove(lockerName);
}
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment