TaskHelpers.cs
namespace GenXdev.Helpers
{ public static class TaskHelpers { internal static Dictionary<string, Dictionary<string, TaskInfo>> tasks = new Dictionary<string, Dictionary<string, TaskInfo>>(); public static bool TryLockIfExpired(string taskGroup, string taskName, out TaskInfo taskInfo) { taskInfo = FindOrCreateTask(taskGroup, taskName); return taskInfo.TryLockIfExpired(); } public static bool TryLock(string taskGroup, string taskName, out TaskInfo taskInfo) { taskInfo = FindOrCreateTask(taskGroup, taskName); return taskInfo.TryLock(); } public static bool NotLockedOrExpired(string taskGroup, string taskName, TimeSpan? expirationTime = null, bool force = false) { var taskInfo = FindOrCreateTask(taskGroup, taskName); bool result = false; try { if (force) { result = taskInfo.TryLock(); } else { result = taskInfo.TryLockIfExpired(); } } finally { if (result) taskInfo.UnLock(expirationTime); } return result; } /// <summary> /// if successfull and expirationTime is set, it will fail for that duration afterwards /// </summary> public static bool HadRecentActivity( string taskGroup, string taskName, TimeSpan? expirationTime) { var taskInfo = FindOrCreateTask(taskGroup, taskName); if (taskInfo.TryLockIfExpired()) try { return true; } finally { taskInfo.UnLock(expirationTime); } return false; } /// <summary> /// if successfull and expirationTime is set, it will fail for that duration afterwards /// </summary> public static void ClearOutCurrentlyActiveExpiration(string taskGroup, string taskName) { var taskInfo = FindOrCreateTask(taskGroup, taskName); taskInfo.UnLock(); } public static IEnumerable<TaskInfo> GetExpiredTasks(string GroupName) { return new ExpiredTaskEnumerable(GroupName); } static long lastTimestamp = System.DateTime.UtcNow.Ticks; private static TaskInfo FindOrCreateTask(string taskGroup, string taskName) { TaskInfo taskInfo; lock (tasks) { long now = System.DateTime.UtcNow.Ticks; if (now < lastTimestamp) { tasks.Clear(); } lastTimestamp = now; // find or create group if (!tasks.TryGetValue(taskGroup, out Dictionary<string, TaskInfo> foundGroup)) { foundGroup = new Dictionary<string, TaskInfo>(); tasks.Add(taskGroup, foundGroup); } // find task if (!foundGroup.TryGetValue(taskName, out taskInfo)) { taskInfo = new TaskInfo() { GroupName = taskGroup, TaskName = taskName }; foundGroup.Add(taskName, taskInfo); } } return taskInfo; } } public class TaskInfo { public TaskInfo() { Properties = new Dictionary<string, object>(); Expires = System.DateTime.MinValue; } internal long state; public Dictionary<string, object> Properties { get; private set; } public string GroupName { get; internal set; } public string TaskName { get; internal set; } public System.DateTime Expires { get { lock (this) { return _Expires; } } internal set { lock (this) { _Expires = value; } } } System.DateTime _Expires; public bool TryLock() { return Interlocked.CompareExchange(ref state, 1, 0) == 0; } public bool TryLockIfExpired() { lock (this) { if (IsExpired()) { return Interlocked.CompareExchange(ref state, 1, 0) == 0; } return false; } } public bool IsExpired() { lock (this) return System.DateTime.UtcNow >= Expires; } public void UnLock(TimeSpan? expires = null) { if (Interlocked.CompareExchange(ref state, 2, 1) == 1) { if (expires.HasValue) { lock (this) { Expires = System.DateTime.UtcNow + expires.Value; Interlocked.Exchange(ref state, 0); } } else { lock (TaskHelpers.tasks) { // find group if (TaskHelpers.tasks.TryGetValue(GroupName, out Dictionary<string, TaskInfo> foundGroup)) { foundGroup.Remove(TaskName); if (foundGroup.Count == 0) { TaskHelpers.tasks.Remove(GroupName); } } } } } } } } |