Skip to content

Commit 888a8f7

Browse files
authored
fix: js thread lock on scene lifecycle (#8702)
1 parent 9620418 commit 888a8f7

18 files changed

Lines changed: 341 additions & 112 deletions

File tree

Explorer/Assets/DCL/Character/CharacterMotion/Platforms/PlatformSaveLocalPosition.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ public static void Execute(ref CharacterPlatformComponent platformComponent, Vec
2020

2121
platformComponent.LastAvatarRelativePosition = platform.InverseTransformPoint(characterPosition);
2222

23-
// We only update the changed flag if a scene tick happened since last update
2423
// We are assuming that to hit something, that game object must be part of the current scene
25-
// if (currentScene != null && currentScene.SceneStateProvider.TickNumber > platformComponent.LastUpdateTick)
24+
if (currentScene != null && currentScene.SceneStateProvider.State == SceneState.Running)
2625
{
2726
Vector3 updatedPosition = platform.position;
2827

Explorer/Assets/DCL/Character/CharacterMotion/Systems/CharacterPlatformUpdateSceneTickSystem.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,14 @@ protected override void Update(float t)
3030
private void UpdateTick(ref CharacterPlatformComponent platformComponent)
3131
{
3232
ISceneFacade? currentScene = scenesCache.CurrentScene.Value;
33-
platformComponent.LastUpdateTick = currentScene?.SceneStateProvider.TickNumber ?? 0;
33+
34+
if (currentScene != null)
35+
{
36+
if (currentScene.SceneStateProvider.State == SceneState.Running)
37+
platformComponent.LastUpdateTick = currentScene.SceneStateProvider.TickNumber;
38+
}
39+
else
40+
platformComponent.LastUpdateTick = 0;
3441
}
3542
}
3643
}

Explorer/Assets/DCL/ECS/GlobalPartitioning/GlobalDeferredLoadingSystem.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,11 @@ private void FilterHandlersIfInTeleport()
8282
//We check if the player is teleporting, and if the scene we want to teleport to has started.
8383
//If so, only scene metadata will be allowed to de downloaded
8484
TeleportUtils.PlayerTeleportingState teleportParcel = TeleportUtils.GetTeleportParcel(World, playerEntity);
85-
if (teleportParcel.IsTeleporting)
86-
{
87-
if (scenesCache.Contains(teleportParcel.Parcel))
88-
downloadOnlySceneMetadata = true;
89-
}
85+
86+
if (teleportParcel.IsTeleporting
87+
&& scenesCache.TryGetByParcel(teleportParcel.Parcel, out ISceneFacade scene)
88+
&& scene.SceneStateProvider.State == SceneState.Running)
89+
downloadOnlySceneMetadata = true;
9090

9191
sameBoatQueries = downloadOnlySceneMetadata ? COMPONENT_HANDLERS_SCENES : COMPONENT_HANDLERS_SCENES_ASSETS;
9292
}

Explorer/Assets/DCL/Infrastructure/ECS/Groups/SyncedGroup.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,23 +58,26 @@ public override void Initialize()
5858

5959
public override void BeforeUpdate(in float t, bool throttle)
6060
{
61-
if (sceneStateProvider.State != SceneState.Running)
61+
if (sceneStateProvider.State != SceneState.Running
62+
&& sceneStateProvider.State != SceneState.Starting)
6263
return;
6364

6465
BeforeUpdateInternal(in t, throttle);
6566
}
6667

6768
public override void Update(in float t, bool throttle)
6869
{
69-
if (sceneStateProvider.State != SceneState.Running)
70+
if (sceneStateProvider.State != SceneState.Running
71+
&& sceneStateProvider.State != SceneState.Starting)
7072
return;
7173

7274
UpdateInternal(in t, throttle);
7375
}
7476

