# HG changeset patch
# User cin
# Date 2016-04-18 21:50:14
# Node ID 75103928da090cf50ce0feeaaacd9e867e4a90f8
# Parent  822aab37b107951b00cb44f7661c09c5c1b30320
working on cancelation and error handling
diff --git a/Implab/AbstractEvent.cs b/Implab/AbstractEvent.cs
--- a/Implab/AbstractEvent.cs
+++ b/Implab/AbstractEvent.cs
@@ -77,19 +77,14 @@ namespace Implab {
         /// Исключение возникшее при выполнении операции
         /// Данное обещание уже выполнено
         protected void SetError(Exception error) {
-            while (error is PromiseTransientException)
-                error = error.InnerException;
-
-            var isCancel = error is OperationCanceledException;
-            
             if (BeginTransit()) {
-                m_error = isCancel ? error.InnerException : error;
-                CompleteTransit(isCancel ? CANCELLED_STATE : REJECTED_STATE);
+                m_error = error;
+                CompleteTransit(REJECTED_STATE);
 
                 Signal();
             } else {
                 WaitTransition();
-                if (!isCancel || m_state == SUCCEEDED_STATE)
+                if (m_state == SUCCEEDED_STATE)
                     throw new InvalidOperationException("The promise is already resolved");
             }
         }
@@ -140,11 +135,11 @@ namespace Implab {
                 case SUCCEEDED_STATE:
                     return;
                 case CANCELLED_STATE:
-                    throw new OperationCanceledException();
+                    throw new OperationCanceledException("The operation has been cancelled", m_error);
                 case REJECTED_STATE:
                     throw new TargetInvocationException(m_error);
                 default:
-                    throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
+                    throw new ApplicationException(String.Format("The promise state {0} is invalid", m_state));
             }
         }
         #endregion
diff --git a/Implab/AbstractPromise.cs b/Implab/AbstractPromise.cs
--- a/Implab/AbstractPromise.cs
+++ b/Implab/AbstractPromise.cs
@@ -134,8 +134,8 @@ namespace Implab {
         }
 
         protected void SetResult() {
-            BeginSetResult();
-            EndSetResult();
+            if(BeginSetResult())
+                EndSetResult();
         }
     }
 }
diff --git a/Implab/ActionChainTaskBase.cs b/Implab/ActionChainTaskBase.cs
--- a/Implab/ActionChainTaskBase.cs
+++ b/Implab/ActionChainTaskBase.cs
@@ -20,34 +20,51 @@ namespace Implab {
                 HandleErrorInternal(error);
         }
 
-
-
         public override void CancelOperation(Exception reason) {
             if (LockCancelation()) {
+                if (!(reason is OperationCanceledException))
+                    reason = reason != null ? new OperationCanceledException(null, reason) : new OperationCanceledException();
+                
                 if (m_cancel != null) {
                     try {
-                        m_cancel(reason).On(SetResult, SetError, SetCancelled);
+                        m_cancel(reason).On(SetResult, HandleErrorInternal, HandleCancelInternal);
                     } catch (Exception err) {
                         HandleErrorInternal(err);
                     }
                 } else {
-                    SetCancelled(reason);
+                    HandleErrorInternal(reason);
                 }
             }
         }
 
-        protected void HandleErrorInternal(Exception error) {
+        void HandleCancelInternal(Exception reason) {
+            if (!(reason is OperationCanceledException))
+                reason = reason != null ? new OperationCanceledException(null, reason) : new OperationCanceledException();
+            HandleErrorInternal(reason);
+        }
+
+        void HandleErrorInternal(Exception error) {
             if (m_error != null) {
                 try {
                     var p = m_error(error);
-                    p.On(SetResult,SetError,SetCancelled);
+                    p.On(SetResult, SetError, SetCancelled);
                     CancellationRequested(p.Cancel);
                 } catch (Exception err) {
-                    SetError(err);
+                    error = err;
                 }
             } else {
+                SetErrorInternal(error);
+            }
+        }
+
+        void SetErrorInternal(Exception error) {
+            while (error is PromiseTransientException)
+                error = error.InnerException;
+
+            if (error is OperationCanceledException)
+                SetCancelled(error);
+            else
                 SetError(error);
-            }
         }
 
         protected bool LockCancelation() {
diff --git a/Implab/Components/RunnableComponent.cs b/Implab/Components/RunnableComponent.cs
--- a/Implab/Components/RunnableComponent.cs
+++ b/Implab/Components/RunnableComponent.cs
@@ -139,14 +139,7 @@ namespace Implab.Components {
                         throw new PromiseTransientException(e);
                     },
                     r => {
-                        lock(m_stateMachine) {
-                            if (m_pending == promise) {
-                                Move(Commands.Fail);
-                                m_pending = null;
-                                m_lastError = new OperationCanceledException("The operation has been cancelled", r);
-                            }
-
-                        }
+                        // handle cancellation as exception
                         throw new OperationCanceledException("The operation has been cancelled", r);
                     }
                 );
@@ -201,7 +194,7 @@ namespace Implab.Components {
             if (current == null) {
                 stop.Resolve();
             } else {
-                current.On(stop.Resolve, stop.Reject, stop.CancelOperation);
+                current.On(stop.Resolve, stop.Reject, e => stop.Resolve());
                 current.Cancel();
             }
         }