##// END OF EJS Templates
Implemented PollingRunnableComponent
Implemented PollingRunnableComponent

File last commit:

r202:2651cb9a4250 v2
r202:2651cb9a4250 v2
Show More
PollingRunnableComponent.cs
98 lines | 3.1 KiB | text/x-csharp | CSharpLexer
/ Implab / Components / PollingRunnableComponent.cs
using System;
using System.Threading;
using Implab.Diagnostics;
namespace Implab.Components {
public class PollingRunnableComponent : RunnableComponent {
readonly Timer m_timer;
readonly Func<Func<IPromise>, IPromise> m_dispatcher;
readonly TimeSpan m_interval;
int m_processing;
Promise m_pending;
protected PollingRunnableComponent(TimeSpan interval, Func<Func<IPromise>, IPromise> dispatcher, bool initialized) : base(initialized) {
m_timer = new Timer(OnInternalTick);
m_interval = interval;
m_dispatcher = dispatcher;
}
protected override IPromise OnStart() {
m_timer.Change(TimeSpan.Zero, m_interval);
return base.OnStart();
}
void OnInternalTick(object state) {
if (StartTick()) {
try {
AwaitTick(m_dispatcher != null ? m_dispatcher(OnTick) : OnTick());
} catch (Exception error) {
HandleTickError(error);
}
}
}
/// <summary>
/// Starts the tick handler.
/// </summary>
/// <returns>boolean value, true - the new tick handler may be invoked, false - a tick handler is already running or a component isn't running.</returns>
/// <remarks>
/// If the component is stopping no new handlers can be run. Every successful call to this method must be completed with either AwaitTick or HandleTickError handlers.
/// </remarks>
protected virtual bool StartTick() {
if (State == ExecutionState.Running && Interlocked.CompareExchange(ref m_processing, 1, 0) == 0) {
m_pending = new Promise();
m_pending
.On(() => m_processing = 0, PromiseEventType.All)
.On(null, LogTickError);
return true;
}
return false;
}
protected virtual void AwaitTick(IPromise tick) {
if (tick == null) {
m_pending.Resolve();
} else {
tick.On(
m_pending.Resolve,
m_pending.Reject,
m_pending.CancelOperation
);
m_pending.CancellationRequested(tick.Cancel);
}
}
protected virtual void HandleTickError(Exception error) {
m_pending.Reject(error);
}
protected virtual void LogTickError(Exception error) {
}
protected virtual IPromise OnTick() {
return Promise.SUCCESS;
}
protected override IPromise OnStop() {
m_timer.Change(-1, -1);
if (m_pending != null) {
m_pending.Cancel();
return m_pending.Then(base.OnStop);
}
return base.OnStop();
}
protected override void Dispose(bool disposing, Exception lastError) {
if (disposing)
Safe.Dispose(m_timer);
base.Dispose(disposing, lastError);
}
}
}