mirror of
https://github.com/osukey/osukey.git
synced 2025-05-07 22:57:31 +09:00
Ensure all async writes are completed before realm is disposed
This commit is contained in:
parent
1fc4fa6820
commit
c39c99bd43
@ -388,16 +388,28 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly CountdownEvent pendingAsyncWrites = new CountdownEvent(0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Write changes to realm asynchronously, guaranteeing order of execution.
|
/// Write changes to realm asynchronously, guaranteeing order of execution.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="action">The work to run.</param>
|
/// <param name="action">The work to run.</param>
|
||||||
public Task WriteAsync(Action<Realm> action)
|
public Task WriteAsync(Action<Realm> action)
|
||||||
{
|
{
|
||||||
|
// Required to ensure the write is tracked and accounted for before disposal.
|
||||||
|
// Can potentially be avoided if we have a need to do so in the future.
|
||||||
|
if (!ThreadSafety.IsUpdateThread)
|
||||||
|
throw new InvalidOperationException(@$"{nameof(WriteAsync)} must be called from the update thread.");
|
||||||
|
|
||||||
|
lock (realmLock)
|
||||||
|
{
|
||||||
|
// CountdownEvent will fail if already at zero.
|
||||||
|
if (!pendingAsyncWrites.TryAddCount())
|
||||||
|
pendingAsyncWrites.Reset(1);
|
||||||
|
|
||||||
// Regardless of calling Realm.GetInstance or Realm.GetInstanceAsync, there is a blocking overhead on retrieval.
|
// Regardless of calling Realm.GetInstance or Realm.GetInstanceAsync, there is a blocking overhead on retrieval.
|
||||||
// Adding a forced Task.Run resolves this.
|
// Adding a forced Task.Run resolves this.
|
||||||
|
var writeTask = Task.Run(async () =>
|
||||||
return Task.Run(async () =>
|
|
||||||
{
|
{
|
||||||
total_writes_async.Value++;
|
total_writes_async.Value++;
|
||||||
|
|
||||||
@ -407,7 +419,12 @@ namespace osu.Game.Database
|
|||||||
using (var realm = getRealmInstance())
|
using (var realm = getRealmInstance())
|
||||||
// ReSharper disable once AccessToDisposedClosure (WriteAsync should be marked as [InstantHandle]).
|
// ReSharper disable once AccessToDisposedClosure (WriteAsync should be marked as [InstantHandle]).
|
||||||
await realm.WriteAsync(() => action(realm));
|
await realm.WriteAsync(() => action(realm));
|
||||||
|
|
||||||
|
pendingAsyncWrites.Signal();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return writeTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -910,6 +927,9 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
if (!pendingAsyncWrites.Wait(10000))
|
||||||
|
Logger.Log("Realm took too long waiting on pending async writes", level: LogLevel.Error);
|
||||||
|
|
||||||
lock (realmLock)
|
lock (realmLock)
|
||||||
{
|
{
|
||||||
updateRealm?.Dispose();
|
updateRealm?.Dispose();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user