diff Implab/AbstractPromise.cs @ 138:f75cfa58e3d4 v2

added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
author cin
date Tue, 17 Feb 2015 18:16:26 +0300
parents 671f60cd0250
children 16f926ee499d
line wrap: on
line diff
--- a/Implab/AbstractPromise.cs	Mon Feb 16 17:48:39 2015 +0300
+++ b/Implab/AbstractPromise.cs	Tue Feb 17 18:16:26 2015 +0300
@@ -68,9 +68,15 @@
         /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
         protected void SetError(Exception error) {
             if (BeginTransit()) {
-                m_error = error is PromiseTransientException ? error.InnerException : error;
-                CompleteTransit(REJECTED_STATE);
-                OnError();
+                if (error is OperationCanceledException) {
+                    CompleteTransit(CANCELLED_STATE);
+                    m_error = error.InnerException;
+                    OnCancelled();
+                } else {
+                    m_error = error is PromiseTransientException ? error.InnerException : error;
+                    CompleteTransit(REJECTED_STATE);
+                    OnError();
+                }
             } else {
                 WaitTransition();
                 if (m_state == SUCCEEDED_STATE)
@@ -82,8 +88,9 @@
         /// Отменяет операцию, если это возможно.
         /// </summary>
         /// <remarks>Для определения была ли операция отменена следует использовать свойство <see cref="IsCancelled"/>.</remarks>
-        protected void SetCancelled() {
+        protected void SetCancelled(Exception reason) {
             if (BeginTransit()) {
+                m_error = reason;
                 CompleteTransit(CANCELLED_STATE);
                 OnCancelled();
             }
@@ -93,7 +100,7 @@
 
         protected abstract void SignalError(THandler handler, Exception error);
 
-        protected abstract void SignalCancelled(THandler handler);
+        protected abstract void SignalCancelled(THandler handler, Exception reason);
 
         void OnSuccess() {
             var hp = m_handlerPointer;
@@ -137,7 +144,7 @@
             var slot = hp +1 ;
             while (slot < m_handlersCommited) {
                 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
-                    SignalCancelled(m_handlers[slot]);
+                    SignalCancelled(m_handlers[slot], m_error);
                 }
                 hp = m_handlerPointer;
                 slot = hp +1 ;
@@ -146,7 +153,7 @@
             if (m_extraHandlers != null) {
                 THandler handler;
                 while (m_extraHandlers.TryDequeue(out handler))
-                    SignalCancelled(handler);
+                    SignalCancelled(handler, m_error);
             }
         }
 
@@ -241,7 +248,7 @@
                     SignalSuccess(handler);
                     break;
                 case CANCELLED_STATE:
-                    SignalCancelled(handler);
+                    SignalCancelled(handler, m_error);
                     break;
                 case REJECTED_STATE:
                     SignalError(handler, m_error);
@@ -282,10 +289,20 @@
         #region ICancellable implementation
 
         public void Cancel() {
-            SetCancelled();
+            SetCancelled(null);
+        }
+
+        public void Cancel(Exception reason) {
+            SetCancelled(reason);
         }
 
         #endregion
+
+        public Exception Error {
+            get {
+                return m_error;
+            }
+        }
     }
 }