diff --git a/src/Uno.UWP/Devices/Sensors/Accelerometer.Android.cs b/src/Uno.UWP/Devices/Sensors/Accelerometer.Android.cs index 3c173bb8835d..5a6d586ec43a 100644 --- a/src/Uno.UWP/Devices/Sensors/Accelerometer.Android.cs +++ b/src/Uno.UWP/Devices/Sensors/Accelerometer.Android.cs @@ -27,7 +27,7 @@ public uint ReportInterval return; } - lock (_syncLock) + lock (_readingChangedWrapper.SyncLock) { _reportInterval = value; diff --git a/src/Uno.UWP/Devices/Sensors/Accelerometer.cs b/src/Uno.UWP/Devices/Sensors/Accelerometer.cs index c84a5a9c66ad..5e55e86004d6 100644 --- a/src/Uno.UWP/Devices/Sensors/Accelerometer.cs +++ b/src/Uno.UWP/Devices/Sensors/Accelerometer.cs @@ -1,4 +1,6 @@ #if __IOS__ || __ANDROID__ || __WASM__ +#nullable enable + using System; using System.Collections.Generic; using System.Text; @@ -12,10 +14,7 @@ namespace Windows.Devices.Sensors /// public partial class Accelerometer { - private readonly static object _syncLock = new(); - - private static Accelerometer _instance; - private static bool _initializationAttempted; + private readonly static Lazy _instance = new Lazy(() => TryCreateInstance()); private readonly StartStopTypedEventWrapper _readingChangedWrapper; private readonly StartStopTypedEventWrapper _shakenWrapper; @@ -36,34 +35,17 @@ private Accelerometer() { _readingChangedWrapper = new StartStopTypedEventWrapper( () => StartReadingChanged(), - () => StopReadingChanged(), - _syncLock); + () => StopReadingChanged()); _shakenWrapper = new StartStopTypedEventWrapper( () => StartShaken(), - () => StopShaken(), - _syncLock); + () => StopShaken()); } /// /// Returns the default accelerometer. /// /// The default accelerometer or null if no integrated accelerometers are found. - public static Accelerometer GetDefault() - { - if (_initializationAttempted) - { - return _instance; - } - lock (_syncLock) - { - if (!_initializationAttempted) - { - _instance = TryCreateInstance(); - _initializationAttempted = true; - } - return _instance; - } - } + public static Accelerometer? GetDefault() => _instance.Value; /// /// Occurs each time the accelerometer reports a new sensor reading. diff --git a/src/Uno.UWP/Devices/Sensors/Accelerometer.iOS.cs b/src/Uno.UWP/Devices/Sensors/Accelerometer.iOS.cs index e3b09e9645ae..1c362c249ece 100644 --- a/src/Uno.UWP/Devices/Sensors/Accelerometer.iOS.cs +++ b/src/Uno.UWP/Devices/Sensors/Accelerometer.iOS.cs @@ -40,7 +40,7 @@ public uint ReportInterval internal static void HandleShake() { - _instance?.OnShaken(DateTimeOffset.UtcNow); + _instance.Value?.OnShaken(DateTimeOffset.UtcNow); } private static Accelerometer? TryCreateInstance() diff --git a/src/Uno.UWP/Devices/Sensors/Accelerometer.wasm.cs b/src/Uno.UWP/Devices/Sensors/Accelerometer.wasm.cs index 3b84385399b9..5f06fcec9d44 100644 --- a/src/Uno.UWP/Devices/Sensors/Accelerometer.wasm.cs +++ b/src/Uno.UWP/Devices/Sensors/Accelerometer.wasm.cs @@ -83,22 +83,22 @@ private void DetachDeviceMotion() /// 0 - needed to bind method from WASM internal static int DispatchReading(float x, float y, float z) { - if (_instance == null) + if (_instance.Value == null) { throw new InvalidOperationException("Accelerometer:DispatchReading can be called only after Accelerometer is initialized"); } var now = DateTimeOffset.UtcNow; - if ((now - _instance._lastReading).TotalMilliseconds >= _instance.ReportInterval * 0.8) + if ((now - _instance.Value._lastReading).TotalMilliseconds >= _instance.Value.ReportInterval * 0.8) { - _instance._lastReading = now; - _instance.OnReadingChanged( + _instance.Value._lastReading = now; + _instance.Value.OnReadingChanged( new AccelerometerReading( x / Gravity * -1, y / Gravity * -1, z / Gravity * -1, now)); } - _instance._shakeDetector?.OnSensorChanged(x, y, z, DateTimeOffset.UtcNow); + _instance.Value._shakeDetector?.OnSensorChanged(x, y, z, DateTimeOffset.UtcNow); return 0; } } diff --git a/src/Uno.UWP/Devices/Sensors/Barometer.Android.cs b/src/Uno.UWP/Devices/Sensors/Barometer.Android.cs index c91a9004bde8..3345e1c376e5 100644 --- a/src/Uno.UWP/Devices/Sensors/Barometer.Android.cs +++ b/src/Uno.UWP/Devices/Sensors/Barometer.Android.cs @@ -26,7 +26,7 @@ public uint ReportInterval return; } - lock (_syncLock) + lock (_readingChangedWrapper.SyncLock) { _reportInterval = value; diff --git a/src/Uno.UWP/Devices/Sensors/Barometer.cs b/src/Uno.UWP/Devices/Sensors/Barometer.cs index 32a70396bb33..f0bbfb4fff76 100644 --- a/src/Uno.UWP/Devices/Sensors/Barometer.cs +++ b/src/Uno.UWP/Devices/Sensors/Barometer.cs @@ -1,5 +1,7 @@ #if __ANDROID__ || __IOS__ +#nullable enable +using System; using Uno.Helpers; using Windows.Foundation; @@ -10,10 +12,7 @@ namespace Windows.Devices.Sensors /// public partial class Barometer { - private static readonly object _syncLock = new(); - - private static bool _initializationAttempted; - private static Barometer _instance; + private readonly static Lazy _instance = new Lazy(() => TryCreateInstance()); private readonly StartStopTypedEventWrapper _readingChangedWrapper; @@ -24,30 +23,14 @@ private Barometer() { _readingChangedWrapper = new StartStopTypedEventWrapper( () => StartReading(), - () => StopReading(), - _syncLock); + () => StopReading()); } /// /// Returns the default barometer sensor. /// /// If no barometer sensor is available, this method will return null. - public static Barometer GetDefault() - { - if (_initializationAttempted) - { - return _instance; - } - lock (_syncLock) - { - if (!_initializationAttempted) - { - _instance = TryCreateInstance(); - _initializationAttempted = true; - } - return _instance; - } - } + public static Barometer? GetDefault() => _instance.Value; /// /// Occurs each time the barometer reports a new sensor reading. diff --git a/src/Uno.UWP/Devices/Sensors/Compass.Android.cs b/src/Uno.UWP/Devices/Sensors/Compass.Android.cs index 0e2796f26e57..210d9ac11e0b 100644 --- a/src/Uno.UWP/Devices/Sensors/Compass.Android.cs +++ b/src/Uno.UWP/Devices/Sensors/Compass.Android.cs @@ -27,7 +27,7 @@ public uint ReportInterval get => _reportInterval; set { - lock (_syncLock) + lock (_readingChangedWrapper.SyncLock) { if (_reportInterval == value) { diff --git a/src/Uno.UWP/Devices/Sensors/Compass.cs b/src/Uno.UWP/Devices/Sensors/Compass.cs index f6d16aad74d0..5883cd74e467 100644 --- a/src/Uno.UWP/Devices/Sensors/Compass.cs +++ b/src/Uno.UWP/Devices/Sensors/Compass.cs @@ -1,4 +1,7 @@ #if __IOS__ || __ANDROID__ || __WASM__ +#nullable enable + +using System; using Uno.Helpers; using Windows.Foundation; @@ -10,10 +13,7 @@ namespace Windows.Devices.Sensors; /// public partial class Compass { - private readonly static object _syncLock = new(); - - private static Compass _instance; - private static bool _initializationAttempted; + private readonly static Lazy _instance = new Lazy(() => TryCreateInstance()); private readonly StartStopTypedEventWrapper _readingChangedWrapper; @@ -24,30 +24,14 @@ private Compass() { _readingChangedWrapper = new StartStopTypedEventWrapper( () => StartReadingChanged(), - () => StopReadingChanged(), - _syncLock); + () => StopReadingChanged()); } /// /// Returns the default compass. /// /// The default compass or null if no integrated compasses are found. - public static Compass GetDefault() - { - if (_initializationAttempted) - { - return _instance; - } - lock (_syncLock) - { - if (!_initializationAttempted) - { - _instance = TryCreateInstance(); - _initializationAttempted = true; - } - return _instance; - } - } + public static Compass? GetDefault() => _instance.Value; /// /// Occurs each time the compass reports a new sensor reading. diff --git a/src/Uno.UWP/Devices/Sensors/Compass.wasm.cs b/src/Uno.UWP/Devices/Sensors/Compass.wasm.cs index 36af6472176d..5a77f2198c25 100644 --- a/src/Uno.UWP/Devices/Sensors/Compass.wasm.cs +++ b/src/Uno.UWP/Devices/Sensors/Compass.wasm.cs @@ -28,7 +28,7 @@ public uint ReportInterval return; } - lock (_syncLock) + lock (_readingChangedWrapper.SyncLock) { _reportInterval = value; diff --git a/src/Uno.UWP/Devices/Sensors/Gyrometer.Android.cs b/src/Uno.UWP/Devices/Sensors/Gyrometer.Android.cs index bfffc0dd36a6..d680a82aafc7 100644 --- a/src/Uno.UWP/Devices/Sensors/Gyrometer.Android.cs +++ b/src/Uno.UWP/Devices/Sensors/Gyrometer.Android.cs @@ -27,7 +27,7 @@ public uint ReportInterval return; } - lock (_syncLock) + lock (_readingChangedWrapper.SyncLock) { _reportInterval = value; diff --git a/src/Uno.UWP/Devices/Sensors/Gyrometer.cs b/src/Uno.UWP/Devices/Sensors/Gyrometer.cs index b85b9408127c..4173ebb0a9fa 100644 --- a/src/Uno.UWP/Devices/Sensors/Gyrometer.cs +++ b/src/Uno.UWP/Devices/Sensors/Gyrometer.cs @@ -1,4 +1,7 @@ #if __IOS__ || __ANDROID__ || __WASM__ +#nullable enable + +using System; using Uno.Extensions; using Uno.Foundation.Logging; using Uno.Helpers; @@ -11,10 +14,7 @@ namespace Windows.Devices.Sensors /// public partial class Gyrometer { - private readonly static object _syncLock = new(); - - private static Gyrometer _instance; - private static bool _initializationAttempted; + private readonly static Lazy _instance = new Lazy(() => TryCreateInstance()); private readonly StartStopTypedEventWrapper _readingChangedWrapper; @@ -25,30 +25,14 @@ private Gyrometer() { _readingChangedWrapper = new StartStopTypedEventWrapper( () => StartReading(), - () => StopReading(), - _syncLock); + () => StopReading()); } /// /// Returns the default gyrometer. /// /// Null if no integrated gyrometers are found. - public static Gyrometer GetDefault() - { - if (_initializationAttempted) - { - return _instance; - } - lock (_syncLock) - { - if (!_initializationAttempted) - { - _instance = TryCreateInstance(); - _initializationAttempted = true; - } - return _instance; - } - } + public static Gyrometer? GetDefault() => _instance.Value; /// /// Occurs each time the gyrometer reports the current sensor reading. diff --git a/src/Uno.UWP/Devices/Sensors/Gyrometer.wasm.cs b/src/Uno.UWP/Devices/Sensors/Gyrometer.wasm.cs index c79d732b6359..87b637d27c31 100644 --- a/src/Uno.UWP/Devices/Sensors/Gyrometer.wasm.cs +++ b/src/Uno.UWP/Devices/Sensors/Gyrometer.wasm.cs @@ -47,15 +47,15 @@ private void StopReading() [JSExport] internal static int DispatchReading(float x, float y, float z) { - if (_instance == null) + if (_instance.Value == null) { throw new InvalidOperationException("Gyrometer:DispatchReading can be called only after Gyrometer is initialized"); } var now = DateTimeOffset.UtcNow; - if ((now - _instance._lastReading).TotalMilliseconds >= _instance.ReportInterval * 0.8) + if ((now - _instance.Value._lastReading).TotalMilliseconds >= _instance.Value.ReportInterval * 0.8) { - _instance._lastReading = now; - _instance.OnReadingChanged( + _instance.Value._lastReading = now; + _instance.Value.OnReadingChanged( new GyrometerReading( x * SensorConstants.RadToDeg, y * SensorConstants.RadToDeg, diff --git a/src/Uno.UWP/Devices/Sensors/Magnetometer.Android.cs b/src/Uno.UWP/Devices/Sensors/Magnetometer.Android.cs index e05155bd701e..f4fd1845d0ed 100644 --- a/src/Uno.UWP/Devices/Sensors/Magnetometer.Android.cs +++ b/src/Uno.UWP/Devices/Sensors/Magnetometer.Android.cs @@ -27,7 +27,7 @@ public uint ReportInterval return; } - lock (_syncLock) + lock (_readingChangedWrapper.SyncLock) { _reportInterval = value; diff --git a/src/Uno.UWP/Devices/Sensors/Magnetometer.cs b/src/Uno.UWP/Devices/Sensors/Magnetometer.cs index 512ea991b0f6..93422c530acc 100644 --- a/src/Uno.UWP/Devices/Sensors/Magnetometer.cs +++ b/src/Uno.UWP/Devices/Sensors/Magnetometer.cs @@ -1,4 +1,6 @@ #if __IOS__ || __ANDROID__ || __WASM__ +#nullable enable + using System; using System.Collections.Generic; using System.Linq; @@ -14,10 +16,7 @@ namespace Windows.Devices.Sensors /// public partial class Magnetometer { - private readonly static object _syncLock = new(); - - private static Magnetometer _instance; - private static bool _initializationAttempted; + private readonly static Lazy _instance = new Lazy(() => TryCreateInstance()); private readonly StartStopTypedEventWrapper _readingChangedWrapper; @@ -28,30 +27,14 @@ private Magnetometer() { _readingChangedWrapper = new StartStopTypedEventWrapper( () => StartReading(), - () => StopReading(), - _syncLock); + () => StopReading()); } /// /// Returns the default magnetometer. /// /// The default magnetometer. - public static Magnetometer GetDefault() - { - if (_initializationAttempted) - { - return _instance; - } - lock (_syncLock) - { - if (!_initializationAttempted) - { - _instance = TryCreateInstance(); - _initializationAttempted = true; - } - return _instance; - } - } + public static Magnetometer? GetDefault() => _instance.Value; /// /// Occurs each time the compass reports a new sensor reading. diff --git a/src/Uno.UWP/Devices/Sensors/Magnetometer.wasm.cs b/src/Uno.UWP/Devices/Sensors/Magnetometer.wasm.cs index c68a68a1a3ad..ac44babd54b5 100644 --- a/src/Uno.UWP/Devices/Sensors/Magnetometer.wasm.cs +++ b/src/Uno.UWP/Devices/Sensors/Magnetometer.wasm.cs @@ -47,15 +47,15 @@ private void StopReading() [JSExport] internal static int DispatchReading(float x, float y, float z) { - if (_instance == null) + if (_instance.Value == null) { throw new InvalidOperationException("Magnetometer:DispatchReading can be called only after Magnetometer is initialized"); } var now = DateTimeOffset.UtcNow; - if ((now - _instance._lastReading).TotalMilliseconds >= _instance.ReportInterval * 0.8) + if ((now - _instance.Value._lastReading).TotalMilliseconds >= _instance.Value.ReportInterval * 0.8) { - _instance._lastReading = now; - _instance.OnReadingChanged( + _instance.Value._lastReading = now; + _instance.Value.OnReadingChanged( new MagnetometerReading( x, y, diff --git a/src/Uno.UWP/Devices/Sensors/Pedometer.Android.cs b/src/Uno.UWP/Devices/Sensors/Pedometer.Android.cs index 7a478e6d4c0f..12fae2b6ef5d 100644 --- a/src/Uno.UWP/Devices/Sensors/Pedometer.Android.cs +++ b/src/Uno.UWP/Devices/Sensors/Pedometer.Android.cs @@ -26,7 +26,7 @@ public uint ReportInterval return; } - lock (_syncLock) + lock (_readingChangedWrapper.SyncLock) { _reportInterval = value; diff --git a/src/Uno.UWP/Devices/Sensors/Pedometer.cs b/src/Uno.UWP/Devices/Sensors/Pedometer.cs index 6d5714535b18..8d01203a69f0 100644 --- a/src/Uno.UWP/Devices/Sensors/Pedometer.cs +++ b/src/Uno.UWP/Devices/Sensors/Pedometer.cs @@ -1,4 +1,6 @@ #if __IOS__ || __ANDROID__ +#nullable enable + using System; using System.Threading.Tasks; using Uno.Helpers; @@ -12,10 +14,7 @@ namespace Windows.Devices.Sensors /// public partial class Pedometer { - private readonly static object _syncLock = new(); - - private static bool _initializationAttempted; - private static Task _instanceTask; + private readonly static Lazy> _instance = new Lazy>(() => Task.Run(() => TryCreateInstance())); private readonly StartStopTypedEventWrapper _readingChangedWrapper; @@ -26,28 +25,12 @@ private Pedometer() { _readingChangedWrapper = new StartStopTypedEventWrapper( () => StartReading(), - () => StopReading(), - _syncLock); + () => StopReading()); } - public static IAsyncOperation GetDefaultAsync() => GetDefaultImplAsync().AsAsyncOperation(); + public static IAsyncOperation GetDefaultAsync() => GetDefaultImplAsync().AsAsyncOperation(); - private static async Task GetDefaultImplAsync() - { - if (_initializationAttempted) - { - return await _instanceTask; - } - lock (_syncLock) - { - if (!_initializationAttempted) - { - _instanceTask = Task.Run(() => TryCreateInstance()); - _initializationAttempted = true; - } - } - return await _instanceTask; - } + private static async Task GetDefaultImplAsync() => await _instance.Value; public event TypedEventHandler ReadingChanged { diff --git a/src/Uno.UWP/Devices/Sensors/SimpleOrientationSensor.cs b/src/Uno.UWP/Devices/Sensors/SimpleOrientationSensor.cs index 884429fa0999..76e82327a1cf 100644 --- a/src/Uno.UWP/Devices/Sensors/SimpleOrientationSensor.cs +++ b/src/Uno.UWP/Devices/Sensors/SimpleOrientationSensor.cs @@ -1,3 +1,5 @@ +#nullable enable + using System; using Windows.UI.Core; using Windows.Foundation; @@ -10,9 +12,7 @@ public partial class SimpleOrientationSensor private readonly StartStopTypedEventWrapper _orientationChangedWrapper; #region Static - private static SimpleOrientationSensor _instance; - private static bool _initialized; - private readonly static object _syncLock = new(); + private readonly static Lazy _instance = new Lazy(() => TryCreateInstance()); /// /// Gets the default simple orientation sensor. @@ -20,26 +20,9 @@ public partial class SimpleOrientationSensor /// /// The default simple orientation sensor or null if no simple orientation sensors are found. /// - public static SimpleOrientationSensor GetDefault() - { - if (_initialized) - { - return _instance; - } - - lock (_syncLock) - { - if (!_initialized) - { - _instance = TryCreateInstance(); - _initialized = true; - } - - return _instance; - } - } + public static SimpleOrientationSensor? GetDefault() => _instance.Value; - private static partial SimpleOrientationSensor TryCreateInstance(); + private static partial SimpleOrientationSensor? TryCreateInstance(); #endregion partial void StartListeningOrientationChanged(); @@ -57,8 +40,7 @@ private SimpleOrientationSensor() { _orientationChangedWrapper = new StartStopTypedEventWrapper( () => StartListeningOrientationChanged(), - () => StopListeningOrientationChanged(), - _syncLock); + () => StopListeningOrientationChanged()); Initialize(); } @@ -69,7 +51,7 @@ private SimpleOrientationSensor() /// Gets the device identifier. /// [Uno.NotImplemented] - public string DeviceId { get; } + public string DeviceId { get; } = string.Empty; /// /// Gets or sets the transformation that needs to be applied to sensor data. Transformations to be applied are tied to the display orientation with which to align the sensor data.