using System;
using System.Collections.Generic;
using AlicizaX.Runtime;
using UnityEngine;
namespace AlicizaX.Timer.Runtime
{
public struct TimerInfo
{
public float Interval;
public int Repeat;
public float Elapsed;
}
///
/// 定时器管理器
///
[UnityEngine.Scripting.Preserve]
internal sealed class TimerManager : ITimerManager
{
class TimerItem
{
public float Interval;
public int Repeat;
public Action Callback;
public object Param;
public float Elapsed;
public bool Deleted;
public void Set(float interval, int repeat, Action callback, object param)
{
this.Interval = interval;
this.Repeat = repeat;
this.Callback = callback;
this.Param = param;
}
}
private readonly Dictionary, TimerItem> _items = new Dictionary, TimerItem>();
private readonly Dictionary, TimerItem> _toAdd = new Dictionary, TimerItem>();
private readonly List _toRemove = new List();
private readonly List _pool = new List(100);
private static readonly object Locker = new object();
///
/// 是否触发回调异常
///
public static bool CatchCallbackExceptions = false;
void IModuleUpdate.Update(float elapseSeconds, float realElapseSeconds)
{
lock (Locker)
{
Dictionary, TimerItem>.Enumerator enumerator;
if (_items.Count > 0)
{
enumerator = _items.GetEnumerator();
while (enumerator.MoveNext())
{
TimerItem timerItem = enumerator.Current.Value;
if (timerItem.Deleted)
{
_toRemove.Add(timerItem);
continue;
}
timerItem.Elapsed += realElapseSeconds;
if (timerItem.Elapsed < timerItem.Interval)
{
continue;
}
timerItem.Elapsed -= timerItem.Interval;
if (timerItem.Elapsed < 0 || timerItem.Elapsed > 0.03f)
timerItem.Elapsed = 0;
if (timerItem.Repeat > 0)
{
timerItem.Repeat--;
if (timerItem.Repeat == 0)
{
timerItem.Deleted = true;
_toRemove.Add(timerItem);
}
}
// var repeat = i.Repeat;
if (timerItem.Callback != null)
{
if (CatchCallbackExceptions)
{
try
{
timerItem.Callback(timerItem.Param);
}
catch (Exception e)
{
timerItem.Deleted = true;
Debug.LogWarning("Timer: timer(internal=" + timerItem.Interval + ", repeat=" + timerItem.Repeat + ") callback error > " + e.Message);
}
}
else
{
timerItem.Callback(timerItem.Param);
}
}
}
enumerator.Dispose();
}
int len = _toRemove.Count;
if (len > 0)
{
for (int k = 0; k < len; k++)
{
TimerItem i = _toRemove[k];
if (i.Deleted && i.Callback != null)
{
_items.Remove(i.Callback);
ReturnToPool(i);
}
}
_toRemove.Clear();
}
if (_toAdd.Count > 0)
{
enumerator = _toAdd.GetEnumerator();
while (enumerator.MoveNext())
{
_items.Add(enumerator.Current.Key, enumerator.Current.Value);
}
enumerator.Dispose();
_toAdd.Clear();
}
}
}
void IModule.Dispose()
{
lock (Locker)
{
this._toRemove.Clear();
this._toAdd.Clear();
this._items.Clear();
}
}
///
/// 添加一个定时调用的任务
///
/// 间隔时间(以秒为单位)
/// 重复次数(0 表示无限重复)
/// 要执行的回调函数
/// 回调函数的参数(可选)
public void Add(float interval, int repeat, Action callback, object callbackParam = null)
{
lock (Locker)
{
if (callback == null)
{
Debug.LogWarning("timer callback is null, " + interval + "," + repeat);
return;
}
if (_items.TryGetValue(callback, out var t))
{
t.Set(interval, repeat, callback, callbackParam);
t.Elapsed = 0;
t.Deleted = false;
return;
}
if (_toAdd.TryGetValue(callback, out t))
{
t.Set(interval, repeat, callback, callbackParam);
return;
}
t = GetFromPool();
t.Interval = interval;
t.Repeat = repeat;
t.Callback = callback;
t.Param = callbackParam;
_toAdd[callback] = t;
}
}
///
/// 添加一个只执行一次的任务
///
/// 间隔时间(以秒为单位)
/// 要执行的回调函数
/// 回调函数的参数(可选)
public void AddOnce(float interval, Action callback, object callbackParam = null)
{
Add(interval, 1, callback, callbackParam);
}
///
/// 添加一个每帧更新执行的任务
///
/// 要执行的回调函数
public void AddUpdate(Action callback)
{
Add(0.001f, 0, callback);
}
///
/// 添加一个每帧更新执行的任务
///
/// 要执行的回调函数
/// 回调函数的参数
public void AddUpdate(Action callback, object callbackParam)
{
Add(0.001f, 0, callback, callbackParam);
}
///
/// 检查指定的任务是否存在
///
/// 要检查的回调函数
/// 存在返回 true,不存在返回 false
public bool Exists(Action callback)
{
lock (Locker)
{
if (_toAdd.ContainsKey(callback))
{
return true;
}
if (_items.TryGetValue(callback, out var at))
{
return !at.Deleted;
}
return false;
}
}
///
/// 移除指定的任务
///
/// 要移除的回调函数
public void Remove(Action callback)
{
lock (Locker)
{
if (_toAdd.TryGetValue(callback, out var t))
{
_toAdd.Remove(callback);
ReturnToPool(t);
}
if (_items.TryGetValue(callback, out t))
{
t.Deleted = true;
}
}
}
private TimerItem GetFromPool()
{
TimerItem t;
int cnt = _pool.Count;
if (cnt > 0)
{
t = _pool[cnt - 1];
_pool.RemoveAt(cnt - 1);
t.Deleted = false;
t.Elapsed = 0;
}
else
{
t = new TimerItem();
}
return t;
}
private void ReturnToPool(TimerItem t)
{
t.Callback = null;
_pool.Add(t);
}
public int Priority
{
get => 0;
}
///
/// 获取所有正在运行的定时器的信息
///
/// 一个列表,其中包含每个定时器的信息
public List GetTimerInfos()
{
List timerInfos = new List();
lock (Locker)
{
foreach (var timerItem in _items.Values)
{
if (!timerItem.Deleted) // 确保定时器未被删除
{
timerInfos.Add(new TimerInfo
{
Interval = timerItem.Interval,
Repeat = timerItem.Repeat,
Elapsed = timerItem.Elapsed,
});
}
}
}
return timerInfos;
}
}
}