annotate Implab/Components/PollingComponent.cs @ 209:a867536c68fc v2

Bound promise to CancellationToken Added new states to ExecutionSate enum. Added Safe.Guard() method to handle cleanup of the result of the promise
author cin
date Wed, 16 Nov 2016 03:06:08 +0300
parents 7d07503621fe
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
203
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
1 using System;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
2 using System.Threading;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
3 using Implab.Diagnostics;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
4
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
5 namespace Implab.Components {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
6 public class PollingComponent : RunnableComponent {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
7 readonly Timer m_timer;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
8 readonly Func<Func<ICancellationToken, IPromise>, IPromise> m_dispatcher;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
9 readonly TimeSpan m_interval;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
10
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
11 readonly object m_lock = new object();
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
12
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
13 ActionTask m_pending;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
14
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
15 protected PollingComponent(TimeSpan interval, Func<Func<ICancellationToken, IPromise>, IPromise> dispatcher, bool initialized) : base(initialized) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
16 m_timer = new Timer(OnInternalTick);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
17
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
18 m_interval = interval;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
19 m_dispatcher = dispatcher;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
20 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
21
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
22 protected override IPromise OnStart() {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
23 m_timer.Change(TimeSpan.Zero, m_interval);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
24
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
25 return base.OnStart();
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
26 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
27
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
28 void OnInternalTick(object state) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
29 if (StartTick()) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
30 try {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
31 if (m_dispatcher != null) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
32 var result = m_dispatcher(OnTick);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
33 m_pending.CancellationRequested(result.Cancel);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
34 AwaitTick(result);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
35 } else {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
36 AwaitTick(OnTick(m_pending));
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
37 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
38 } catch (Exception error) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
39 HandleTickError(error);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
40 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
41 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
42 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
43
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
44 /// <summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
45 /// Checks wheather there is no running handler in the component and marks that the handler is starting.
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
46 /// </summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
47 /// <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>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
48 /// <remarks>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
49 /// 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.
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
50 /// </remarks>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
51 protected virtual bool StartTick() {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
52 lock (m_lock) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
53 if (State != ExecutionState.Running || m_pending != null)
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
54 return false;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
55 // actually the component may be in a not running state here (stopping, disposed or what ever),
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
56 // but OnStop method also locks on the same object and will handle operation in m_pending
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
57 m_pending = new ActionTask(
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
58 () => {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
59 // only one operation is running, it's safe to assing m_pending from it
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
60 m_pending = null;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
61 },
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
62 ex => {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
63 try {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
64 OnTickError(ex);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
65 // Analysis disable once EmptyGeneralCatchClause
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
66 } catch {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
67 } finally {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
68 m_pending = null;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
69 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
70 // suppress error
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
71 },
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
72 ex => {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
73 try {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
74 OnTickCancel(ex);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
75 // Analysis disable once EmptyGeneralCatchClause
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
76 } catch {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
77 } finally {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
78 m_pending = null;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
79 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
80 // supress cancellation
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
81 },
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
82 false
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
83 );
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
84 return true;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
85 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
86 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
87
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
88 /// <summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
89 /// Awaits the tick.
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
90 /// </summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
91 /// <param name="tick">Tick.</param>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
92 /// <remarks>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
93 /// This method is called only after StartTick method and m_pending will hold the promise which should be fulfilled.
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
94 /// </remarks>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
95 void AwaitTick(IPromise tick) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
96 if (tick == null) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
97 m_pending.Resolve();
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
98 } else {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
99 tick.On(
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
100 m_pending.Resolve,
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
101 m_pending.Reject,
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
102 m_pending.CancelOperation
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
103 );
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
104 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
105 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
106
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
107 /// <summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
108 /// Handles the tick error.
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
109 /// </summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
110 /// <remarks>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
111 /// This method is called only after StartTick method and m_pending will hold the promise which should be fulfilled.
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
112 /// </remarks>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
113 void HandleTickError(Exception error) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
114 m_pending.Reject(error);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
115 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
116
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
117 protected virtual void OnTickError(Exception error) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
118 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
119
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
120 protected virtual void OnTickCancel(Exception error) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
121 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
122
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
123 /// <summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
124 /// Invoked when the timer ticks, use this method to implement your logic
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
125 /// </summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
126 protected virtual IPromise OnTick(ICancellationToken cancellationToken) {
205
8200ab154c8a Added ResetState to RunnableComponent to reset in case of failure
cin
parents: 203
diff changeset
127 return Promise.Success;
203
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
128 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
129
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
130 protected override IPromise OnStop() {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
131 m_timer.Change(-1, -1);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
132
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
133 // the component is in the stopping state
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
134 lock (m_lock) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
135 // after this lock no more pending operations could be created
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
136 var pending = m_pending;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
137 // m_pending could be fulfilled and set to null already
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
138 if (pending != null) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
139 pending.Cancel();
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
140 return pending.Then(base.OnStop);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
141 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
142 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
143
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
144 return base.OnStop();
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
145 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
146
208
7d07503621fe RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents: 205
diff changeset
147 protected override void Dispose(bool disposing) {
203
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
148 if (disposing)
208
7d07503621fe RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents: 205
diff changeset
149 m_timer.Dispose();
203
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
150
208
7d07503621fe RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents: 205
diff changeset
151 base.Dispose(disposing);
203
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
152 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
153 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
154 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
diff changeset
155