您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

166 行
5.4 KiB

using System;
using System.Runtime.InteropServices;
using AOT;
using Unity.UIWidgets.ui;
using UnityEngine;
namespace Unity.UIWidgets.async {
public abstract class Timer : IDisposable {
public static Timer create(TimeSpan duration, ZoneCallback callback) {
if (Zone.current == Zone.root) {
return Zone.current.createTimer(duration, callback);
}
return Zone.current
.createTimer(duration, Zone.current.bindCallbackGuarded(callback));
}
public static Timer create(TimeSpan duration, Action callback) {
return create(duration, () => {
callback.Invoke();
return null;
});
}
public static Timer periodic(TimeSpan duration, ZoneUnaryCallback callback) {
if (Zone.current == Zone.root) {
return Zone.current.createPeriodicTimer(duration, callback);
}
var boundCallback = Zone.current.bindUnaryCallbackGuarded(callback);
return Zone.current.createPeriodicTimer(duration, boundCallback);
}
public static void run(ZoneCallback callback) {
create(TimeSpan.Zero, callback);
}
public abstract void cancel();
public void Dispose() {
cancel();
}
public abstract long tick { get; }
public abstract bool isActive { get; }
internal static Timer _createTimer(TimeSpan duration, ZoneCallback callback) {
return _Timer._createTimer(_ => callback(), (int) duration.TotalMilliseconds, false);
}
internal static Timer _createPeriodicTimer(
TimeSpan duration, ZoneUnaryCallback callback) {
return _Timer._createTimer(callback, (int) duration.TotalMilliseconds, true);
}
}
class _Timer : Timer {
long _tick = 0;
ZoneUnaryCallback _callback;
long _wakeupTime;
readonly int _milliSeconds;
readonly bool _repeating;
_Timer(ZoneUnaryCallback callback, long wakeupTime, int milliSeconds, bool repeating) {
_callback = callback;
_wakeupTime = wakeupTime;
_milliSeconds = milliSeconds;
_repeating = repeating;
}
public static TimeSpan timespanSinceStartup {
get { return TimeSpan.FromMilliseconds(UIMonoState_timerMillisecondClock()); }
}
internal static _Timer _createTimer(ZoneUnaryCallback callback, int milliSeconds, bool repeating) {
if (milliSeconds < 0) {
milliSeconds = 0;
}
long now = UIMonoState_timerMillisecondClock();
long wakeupTime = (milliSeconds == 0) ? now : (now + 1 + milliSeconds);
_Timer timer = new _Timer(callback, wakeupTime, milliSeconds, repeating);
timer._enqueue();
return timer;
}
public override void cancel() {
_callback = null;
}
public override bool isActive => _callback != null;
public override long tick => _tick;
void _advanceWakeupTime() {
if (_milliSeconds > 0) {
_wakeupTime += _milliSeconds;
}
else {
_wakeupTime = UIMonoState_timerMillisecondClock();
}
}
const long MILLI_TO_NANO = 1000000L;
void _enqueue() {
Isolate.ensureExists();
GCHandle callbackHandle = GCHandle.Alloc(this);
UIMonoState_postTaskForTime(_postTaskForTime, (IntPtr) callbackHandle, _wakeupTime * MILLI_TO_NANO);
}
[MonoPInvokeCallback(typeof(UIMonoState_postTaskForTimeCallback))]
static void _postTaskForTime(IntPtr callbackHandle) {
GCHandle timerHandle = (GCHandle) callbackHandle;
var timer = (_Timer) timerHandle.Target;
timerHandle.Free();
try {
if (timer._callback != null) {
var callback = timer._callback;
if (!timer._repeating) {
timer._callback = null;
}
else if (timer._milliSeconds > 0) {
var ms = timer._milliSeconds;
long overdue = UIMonoState_timerMillisecondClock() - timer._wakeupTime;
if (overdue > ms) {
long missedTicks = overdue / ms;
timer._wakeupTime += missedTicks * ms;
timer._tick += missedTicks;
}
}
timer._tick += 1;
callback(timer);
if (timer._repeating && (timer._callback != null)) {
timer._advanceWakeupTime();
timer._enqueue();
}
}
}
catch (Exception ex) {
Debug.LogException(ex);
}
}
[DllImport(NativeBindings.dllName)]
static extern long UIMonoState_timerMillisecondClock();
delegate void UIMonoState_postTaskForTimeCallback(IntPtr callbackHandle);
[DllImport(NativeBindings.dllName)]
static extern void UIMonoState_postTaskForTime(UIMonoState_postTaskForTimeCallback callback,
IntPtr callbackHandle, long targetTimeNanos);
}
}