mirror of
https://github.com/osukey/osukey.git
synced 2025-05-07 06:37:18 +09:00
Merge pull request #17432 from peppy/realm-subscription-any-thread
Allow realm subscriptions to be initiated from any thread
This commit is contained in:
commit
c6182c2b09
@ -51,8 +51,8 @@
|
|||||||
<Reference Include="Java.Interop" />
|
<Reference Include="Java.Interop" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.304.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.325.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.314.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.325.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Transitive Dependencies">
|
<ItemGroup Label="Transitive Dependencies">
|
||||||
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
||||||
|
@ -26,7 +26,7 @@ namespace osu.Game.Tournament.Screens.Setup
|
|||||||
dropdown.Current.BindValueChanged(v => Button.Enabled.Value = v.NewValue != startupTournament, true);
|
dropdown.Current.BindValueChanged(v => Button.Enabled.Value = v.NewValue != startupTournament, true);
|
||||||
|
|
||||||
Action = () => game.GracefullyExit();
|
Action = () => game.GracefullyExit();
|
||||||
folderButton.Action = storage.PresentExternally;
|
folderButton.Action = () => storage.PresentExternally();
|
||||||
|
|
||||||
ButtonText = "Close osu!";
|
ButtonText = "Close osu!";
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
@ -17,6 +19,7 @@ using osu.Framework.Input.Bindings;
|
|||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Statistics;
|
using osu.Framework.Statistics;
|
||||||
|
using osu.Framework.Threading;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Input.Bindings;
|
using osu.Game.Input.Bindings;
|
||||||
@ -28,8 +31,6 @@ using osu.Game.Stores;
|
|||||||
using Realms;
|
using Realms;
|
||||||
using Realms.Exceptions;
|
using Realms.Exceptions;
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
namespace osu.Game.Database
|
namespace osu.Game.Database
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -46,6 +47,8 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
private readonly IDatabaseContextFactory? efContextFactory;
|
private readonly IDatabaseContextFactory? efContextFactory;
|
||||||
|
|
||||||
|
private readonly SynchronizationContext? updateThreadSyncContext;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version history:
|
/// Version history:
|
||||||
/// 6 ~2021-10-18 First tracked version.
|
/// 6 ~2021-10-18 First tracked version.
|
||||||
@ -143,12 +146,15 @@ namespace osu.Game.Database
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="storage">The game storage which will be used to create the realm backing file.</param>
|
/// <param name="storage">The game storage which will be used to create the realm backing file.</param>
|
||||||
/// <param name="filename">The filename to use for the realm backing file. A ".realm" extension will be added automatically if not specified.</param>
|
/// <param name="filename">The filename to use for the realm backing file. A ".realm" extension will be added automatically if not specified.</param>
|
||||||
|
/// <param name="updateThread">The game update thread, used to post realm operations into a thread-safe context.</param>
|
||||||
/// <param name="efContextFactory">An EF factory used only for migration purposes.</param>
|
/// <param name="efContextFactory">An EF factory used only for migration purposes.</param>
|
||||||
public RealmAccess(Storage storage, string filename, IDatabaseContextFactory? efContextFactory = null)
|
public RealmAccess(Storage storage, string filename, GameThread? updateThread = null, IDatabaseContextFactory? efContextFactory = null)
|
||||||
{
|
{
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
this.efContextFactory = efContextFactory;
|
this.efContextFactory = efContextFactory;
|
||||||
|
|
||||||
|
updateThreadSyncContext = updateThread?.SynchronizationContext ?? SynchronizationContext.Current;
|
||||||
|
|
||||||
Filename = filename;
|
Filename = filename;
|
||||||
|
|
||||||
if (!Filename.EndsWith(realm_extension, StringComparison.Ordinal))
|
if (!Filename.EndsWith(realm_extension, StringComparison.Ordinal))
|
||||||
@ -379,9 +385,6 @@ namespace osu.Game.Database
|
|||||||
public IDisposable RegisterForNotifications<T>(Func<Realm, IQueryable<T>> query, NotificationCallbackDelegate<T> callback)
|
public IDisposable RegisterForNotifications<T>(Func<Realm, IQueryable<T>> query, NotificationCallbackDelegate<T> callback)
|
||||||
where T : RealmObjectBase
|
where T : RealmObjectBase
|
||||||
{
|
{
|
||||||
if (!ThreadSafety.IsUpdateThread)
|
|
||||||
throw new InvalidOperationException(@$"{nameof(RegisterForNotifications)} must be called from the update thread.");
|
|
||||||
|
|
||||||
lock (realmLock)
|
lock (realmLock)
|
||||||
{
|
{
|
||||||
Func<Realm, IDisposable?> action = realm => query(realm).QueryAsyncWithNotifications(callback);
|
Func<Realm, IDisposable?> action = realm => query(realm).QueryAsyncWithNotifications(callback);
|
||||||
@ -459,23 +462,24 @@ namespace osu.Game.Database
|
|||||||
/// <returns>An <see cref="IDisposable"/> which should be disposed to unsubscribe any inner subscription.</returns>
|
/// <returns>An <see cref="IDisposable"/> which should be disposed to unsubscribe any inner subscription.</returns>
|
||||||
public IDisposable RegisterCustomSubscription(Func<Realm, IDisposable?> action)
|
public IDisposable RegisterCustomSubscription(Func<Realm, IDisposable?> action)
|
||||||
{
|
{
|
||||||
if (!ThreadSafety.IsUpdateThread)
|
if (updateThreadSyncContext == null)
|
||||||
throw new InvalidOperationException(@$"{nameof(RegisterForNotifications)} must be called from the update thread.");
|
throw new InvalidOperationException("Attempted to register a realm subscription before update thread registration.");
|
||||||
|
|
||||||
var syncContext = SynchronizationContext.Current;
|
|
||||||
|
|
||||||
total_subscriptions.Value++;
|
total_subscriptions.Value++;
|
||||||
|
|
||||||
registerSubscription(action);
|
if (ThreadSafety.IsUpdateThread)
|
||||||
|
updateThreadSyncContext.Send(_ => registerSubscription(action), null);
|
||||||
|
else
|
||||||
|
updateThreadSyncContext.Post(_ => registerSubscription(action), null);
|
||||||
|
|
||||||
// This token is returned to the consumer.
|
// This token is returned to the consumer.
|
||||||
// When disposed, it will cause the registration to be permanently ceased (unsubscribed with realm and unregistered by this class).
|
// When disposed, it will cause the registration to be permanently ceased (unsubscribed with realm and unregistered by this class).
|
||||||
return new InvokeOnDisposal(() =>
|
return new InvokeOnDisposal(() =>
|
||||||
{
|
{
|
||||||
if (ThreadSafety.IsUpdateThread)
|
if (ThreadSafety.IsUpdateThread)
|
||||||
syncContext.Send(_ => unsubscribe(), null);
|
updateThreadSyncContext.Send(_ => unsubscribe(), null);
|
||||||
else
|
else
|
||||||
syncContext.Post(_ => unsubscribe(), null);
|
updateThreadSyncContext.Post(_ => unsubscribe(), null);
|
||||||
|
|
||||||
void unsubscribe()
|
void unsubscribe()
|
||||||
{
|
{
|
||||||
|
@ -70,9 +70,9 @@ namespace osu.Game.IO
|
|||||||
public override Stream GetStream(string path, FileAccess access = FileAccess.Read, FileMode mode = FileMode.OpenOrCreate) =>
|
public override Stream GetStream(string path, FileAccess access = FileAccess.Read, FileMode mode = FileMode.OpenOrCreate) =>
|
||||||
UnderlyingStorage.GetStream(MutatePath(path), access, mode);
|
UnderlyingStorage.GetStream(MutatePath(path), access, mode);
|
||||||
|
|
||||||
public override void OpenFileExternally(string filename) => UnderlyingStorage.OpenFileExternally(MutatePath(filename));
|
public override bool OpenFileExternally(string filename) => UnderlyingStorage.OpenFileExternally(MutatePath(filename));
|
||||||
|
|
||||||
public override void PresentFileExternally(string filename) => UnderlyingStorage.PresentFileExternally(MutatePath(filename));
|
public override bool PresentFileExternally(string filename) => UnderlyingStorage.PresentFileExternally(MutatePath(filename));
|
||||||
|
|
||||||
public override Storage GetStorageForDirectory(string path)
|
public override Storage GetStorageForDirectory(string path)
|
||||||
{
|
{
|
||||||
|
@ -200,7 +200,7 @@ namespace osu.Game
|
|||||||
if (Storage.Exists(DatabaseContextFactory.DATABASE_NAME))
|
if (Storage.Exists(DatabaseContextFactory.DATABASE_NAME))
|
||||||
dependencies.Cache(EFContextFactory = new DatabaseContextFactory(Storage));
|
dependencies.Cache(EFContextFactory = new DatabaseContextFactory(Storage));
|
||||||
|
|
||||||
dependencies.Cache(realm = new RealmAccess(Storage, "client", EFContextFactory));
|
dependencies.Cache(realm = new RealmAccess(Storage, "client", Host.UpdateThread, EFContextFactory));
|
||||||
|
|
||||||
dependencies.CacheAs<RulesetStore>(RulesetStore = new RealmRulesetStore(realm, Storage));
|
dependencies.CacheAs<RulesetStore>(RulesetStore = new RealmRulesetStore(realm, Storage));
|
||||||
dependencies.CacheAs<IRulesetStore>(RulesetStore);
|
dependencies.CacheAs<IRulesetStore>(RulesetStore);
|
||||||
|
@ -68,7 +68,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
Add(new SettingsButton
|
Add(new SettingsButton
|
||||||
{
|
{
|
||||||
Text = GeneralSettingsStrings.OpenOsuFolder,
|
Text = GeneralSettingsStrings.OpenOsuFolder,
|
||||||
Action = storage.PresentExternally,
|
Action = () => storage.PresentExternally(),
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(new SettingsButton
|
Add(new SettingsButton
|
||||||
|
@ -36,8 +36,8 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Realm" Version="10.10.0" />
|
<PackageReference Include="Realm" Version="10.10.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2022.314.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2022.325.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.304.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.325.0" />
|
||||||
<PackageReference Include="Sentry" Version="3.14.1" />
|
<PackageReference Include="Sentry" Version="3.14.1" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.30.1" />
|
<PackageReference Include="SharpCompress" Version="0.30.1" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||||
|
@ -61,8 +61,8 @@
|
|||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.314.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.325.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.304.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.325.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net6.0) -->
|
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net6.0) -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@ -84,7 +84,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.14" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.14" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="5.0.14" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="5.0.14" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2022.314.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2022.325.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.30.1" />
|
<PackageReference Include="SharpCompress" Version="0.30.1" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user