82 lines
3.0 KiB
C#
82 lines
3.0 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Threading;
|
|
|
|
namespace MultiWheelC.TrajectoryPlanning.Utils;
|
|
|
|
/// <summary>一次规划操作的中立停止原因;Map 与 CoarsePath 分别映射为自己的结果状态。</summary>
|
|
internal enum PlanningOperationStopReason
|
|
{
|
|
/// <summary>预算仍可继续执行。</summary>
|
|
None,
|
|
/// <summary>调用方取消了本次操作。</summary>
|
|
Cancelled,
|
|
/// <summary>从预算创建起已经达到总超时。</summary>
|
|
TimedOut,
|
|
}
|
|
|
|
/// <summary>
|
|
/// 以单调时钟统一控制一次规划操作的取消和总超时。
|
|
/// 本类不依赖 Map 或 CoarsePath,供两层在长循环检查同一个停止条件。
|
|
/// </summary>
|
|
internal sealed class PlanningOperationBudget
|
|
{
|
|
private const int CheckIntervalWorkItems = 256;
|
|
|
|
private readonly CancellationToken _cancellationToken;
|
|
private readonly Stopwatch _stopwatch;
|
|
private readonly TimeSpan _timeout;
|
|
private readonly bool _hasTimeout;
|
|
|
|
/// <summary>
|
|
/// 创建具有总超时的操作预算。
|
|
/// 参数:cancellationToken 为调用方停止请求;timeout 必须非负,且从构造时开始计时。
|
|
/// </summary>
|
|
internal PlanningOperationBudget(CancellationToken cancellationToken, TimeSpan timeout)
|
|
{
|
|
if (timeout < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(timeout));
|
|
_cancellationToken = cancellationToken;
|
|
_timeout = timeout;
|
|
_hasTimeout = true;
|
|
_stopwatch = Stopwatch.StartNew();
|
|
}
|
|
|
|
private PlanningOperationBudget(CancellationToken cancellationToken)
|
|
{
|
|
_cancellationToken = cancellationToken;
|
|
_timeout = TimeSpan.Zero;
|
|
_hasTimeout = false;
|
|
_stopwatch = Stopwatch.StartNew();
|
|
}
|
|
|
|
/// <summary>创建只响应取消、不限制总耗时的兼容预算。</summary>
|
|
internal static PlanningOperationBudget Unlimited(CancellationToken cancellationToken)
|
|
{
|
|
return new PlanningOperationBudget(cancellationToken);
|
|
}
|
|
|
|
/// <summary>从预算创建到当前的单调经过时间。</summary>
|
|
internal TimeSpan Elapsed { get { return _stopwatch.Elapsed; } }
|
|
|
|
/// <summary>立即查询当前停止原因;取消优先于超时。</summary>
|
|
internal PlanningOperationStopReason GetStopReason()
|
|
{
|
|
if (_cancellationToken.IsCancellationRequested) return PlanningOperationStopReason.Cancelled;
|
|
return _hasTimeout && _stopwatch.Elapsed >= _timeout
|
|
? PlanningOperationStopReason.TimedOut
|
|
: PlanningOperationStopReason.None;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 在循环工作单元中按固定上限检查预算。
|
|
/// 参数:workItemCount 为当前循环共享的已处理单元计数;首次及每 256 个单元检查一次。
|
|
/// </summary>
|
|
internal PlanningOperationStopReason CheckEvery(ref int workItemCount)
|
|
{
|
|
workItemCount++;
|
|
return workItemCount == 1 || workItemCount % CheckIntervalWorkItems == 0
|
|
? GetStopReason()
|
|
: PlanningOperationStopReason.None;
|
|
}
|
|
}
|