1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-12 06:07:28 +08:00
osu-lazer/osu.Game/Database/RealmLive.cs

109 lines
3.3 KiB
C#
Raw Normal View History

2021-09-30 22:46:16 +08:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Development;
2021-09-30 22:46:16 +08:00
using Realms;
#nullable enable
namespace osu.Game.Database
{
/// <summary>
/// Provides a method of working with realm objects over longer application lifetimes.
/// </summary>
/// <typeparam name="T">The underlying object type.</typeparam>
public class RealmLive<T> : ILive<T> where T : RealmObject, IHasGuidPrimaryKey
{
public Guid ID { get; }
public bool IsManaged => data.IsManaged;
2021-09-30 22:46:16 +08:00
/// <summary>
/// The original live data used to create this instance.
/// </summary>
private readonly T data;
/// <summary>
/// Construct a new instance of live realm data.
/// </summary>
/// <param name="data">The realm data.</param>
public RealmLive(T data)
{
this.data = data;
ID = data.ID;
}
/// <summary>
/// Perform a read operation on this live object.
/// </summary>
/// <param name="perform">The action to perform.</param>
public void PerformRead(Action<T> perform)
{
if (!IsManaged)
2021-09-30 22:46:16 +08:00
{
perform(data);
return;
}
using (var realm = Realm.GetInstance(data.Realm.Config))
perform(realm.Find<T>(ID));
}
/// <summary>
/// Perform a read operation on this live object.
/// </summary>
/// <param name="perform">The action to perform.</param>
public TReturn PerformRead<TReturn>(Func<T, TReturn> perform)
{
if (typeof(RealmObjectBase).IsAssignableFrom(typeof(TReturn)))
throw new InvalidOperationException($"Realm live objects should not exit the scope of {nameof(PerformRead)}.");
if (!IsManaged)
2021-09-30 22:46:16 +08:00
return perform(data);
using (var realm = Realm.GetInstance(data.Realm.Config))
return perform(realm.Find<T>(ID));
}
/// <summary>
/// Perform a write operation on this live object.
/// </summary>
/// <param name="perform">The action to perform.</param>
public void PerformWrite(Action<T> perform)
{
if (!IsManaged)
throw new InvalidOperationException("Can't perform writes on a non-managed underlying value");
2021-09-30 22:46:16 +08:00
PerformRead(t =>
{
var transaction = t.Realm.BeginWrite();
perform(t);
transaction.Commit();
});
}
2021-09-30 22:46:16 +08:00
public T Value
{
get
{
if (!IsManaged)
2021-09-30 22:46:16 +08:00
return data;
if (!ThreadSafety.IsUpdateThread)
throw new InvalidOperationException($"Can't use {nameof(Value)} on managed objects from non-update threads");
2021-09-30 22:46:16 +08:00
// 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
2021-09-30 22:46:16 +08:00
var realm = Realm.GetInstance(data.Realm.Config);
2021-09-30 22:46:16 +08:00
return realm.Find<T>(ID);
2021-09-30 22:46:16 +08:00
}
}
2021-11-26 13:38:39 +08:00
public bool Equals(ILive<T>? other) => ID == other?.ID;
2021-09-30 22:46:16 +08:00
}
}