1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 13:37:25 +08:00

Merge pull request #15812 from peppy/realm-live-unmanaged-fetch-fix

Avoid attempting to fetch a non-managed `RealmLive` instance from the realm backing
This commit is contained in:
Dan Balasescu 2021-11-26 15:37:58 +09:00 committed by GitHub
commit 5e53f51c99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 4 deletions

View File

@ -29,6 +29,23 @@ namespace osu.Game.Tests.Database
});
}
[Test]
public void TestAccessNonManaged()
{
var beatmap = new RealmBeatmap(CreateRuleset(), new RealmBeatmapDifficulty(), new RealmBeatmapMetadata());
var liveBeatmap = beatmap.ToLive();
Assert.IsFalse(beatmap.Hidden);
Assert.IsFalse(liveBeatmap.Value.Hidden);
Assert.IsFalse(liveBeatmap.PerformRead(l => l.Hidden));
Assert.Throws<InvalidOperationException>(() => liveBeatmap.PerformWrite(l => l.Hidden = true));
Assert.IsFalse(beatmap.Hidden);
Assert.IsFalse(liveBeatmap.Value.Hidden);
Assert.IsFalse(liveBeatmap.PerformRead(l => l.Hidden));
}
[Test]
public void TestValueAccessWithOpenContext()
{

View File

@ -11,6 +11,7 @@ namespace osu.Game.Database
{
public EntityFrameworkLive(T item)
{
IsManaged = true; // no way to really know.
Value = item;
}
@ -31,6 +32,8 @@ namespace osu.Game.Database
perform(Value);
}
public bool IsManaged { get; }
public T Value { get; }
public bool Equals(ILive<T>? other) => ID == other?.ID;

View File

@ -32,6 +32,11 @@ namespace osu.Game.Database
/// <param name="perform">The action to perform.</param>
void PerformWrite(Action<T> perform);
/// <summary>
/// Whether this instance is tracking data which is managed by the database backing.
/// </summary>
bool IsManaged { get; }
/// <summary>
/// Resolve the value of this instance on the current thread's context.
/// </summary>

View File

@ -17,6 +17,8 @@ namespace osu.Game.Database
{
public Guid ID { get; }
public bool IsManaged { get; }
private readonly SynchronizationContext? fetchedContext;
private readonly int fetchedThreadId;
@ -33,8 +35,13 @@ namespace osu.Game.Database
{
this.data = data;
fetchedContext = SynchronizationContext.Current;
fetchedThreadId = Thread.CurrentThread.ManagedThreadId;
if (data.IsManaged)
{
IsManaged = true;
fetchedContext = SynchronizationContext.Current;
fetchedThreadId = Thread.CurrentThread.ManagedThreadId;
}
ID = data.ID;
}
@ -75,13 +82,18 @@ namespace osu.Game.Database
/// Perform a write operation on this live object.
/// </summary>
/// <param name="perform">The action to perform.</param>
public void PerformWrite(Action<T> perform) =>
public void PerformWrite(Action<T> perform)
{
if (!IsManaged)
throw new InvalidOperationException("Can't perform writes on a non-managed underlying value");
PerformRead(t =>
{
var transaction = t.Realm.BeginWrite();
perform(t);
transaction.Commit();
});
}
public T Value
{
@ -102,7 +114,7 @@ namespace osu.Game.Database
}
}
private bool originalDataValid => isCorrectThread && data.IsValid;
private bool originalDataValid => !IsManaged || (isCorrectThread && data.IsValid);
// 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