Removing Utils directory to better match namespaces

This commit is contained in:
Chris Cameron
2017-07-06 10:57:04 -04:00
parent c56d9fce3b
commit ac6ca84a8a
68 changed files with 65 additions and 65 deletions

View File

@@ -0,0 +1,67 @@
#if SIMPLSHARP
using Crestron.SimplSharp;
#else
using System.Diagnostics;
#endif
namespace ICD.Common.Utils.Timers
{
public sealed class IcdStopwatch
{
private readonly Stopwatch m_Stopwatch;
#region Properties
public long ElapsedMilliseconds { get { return m_Stopwatch.ElapsedMilliseconds; } }
public bool IsRunning { get { return m_Stopwatch.IsRunning; } }
#endregion
#region Constructors
/// <summary>
/// Constructor.
/// </summary>
public IcdStopwatch()
: this(new Stopwatch())
{
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="stopwatch"></param>
public IcdStopwatch(Stopwatch stopwatch)
{
m_Stopwatch = stopwatch;
}
public static IcdStopwatch StartNew()
{
return new IcdStopwatch(Stopwatch.StartNew());
}
#endregion
#region Methods
public void Stop()
{
m_Stopwatch.Stop();
}
public void Start()
{
m_Stopwatch.Start();
}
public void Reset()
{
m_Stopwatch.Reset();
}
#endregion
}
}

View File

@@ -0,0 +1,166 @@
using System;
using ICD.Common.EventArguments;
using ICD.Common.Utils.Extensions;
namespace ICD.Common.Utils.Timers
{
/// <summary>
/// IcdTimer provides events for time increments as well as timer elapsed.
/// </summary>
public sealed class IcdTimer : IDisposable
{
private const long DEFAULT_HEARTBEAT_INTERVAL = 500;
/// <summary>
/// Called when the timer is restarted/stopped.
/// </summary>
public event EventHandler<BoolEventArgs> OnIsRunningChanged;
/// <summary>
/// Called when the timer has elapsed.
/// </summary>
public event EventHandler OnElapsed;
/// <summary>
/// Called when the milliseconds count changes. Useful for updating UIs.
/// </summary>
public event EventHandler OnMillisecondsChanged;
private readonly IcdStopwatch m_Stopwatch;
private readonly SafeTimer m_Heartbeat;
private long m_LastHeartbeatMilliseconds;
#region Properties
/// <summary>
/// Returns true if the timer is stopped.
/// </summary>
public bool IsStopped { get { return !m_Stopwatch.IsRunning; } }
/// <summary>
/// Returns true if the timer is running.
/// </summary>
public bool IsRunning { get { return m_Stopwatch.IsRunning; } }
/// <summary>
/// Returns true if the timer has elapsed.
/// </summary>
public bool IsElapsed { get { return Milliseconds > Length; } }
/// <summary>
/// Returns the number of milliseconds that have passed since the timer started.
/// </summary>
public long Milliseconds { get { return m_Stopwatch.ElapsedMilliseconds; } }
/// <summary>
/// The number of milliseconds before the timer is elapsed.
/// </summary>
public long Length { get; private set; }
/// <summary>
/// Gets the remaining number of milliseconds until the timer is elapsed. Returns 0 if the timer has elapsed.
/// </summary>
public long Remaining { get { return Math.Max(Length - Milliseconds, 0); } }
/// <summary>
/// Gets the remaining number of seconds until the timer is elapsed. Returns 0 if the timer has elapsed.
/// </summary>
public long RemainingSeconds { get { return (long)Math.Ceiling(Remaining / 1000.0f); } }
#endregion
#region Constructors
/// <summary>
/// Constructor.
/// </summary>
public IcdTimer()
: this(DEFAULT_HEARTBEAT_INTERVAL)
{
}
/// <summary>
/// Creates an IcdTimer with the specified heartbeat interval for the internal timer.
/// This allows a finer resolution for timing than the default 500ms.
/// </summary>
/// <param name="heartbeatInterval"></param>
public IcdTimer(long heartbeatInterval)
{
m_Heartbeat = new SafeTimer(HeartbeatCallback, heartbeatInterval, heartbeatInterval);
m_Stopwatch = new IcdStopwatch();
Stop();
}
#endregion
#region Methods
/// <summary>
/// Release resources.
/// </summary>
public void Dispose()
{
OnIsRunningChanged = null;
OnElapsed = null;
OnMillisecondsChanged = null;
m_Stopwatch.Stop();
m_Heartbeat.Dispose();
}
/// <summary>
/// Restarts the timer.
/// </summary>
public void Restart(long length)
{
Length = length;
m_Stopwatch.Reset();
m_Stopwatch.Start();
RaiseOnIsRunningChanged();
}
/// <summary>
/// Stops the timer.
/// </summary>
public void Stop()
{
m_Stopwatch.Stop();
RaiseOnIsRunningChanged();
}
#endregion
#region Private Methods
/// <summary>
/// Called when the heartbeat timer elapses.
/// </summary>
private void HeartbeatCallback()
{
if (Milliseconds == m_LastHeartbeatMilliseconds)
return;
OnMillisecondsChanged.Raise(this);
if (m_LastHeartbeatMilliseconds <= Length && IsElapsed)
OnElapsed.Raise(this);
m_LastHeartbeatMilliseconds = Milliseconds;
}
/// <summary>
/// Raises the OnIsRunningChanged event.
/// </summary>
private void RaiseOnIsRunningChanged()
{
OnIsRunningChanged.Raise(this, new BoolEventArgs(IsRunning));
}
#endregion
}
}

View File

@@ -0,0 +1,100 @@
using System;
using ICD.Common.Properties;
using ICD.Common.Utils.Extensions;
namespace ICD.Common.Utils.Timers
{
/// <summary>
/// Simple class for implementing things like volume ramps, where a button has an
/// immediate effect, and then begins ramping after a brief delay.
/// </summary>
[PublicAPI]
public sealed class Repeater : IDisposable
{
/// <summary>
/// Raised on the initial repeat.
/// </summary>
[PublicAPI]
public event EventHandler OnInitialRepeat;
/// <summary>
/// Raised on each subsequent repeat.
/// </summary>
[PublicAPI]
public event EventHandler OnRepeat;
private readonly SafeTimer m_RepeatTimer;
private readonly long m_BeforeRepeat;
private readonly long m_BetweenRepeat;
#region Constructor
/// <summary>
/// Constructor.
/// </summary>
/// <param name="beforeRepeat">The delay before the second increment</param>
/// <param name="betweenRepeat">The delay between each subsequent repeat</param>
public Repeater(long beforeRepeat, long betweenRepeat)
{
m_RepeatTimer = SafeTimer.Stopped(RepeatCallback);
m_BeforeRepeat = beforeRepeat;
m_BetweenRepeat = betweenRepeat;
}
/// <summary>
/// Destructor.
/// </summary>
~Repeater()
{
Dispose();
}
#endregion
#region Methods
/// <summary>
/// Release resources.
/// </summary>
public void Dispose()
{
m_RepeatTimer.Dispose();
}
/// <summary>
/// Begin repeating.
/// </summary>
[PublicAPI]
public void Start()
{
OnInitialRepeat.Raise(this);
m_RepeatTimer.Reset(m_BeforeRepeat, m_BetweenRepeat);
}
/// <summary>
/// Stop repeating volume.
/// </summary>
[PublicAPI]
public void Stop()
{
m_RepeatTimer.Stop();
}
#endregion
#region Private Methods
/// <summary>
/// Called for every repeat.
/// </summary>
private void RepeatCallback()
{
OnRepeat.Raise(this);
}
#endregion
}
}

View File

@@ -0,0 +1,180 @@
using System;
#if SIMPLSHARP
using Crestron.SimplSharp;
#else
using System.Threading;
#endif
using ICD.Common.Services;
using ICD.Common.Services.Logging;
namespace ICD.Common.Utils.Timers
{
/// <summary>
/// SafeTimer wraps CTimer to hide some of the jank.
/// </summary>
public sealed class SafeTimer : IStateDisposable
{
#if SIMPLSHARP
private readonly CTimer m_Timer;
#else
private readonly Timer m_Timer;
private int m_DueTime, m_RepeatPeriod;
#endif
private readonly Action m_Callback;
/// <summary>
/// Returns true if this instance has been disposed.
/// </summary>
public bool IsDisposed { get; private set; }
#region Constructors
/// <summary>
/// Creates a timer that is called every repeatPeriod in milliseconds.
/// </summary>
/// <param name="callback"></param>
/// <param name="repeatPeriod"></param>
public SafeTimer(Action callback, long repeatPeriod)
: this(callback, 0, repeatPeriod)
{
}
/// <summary>
/// Creates a timer that is called in dueTime milliseconds and then every
/// repeatPeriod milliseconds afterwards.
/// </summary>
/// <param name="callback"></param>
/// <param name="dueTime"></param>
/// <param name="repeatPeriod"></param>
public SafeTimer(Action callback, long dueTime, long repeatPeriod)
{
m_Callback = callback;
#if SIMPLSHARP
m_Timer = new CTimer(SafeCallback, null, dueTime, repeatPeriod);
#else
m_DueTime = (int)dueTime;
m_RepeatPeriod = (int)repeatPeriod;
m_Timer = new Timer(SafeCallback, null, m_DueTime, m_RepeatPeriod);
#endif
}
/// <summary>
/// Creates a timer that is initially stopped.
/// </summary>
/// <param name="callback"></param>
/// <returns></returns>
public static SafeTimer Stopped(Action callback)
{
SafeTimer output = new SafeTimer(callback, 0);
output.Stop();
return output;
}
#endregion
#region Methods
/// <summary>
/// Release resources.
/// </summary>
public void Dispose()
{
Stop();
m_Timer.Dispose();
IsDisposed = true;
}
/// <summary>
/// Stops the timer.
/// </summary>
public void Stop()
{
#if SIMPLSHARP
m_Timer.Stop();
#else
m_Timer.Change(Timeout.Infinite, Timeout.Infinite);
#endif
}
/// <summary>
/// Immediately calls the callback and resets the timer
/// </summary>
public void Trigger()
{
#if SIMPLSHARP
m_Timer.Reset();
#else
m_Timer.Change(0, m_RepeatPeriod);
#endif
}
/// <summary>
/// Callback is called after the dueTime milliseconds.
/// </summary>
/// <param name="dueTime"></param>
public void Reset(long dueTime)
{
#if SIMPLSHARP
m_Timer.Reset(dueTime);
#else
m_DueTime = (int)dueTime;
m_Timer.Change(m_DueTime, m_RepeatPeriod);
#endif
}
/// <summary>
/// Callback is called after the dueTime milliseconds and every repeatPeriod milliseconds.
/// </summary>
/// <param name="dueTime"></param>
/// <param name="repeatPeriod"></param>
public void Reset(long dueTime, long repeatPeriod)
{
#if SIMPLSHARP
m_Timer.Reset(dueTime, repeatPeriod);
#else
m_DueTime = (int)dueTime;
m_RepeatPeriod = (int)repeatPeriod;
m_Timer.Change(m_DueTime, m_RepeatPeriod);
#endif
}
#endregion
#region Private Methods
/// <summary>
/// Only executes the callback if the timer has not been disposed.
/// Catches any exceptions and logs them.
/// </summary>
/// <param name="unused"></param>
private void SafeCallback(object unused)
{
// Essentially the meat of this class. There's some weirdness with the garbage collector where
// the reference to the timer will be cleared, and eventually the CTimer will call the callback
// despite being stopped/disposed.
if (m_Timer == null
#if SIMPLSHARP
|| m_Timer.Disposed
#endif
)
return;
try
{
m_Callback();
}
catch (Exception e)
{
LogException(e);
}
}
private void LogException(Exception e)
{
string message = string.Format("{0} failed to execute callback - {1}", GetType().Name, e.Message);
ServiceProvider.TryGetService<ILoggerService>().AddEntry(eSeverity.Error, e, message);
}
#endregion
}
}