diff --git a/Bugsnag/Assets/Bugsnag/Runtime/BugsnagAutoInit.cs b/Bugsnag/Assets/Bugsnag/Runtime/BugsnagAutoInit.cs index 26c076da..754c5c9d 100644 --- a/Bugsnag/Assets/Bugsnag/Runtime/BugsnagAutoInit.cs +++ b/Bugsnag/Assets/Bugsnag/Runtime/BugsnagAutoInit.cs @@ -4,7 +4,7 @@ namespace BugsnagUnity public class BugsnagAutoInit { - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] static void OnBeforeSceneLoadRuntimeMethod() { var settings = Resources.Load("Bugsnag/BugsnagSettingsObject"); diff --git a/Bugsnag/Assets/Bugsnag/Runtime/Client.cs b/Bugsnag/Assets/Bugsnag/Runtime/Client.cs index c751840e..d8448630 100644 --- a/Bugsnag/Assets/Bugsnag/Runtime/Client.cs +++ b/Bugsnag/Assets/Bugsnag/Runtime/Client.cs @@ -116,7 +116,6 @@ private void SetupAdvancedExceptionInterceptor() public Client(INativeClient nativeClient) { - InitMainthreadDispatcher(); NativeClient = nativeClient; _errorBuilder = new ErrorBuilder(nativeClient); CacheManager = new CacheManager(Configuration); @@ -144,11 +143,6 @@ public Client(INativeClient nativeClient) InitLogHandlers(); } - private void InitMainthreadDispatcher() - { - MainThreadDispatchBehaviour.Instance(); - } - private bool IsUnity2019OrHigher() { var version = Application.unityVersion; @@ -384,8 +378,7 @@ private void Notify(Error[] exceptions, HandledState handledState, Func { NotifyOnMainThread(exceptions, handledState, callback,logType, correlation); }); + MainThreadDispatchBehaviour.Enqueue(() => { NotifyOnMainThread(exceptions, handledState, callback,logType, correlation); }); } catch { diff --git a/Bugsnag/Assets/Bugsnag/Runtime/Delivery.cs b/Bugsnag/Assets/Bugsnag/Runtime/Delivery.cs index 55b8601f..644c038b 100644 --- a/Bugsnag/Assets/Bugsnag/Runtime/Delivery.cs +++ b/Bugsnag/Assets/Bugsnag/Runtime/Delivery.cs @@ -91,7 +91,7 @@ public void Deliver(IPayload payload) } try { - MainThreadDispatchBehaviour.Instance().Enqueue(PushToServer(payload)); + MainThreadDispatchBehaviour.Enqueue(PushToServer(payload)); } catch { @@ -508,7 +508,7 @@ public void StartDeliveringCachedPayloads() try { _finishedCacheDeliveries.Clear(); - MainThreadDispatchBehaviour.Instance().Enqueue(DeliverCachedPayloads()); + MainThreadDispatchBehaviour.Enqueue(DeliverCachedPayloads()); } catch { diff --git a/Bugsnag/Assets/Bugsnag/Runtime/MainThreadDispatchBehaviour.cs b/Bugsnag/Assets/Bugsnag/Runtime/MainThreadDispatchBehaviour.cs index 8366f333..54183fb9 100644 --- a/Bugsnag/Assets/Bugsnag/Runtime/MainThreadDispatchBehaviour.cs +++ b/Bugsnag/Assets/Bugsnag/Runtime/MainThreadDispatchBehaviour.cs @@ -1,49 +1,50 @@ -/* -Copyright 2015 Pim de Witte All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; +using System; using System.Collections.Generic; using System.Collections; using UnityEngine; +using UnityEngine.LowLevel; -/// Author: Pim de Witte (pimdewitte.com) and contributors -/// -/// A thread-safe class which holds a queue with actions to execute on the next Update() method. It can be used to make calls to the main thread for -/// things such as UI Manipulation in Unity. It was developed for use in combination with the Firebase Unity plugin, which uses separate threads for event handling -/// namespace BugsnagUnity { - public class MainThreadDispatchBehaviour : MonoBehaviour + public class BugsnagCoroutineRunner : MonoBehaviour { + private static BugsnagCoroutineRunner _instance; - private static MainThreadDispatchBehaviour _instance; - - private static readonly Queue _executionQueue = new Queue(); + public static BugsnagCoroutineRunner Instance + { + get + { + if (_instance == null) + { + var runnerObject = new GameObject("BugsnagCoroutineRunner"); + _instance = runnerObject.AddComponent(); + DontDestroyOnLoad(runnerObject); + } + return _instance; + } + } + } + public class MainThreadDispatchBehaviour + { + private static readonly Queue _executionQueue = new Queue(); - public static MainThreadDispatchBehaviour Instance() + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + private static void InitializeLoop() { - if (_instance == null) + var playerLoop = PlayerLoop.GetCurrentPlayerLoop(); + var newSystem = new PlayerLoopSystem { - _instance = new GameObject("Bugsnag main thread dispatcher").AddComponent(); - } - return _instance; + updateDelegate = OnUpdate + }; + + var systems = new List(playerLoop.subSystemList); + systems.Insert(0, newSystem); + playerLoop.subSystemList = systems.ToArray(); + PlayerLoop.SetPlayerLoop(playerLoop); } - public void Update() + private static void OnUpdate() { lock (_executionQueue) { @@ -54,50 +55,23 @@ public void Update() } } - /// - /// Locks the queue and adds the IEnumerator to the queue - /// - /// IEnumerator function that will be executed from the main thread. - public void Enqueue(IEnumerator action) + public static void Enqueue(IEnumerator action) { lock (_executionQueue) { _executionQueue.Enqueue(() => { - StartCoroutine(action); + BugsnagCoroutineRunner.Instance.StartCoroutine(action); }); } } - /// - /// Locks the queue and adds the Action to the queue - /// - /// function that will be executed from the main thread. - public void Enqueue(Action action) + public static void Enqueue(Action action) { - Enqueue(ActionWrapper(action)); - } - IEnumerator ActionWrapper(Action a) - { - a(); - yield return null; - } - - public void EnqueueWithDelayCoroutine(Action action, float delay) - { - StartCoroutine(DelayAction(action, delay)); - } - - private IEnumerator DelayAction(Action action, float delay) - { - yield return new WaitForSeconds(delay); - action.Invoke(); - } - - private void Awake() - { - DontDestroyOnLoad(gameObject); + lock (_executionQueue) + { + _executionQueue.Enqueue(action); + } } - } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 75968f69..e62bb7e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## TBD + +### Enhancements + +- Allow the notifier to be started much earlier in the Unity lifecycle. [#862](https://github.com/bugsnag/bugsnag-unity/pull/862) + ## 8.3.1 (2024-12-09) ### Bug Fixes