mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
A task's progress push took the widget state lock on the main thread and made, measured and updated the task's widget there, behind whatever frame the video thread was drawing. The widget and the task pointed at each other, so freeing either meant reaching into the other from the wrong thread at the right moment - most of the comments this removes were about that. The main thread now sends what the task looks like - title or error, progress, flags, style - and nothing else. The owner applies the updates once a frame, before it touches the queue: it finds the widget by a key, makes one if the task has none, and measures it with the font it owns. The key is a number the task carries in frontend_userdata, so nothing holds a pointer to a task or expects one to a widget; a widget freed or a task retired is simply not found. gfx_widgets_task_transfer() moves the key and tells the owner, which re-keys the widget before the old owner's finished state can start it expiring. Updates travel on a lock-free list the owner takes whole. Progress is sent every frame and gives way when the owner falls behind; a finished task's last update is always sent. Task widgets wait for room on the owner's side, and a stamp keeps their order against plain messages, which stay on the pending ring. The state lock remains for layout, fonts and lifecycle, and on a backend without pointer atomics it guards the update list. The task-gate sample now runs titled tasks to retirement against an owner thread under ThreadSanitizer; the ownership and bar-stack tests follow the updates to the owner.