Last active
June 9, 2016 23:37
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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