Make further properties multi-client and thread-safe
Move MovingPrimary, MovingSecondary, EarliestNonSlewingTime to SharedResources, make all new properties thread-safe (atomic) operations.
This commit is contained in:
@@ -146,6 +146,10 @@
|
||||
<Compile Include="ProfileProperties.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="TelescopeList.cs" />
|
||||
<Compile Include="ThreadSafeBool.cs" />
|
||||
<Compile Include="ThreadSafeDateTime.cs" />
|
||||
<Compile Include="ThreadSafeEnum.cs" />
|
||||
<Compile Include="ThreadSafeNullableDouble.cs" />
|
||||
<Compile Include="Win32Utilities.cs" />
|
||||
<Compile Include="Wrapper\IProfileWrapper.cs" />
|
||||
<Compile Include="Wrapper\SharedResourcesWrapper.cs" />
|
||||
|
||||
@@ -19,6 +19,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using ASCOM.DeviceInterface;
|
||||
using ASCOM.Meade.net.Wrapper;
|
||||
@@ -245,7 +246,7 @@ namespace ASCOM.Meade.net
|
||||
private const string HandShakeDefault = "None";
|
||||
private const string ParityDefault = "None";
|
||||
private const string SendDateTimeDefault = "false";
|
||||
private static string ParkedBehaviourDefault = "No Coordinates";
|
||||
private const string ParkedBehaviourDefault = "No Coordinates";
|
||||
private const string ParkedAltDefault = "0";
|
||||
private const string ParkedAzimuthDefault = "180";
|
||||
|
||||
@@ -501,22 +502,78 @@ namespace ASCOM.Meade.net
|
||||
ParkedPosition = parkedPosition;
|
||||
}
|
||||
|
||||
public static bool IsParked { get; private set; }
|
||||
private static readonly ThreadSafeBool _isParked = false;
|
||||
public static bool IsParked
|
||||
{
|
||||
get => _isParked;
|
||||
private set => _isParked.Set(value);
|
||||
}
|
||||
|
||||
public static ParkedPosition ParkedPosition { get; private set; }
|
||||
private static ParkedPosition _parkedPosition;
|
||||
public static ParkedPosition ParkedPosition
|
||||
{
|
||||
get => _parkedPosition;
|
||||
private set => Interlocked.Exchange(ref _parkedPosition, value);
|
||||
}
|
||||
|
||||
private static readonly ThreadSafeEnum<PierSide> _sideOfPier = PierSide.pierUnknown;
|
||||
/// <summary>
|
||||
/// Start with <see cref="PierSide.pierUnknown"/>.
|
||||
/// As we do not know the physical declination axis position, we have to keep track manually.
|
||||
/// </summary>
|
||||
public static PierSide SideOfPier { get; internal set; } = PierSide.pierUnknown;
|
||||
public static PierSide SideOfPier
|
||||
{
|
||||
get => _sideOfPier;
|
||||
internal set => _sideOfPier.Set(value);
|
||||
}
|
||||
|
||||
public static double? TargetRightAscension { get; internal set; }
|
||||
private static readonly ThreadSafeNullableDouble _targetRightAscension = null as double?;
|
||||
public static double? TargetRightAscension
|
||||
{
|
||||
get => _targetRightAscension;
|
||||
internal set => _targetRightAscension.Set(value);
|
||||
}
|
||||
|
||||
public static double? TargetDeclination { get; internal set; }
|
||||
private static readonly ThreadSafeNullableDouble _targetDeclination = null as double?;
|
||||
public static double? TargetDeclination
|
||||
{
|
||||
get => _targetDeclination;
|
||||
internal set => _targetDeclination.Set(value);
|
||||
}
|
||||
|
||||
public static short SlewSettleTime { get; internal set; }
|
||||
private static int _slewSettleTime;
|
||||
public static short SlewSettleTime
|
||||
{
|
||||
get => Convert.ToInt16(_slewSettleTime);
|
||||
internal set => Interlocked.Exchange(ref _slewSettleTime, value);
|
||||
}
|
||||
|
||||
public static bool IsLongFormat { get; internal set; }
|
||||
private static readonly ThreadSafeBool _isLongFormat = false;
|
||||
public static bool IsLongFormat
|
||||
{
|
||||
get => _isLongFormat;
|
||||
internal set => _isLongFormat.Set(value);
|
||||
}
|
||||
|
||||
private static readonly ThreadSafeBool _movingPrimary = false;
|
||||
public static bool MovingPrimary
|
||||
{
|
||||
get => _movingPrimary;
|
||||
internal set => _movingPrimary.Set(value);
|
||||
}
|
||||
|
||||
private static readonly ThreadSafeBool _movingSecondary = false;
|
||||
public static bool MovingSecondary
|
||||
{
|
||||
get => _movingSecondary;
|
||||
internal set => _movingSecondary.Set(value);
|
||||
}
|
||||
|
||||
private static readonly ThreadSafeDateTime _earliestNonSlewingTime = DateTime.MinValue;
|
||||
public static DateTime EarliestNonSlewingTime
|
||||
{
|
||||
get => _earliestNonSlewingTime;
|
||||
internal set => _earliestNonSlewingTime.Set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Threading;
|
||||
|
||||
namespace ASCOM.Meade.net
|
||||
{
|
||||
public class ThreadSafeBool
|
||||
{
|
||||
private object _value;
|
||||
|
||||
public ThreadSafeBool(in bool value) => _value = value;
|
||||
|
||||
public void Set(in bool value) => Interlocked.Exchange(ref _value, value);
|
||||
|
||||
public static implicit operator ThreadSafeBool(in bool value) => new ThreadSafeBool(value);
|
||||
|
||||
public static implicit operator bool(ThreadSafeBool @this) => (bool)@this._value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace ASCOM.Meade.net
|
||||
{
|
||||
public class ThreadSafeDateTime
|
||||
{
|
||||
private long _value;
|
||||
|
||||
public ThreadSafeDateTime(in DateTime value) => _value = DateTimeToLong(value);
|
||||
|
||||
public void Set(in DateTime value) => Interlocked.Exchange(ref _value, DateTimeToLong(value));
|
||||
|
||||
private static long DateTimeToLong(in DateTime value) => value.ToUniversalTime().Ticks;
|
||||
|
||||
public static implicit operator ThreadSafeDateTime(in DateTime value) => new ThreadSafeDateTime(value);
|
||||
|
||||
public static implicit operator DateTime(ThreadSafeDateTime @this) => new DateTime(Interlocked.Read(ref @this._value), DateTimeKind.Utc);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace ASCOM.Meade.net
|
||||
{
|
||||
public class ThreadSafeEnum<T>
|
||||
where T: struct, Enum
|
||||
{
|
||||
private long _value;
|
||||
|
||||
public ThreadSafeEnum(T value) => _value = EnumToLong(value);
|
||||
|
||||
public void Set(T value) => Interlocked.Exchange(ref _value, EnumToLong(value));
|
||||
|
||||
private static long EnumToLong(T value) => Convert.ToInt64(value);
|
||||
|
||||
public static implicit operator ThreadSafeEnum<T>(T value) => new ThreadSafeEnum<T>(value);
|
||||
|
||||
public static implicit operator T(ThreadSafeEnum<T> @this) => (T) Enum.ToObject(typeof(T), Interlocked.Read(ref @this._value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace ASCOM.Meade.net
|
||||
{
|
||||
public class ThreadSafeNullableDouble
|
||||
{
|
||||
private long _value;
|
||||
|
||||
public ThreadSafeNullableDouble(in double? value) => _value = NullableDoubleToLong(value);
|
||||
|
||||
public void Set(in double? value) => Interlocked.Exchange(ref _value, NullableDoubleToLong(value));
|
||||
|
||||
private static long NullableDoubleToLong(in double? value) => BitConverter.DoubleToInt64Bits(value ?? double.NaN);
|
||||
|
||||
public static implicit operator ThreadSafeNullableDouble(in double? value) => new ThreadSafeNullableDouble(value);
|
||||
|
||||
public static implicit operator double?(ThreadSafeNullableDouble @this)
|
||||
{
|
||||
var doubleValue = BitConverter.Int64BitsToDouble(Interlocked.Read(ref @this._value));
|
||||
return double.IsNaN(doubleValue) ? null as double? : doubleValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,12 @@ namespace ASCOM.Meade.net.Wrapper
|
||||
short SlewSettleTime { get; set; }
|
||||
|
||||
bool IsLongFormat { get; set; }
|
||||
|
||||
bool MovingPrimary { get; set; }
|
||||
|
||||
bool MovingSecondary { get; set; }
|
||||
|
||||
DateTime EarliestNonSlewingTime { get; set; }
|
||||
}
|
||||
|
||||
public class SharedResourcesWrapper : ISharedResourcesWrapper
|
||||
@@ -151,5 +157,23 @@ namespace ASCOM.Meade.net.Wrapper
|
||||
get => SharedResources.IsLongFormat;
|
||||
set => SharedResources.IsLongFormat = value;
|
||||
}
|
||||
|
||||
public bool MovingPrimary
|
||||
{
|
||||
get => SharedResources.MovingPrimary;
|
||||
set => SharedResources.MovingPrimary = value;
|
||||
}
|
||||
|
||||
public bool MovingSecondary
|
||||
{
|
||||
get => SharedResources.MovingSecondary;
|
||||
set => SharedResources.MovingSecondary = value;
|
||||
}
|
||||
|
||||
public DateTime EarliestNonSlewingTime
|
||||
{
|
||||
get => SharedResources.EarliestNonSlewingTime;
|
||||
set => SharedResources.EarliestNonSlewingTime = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user