1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-14 17:17:24 +08:00

Ensure realm blocks until all threaded usages are completed

This commit is contained in:
Dean Herbert 2021-10-01 01:32:28 +09:00
parent 9c0abae2b0
commit cfd3bdf888

View File

@ -133,20 +133,43 @@ namespace osu.Game.Database
if (IsDisposed) if (IsDisposed)
throw new ObjectDisposedException(nameof(RealmContextFactory)); throw new ObjectDisposedException(nameof(RealmContextFactory));
// TODO: this can be added for safety once we figure how to bypass in test
// if (!ThreadSafety.IsUpdateThread)
// throw new InvalidOperationException($"{nameof(BlockAllOperations)} must be called from the update thread.");
Logger.Log(@"Blocking realm operations.", LoggingTarget.Database); Logger.Log(@"Blocking realm operations.", LoggingTarget.Database);
contextCreationLock.Wait(); try
{
contextCreationLock.Wait();
context?.Dispose(); const int sleep_length = 200;
context = null; int timeout = 5000;
return new InvokeOnDisposal<RealmContextFactory>(this, endBlockingSection); context?.Dispose();
context = null;
static void endBlockingSection(RealmContextFactory factory) // see https://github.com/realm/realm-dotnet/discussions/2657
while (!Compact())
{
Thread.Sleep(sleep_length);
timeout -= sleep_length;
if (timeout < 0)
throw new TimeoutException("Took too long to acquire lock");
}
}
catch
{
contextCreationLock.Release();
throw;
}
return new InvokeOnDisposal<RealmContextFactory>(this, factory =>
{ {
factory.contextCreationLock.Release(); factory.contextCreationLock.Release();
Logger.Log(@"Restoring realm operations.", LoggingTarget.Database); Logger.Log(@"Restoring realm operations.", LoggingTarget.Database);
} });
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
@ -155,8 +178,8 @@ namespace osu.Game.Database
if (!IsDisposed) if (!IsDisposed)
{ {
// intentionally block all operations indefinitely. this ensures that nothing can start consuming a new context after disposal. // intentionally block context creation indefinitely. this ensures that nothing can start consuming a new context after disposal.
BlockAllOperations(); contextCreationLock.Wait();
contextCreationLock.Dispose(); contextCreationLock.Dispose();
} }