From ae784295e809c18173c6de42da62f1a5feabc2ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Thu, 22 Nov 2018 01:00:41 +0000 Subject: [PATCH] Add lazy initialization to AdcController MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add lazy initialization to I2cController. - Also changed DeviceCollection making it accessible as property. - Make sure that the variables do exist when being used. Using the previous code was causing issues because, on occasions, the related types could still be unresolved. - Add AdcControllerManager allowing multiple ADC controllers. - Decorate fields with DebuggerBrowsableState to hide them on debug session. Signed-off-by: José Simões --- source/Windows.Devices.Adc/AdcChannel.cs | 23 +++--- source/Windows.Devices.Adc/AdcController.cs | 70 +++++++++++++++---- .../AdcControllerManager.cs | 48 +++++++++++++ .../Windows.Devices.Adc.nfproj | 3 +- 4 files changed, 120 insertions(+), 24 deletions(-) create mode 100644 source/Windows.Devices.Adc/AdcControllerManager.cs diff --git a/source/Windows.Devices.Adc/AdcChannel.cs b/source/Windows.Devices.Adc/AdcChannel.cs index 91cf87d..9daaf33 100644 --- a/source/Windows.Devices.Adc/AdcChannel.cs +++ b/source/Windows.Devices.Adc/AdcChannel.cs @@ -13,12 +13,19 @@ namespace Windows.Devices.Adc /// public sealed class AdcChannel : IAdcChannel, IDisposable { + // this is used as the lock object + // a lock is required because multiple threads can access the channel + [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] + private readonly object _syncLock = new object(); + + [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] private readonly int _channelNumber; + + [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] private AdcController _adcController; - // this is used as the lock object - // a lock is required because multiple threads can access the AdcChannel - private object _syncLock = new object(); + [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] + private bool _disposed; internal AdcChannel(AdcController controller, int channelNumber) { @@ -63,7 +70,7 @@ public int ReadValue() lock (_syncLock) { // check if pin has been disposed - if (_disposedValue) { throw new ObjectDisposedException(); } + if (_disposed) { throw new ObjectDisposedException(); } return NativeReadValue(); } @@ -72,7 +79,7 @@ public int ReadValue() private void ThowIfDisposed() { // check if pin has been disposed - if (_disposedValue) + if (_disposed) { throw new ObjectDisposedException(); } @@ -80,8 +87,6 @@ private void ThowIfDisposed() #region IDisposable Support - private bool _disposedValue; - private void Dispose(bool disposing) { if (_adcController != null) @@ -93,7 +98,7 @@ private void Dispose(bool disposing) } - _disposedValue = true; + _disposed = true; } } @@ -104,7 +109,7 @@ public void Dispose() { lock (_syncLock) { - if (!_disposedValue) + if (!_disposed) { Dispose(true); GC.SuppressFinalize(this); diff --git a/source/Windows.Devices.Adc/AdcController.cs b/source/Windows.Devices.Adc/AdcController.cs index d728882..88e9637 100644 --- a/source/Windows.Devices.Adc/AdcController.cs +++ b/source/Windows.Devices.Adc/AdcController.cs @@ -14,27 +14,66 @@ namespace Windows.Devices.Adc /// public sealed class AdcController : IAdcController { - private readonly int _deviceId; + // this is used as the lock object + // a lock is required because multiple threads can access the AdcController + [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] + private readonly object _syncLock = new object(); + + [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] + private readonly int _controllerId; + + [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] private AdcChannelMode _channelMode; - // need to store the ADC controllers that are open - internal static Hashtable s_deviceCollection = new Hashtable(); + // backing field for DeviceCollection + [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] + private Hashtable s_deviceCollection; + + /// + /// Device collection associated with this . + /// + /// + /// This collection is for internal use only. + /// + internal Hashtable DeviceCollection + { + get + { + if (s_deviceCollection == null) + { + lock (_syncLock) + { + if (s_deviceCollection == null) + { + s_deviceCollection = new Hashtable(); + } + } + } + + return s_deviceCollection; + } + + set + { + s_deviceCollection = value; + } + } internal AdcController(string adcController) { // check if this device is already opened - if (!s_deviceCollection.Contains(adcController)) + if (!AdcControllerManager.ControllersCollection.Contains(adcController)) { // the ADC id is an ASCII string with the format 'ADCn' // need to grab 'n' from the string and convert that to the integer value from the ASCII code (do this by subtracting 48 from the char value) - _deviceId = adcController[3] - 48; + _controllerId = adcController[3] - '0'; // call native init to allow HAL/PAL inits related with ADC hardware // this is also used to check if the requested ADC actually exists NativeInit(); // add ADC controller to collection - s_deviceCollection.Add(adcController, this); + AdcControllerManager.ControllersCollection.Add(adcController, this); } else { @@ -121,18 +160,21 @@ public int ResolutionInBits { /// public static AdcController GetDefault() { - string controllers = GetDeviceSelector(); - string[] devices = controllers.Split(','); + string controllersAqs = GetDeviceSelector(); + string[] controllers = controllersAqs.Split(','); - if(devices.Length > 0) + if(controllers.Length > 0) { - if (s_deviceCollection.Contains(devices[0])) + if (AdcControllerManager.ControllersCollection.Contains(controllers[0])) { - // this is already open - return (AdcController)s_deviceCollection[devices[0]]; + // controller is already open + return (AdcController)AdcControllerManager.ControllersCollection[controllers[0]]; + } + else + { + // there is no controller yet, create one + return new AdcController(controllers[0]); } - - return new AdcController(devices[0]); } // the system has no ADC controller diff --git a/source/Windows.Devices.Adc/AdcControllerManager.cs b/source/Windows.Devices.Adc/AdcControllerManager.cs new file mode 100644 index 0000000..bf74b52 --- /dev/null +++ b/source/Windows.Devices.Adc/AdcControllerManager.cs @@ -0,0 +1,48 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +using System.Collections; + +namespace Windows.Devices.Adc +{ + internal sealed class AdcControllerManager + { + private static readonly object _syncLock = new object(); + + // backing field for ControllersCollection + // to store the controllers that are open + private static Hashtable s_controllersCollection; + + /// + /// collection. + /// + /// + /// This collection is for internal use only. + /// + internal static Hashtable ControllersCollection + { + get + { + if (s_controllersCollection == null) + { + lock (_syncLock) + { + if (s_controllersCollection == null) + { + s_controllersCollection = new Hashtable(); + } + } + } + + return s_controllersCollection; + } + + set + { + s_controllersCollection = value; + } + } + } +} diff --git a/source/Windows.Devices.Adc/Windows.Devices.Adc.nfproj b/source/Windows.Devices.Adc/Windows.Devices.Adc.nfproj index 3638996..e4a8132 100644 --- a/source/Windows.Devices.Adc/Windows.Devices.Adc.nfproj +++ b/source/Windows.Devices.Adc/Windows.Devices.Adc.nfproj @@ -54,6 +54,7 @@ + @@ -81,4 +82,4 @@ - + \ No newline at end of file