< Summary

Class:DCL.MessagingControllersManager
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/Scene/Messaging/MessagingControllersManager.cs
Covered lines:129
Uncovered lines:16
Coverable lines:145
Total lines:327
Line coverage:88.9% (129 of 145)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
MessagingControllersManager(...)0%110100%
Initialize()0%440100%
MarkBusesDirty()0%110100%
PopulateBusesToBeProcessed()0%20.420090%
Dispose()0%440100%
ContainsController(...)0%110100%
AddController(...)0%550100%
AddControllerIfNotExists(...)0%220100%
RemoveController(...)0%220100%
DisposeController(...)0%110100%
Enqueue(...)0%2100%
ForceEnqueueToGlobal(...)0%110100%
SetSceneReady(...)0%3.192033.33%
ProcessMessages()0%12.1412090%
ProcessBus(...)0%440100%
RefreshControllerEnabledState(...)0%6.976070%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/Scene/Messaging/MessagingControllersManager.cs

#LineLine coverage
 1using DCL.Controllers;
 2using System.Collections;
 3using System.Collections.Concurrent;
 4using System.Collections.Generic;
 5using UnityEngine;
 6
 7namespace DCL
 8{
 9    public class MessagingControllersManager : IMessagingControllersManager
 10    {
 11        public static bool VERBOSE = false;
 12
 13        private const float MAX_GLOBAL_MSG_BUDGET = 0.006f;
 14        private const float MAX_SYSTEM_MSG_BUDGET_FOR_FAR_SCENES = 0.003f;
 15
 16        private const float GLTF_BUDGET_MAX = 0.033f;
 17        private const float GLTF_BUDGET_MIN = 0.008f;
 18
 19        public const string GLOBAL_MESSAGING_CONTROLLER = "global_messaging_controller";
 20
 63621        public ConcurrentDictionary<string, MessagingController> messagingControllers { get; set; } = new ConcurrentDict
 22
 23        private Coroutine mainCoroutine;
 24
 2825        public bool hasPendingMessages => pendingMessagesCount > 0;
 26
 63627        public float timeBudgetCounter = MAX_GLOBAL_MSG_BUDGET;
 5428        public long processedInitMessagesCount { get; set; }
 13629        public int pendingMessagesCount { get; set;  }
 10830        public int pendingInitMessagesCount { get; set; }
 31
 032        public bool isRunning => mainCoroutine != null;
 33
 4234        public bool paused { get; set; }
 35
 63636        private readonly ConcurrentDictionary<string, MessagingController> globalSceneControllers = new ConcurrentDictio
 63637        private readonly List<MessagingController> sortedControllers = new List<MessagingController>();
 63638        private readonly List<MessagingBus> busesToProcess = new List<MessagingBus>();
 39        private int busesToProcessCount = 0;
 40        private int sortedControllersCount = 0;
 41
 42        private MessagingController globalController = null;
 43        private MessagingController currentSceneController = null;
 44
 45        private IMessageProcessHandler messageHandler;
 46
 190847        public MessagingControllersManager (IMessageProcessHandler messageHandler = null) { this.messageHandler = messag
 48
 49        public void Initialize()
 50        {
 62951            if ( messageHandler == null )
 62952                messageHandler = Environment.i.world.sceneController;
 53
 62954            messagingControllers[GLOBAL_MESSAGING_CONTROLLER] = new MessagingController(this, messageHandler, GLOBAL_MES
 55
 62956            if (!string.IsNullOrEmpty(GLOBAL_MESSAGING_CONTROLLER))
 62957                messagingControllers.TryGetValue(GLOBAL_MESSAGING_CONTROLLER, out globalController);
 58
 62959            Environment.i.world.sceneController.OnSortScenes += MarkBusesDirty;
 60
 62961            if (mainCoroutine == null)
 62            {
 62963                mainCoroutine = CoroutineStarter.Start(ProcessMessages());
 64            }
 62965        }
 66
 63667        bool populateBusesDirty = true;
 68
 124269        public void MarkBusesDirty() { populateBusesDirty = true; }
 70
 71        public void PopulateBusesToBeProcessed()
 72        {
 124673            lock (sortedControllers)
 124674            lock (busesToProcess)
 75            {
 124676                IWorldState worldState = Environment.i.world.state;
 124677                string currentSceneId = worldState.currentSceneId;
 124678                List<IParcelScene> scenesSortedByDistance = worldState.scenesSortedByDistance;
 79
 124680                int count = scenesSortedByDistance.Count; // we need to retrieve list count everytime because it
 81                // may change after a yield return
 82
 124683                sortedControllers.Clear();
 84
 124685                if (!string.IsNullOrEmpty(currentSceneId) && messagingControllers.ContainsKey(currentSceneId))
 086                    currentSceneController = messagingControllers[currentSceneId];
 87
 287688                for (int i = 0; i < count; i++)
 89                {
 19290                    string controllerId = scenesSortedByDistance[i].sceneData.id;
 91
 19292                    if (controllerId != currentSceneId)
 93                    {
 18494                        if (!messagingControllers.ContainsKey(controllerId))
 95                            continue;
 96
 15497                        sortedControllers.Add(messagingControllers[controllerId]);
 98                    }
 99                }
 100
 1246101                sortedControllersCount = sortedControllers.Count;
 102
 1246103                bool globalSceneControllerActive = globalSceneControllers.Count > 0;
 1246104                bool globalControllerActive = globalController != null && globalController.enabled;
 1246105                bool currentSceneControllerActive = currentSceneController != null && currentSceneController.enabled;
 106
 1246107                bool atLeastOneControllerShouldBeProcessed = globalSceneControllerActive || globalControllerActive || cu
 108
 1246109                if (!atLeastOneControllerShouldBeProcessed)
 0110                    return;
 111
 1246112                busesToProcess.Clear();
 113
 114                //-------------------------------------------------------------------------------------------
 115                // Global scenes
 1246116                using (var globalScenecontrollersIterator = globalSceneControllers.GetEnumerator())
 117                {
 1248118                    while (globalScenecontrollersIterator.MoveNext())
 119                    {
 2120                        busesToProcess.Add(globalScenecontrollersIterator.Current.Value.uiBus);
 2121                        busesToProcess.Add(globalScenecontrollersIterator.Current.Value.initBus);
 2122                        busesToProcess.Add(globalScenecontrollersIterator.Current.Value.systemBus);
 123                    }
 1246124                }
 125
 1246126                if (globalControllerActive)
 127                {
 1243128                    busesToProcess.Add(globalController.initBus);
 129                }
 130
 1246131                if (currentSceneControllerActive)
 132                {
 0133                    busesToProcess.Add(currentSceneController.initBus);
 0134                    busesToProcess.Add(currentSceneController.uiBus);
 0135                    busesToProcess.Add(currentSceneController.systemBus);
 136                }
 137
 2800138                for (int i = 0; i < sortedControllersCount; ++i)
 139                {
 154140                    MessagingController msgController = sortedControllers[i];
 141
 154142                    busesToProcess.Add(msgController.initBus);
 154143                    busesToProcess.Add(msgController.uiBus);
 144                }
 145
 2800146                for (int i = 0; i < sortedControllersCount; ++i)
 147                {
 154148                    MessagingController msgController = sortedControllers[i];
 154149                    busesToProcess.Add(msgController.systemBus);
 150                }
 151
 1246152                busesToProcessCount = busesToProcess.Count;
 1246153            }
 1246154        }
 155
 156        public void Dispose()
 157        {
 629158            if (mainCoroutine != null)
 159            {
 629160                CoroutineStarter.Stop(mainCoroutine);
 629161                mainCoroutine = null;
 162            }
 163
 629164            using (var controllersIterator = messagingControllers.GetEnumerator())
 165            {
 1258166                while (controllersIterator.MoveNext())
 167                {
 629168                    controllersIterator.Current.Value.Stop();
 629169                    DisposeController(controllersIterator.Current.Value);
 170                }
 629171            }
 172
 629173            Environment.i.world.sceneController.OnSortScenes -= PopulateBusesToBeProcessed;
 174
 629175            messagingControllers.Clear();
 629176        }
 177
 27178        public bool ContainsController(string sceneId) { return messagingControllers.ContainsKey(sceneId); }
 179
 180        public void AddController(IMessageProcessHandler messageHandler, string sceneId, bool isGlobal = false)
 181        {
 27182            if (!messagingControllers.ContainsKey(sceneId))
 183            {
 27184                messagingControllers.TryAdd(sceneId, new MessagingController(this, messageHandler, sceneId));
 185            }
 186
 27187            if (isGlobal && !string.IsNullOrEmpty(sceneId))
 188            {
 1189                messagingControllers.TryGetValue(sceneId, out MessagingController newGlobalSceneController);
 190
 1191                if (!globalSceneControllers.ContainsKey(sceneId))
 1192                    globalSceneControllers.TryAdd(sceneId, newGlobalSceneController);
 193            }
 194
 27195            PopulateBusesToBeProcessed();
 27196        }
 197
 198        public void AddControllerIfNotExists(IMessageProcessHandler messageHandler, string sceneId, bool isGlobal = fals
 199        {
 27200            if (!ContainsController(sceneId))
 27201                AddController(messageHandler, sceneId, isGlobal);
 27202        }
 203
 204        public void RemoveController(string sceneId)
 205        {
 384206            if (messagingControllers.ContainsKey(sceneId))
 207            {
 208                // In case there is any pending message from a scene being unloaded we decrease the count accordingly
 27209                pendingMessagesCount -= messagingControllers[sceneId].messagingBuses[MessagingBusType.INIT].pendingMessa
 210                                        messagingControllers[sceneId].messagingBuses[MessagingBusType.UI].pendingMessage
 211                                        messagingControllers[sceneId].messagingBuses[MessagingBusType.SYSTEM].pendingMes
 212
 27213                DisposeController(messagingControllers[sceneId]);
 27214                messagingControllers.TryRemove(sceneId, out MessagingController _);
 215            }
 216
 384217            globalSceneControllers.TryRemove(sceneId, out MessagingController _);
 384218        }
 219
 220        void DisposeController(MessagingController controller)
 221        {
 656222            controller.Stop();
 656223            controller.Dispose();
 656224        }
 225
 0226        public void Enqueue(bool isUiBus, QueuedSceneMessage_Scene queuedMessage) { messagingControllers[queuedMessage.s
 227
 54228        public void ForceEnqueueToGlobal(MessagingBusType busId, QueuedSceneMessage queuedMessage) { messagingController
 229
 230        public void SetSceneReady(string sceneId)
 231        {
 232            // Start processing SYSTEM queue
 368233            if (messagingControllers.ContainsKey(sceneId))
 234            {
 235                // Start processing SYSTEM queue
 0236                MessagingController sceneMessagingController = messagingControllers[sceneId];
 0237                sceneMessagingController.StartBus(MessagingBusType.SYSTEM);
 0238                sceneMessagingController.StartBus(MessagingBusType.UI);
 0239                sceneMessagingController.StopBus(MessagingBusType.INIT);
 240            }
 368241        }
 242
 243        IEnumerator ProcessMessages()
 244        {
 6966245            while (true)
 246            {
 7595247                if (paused)
 248                {
 0249                    yield return null;
 250
 0251                    continue;
 252                }
 253
 7595254                if (populateBusesDirty)
 255                {
 1219256                    PopulateBusesToBeProcessed();
 1219257                    populateBusesDirty = false;
 258                }
 259
 7595260                timeBudgetCounter = CommonScriptableObjects.rendererState.Get() ? MAX_GLOBAL_MSG_BUDGET : float.MaxValue
 261
 30654262                for (int i = 0; i < busesToProcessCount; ++i)
 263                {
 264                    MessagingBus bus;
 265
 7734266                    lock (busesToProcess)
 267                    {
 7734268                        bus = busesToProcess[i];
 7734269                    }
 270
 7734271                    if (ProcessBus(bus))
 272                        break;
 273                }
 274
 7595275                if (pendingInitMessagesCount == 0)
 276                {
 7593277                    AssetPromiseKeeper_GLTF.i.throttlingCounter.budgetPerFrameInMilliseconds = Mathf.Clamp(timeBudgetCou
 7593278                }
 279                else
 280                {
 2281                    AssetPromiseKeeper_GLTF.i.throttlingCounter.budgetPerFrameInMilliseconds = 0;
 282                }
 283
 7595284                yield return null;
 285            }
 286        }
 287
 288        bool ProcessBus(MessagingBus bus)
 289        {
 7734290            if (!bus.enabled || bus.pendingMessagesCount <= 0)
 7725291                return false;
 292
 9293            float startTime = Time.realtimeSinceStartup;
 294
 9295            float timeBudget = timeBudgetCounter;
 296
 297            //TODO(Brian): We should use the returning yieldReturn IEnumerator and MoveNext() it manually each frame to
 298            //             account the coroutine processing into the budget. Until we do that we just skip it.
 9299            bus.ProcessQueue(timeBudget, out _);
 9300            RefreshControllerEnabledState(bus.owner);
 301
 9302            timeBudgetCounter -= Time.realtimeSinceStartup - startTime;
 303
 9304            if (timeBudgetCounter <= 0)
 2305                return true;
 306
 7307            return false;
 308        }
 309
 310        private void RefreshControllerEnabledState(MessagingController controller)
 311        {
 9312            if (controller == null || !controller.enabled)
 0313                return;
 314
 9315            if (controller.uiBus.pendingMessagesCount != 0)
 0316                return;
 317
 9318            if (controller.initBus.pendingMessagesCount != 0)
 2319                return;
 320
 7321            if (controller.systemBus.pendingMessagesCount != 0)
 0322                return;
 323
 7324            controller.enabled = false;
 7325        }
 326    }
 327}