Skip to content
This repository has been archived by the owner on Apr 19, 2022. It is now read-only.

Commit

Permalink
Add lazy initialization to AdcController
Browse files Browse the repository at this point in the history
- 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 <[email protected]>
  • Loading branch information
josesimoes committed Nov 27, 2018
1 parent 2945ad3 commit 9324915
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 24 deletions.
23 changes: 14 additions & 9 deletions source/Windows.Devices.Adc/AdcChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,19 @@ namespace Windows.Devices.Adc
/// </summary>
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)
{
Expand Down Expand Up @@ -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();
}
Expand All @@ -72,16 +79,14 @@ public int ReadValue()
private void ThowIfDisposed()
{
// check if pin has been disposed
if (_disposedValue)
if (_disposed)
{
throw new ObjectDisposedException();
}
}

#region IDisposable Support

private bool _disposedValue;

private void Dispose(bool disposing)
{
if (_adcController != null)
Expand All @@ -93,7 +98,7 @@ private void Dispose(bool disposing)

}

_disposedValue = true;
_disposed = true;
}
}

Expand All @@ -104,7 +109,7 @@ public void Dispose()
{
lock (_syncLock)
{
if (!_disposedValue)
if (!_disposed)
{
Dispose(true);
GC.SuppressFinalize(this);
Expand Down
75 changes: 61 additions & 14 deletions source/Windows.Devices.Adc/AdcController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,66 @@ namespace Windows.Devices.Adc
/// </summary>
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;

/// <summary>
/// Device collection associated with this <see cref="AdcController"/>.
/// </summary>
/// <remarks>
/// This collection is for internal use only.
/// </remarks>
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
{
Expand Down Expand Up @@ -121,18 +160,26 @@ public int ResolutionInBits {
/// </returns>
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]))
//////////////////////////////////////////////////////////////////
// note that, by design, the default controller is //
// the first one in the collection returned from the native end //
//////////////////////////////////////////////////////////////////

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
Expand Down
48 changes: 48 additions & 0 deletions source/Windows.Devices.Adc/AdcControllerManager.cs
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// <see cref="AdcController"/> collection.
/// </summary>
/// <remarks>
/// This collection is for internal use only.
/// </remarks>
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;
}
}
}
}
3 changes: 2 additions & 1 deletion source/Windows.Devices.Adc/Windows.Devices.Adc.nfproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<Compile Include="AdcChannel.cs" />
<Compile Include="AdcChannelMode.cs" />
<Compile Include="AdcController.cs" />
<Compile Include="AdcControllerManager.cs" />
<Compile Include="IAdcChannel.cs" />
<Compile Include="IAdcController.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down Expand Up @@ -81,4 +82,4 @@
</PropertyGroup>
<Error Condition="!Exists('..\packages\Nerdbank.GitVersioning.2.2.33\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Nerdbank.GitVersioning.2.2.33\build\Nerdbank.GitVersioning.targets'))" />
</Target>
</Project>
</Project>

0 comments on commit 9324915

Please sign in to comment.