mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 23:24:04 +09:00
Improve safety of ongoing operation tracker
Finishing an operation started via `OngoingOperationTracker.BeginOperation()` was risky in cases where the operation ended at a callback on another thread (which, in the case of multiplayer, is *most* cases). In particular, if any consumer registered a callback that mutates transforms when the operation ends, it would result in crashes after the framework-side safety checks. Rework `OngoingOperationTracker` into an always-present component residing in the drawable hierarchy, and ensure that the `operationInProgress` bindable is always updated on the update thread. This way consumers don't have to add local schedules in multiple places.
This commit is contained in:
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay
|
||||
{
|
||||
@ -11,7 +12,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
/// Utility class to track ongoing online operations' progress.
|
||||
/// Can be used to disable interactivity while waiting for a response from online sources.
|
||||
/// </summary>
|
||||
public class OngoingOperationTracker
|
||||
public class OngoingOperationTracker : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether there is an online operation in progress.
|
||||
@ -22,6 +23,11 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
private LeasedBindable<bool> leasedInProgress;
|
||||
|
||||
public OngoingOperationTracker()
|
||||
{
|
||||
AlwaysPresent = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begins tracking a new online operation.
|
||||
/// </summary>
|
||||
@ -37,7 +43,8 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
leasedInProgress = inProgress.BeginLease(true);
|
||||
leasedInProgress.Value = true;
|
||||
|
||||
return new InvokeOnDisposal(endOperation);
|
||||
// for extra safety, marshal the end of operation back to the update thread if necessary.
|
||||
return new InvokeOnDisposal(() => Scheduler.Add(endOperation, false));
|
||||
}
|
||||
|
||||
private void endOperation()
|
||||
|
Reference in New Issue
Block a user