82 lines
2.4 KiB
GDScript
82 lines
2.4 KiB
GDScript
class_name PresentationNavRequestBudget
|
|
extends RefCounted
|
|
|
|
const MAX_NEW_REQUESTS_PER_FRAME := 2
|
|
|
|
var _pending_by_id: Dictionary = {}
|
|
var _in_flight_ids: Dictionary = {}
|
|
var _last_drained_frame := -1
|
|
|
|
|
|
func enqueue(stable_id: StringName, priority: int = 0, reason_trace: Array[String] = []) -> bool:
|
|
if stable_id.is_empty() or _pending_by_id.has(stable_id) or _in_flight_ids.has(stable_id):
|
|
return false
|
|
var normalized_trace := reason_trace.duplicate()
|
|
normalized_trace.sort()
|
|
_pending_by_id[stable_id] = {
|
|
"stable_id": stable_id,
|
|
"priority": priority,
|
|
"reason_trace": normalized_trace,
|
|
}
|
|
return true
|
|
|
|
|
|
func take_new_requests(frame_index: int) -> Array[Dictionary]:
|
|
var result: Array[Dictionary] = []
|
|
if frame_index < 0 or frame_index <= _last_drained_frame:
|
|
return result
|
|
_last_drained_frame = frame_index
|
|
var pending: Array[Dictionary] = []
|
|
for request in _pending_by_id.values():
|
|
pending.append((request as Dictionary).duplicate(true))
|
|
pending.sort_custom(_request_before)
|
|
for index in mini(MAX_NEW_REQUESTS_PER_FRAME, pending.size()):
|
|
var request: Dictionary = pending[index]
|
|
var stable_id: StringName = request["stable_id"]
|
|
_pending_by_id.erase(stable_id)
|
|
_in_flight_ids[stable_id] = true
|
|
request["reason_trace"].append("granted_frame_%d" % frame_index)
|
|
result.append(request)
|
|
return result
|
|
|
|
|
|
func complete(stable_id: StringName) -> bool:
|
|
return _in_flight_ids.erase(stable_id)
|
|
|
|
|
|
func cancel(stable_id: StringName) -> bool:
|
|
var changed := _pending_by_id.erase(stable_id)
|
|
return _in_flight_ids.erase(stable_id) or changed
|
|
|
|
|
|
func get_pending_ids() -> Array[StringName]:
|
|
var result: Array[StringName] = []
|
|
for stable_id in _pending_by_id:
|
|
result.append(StringName(stable_id))
|
|
result.sort_custom(_stable_id_before)
|
|
return result
|
|
|
|
|
|
func get_in_flight_ids() -> Array[StringName]:
|
|
var result: Array[StringName] = []
|
|
for stable_id in _in_flight_ids:
|
|
result.append(StringName(stable_id))
|
|
result.sort_custom(_stable_id_before)
|
|
return result
|
|
|
|
|
|
func clear() -> void:
|
|
_pending_by_id.clear()
|
|
_in_flight_ids.clear()
|
|
_last_drained_frame = -1
|
|
|
|
|
|
func _request_before(first: Dictionary, second: Dictionary) -> bool:
|
|
if int(first["priority"]) != int(second["priority"]):
|
|
return int(first["priority"]) > int(second["priority"])
|
|
return String(first["stable_id"]) < String(second["stable_id"])
|
|
|
|
|
|
func _stable_id_before(first: StringName, second: StringName) -> bool:
|
|
return String(first) < String(second)
|