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
1 changed files with 35 additions and 3 deletions

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 @@ public class RealmLive<T> : ILive<T> where T : RealmObject, IHasGuidPrimaryKey
/// <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 @@ public RealmLive(T data, RealmAccess realm)
this.realm = realm; this.realm = realm;
ID = data.ID; ID = data.ID;
dataIsFromUpdateThread = ThreadSafety.IsUpdateThread;
} }
/// <summary> /// <summary>
@ -51,7 +55,17 @@ public void PerformRead(Action<T> perform)
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 @@ public TReturn PerformRead<TReturn>(Func<T, TReturn> perform)
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 @@ public T Value
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);