Avoid creating realm contexts or refetching when accessing RealmLive from the update thread

This commit is contained in:
Dean Herbert
2022-01-17 18:32:57 +09:00
parent cdd63e428c
commit d76822b685

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Diagnostics;
using osu.Framework.Development; using osu.Framework.Development;
using Realms; using Realms;
@ -22,7 +23,9 @@ namespace osu.Game.Database
/// <summary> /// <summary>
/// The original live data used to create this instance. /// The original live data used to create this instance.
/// </summary> /// </summary>
private readonly T data; private T data;
private bool dataIsFromUpdateThread;
private readonly RealmAccess realm; private readonly RealmAccess realm;
@ -37,6 +40,7 @@ namespace osu.Game.Database
this.realm = realm; this.realm = realm;
ID = data.ID; ID = data.ID;
dataIsFromUpdateThread = ThreadSafety.IsUpdateThread;
} }
/// <summary> /// <summary>
@ -51,7 +55,17 @@ namespace osu.Game.Database
return; return;
} }
realm.Run(r => perform(retrieveFromID(r, ID))); realm.Run(r =>
{
if (ThreadSafety.IsUpdateThread)
{
ensureDataIsFromUpdateThread();
perform(data);
return;
}
perform(retrieveFromID(r, ID));
});
} }
/// <summary> /// <summary>
@ -63,6 +77,12 @@ namespace osu.Game.Database
if (!IsManaged) if (!IsManaged)
return perform(data); return perform(data);
if (ThreadSafety.IsUpdateThread)
{
ensureDataIsFromUpdateThread();
return perform(data);
}
return realm.Run(r => return realm.Run(r =>
{ {
var returnData = perform(retrieveFromID(r, ID)); var returnData = perform(retrieveFromID(r, ID));
@ -101,10 +121,22 @@ namespace osu.Game.Database
if (!ThreadSafety.IsUpdateThread) if (!ThreadSafety.IsUpdateThread)
throw new InvalidOperationException($"Can't use {nameof(Value)} on managed objects from non-update threads"); throw new InvalidOperationException($"Can't use {nameof(Value)} on managed objects from non-update threads");
return realm.Realm.Find<T>(ID); ensureDataIsFromUpdateThread();
return data;
} }
} }
private void ensureDataIsFromUpdateThread()
{
Debug.Assert(ThreadSafety.IsUpdateThread);
if (dataIsFromUpdateThread)
return;
dataIsFromUpdateThread = true;
data = retrieveFromID(realm.Realm, ID);
}
private T retrieveFromID(Realm realm, Guid id) private T retrieveFromID(Realm realm, Guid id)
{ {
var found = realm.Find<T>(ID); var found = realm.Find<T>(ID);