diff Implab/PromiseT.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 656815cb7147
children 8c0b95069066
line wrap: on
line diff
--- a/Implab/PromiseT.cs	Mon Feb 16 17:48:39 2015 +0300
+++ b/Implab/PromiseT.cs	Tue Feb 17 18:16:26 2015 +0300
@@ -39,7 +39,7 @@
     /// </remarks>
     public class Promise<T> : AbstractPromise<IDeferred<T>>, IPromise<T>, IDeferred<T> {
 
-        class StubDeferred : IDeferred<T> {
+        class StubDeferred : IDeferred, IDeferred<T> {
             public static readonly StubDeferred instance = new StubDeferred();
 
             StubDeferred() {
@@ -50,6 +50,9 @@
             public void Resolve(T value) {
             }
 
+            public void Resolve() {
+            }
+
             public void Reject(Exception error) {
             }
 
@@ -60,6 +63,9 @@
             public void Cancel() {
             }
 
+            public void Cancel(Exception reason) {
+            }
+
             #endregion
 
 
@@ -67,11 +73,11 @@
 
         class RemapDescriptor<T2> : IDeferred<T> {
             readonly Func<T,T2> m_remap;
-            readonly Func<Exception,T2> m_failed;
-            readonly Func<T2> m_cancel;
+            readonly Func<Exception, T2> m_failed;
+            readonly Func<Exception, T2> m_cancel;
             readonly IDeferred<T2> m_deferred;
 
-            public RemapDescriptor(Func<T,T2> remap, Func<Exception,T2> failed, Func<T2> cancel, IDeferred<T2> deferred ) {
+            public RemapDescriptor(Func<T,T2> remap, Func<Exception,T2> failed, Func<Exception, T2> cancel, IDeferred<T2> deferred ) {
                 Debug.Assert(deferred != null);
                 m_remap = remap;
                 m_failed = failed;
@@ -110,18 +116,21 @@
 
             #region ICancellable implementation
 
-            public void Cancel() {
+            public void Cancel(Exception reason) {
                 if (m_cancel != null) {
                     try {
-                        m_deferred.Resolve(m_cancel());
+                        m_deferred.Resolve(m_cancel(reason));
                     } catch (Exception ex) {
                         Reject(ex);
                     }
                 } else {
-                    m_deferred.Cancel();
+                    m_deferred.Cancel(reason);
                 }
             }
 
+            public void Cancel() {
+                Cancel(null);
+            }
             #endregion
         }
 
@@ -163,6 +172,10 @@
             #region ICancellable implementation
 
             public void Cancel() {
+                Cancel(null);
+            }
+
+            public void Cancel(Exception reason) {
                 if (m_events.HasFlag(PromiseEventType.Cancelled)){
                     try {
                         m_handler();
@@ -178,10 +191,10 @@
         class ValueEventDescriptor : IDeferred<T> {
             readonly Action<T> m_success;
             readonly Action<Exception> m_failed;
-            readonly Action m_cancelled;
+            readonly Action<Exception> m_cancelled;
             readonly IDeferred<T> m_deferred;
 
-            public ValueEventDescriptor(Action<T> success, Action<Exception> failed, Action cancelled, IDeferred<T> deferred) {
+            public ValueEventDescriptor(Action<T> success, Action<Exception> failed, Action<Exception> cancelled, IDeferred<T> deferred) {
                 Debug.Assert(deferred != null);
 
                 m_success = success;
@@ -220,29 +233,33 @@
 
             #region ICancellable implementation
 
-            public void Cancel() {
+            public void Cancel(Exception reason) {
                 if (m_cancelled != null) {
                     try {
-                        m_cancelled();
+                        m_cancelled(reason);
                         m_deferred.Resolve(default(T));
-                    } catch(Exception ex) {
+                    } catch (Exception ex) {
                         Reject(ex);
                     }
                 } else {
-                    m_deferred.Cancel();
+                    m_deferred.Cancel(reason);
                 }
             }
 
+            public void Cancel() {
+                Cancel(null);
+            }
+
             #endregion
         }
 
         public class EventDescriptor : IDeferred<T> {
             readonly Action m_success;
             readonly Action<Exception> m_failed;
-            readonly Action m_cancelled;
-            readonly IDeferred<T> m_deferred;
+            readonly Action<Exception> m_cancelled;
+            readonly IDeferred m_deferred;
 
-            public EventDescriptor(Action success, Action<Exception> failed, Action cancelled, IDeferred<T> deferred) {
+            public EventDescriptor(Action success, Action<Exception> failed, Action<Exception> cancelled, IDeferred deferred) {
                 Debug.Assert(deferred != null);
 
                 m_success = success;
@@ -257,7 +274,7 @@
                 if (m_success != null) {
                     try {
                         m_success();
-                        m_deferred.Resolve(value);
+                        m_deferred.Resolve();
                     } catch (Exception ex) {
                         Reject(ex);
                     }
@@ -268,34 +285,36 @@
                 if (m_failed != null) {
                     try {
                         m_failed(error);
-                        m_deferred.Resolve(default(T));
-                    }catch (Exception ex) 
-                    {
+                        m_deferred.Resolve();
+                    } catch (Exception ex) {
                         m_deferred.Reject(ex);
                     }
                 } else {
                     m_deferred.Reject(error);
                 }
-
             }
 
             #endregion
 
             #region ICancellable implementation
 
-            public void Cancel() {
+            public void Cancel(Exception reason) {
                 if (m_cancelled != null) {
                     try {
-                        m_cancelled();
-                        m_deferred.Resolve(default(T));
+                        m_cancelled(reason);
+                        m_deferred.Resolve();
                     } catch (Exception ex) {
                         Reject(ex);
                     }
                 } else {
-                    m_deferred.Cancel();
+                    m_deferred.Cancel(reason);
                 }
             }
 
+            public void Cancel() {
+                Cancel(null);
+            }
+
             #endregion
         }
 
@@ -327,7 +346,7 @@
             return m_result;
         }
             
-        public IPromise<T> On(Action<T> success, Action<Exception> error, Action cancel) {
+        public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
             AddHandler(new ValueEventDescriptor(success, error, cancel, StubDeferred.instance));
             return this;
         }
@@ -347,10 +366,10 @@
             return this;
         }
 
-        public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<T2> cancel) {
+        public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<Exception, T2> cancel) {
             var promise = new Promise<T2>();
             if (mapper != null)
-                promise.On(Cancel, PromiseEventType.Cancelled);
+                promise.On((Action)null, null, Cancel);
             AddHandler(new RemapDescriptor<T2>(mapper, error, cancel, promise));
             return promise;
         }
@@ -358,7 +377,7 @@
         public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error) {
             var promise = new Promise<T2>();
             if (mapper != null)
-                promise.On(Cancel, PromiseEventType.Cancelled);
+                promise.On((Action)null, null, Cancel);
             AddHandler(new RemapDescriptor<T2>(mapper, error, null, promise));
             return promise;
         }
@@ -366,12 +385,12 @@
         public IPromise<T2> Then<T2>(Func<T, T2> mapper) {
             var promise = new Promise<T2>();
             if (mapper != null)
-                promise.On(Cancel, PromiseEventType.Cancelled);
+                promise.On((Action)null, null, Cancel);
             AddHandler(new RemapDescriptor<T2>(mapper, null, null, promise));
             return promise;
         }
 
-        public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<IPromise<T2>> cancel) {
+        public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) {
             // this promise will be resolved when an asyc operation is started
             var promise = new Promise<IPromise<T2>>();
 
@@ -404,7 +423,7 @@
                 result.On(
                     medium.Resolve,
                     medium.Reject,
-                    () => medium.Reject(new OperationCanceledException())
+                    medium.Cancel
                 );
                 medium.On(result.Cancel, PromiseEventType.Cancelled);
             } else {
@@ -425,46 +444,10 @@
             return Chain(chained, null, null);
         }
 
-        public IPromise<T2> Error<T2>(Func<Exception, T2> error) {
-            var promise = new Promise<T2>();
-            if (error != null)
-                On(
-                    (Action<T>)null,
-                    ex => {
-                        try {
-                            promise.Resolve(error(ex));
-                        } catch (Exception ex2) {
-                            promise.Reject(ex2);
-                        }
-                    }
-                );
-            else
-                Listen(PromiseEventType.Error, () => promise.Resolve(default(T2)));
-            return promise;
-        }
-
-        public IPromise<T2> Cancelled<T2>(Func<T2> handler) {
-            var promise = new Promise<T2>();
-            if (handler != null)
-                On(
-                    (Action<T>)null,
-                    null,
-                    () => {
-                        try {
-                            promise.Resolve(handler());
-                        } catch (Exception ex) {
-                            promise.Reject(ex);
-                        }
-                });
-            else
-                Listen(PromiseEventType.Cancelled, () => promise.Resolve(default(T2)));
-            return promise;
-        }
-
-        public IPromise Then(Action success, Action<Exception> error, Action cancel) {
-            var promise = new Promise<T>();
+        public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) {
+            var promise = new Promise();
             if (success != null)
-                promise.On(Cancel, PromiseEventType.Cancelled);
+                promise.On(null, null, Cancel);
 
             AddHandler(new EventDescriptor(success, error, cancel, promise));
 
@@ -479,7 +462,7 @@
             return Then(success, null, null);
         }
 
-        public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<IPromise> cancel) {
+        public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) {
             var promise = new Promise<IPromise>();
 
             AddHandler(
@@ -493,7 +476,7 @@
 
             var medium = new Promise();
             if (chained != null)
-                medium.On(Cancel, PromiseEventType.Cancelled);
+                medium.On(null, null, Cancel);
 
             promise.On(
                 result => ConnectPromise(result, medium),
@@ -509,9 +492,9 @@
                 result.On(
                     medium.Resolve,
                     medium.Reject,
-                    () => medium.Reject(new OperationCanceledException())
+                    medium.Cancel
                 );
-                medium.On(result.Cancel, PromiseEventType.Cancelled);
+                medium.On(null, null, result.Cancel);
             } else {
                 medium.Reject(
                     new NullReferenceException(
@@ -530,7 +513,7 @@
             return Chain(chained, null, null);
         }
 
-        public IPromise On(Action success, Action<Exception> error, Action cancel) {
+        public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
             AddHandler(new EventDescriptor(success,error,cancel, StubDeferred.instance));
             return this;
         }
@@ -550,43 +533,6 @@
             return this;
         }
 
-        public IPromise Error(Action<Exception> error) {
-            var promise = new Promise();
-            if (error != null)
-                On(
-                    (Action<T>)null,
-                    ex => {
-                    try {
-                        error(ex);
-                        promise.Resolve();
-                    } catch (Exception ex2) {
-                        promise.Reject(ex2);
-                    }
-                });
-            else
-                Listen(PromiseEventType.Error, promise.Resolve);
-            return promise;
-        }
-
-        public IPromise Cancelled(Action handler) {
-            var promise = new Promise();
-            if (handler != null)
-                On(
-                    (Action<T>)null,
-                    null,
-                    () => {
-                        try {
-                            handler();
-                            promise.Resolve();
-                        } catch (Exception ex) {
-                            promise.Reject(ex);
-                        }
-                    });
-            else
-                Listen(PromiseEventType.Cancelled, promise.Resolve);
-            return promise;
-        }
-
         public IPromise<T2> Cast<T2>() {
             return (IPromise<T2>)this;
         }
@@ -601,8 +547,8 @@
             handler.Reject(error);
         }
 
-        protected override void SignalCancelled(IDeferred<T> handler) {
-            handler.Cancel();
+        protected override void SignalCancelled(IDeferred<T> handler, Exception reason) {
+            handler.Cancel(reason);
         }
 
         protected override void Listen(PromiseEventType events, Action handler) {