Remove all optimisations from `RealmLive`

This commit is contained in:
Dean Herbert 2021-11-30 11:47:29 +09:00
parent 791f7e3801
commit 35d68d6ab0
1 changed files with 11 additions and 32 deletions

View File

@ -2,7 +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.Threading; using osu.Framework.Development;
using Realms; using Realms;
#nullable enable #nullable enable
@ -17,10 +17,7 @@ public class RealmLive<T> : ILive<T> where T : RealmObject, IHasGuidPrimaryKey
{ {
public Guid ID { get; } public Guid ID { get; }
public bool IsManaged { get; } public bool IsManaged => data.IsManaged;
private readonly SynchronizationContext? fetchedContext;
private readonly int fetchedThreadId;
/// <summary> /// <summary>
/// The original live data used to create this instance. /// The original live data used to create this instance.
@ -35,14 +32,6 @@ public RealmLive(T data)
{ {
this.data = data; this.data = data;
if (data.IsManaged)
{
IsManaged = true;
fetchedContext = SynchronizationContext.Current;
fetchedThreadId = Thread.CurrentThread.ManagedThreadId;
}
ID = data.ID; ID = data.ID;
} }
@ -52,7 +41,7 @@ public RealmLive(T data)
/// <param name="perform">The action to perform.</param> /// <param name="perform">The action to perform.</param>
public void PerformRead(Action<T> perform) public void PerformRead(Action<T> perform)
{ {
if (originalDataValid) if (!IsManaged)
{ {
perform(data); perform(data);
return; return;
@ -71,7 +60,7 @@ public TReturn PerformRead<TReturn>(Func<T, TReturn> perform)
if (typeof(RealmObjectBase).IsAssignableFrom(typeof(TReturn))) if (typeof(RealmObjectBase).IsAssignableFrom(typeof(TReturn)))
throw new InvalidOperationException($"Realm live objects should not exit the scope of {nameof(PerformRead)}."); throw new InvalidOperationException($"Realm live objects should not exit the scope of {nameof(PerformRead)}.");
if (originalDataValid) if (!IsManaged)
return perform(data); return perform(data);
using (var realm = Realm.GetInstance(data.Realm.Config)) using (var realm = Realm.GetInstance(data.Realm.Config))
@ -99,31 +88,21 @@ public T Value
{ {
get get
{ {
if (originalDataValid) if (!IsManaged)
return data; return data;
if (!isCorrectThread) if (!ThreadSafety.IsUpdateThread)
throw new InvalidOperationException($"Can't use {nameof(Value)} unless on the same thread the original data was fetched from."); throw new InvalidOperationException($"Can't use {nameof(Value)} on managed objects from non-update threads");
// When using Value, we rely on garbage collection for the realm instance used to retrieve the instance.
// As we are sure that this is on the same thread
var realm = Realm.GetInstance(data.Realm.Config); var realm = Realm.GetInstance(data.Realm.Config);
var retrieved = realm.Find<T>(ID);
if (!retrieved.IsValid) return realm.Find<T>(ID);
throw new InvalidOperationException("Attempted to access value without an open context");
return retrieved;
} }
} }
// TODO: Revisit adding these conditionals back as an optimisation: || (isCorrectThread && data.IsValid);
// They have temporarily been removed due to an oversight involving .AsQueryable, see https://github.com/realm/realm-dotnet/discussions/2734.
// This means we are fetching a new context every `PerformRead` or `PerformWrite`, even when on the correct thread.
private bool originalDataValid => !IsManaged;
// this matches realm's internal thread validation (see https://github.com/realm/realm-dotnet/blob/903b4d0b304f887e37e2d905384fb572a6496e70/Realm/Realm/Native/SynchronizationContextScheduler.cs#L72)
private bool isCorrectThread
=> (fetchedContext != null && SynchronizationContext.Current == fetchedContext) || fetchedThreadId == Thread.CurrentThread.ManagedThreadId;
public bool Equals(ILive<T>? other) => ID == other?.ID; public bool Equals(ILive<T>? other) => ID == other?.ID;
} }
} }