107 lines
3.7 KiB
C#
107 lines
3.7 KiB
C#
using SimpleCore.Library;
|
|||
|
|
using System;
|
||
|
|
using System.Collections.Concurrent;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Reflection;
|
||
|
|
using System.Runtime.CompilerServices;
|
||
|
|
using System.Threading.Tasks;
|
||
|
|
|
||
|
|
|
||
|
|
namespace StandardScene
|
||
|
|
{
|
||
|
|
public class LadderLogic
|
||
|
|
{
|
||
|
|
/// below defines some useful functions...
|
||
|
|
|
||
|
|
private static ConcurrentDictionary<string, (DateTime dt, int state)> pressedDT = new ConcurrentDictionary<string, (DateTime dt, int state)>();
|
||
|
|
// if active for millis, trigger once.
|
||
|
|
public static void TriggerOnce(bool active, int millis, Action trigger,int index=0,
|
||
|
|
[CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||
|
|
{
|
||
|
|
var id = $"{sourceFilePath}:{sourceLineNumber+ index}";
|
||
|
|
if (!active)
|
||
|
|
{
|
||
|
|
if (pressedDT.TryGetValue(id, out var pair1) && pair1.state != 1)
|
||
|
|
pressedDT.TryRemove(id, out _);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (pressedDT.TryGetValue(id, out var pair))
|
||
|
|
{
|
||
|
|
if (pair.state != 0) return;
|
||
|
|
if ((DateTime.Now - pair.dt).TotalMilliseconds > millis)
|
||
|
|
{
|
||
|
|
pressedDT[id] = (pair.dt, 1);
|
||
|
|
Task.Run(() =>
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
trigger();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
Diagnosis.Post($"Ex={ExceptionFormatter.FormatEx(ex)}", $"timed_trigger-{id}");
|
||
|
|
pressedDT.TryRemove(id, out _);
|
||
|
|
}
|
||
|
|
|
||
|
|
pressedDT[id] = (pair.dt, 2);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
pressedDT[id] = (DateTime.Now, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static ConcurrentDictionary<string, bool> isochronous = new ConcurrentDictionary<string, bool>();
|
||
|
|
public static object lockobj = new object();
|
||
|
|
public static void IsochronousFork(Action action,
|
||
|
|
[CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||
|
|
{
|
||
|
|
var id = $"{sourceFilePath}:{sourceLineNumber}";
|
||
|
|
lock (lockobj)
|
||
|
|
{
|
||
|
|
if (isochronous.TryGetValue(id, out var calling) && calling) return;
|
||
|
|
isochronous[id] = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
Task.Run(() =>
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
action();
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
Diagnosis.Post($"Ex={ExceptionFormatter.FormatEx(ex)}", $"isochrounous_fork-{id}");
|
||
|
|
}
|
||
|
|
isochronous[id] = false;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Dictionary<MethodInfo, object> keepTrack = new Dictionary<MethodInfo, object>();
|
||
|
|
/// <summary>
|
||
|
|
/// including first call.
|
||
|
|
/// </summary>
|
||
|
|
/// <typeparam name="T1"></typeparam>
|
||
|
|
/// <param name="getter"></param>
|
||
|
|
/// <param name="action">action(T1 old)</param>
|
||
|
|
public static void TriggerIfChanged<T1>(Func<T1> getter, Action<T1> action)
|
||
|
|
{
|
||
|
|
var id = getter.Method;
|
||
|
|
var val = getter.Invoke();
|
||
|
|
if (keepTrack.TryGetValue(id, out var t) && t is T1 old)
|
||
|
|
{
|
||
|
|
if (val.Equals(old)) return;
|
||
|
|
action(old);
|
||
|
|
}
|
||
|
|
else action(default);
|
||
|
|
keepTrack[id] = val;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public static void FlipFlop<T1>(ref T1 target, int millis, params T1[] vs)
|
||
|
|
{
|
||
|
|
target = vs[(((long)DateTime.Now.TimeOfDay.TotalMilliseconds) / millis) % vs.Length];
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|