mirror of https://github.com/ppy/osu
Merge branch 'realm-nested-context-creation-deadlock-fix' into realm-integration/skins-rebase
This commit is contained in:
commit
e83ada40f9
|
@ -36,34 +36,36 @@ public void TestBlockOperations()
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test to ensure that a `CreateContext` call nested inside a subscription doesn't cause any deadlocks
|
||||
/// due to context fetching semaphores.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestNestedContextCreation()
|
||||
public void TestNestedContextCreationWithSubscription()
|
||||
{
|
||||
RunTestWithRealm((realmFactory, _) =>
|
||||
{
|
||||
var mainContext = realmFactory.Context;
|
||||
bool callbackRan = false;
|
||||
|
||||
var subscription = mainContext.All<RealmBeatmap>().SubscribeForNotifications((sender, changes, error) =>
|
||||
using (var context = realmFactory.CreateContext())
|
||||
{
|
||||
realmFactory.CreateContext();
|
||||
callbackRan = true;
|
||||
});
|
||||
|
||||
Task.Factory.StartNew(() =>
|
||||
{
|
||||
using (var threadContext = realmFactory.CreateContext())
|
||||
var subscription = context.All<RealmBeatmap>().SubscribeForNotifications((sender, changes, error) =>
|
||||
{
|
||||
threadContext.Write(r => r.Add(new RealmBeatmap(CreateRuleset(), new RealmBeatmapDifficulty(), new RealmBeatmapMetadata())));
|
||||
}
|
||||
}, TaskCreationOptions.LongRunning | TaskCreationOptions.HideScheduler).Wait();
|
||||
using (realmFactory.CreateContext())
|
||||
{
|
||||
callbackRan = true;
|
||||
}
|
||||
});
|
||||
|
||||
// will create a context but also run the callback above (Refresh is implicitly run when getting a new context).
|
||||
realmFactory.CreateContext();
|
||||
// Force the callback above to run.
|
||||
using (realmFactory.CreateContext())
|
||||
{
|
||||
}
|
||||
|
||||
subscription.Dispose();
|
||||
}
|
||||
|
||||
Assert.IsTrue(callbackRan);
|
||||
|
||||
subscription.Dispose();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -162,6 +162,7 @@ public Realm CreateContext()
|
|||
if (!currentThreadCanCreateContexts.Value)
|
||||
{
|
||||
contextCreationLock.Wait();
|
||||
currentThreadCanCreateContexts.Value = true;
|
||||
tookSemaphoreLock = true;
|
||||
}
|
||||
else
|
||||
|
@ -169,7 +170,6 @@ public Realm CreateContext()
|
|||
// the semaphore is used to handle blocking of all context creation during certain periods.
|
||||
// once the semaphore has been taken by this code section, it is safe to create further contexts on the same thread.
|
||||
// this can happen if a realm subscription is active and triggers a callback which has user code that calls `CreateContext`.
|
||||
currentThreadCanCreateContexts.Value = true;
|
||||
}
|
||||
|
||||
contexts_created.Value++;
|
||||
|
|
Loading…
Reference in New Issue