diff --git a/osu.Game/Database/RealmLive.cs b/osu.Game/Database/RealmLive.cs index f06ba1eff9..c572d52cc6 100644 --- a/osu.Game/Database/RealmLive.cs +++ b/osu.Game/Database/RealmLive.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using osu.Framework.Development; using Realms; @@ -22,7 +23,9 @@ public class RealmLive : ILive where T : RealmObject, IHasGuidPrimaryKey /// /// The original live data used to create this instance. /// - private readonly T data; + private T data; + + private bool dataIsFromUpdateThread; private readonly RealmAccess realm; @@ -37,6 +40,7 @@ public RealmLive(T data, RealmAccess realm) this.realm = realm; ID = data.ID; + dataIsFromUpdateThread = ThreadSafety.IsUpdateThread; } /// @@ -51,7 +55,17 @@ public void PerformRead(Action perform) return; } - realm.Run(r => perform(retrieveFromID(r, ID))); + realm.Run(r => + { + if (ThreadSafety.IsUpdateThread) + { + ensureDataIsFromUpdateThread(); + perform(data); + return; + } + + perform(retrieveFromID(r, ID)); + }); } /// @@ -63,6 +77,12 @@ public TReturn PerformRead(Func perform) if (!IsManaged) return perform(data); + if (ThreadSafety.IsUpdateThread) + { + ensureDataIsFromUpdateThread(); + return perform(data); + } + return realm.Run(r => { var returnData = perform(retrieveFromID(r, ID)); @@ -101,10 +121,22 @@ public T Value if (!ThreadSafety.IsUpdateThread) throw new InvalidOperationException($"Can't use {nameof(Value)} on managed objects from non-update threads"); - return realm.Realm.Find(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) { var found = realm.Find(ID);