// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Linq;
namespace EpicGames.Horde.Compute;
///
/// Manages and hands out request IDs for compute allocation requests
///
public class RequestIdAllocator
{
private readonly object _lock = new();
private readonly List _pendingIds = new();
private readonly List _batchIds = new();
private readonly string _allocatorId;
private int _requestCounter;
///
/// Constructor
///
public RequestIdAllocator()
{
_allocatorId = GenerateAllocatorId(8);
}
///
/// Starts a new batch of requests.
/// Any requests started during current batch will be reset and marked as unfinished.
///
public void StartBatch()
{
lock (_lock)
{
_pendingIds.AddRange(_batchIds);
_batchIds.Clear();
}
}
///
/// Get or create a request ID and mark it as part of current batch
///
/// A request ID
public string AllocateId()
{
lock (_lock)
{
string? reqId;
if (_pendingIds.Count > 0)
{
reqId = _pendingIds[0];
_pendingIds.RemoveAt(0);
}
else
{
reqId = $"{_allocatorId}-{_requestCounter++}";
}
_batchIds.Add(reqId);
return reqId;
}
}
///
/// Mark a request Id as accepted. It won't be re-used for any future requests.
///
/// Request ID to mark as finished
public void MarkAccepted(string reqId)
{
lock (_lock)
{
_batchIds.Remove(reqId);
}
}
private static string GenerateAllocatorId(int length)
{
Random random = new();
string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
}
}