##// END OF EJS Templates
Implemented PollingRunnableComponent
cin -
r202:2651cb9a4250 v2
parent child
Show More
@@ -0,0 +1,98
1 using System;
2 using System.Threading;
3 using Implab.Diagnostics;
4
5 namespace Implab.Components {
6 public class PollingRunnableComponent : RunnableComponent {
7 readonly Timer m_timer;
8 readonly Func<Func<IPromise>, IPromise> m_dispatcher;
9 readonly TimeSpan m_interval;
10
11 int m_processing;
12 Promise m_pending;
13
14 protected PollingRunnableComponent(TimeSpan interval, Func<Func<IPromise>, IPromise> dispatcher, bool initialized) : base(initialized) {
15 m_timer = new Timer(OnInternalTick);
16
17 m_interval = interval;
18 m_dispatcher = dispatcher;
19 }
20
21 protected override IPromise OnStart() {
22 m_timer.Change(TimeSpan.Zero, m_interval);
23
24 return base.OnStart();
25 }
26
27 void OnInternalTick(object state) {
28 if (StartTick()) {
29 try {
30 AwaitTick(m_dispatcher != null ? m_dispatcher(OnTick) : OnTick());
31 } catch (Exception error) {
32 HandleTickError(error);
33 }
34 }
35 }
36
37 /// <summary>
38 /// Starts the tick handler.
39 /// </summary>
40 /// <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>
41 /// <remarks>
42 /// 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.
43 /// </remarks>
44 protected virtual bool StartTick() {
45 if (State == ExecutionState.Running && Interlocked.CompareExchange(ref m_processing, 1, 0) == 0) {
46 m_pending = new Promise();
47 m_pending
48 .On(() => m_processing = 0, PromiseEventType.All)
49 .On(null, LogTickError);
50 return true;
51 }
52 return false;
53 }
54
55 protected virtual void AwaitTick(IPromise tick) {
56 if (tick == null) {
57 m_pending.Resolve();
58 } else {
59 tick.On(
60 m_pending.Resolve,
61 m_pending.Reject,
62 m_pending.CancelOperation
63 );
64 m_pending.CancellationRequested(tick.Cancel);
65 }
66 }
67
68 protected virtual void HandleTickError(Exception error) {
69 m_pending.Reject(error);
70 }
71
72 protected virtual void LogTickError(Exception error) {
73 }
74
75 protected virtual IPromise OnTick() {
76 return Promise.SUCCESS;
77 }
78
79 protected override IPromise OnStop() {
80 m_timer.Change(-1, -1);
81
82 if (m_pending != null) {
83 m_pending.Cancel();
84 return m_pending.Then(base.OnStop);
85 }
86
87 return base.OnStop();
88 }
89
90 protected override void Dispose(bool disposing, Exception lastError) {
91 if (disposing)
92 Safe.Dispose(m_timer);
93
94 base.Dispose(disposing, lastError);
95 }
96 }
97 }
98
@@ -210,7 +210,8 namespace Implab.Components {
210 210
211 211 public ExecutionState State {
212 212 get {
213 return m_stateMachine.State;
213 lock (m_stateMachine)
214 return m_stateMachine.State;
214 215 }
215 216 }
216 217
@@ -194,6 +194,7
194 194 <Compile Include="Components\LazyAndWeak.cs" />
195 195 <Compile Include="AbstractTask.cs" />
196 196 <Compile Include="AbstractTaskT.cs" />
197 <Compile Include="Components\PollingRunnableComponent.cs" />
197 198 </ItemGroup>
198 199 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
199 200 <ItemGroup />
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now