7577
public override void AfterUpdate(in float t, bool throttle)
7678
{
77-
if (sceneStateProvider.State != SceneState.Running)
79+
if (sceneStateProvider.State != SceneState.Running
80+
&& sceneStateProvider.State != SceneState.Starting)
7881
return;
7982

8083
AfterUpdateInternal(in t, throttle);

Explorer/Assets/DCL/Infrastructure/ECS/SceneLifeCycle/Reporting/SceneReadinessReportQueue.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using DCL.Optimization.Pools;
22
using DCL.Utilities;
3+
using SceneRunner.Scene;
34
using System.Collections.Generic;
45
using UnityEngine;
56

@@ -21,11 +22,10 @@ public SceneReadinessReportQueue(IScenesCache scenesCache)
2122
public void Enqueue(Vector2Int parcel, AsyncLoadProcessReport report)
2223
{
2324
// Shortcut
24-
if (scenesCache.Contains(parcel))
25-
{
25+
if (scenesCache.TryGetByParcel(parcel, out ISceneFacade scene)
26+
&& scene.SceneStateProvider.State == SceneState.Running)
2627
// conclude immediately
2728
report.SetProgress(1f);
28-
}
2929

3030
if (!queue.TryGetValue(parcel, out PooledLoadReportList queuedReport))
3131
queue[parcel] = queuedReport = new PooledLoadReportList(REPORT_POOL);

Explorer/Assets/DCL/Infrastructure/ECS/SceneLifeCycle/Systems/ControlSceneUpdateLoopSystem.cs

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
namespace ECS.SceneLifeCycle.Systems
2020
{
21-
2221
/// <summary>
2322
/// Starts the scene or changes fps of its execution
2423
/// </summary>
@@ -68,7 +67,7 @@ private void HandleNotCreatedScenes(in Entity entity, ref ScenePromise promise,
6867
if (!promise.TryConsume(World, out var result) || !result.Succeeded) return;
6968

7069
ISceneFacade scene = result.Asset!;
71-
StartScene(definitionComponent, partition, scene);
70+
StartAndUpdateSceneAsync(definitionComponent, partition, scene).Forget();
7271

7372
World.Add(entity, scene);
7473
}
@@ -80,7 +79,7 @@ private void HandleSmartWearableScenes(Entity entity, in SceneDefinitionComponen
8079
{
8180
World.Add(entity, new SmartWearableSceneStarted());
8281

83-
StartScene(definitionComponent, partition, scene);
82+
StartAndUpdateSceneAsync(definitionComponent, partition, scene).Forget();
8483
}
8584

8685
[Query]
@@ -92,42 +91,33 @@ private void ChangeSceneFPS(ref ISceneFacade sceneFacade, in PartitionComponent
9291
sceneFacade.SetTargetFPS(realmPartitionSettings.GetSceneUpdateFrequency(in partition));
9392
}
9493

95-
private void StartScene(SceneDefinitionComponent definitionComponent, PartitionComponent partition, ISceneFacade scene)
94+
private async UniTaskVoid StartAndUpdateSceneAsync(SceneDefinitionComponent definitionComponent, PartitionComponent partition, ISceneFacade scene)
9695
{
9796
int fps = realmPartitionSettings.GetSceneUpdateFrequency(partition);
98-
RunOnThreadPoolAsync().Forget();
9997

100-
// So we know the scene has started
101-
if (definitionComponent.IsPortableExperience)
102-
scenesCache.AddPortableExperienceScene(scene, definitionComponent.IpfsPath.EntityId);
103-
else
104-
scenesCache.Add(scene, definitionComponent.Parcels);
98+
try
99+
{
100+
if (definitionComponent.IsPortableExperience)
101+
scenesCache.AddPortableExperienceScene(scene, definitionComponent.IpfsPath.EntityId);
102+
else
103+
scenesCache.Add(scene, definitionComponent.Parcels);
105104

106-
ReportHub.LogProductionInfo($"Scene '{definitionComponent.Definition.GetLogSceneName()}' started");
105+
ReportHub.LogProductionInfo($"Scene '{definitionComponent.Definition.GetLogSceneName()}' started");
107106

108-
return;
107+
await DCLTask.SwitchToThreadPool();
109108

110-
async UniTaskVoid RunOnThreadPoolAsync()
111-
{
112-
try
113-
{
114-
await DCLTask.SwitchToThreadPool();
115-
116-
if (destroyCancellationToken.IsCancellationRequested) return;
109+
if (destroyCancellationToken.IsCancellationRequested) return;
117110

118111
#if !UNITY_WEBGL
119-
// Provide basic thread-pool synchronization context
120-
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); // IGNORE_LINE_WEBGL_THREAD_SAFETY_FLAG
112+
113+
// Provide basic thread-pool synchronization context
114+
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); // IGNORE_LINE_WEBGL_THREAD_SAFETY_FLAG
121115
#endif
122116

123-
// FPS is set by another system
124-
await scene.StartUpdateLoopAsync(fps, destroyCancellationToken);
125-
}
126-
catch (Exception e)
127-
{
128-
ReportHub.LogException(e, GetReportData());
129-
}
117+
await scene.StartUpdateLoopAsync(fps, destroyCancellationToken);
130118
}
119+
catch (OperationCanceledException) { }
120+
catch (Exception e) { ReportHub.LogException(e, GetReportData()); }
131121
}
132122
}
133123
}

Explorer/Assets/DCL/Infrastructure/SceneRunner/Scene/ISceneFacade.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ public interface ISceneFacade : IUniTaskAsyncDisposable, IDisposable
2121

2222
void Initialize();
2323

24-
/// <summary>
25-
/// Start an update loop with a given FPS
26-
/// </summary>
2724
UniTask StartUpdateLoopAsync(int targetFPS, CancellationToken ct);
2825

2926
/// <summary>

Explorer/Assets/DCL/Infrastructure/SceneRunner/Scene/ISceneStateProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public interface ISceneStateProvider
1515

1616
ref readonly SceneEngineStartInfo EngineStartInfo { get; }
1717

18-
void SetRunning(SceneEngineStartInfo startInfo);
18+
void Start(SceneEngineStartInfo startInfo);
1919
}
2020

2121
public static class SceneStateProviderExtensions

Explorer/Assets/DCL/Infrastructure/SceneRunner/Scene/SceneState.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ public enum SceneState : byte
1212
/// </summary>
1313
Running,
1414

15+
Starting,
16+
1517
/// <summary>
1618
/// Scene communication has broken
1719
/// </summary>

Explorer/Assets/DCL/Infrastructure/SceneRunner/Scene/SceneStateProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ public class SceneStateProvider : ISceneStateProvider
1717

1818
public ref readonly SceneEngineStartInfo EngineStartInfo => ref engineStartInfo;
1919

20-
public void SetRunning(SceneEngineStartInfo startInfo)
20+
public void Start(SceneEngineStartInfo startInfo)
2121
{
22-
State.Set(SceneState.Running);
22+
State.Set(SceneState.Starting);
2323
engineStartInfo = startInfo;
2424
TickNumber = 0;
2525
}

0 commit comments

Comments
 (0)