You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
5.6 KiB
197 lines
5.6 KiB
1 year ago
|
#if !UNITY_METRO
|
||
|
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Text;
|
||
|
using UniRx.InternalUtil;
|
||
|
|
||
|
namespace UniRx
|
||
|
{
|
||
|
public static partial class Scheduler
|
||
|
{
|
||
|
public static readonly IScheduler ThreadPool = new ThreadPoolScheduler();
|
||
|
|
||
|
class ThreadPoolScheduler : IScheduler, ISchedulerPeriodic
|
||
|
{
|
||
|
public ThreadPoolScheduler()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public DateTimeOffset Now
|
||
|
{
|
||
|
get { return Scheduler.Now; }
|
||
|
}
|
||
|
|
||
|
public IDisposable Schedule(Action action)
|
||
|
{
|
||
|
var d = new BooleanDisposable();
|
||
|
|
||
|
System.Threading.ThreadPool.QueueUserWorkItem(_ =>
|
||
|
{
|
||
|
if (!d.IsDisposed)
|
||
|
{
|
||
|
action();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
public IDisposable Schedule(DateTimeOffset dueTime, Action action)
|
||
|
{
|
||
|
return Schedule(dueTime - Now, action);
|
||
|
}
|
||
|
|
||
|
public IDisposable Schedule(TimeSpan dueTime, Action action)
|
||
|
{
|
||
|
return new Timer(dueTime, action);
|
||
|
}
|
||
|
|
||
|
public IDisposable SchedulePeriodic(TimeSpan period, Action action)
|
||
|
{
|
||
|
return new PeriodicTimer(period, action);
|
||
|
}
|
||
|
|
||
|
public void ScheduleQueueing<T>(ICancelable cancel, T state, Action<T> action)
|
||
|
{
|
||
|
System.Threading.ThreadPool.QueueUserWorkItem(callBackState =>
|
||
|
{
|
||
|
if (!cancel.IsDisposed)
|
||
|
{
|
||
|
action((T)callBackState);
|
||
|
}
|
||
|
}, state);
|
||
|
}
|
||
|
|
||
|
// timer was borrwed from Rx Official
|
||
|
|
||
|
sealed class Timer : IDisposable
|
||
|
{
|
||
|
static readonly HashSet<System.Threading.Timer> s_timers = new HashSet<System.Threading.Timer>();
|
||
|
|
||
|
private readonly SingleAssignmentDisposable _disposable;
|
||
|
|
||
|
private Action _action;
|
||
|
private System.Threading.Timer _timer;
|
||
|
|
||
|
private bool _hasAdded;
|
||
|
private bool _hasRemoved;
|
||
|
|
||
|
public Timer(TimeSpan dueTime, Action action)
|
||
|
{
|
||
|
_disposable = new SingleAssignmentDisposable();
|
||
|
_disposable.Disposable = Disposable.Create(Unroot);
|
||
|
|
||
|
_action = action;
|
||
|
_timer = new System.Threading.Timer(Tick, null, dueTime, TimeSpan.FromMilliseconds(System.Threading.Timeout.Infinite));
|
||
|
|
||
|
lock (s_timers)
|
||
|
{
|
||
|
if (!_hasRemoved)
|
||
|
{
|
||
|
s_timers.Add(_timer);
|
||
|
|
||
|
_hasAdded = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void Tick(object state)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
if (!_disposable.IsDisposed)
|
||
|
{
|
||
|
_action();
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
Unroot();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void Unroot()
|
||
|
{
|
||
|
_action = Stubs.Nop;
|
||
|
|
||
|
var timer = default(System.Threading.Timer);
|
||
|
|
||
|
lock (s_timers)
|
||
|
{
|
||
|
if (!_hasRemoved)
|
||
|
{
|
||
|
timer = _timer;
|
||
|
_timer = null;
|
||
|
|
||
|
if (_hasAdded && timer != null)
|
||
|
s_timers.Remove(timer);
|
||
|
|
||
|
_hasRemoved = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (timer != null)
|
||
|
timer.Dispose();
|
||
|
}
|
||
|
|
||
|
public void Dispose()
|
||
|
{
|
||
|
_disposable.Dispose();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sealed class PeriodicTimer : IDisposable
|
||
|
{
|
||
|
static readonly HashSet<System.Threading.Timer> s_timers = new HashSet<System.Threading.Timer>();
|
||
|
|
||
|
private Action _action;
|
||
|
private System.Threading.Timer _timer;
|
||
|
private readonly AsyncLock _gate;
|
||
|
|
||
|
public PeriodicTimer(TimeSpan period, Action action)
|
||
|
{
|
||
|
this._action = action;
|
||
|
this._timer = new System.Threading.Timer(Tick, null, period, period);
|
||
|
this._gate = new AsyncLock();
|
||
|
|
||
|
lock (s_timers)
|
||
|
{
|
||
|
s_timers.Add(_timer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void Tick(object state)
|
||
|
{
|
||
|
_gate.Wait(() =>
|
||
|
{
|
||
|
_action();
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public void Dispose()
|
||
|
{
|
||
|
var timer = default(System.Threading.Timer);
|
||
|
|
||
|
lock (s_timers)
|
||
|
{
|
||
|
timer = _timer;
|
||
|
_timer = null;
|
||
|
|
||
|
if (timer != null)
|
||
|
s_timers.Remove(timer);
|
||
|
}
|
||
|
|
||
|
if (timer != null)
|
||
|
{
|
||
|
timer.Dispose();
|
||
|
_action = Stubs.Nop;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|