// 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()); } }