annotate Implab/AbstractEvent.cs @ 187:dd4a3590f9c6 ref20160224

Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler Any unhandled OperationCanceledException will cause the promise cancelation
author cin
date Tue, 19 Apr 2016 17:35:20 +0300
parents 75103928da09
children d6fe09f5592c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
1 using System;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
2 using Implab.Parallels;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
3 using System.Threading;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
4 using System.Reflection;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
5
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
6 namespace Implab {
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
7 public abstract class AbstractEvent<THandler> : ICancellationToken, ICancellable {
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
8
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
9 const int UNRESOLVED_SATE = 0;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
10 const int TRANSITIONAL_STATE = 1;
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
11 protected const int SUCCEEDED_STATE = 2;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
12 protected const int REJECTED_STATE = 3;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
13 protected const int CANCELLED_STATE = 4;
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
14
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
15 const int CANCEL_NOT_REQUESTED = 0;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
16 const int CANCEL_REQUESTING = 1;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
17 const int CANCEL_REQUESTED = 2;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
18
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
19 const int RESERVED_HANDLERS_COUNT = 4;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
20
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
21 int m_state;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
22 Exception m_error;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
23 int m_handlersCount;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
24
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
25 //readonly THandler[] m_handlers = new THandler[RESERVED_HANDLERS_COUNT];
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
26 THandler[] m_handlers;
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
27 MTQueue<THandler> m_extraHandlers;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
28 int m_handlerPointer = -1;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
29 int m_handlersCommited;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
30
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
31 int m_cancelRequest;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
32 Exception m_cancelationReason;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
33 MTQueue<Action<Exception>> m_cancelationHandlers;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
34
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
35
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
36 #region state managment
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
37 bool BeginTransit() {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
38 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
39 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
40
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
41 void CompleteTransit(int state) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
42 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
43 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
44 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
45
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
46 void WaitTransition() {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
47 while (m_state == TRANSITIONAL_STATE) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
48 Thread.MemoryBarrier();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
49 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
50 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
51
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
52 protected bool BeginSetResult() {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
53 if (!BeginTransit()) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
54 WaitTransition();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
55 if (m_state != CANCELLED_STATE)
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
56 throw new InvalidOperationException("The promise is already resolved");
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
57 return false;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
58 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
59 return true;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
60 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
61
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
62 protected void EndSetResult() {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
63 CompleteTransit(SUCCEEDED_STATE);
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
64 Signal();
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
65 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
66
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
67
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
68
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
69 /// <summary>
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
70 /// Выполняет обещание, сообщая об ошибке
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
71 /// </summary>
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
72 /// <remarks>
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
73 /// Поскольку обещание должно работать в многопточной среде, при его выполнении сразу несколько потоков
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
74 /// могу вернуть ошибку, при этом только первая будет использована в качестве результата, остальные
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
75 /// будут проигнорированы.
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
76 /// </remarks>
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
77 /// <param name="error">Исключение возникшее при выполнении операции</param>
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
78 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
79 protected void SetError(Exception error) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
80 if (BeginTransit()) {
186
75103928da09 working on cancelation and error handling
cin
parents: 185
diff changeset
81 m_error = error;
75103928da09 working on cancelation and error handling
cin
parents: 185
diff changeset
82 CompleteTransit(REJECTED_STATE);
185
822aab37b107 runnable component, work in progress
cin
parents: 160
diff changeset
83
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
84 Signal();
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
85 } else {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
86 WaitTransition();
186
75103928da09 working on cancelation and error handling
cin
parents: 185
diff changeset
87 if (m_state == SUCCEEDED_STATE)
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
88 throw new InvalidOperationException("The promise is already resolved");
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
89 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
90 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
91
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
92 /// <summary>
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
93 /// Отменяет операцию, если это возможно.
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
94 /// </summary>
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
95 /// <remarks>Для определения была ли операция отменена следует использовать свойство <see cref="IsCancelled"/>.</remarks>
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
96 protected void SetCancelled(Exception reason) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
97 if (BeginTransit()) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
98 m_error = reason;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
99 CompleteTransit(CANCELLED_STATE);
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
100 Signal();
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
101 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
102 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
103
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
104 protected abstract void SignalHandler(THandler handler, int signal);
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
105
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
106 void Signal() {
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
107 var hp = m_handlerPointer;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
108 var slot = hp +1 ;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
109 while (slot < m_handlersCommited) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
110 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
111 SignalHandler(m_handlers[slot], m_state);
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
112 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
113 hp = m_handlerPointer;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
114 slot = hp +1 ;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
115 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
116
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
117
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
118 if (m_extraHandlers != null) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
119 THandler handler;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
120 while (m_extraHandlers.TryDequeue(out handler))
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
121 SignalHandler(handler, m_state);
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
122 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
123 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
124
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
125 #endregion
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
126
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
127 protected abstract Signal GetResolveSignal();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
128
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
129 #region synchronization traits
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
130 protected void WaitResult(int timeout) {
148
e6d4b41f0101 fixed timeout handling in promises
cin
parents: 145
diff changeset
131 if (!(IsResolved || GetResolveSignal().Wait(timeout)))
e6d4b41f0101 fixed timeout handling in promises
cin
parents: 145
diff changeset
132 throw new TimeoutException();
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
133
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
134 switch (m_state) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
135 case SUCCEEDED_STATE:
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
136 return;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
137 case CANCELLED_STATE:
186
75103928da09 working on cancelation and error handling
cin
parents: 185
diff changeset
138 throw new OperationCanceledException("The operation has been cancelled", m_error);
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
139 case REJECTED_STATE:
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
140 throw new TargetInvocationException(m_error);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
141 default:
186
75103928da09 working on cancelation and error handling
cin
parents: 185
diff changeset
142 throw new ApplicationException(String.Format("The promise state {0} is invalid", m_state));
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
143 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
144 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
145 #endregion
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
146
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
147 #region handlers managment
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
148
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
149 protected void AddHandler(THandler handler) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
150
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
151 if (m_state > 1) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
152 // the promise is in the resolved state, just invoke the handler
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
153 SignalHandler(handler, m_state);
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
154 } else {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
155 var slot = Interlocked.Increment(ref m_handlersCount) - 1;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
156
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
157 if (slot < RESERVED_HANDLERS_COUNT) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
158
160
5802131432e4 fixed regression: race condition in Promise
cin
parents: 156
diff changeset
159 if (slot == 0) {
5802131432e4 fixed regression: race condition in Promise
cin
parents: 156
diff changeset
160 m_handlers = new THandler[RESERVED_HANDLERS_COUNT];
5802131432e4 fixed regression: race condition in Promise
cin
parents: 156
diff changeset
161 } else {
5802131432e4 fixed regression: race condition in Promise
cin
parents: 156
diff changeset
162 while (m_handlers == null)
5802131432e4 fixed regression: race condition in Promise
cin
parents: 156
diff changeset
163 Thread.MemoryBarrier();
5802131432e4 fixed regression: race condition in Promise
cin
parents: 156
diff changeset
164 }
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
165
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
166 m_handlers[slot] = handler;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
167
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
168 while (slot != Interlocked.CompareExchange(ref m_handlersCommited, slot + 1, slot)) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
169 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
170
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
171 if (m_state > 1) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
172 do {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
173 var hp = m_handlerPointer;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
174 slot = hp + 1;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
175 if (slot < m_handlersCommited) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
176 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) != hp)
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
177 continue;
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
178 SignalHandler(m_handlers[slot], m_state);
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
179 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
180 break;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
181 } while(true);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
182 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
183 } else {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
184 if (slot == RESERVED_HANDLERS_COUNT) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
185 m_extraHandlers = new MTQueue<THandler>();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
186 } else {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
187 while (m_extraHandlers == null)
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
188 Thread.MemoryBarrier();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
189 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
190
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
191 m_extraHandlers.Enqueue(handler);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
192
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
193 if (m_state > 1 && m_extraHandlers.TryDequeue(out handler))
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
194 // if the promise have been resolved while we was adding the handler to the queue
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
195 // we can't guarantee that someone is still processing it
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
196 // therefore we need to fetch a handler from the queue and execute it
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
197 // note that fetched handler may be not the one that we have added
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
198 // even we can fetch no handlers at all :)
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 148
diff changeset
199 SignalHandler(handler, m_state);
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
200 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
201 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
202 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
203
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
204 #endregion
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
205
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
206 #region IPromise implementation
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
207
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
208 public bool IsResolved {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
209 get {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
210 Thread.MemoryBarrier();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
211 return m_state > 1;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
212 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
213 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
214
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
215 public bool IsCancelled {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
216 get {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
217 Thread.MemoryBarrier();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
218 return m_state == CANCELLED_STATE;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
219 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
220 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
221
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
222 #endregion
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
223
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
224 public Exception Error {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
225 get {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
226 return m_error;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
227 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
228 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
229
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
230 public bool CancelOperationIfRequested() {
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
231 if (IsCancellationRequested) {
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
232 CancelOperation(CancellationReason);
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
233 return true;
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
234 }
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
235 return false;
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
236 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
237
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
238 public virtual void CancelOperation(Exception reason) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
239 SetCancelled(reason);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
240 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
241
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
242 public void CancellationRequested(Action<Exception> handler) {
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
243 Safe.ArgumentNotNull(handler, "handler");
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
244 if (IsCancellationRequested)
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
245 handler(CancellationReason);
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
246
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
247 if (m_cancelationHandlers == null)
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
248 Interlocked.CompareExchange(ref m_cancelationHandlers, new MTQueue<Action<Exception>>(), null);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
249
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
250 m_cancelationHandlers.Enqueue(handler);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
251
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
252 if (IsCancellationRequested && m_cancelationHandlers.TryDequeue(out handler))
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
253 // TryDeque implies MemoryBarrier()
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
254 handler(m_cancelationReason);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
255 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
256
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
257 public bool IsCancellationRequested {
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
258 get {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
259 do {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
260 if (m_cancelRequest == CANCEL_NOT_REQUESTED)
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
261 return false;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
262 if (m_cancelRequest == CANCEL_REQUESTED)
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
263 return true;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
264 Thread.MemoryBarrier();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
265 } while(true);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
266 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
267 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
268
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
269 public Exception CancellationReason {
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
270 get {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
271 do {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
272 Thread.MemoryBarrier();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
273 } while(m_cancelRequest == CANCEL_REQUESTING);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
274
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
275 return m_cancelationReason;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
276 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
277 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
278
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
279 #region ICancellable implementation
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
280
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
281 public void Cancel() {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
282 Cancel(null);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
283 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
284
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
285 public void Cancel(Exception reason) {
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
286 if (CANCEL_NOT_REQUESTED == Interlocked.CompareExchange(ref m_cancelRequest, CANCEL_REQUESTING, CANCEL_NOT_REQUESTED)) {
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
287 m_cancelationReason = reason;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
288 m_cancelRequest = CANCEL_REQUESTED;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
289 if (m_cancelationHandlers != null) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
290 Action<Exception> handler;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
291 while (m_cancelationHandlers.TryDequeue(out handler))
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
292 handler(m_cancelationReason);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
293 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
294 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
295 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
296
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
297 #endregion
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
298 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
299 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
300