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:
commit
5e53f51c99
@ -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()
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user