changeset 107:f5220e5472ef v2

minor fixes and optimizations
author cin
date Tue, 11 Nov 2014 04:14:21 +0300
parents d4e38929ce36
children f3bdb7ba59b9
files Implab/Promise.cs
diffstat 1 files changed, 102 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/Implab/Promise.cs	Mon Nov 10 18:00:28 2014 +0300
+++ b/Implab/Promise.cs	Tue Nov 11 04:14:21 2014 +0300
@@ -48,14 +48,14 @@
             public abstract void Cancel();
         }
 
-        protected class HandlerDescriptor<T2> : AbstractHandler  {
+        protected class RemapDescriptor<T2> : AbstractHandler  {
 
             readonly Func<T,T2> m_resultHandler;
             readonly Func<Exception,T2> m_errorHandler;
             readonly Action m_cancellHandler;
             readonly Promise<T2> m_medium;
 
-            public HandlerDescriptor(Func<T,T2> resultHandler, Func<Exception,T2> errorHandler, Action cancelHandler, Promise<T2> medium) {
+            public RemapDescriptor(Func<T,T2> resultHandler, Func<Exception,T2> errorHandler, Action cancelHandler, Promise<T2> medium) {
                 m_resultHandler = resultHandler;
                 m_errorHandler = errorHandler;
                 m_cancellHandler = cancelHandler;
@@ -82,9 +82,61 @@
                         var res = m_errorHandler(error);
                         if (m_medium != null)
                             m_medium.Resolve(res);
-                        /*} catch (TransientPromiseException err2) {
-                        if (medium != null)
-                            medium.Reject(err2.InnerException);*/
+                    } catch (Exception err2) {
+                        if (m_medium != null)
+                            m_medium.Reject(err2);
+                    }
+                } else if (m_medium != null)
+                    m_medium.Reject(error);
+            }
+
+            public override void Cancel() {
+                if (m_cancellHandler != null) {
+                    try {
+                        m_cancellHandler();
+                    } catch (Exception err) {
+                        Reject(err);
+                        return;
+                    }
+                }
+                if (m_medium != null)
+                    m_medium.Cancel();
+            }
+        }
+
+        protected class HandlerDescriptor : AbstractHandler  {
+
+            readonly Action<T> m_resultHandler;
+            readonly Action<Exception> m_errorHandler;
+            readonly Action m_cancellHandler;
+            readonly Promise<T> m_medium;
+
+            public HandlerDescriptor(Action<T> resultHandler, Action<Exception> errorHandler, Action cancelHandler, Promise<T> medium) {
+                m_resultHandler = resultHandler;
+                m_errorHandler = errorHandler;
+                m_cancellHandler = cancelHandler;
+                m_medium = medium;
+            }
+
+            public override void Resolve(T result) {
+                if (m_resultHandler != null) {
+                    try {
+                        m_resultHandler(result);
+                    } catch (Exception e) {
+                        Reject(e);
+                        return;
+                    }
+                }
+                if(m_medium != null)
+                    m_medium.Resolve(result);
+            }
+
+            public override void Reject(Exception error) {
+                if (m_errorHandler != null) {
+                    try {
+                        m_errorHandler(error);
+                        if (m_medium != null)
+                            m_medium.Resolve(default(T));
                     } catch (Exception err2) {
                         if (m_medium != null)
                             m_medium.Reject(err2);
@@ -126,7 +178,7 @@
 
         public Promise(IPromise parent) {
             if (parent != null)
-                AddHandler<T>(
+                AddMappers<T>(
                     null,
                     null,
                     () => {
@@ -252,43 +304,28 @@
             if (success == null && error == null && cancel == null)
                 return;
 
-            AddHandler(
-                success != null ? new Func<T,T>(x => {
-                    success(x);
-                    return x;
-                }) : null,
-                error != null ? new Func<Exception,T>(e => {
-                    error(e);
-                    return default(T);
-                }) : null,
-                cancel,
-                null,
-                false
-            );
+            AddHandler(success, error, cancel, null, false);
         }
 
         public void On(Action<T> success, Action<Exception> error) {
-            On(success, error, null);
+            AddHandler(success, error, null, null, false);
         }
 
         public void On(Action<T> success) {
-            On(success, null, null);
+            AddHandler(success, null, null, null, false);
         }
 
         public void On(Action handler, PromiseEventType events) {
             Safe.ArgumentNotNull(handler, "handler");
 
-            Func<T,T> success = events.HasFlag(PromiseEventType.Success) ? new Func<T,T>(x => {
-                handler();
-                return x;
-            }) : null;
-            Func<Exception,T> error = events.HasFlag(PromiseEventType.Error) ? new Func<Exception,T>(e => {
-                handler();
-                return default(T);
-            }) : null;
-            Action cancel = events.HasFlag(PromiseEventType.Cancelled) ? handler : null;
 
-            AddHandler(success, error, cancel, null, false);
+            AddHandler(
+                events.HasFlag(PromiseEventType.Success) ? new Action<T>(x => handler()) : null,
+                events.HasFlag(PromiseEventType.Error) ? new Action<Exception>( x => handler()) : null,
+                events.HasFlag(PromiseEventType.Cancelled) ? handler : null,
+                null,
+                false
+            );
         }
 
         public IPromise Error(Action<Exception> error) {
@@ -297,7 +334,7 @@
 
             var medium = new Promise<T>(this);
 
-            AddHandler(
+            AddMappers(
                 null,
                 e => {
                     error(e);
@@ -325,7 +362,7 @@
 
             var medium = new Promise<T>(this);
 
-            AddHandler(null, handler, null, medium, true);
+            AddMappers(null, handler, null, medium, true);
 
             return medium;
         }
@@ -345,7 +382,7 @@
             // создаем прицепленное обещание
             var medium = new Promise<TNew>(this);
 
-            AddHandler(
+            AddMappers(
                 mapper,
                 error,
                 cancel,
@@ -454,7 +491,7 @@
             else
                 cancelHandler = medium.Cancel;
 
-            AddHandler(
+            AddMappers(
                 resultHandler,
                 errorHandler,
                 cancelHandler,
@@ -490,10 +527,7 @@
             var medium = new Promise<T>(this);
 
             AddHandler(
-                x => {
-                    handler();
-                    return x;
-                },
+                x => handler(),
                 e => {
                     handler();
                     throw new TransientPromiseException(e);
@@ -559,11 +593,37 @@
             return Join(Timeout.Infinite);
         }
 
-        void AddHandler<T2>(Func<T,T2> success, Func<Exception,T2> error, Action cancel, Promise<T2> medium, bool inc) {
+        void AddMappers<T2>(Func<T,T2> success, Func<Exception,T2> error, Action cancel, Promise<T2> medium, bool inc) {
             if (inc)
                 Interlocked.Increment(ref m_childrenCount);
 
-            AbstractHandler handler = new HandlerDescriptor<T2>(success, error, cancel, medium);
+            AbstractHandler handler = new RemapDescriptor<T2>(success, error, cancel, medium);
+
+            bool queued;
+
+            if (!IsResolved) {
+                m_handlers.Enqueue(handler);
+                queued = true;
+            } else {
+                // the promise is in resolved state, just invoke the handled with minimum overhead
+                queued = false;
+                InvokeHandler(handler);
+            }
+
+            if (queued && IsResolved && m_handlers.TryDequeue(out handler))
+                // if the promise have been resolved while we was adding handler to the queue
+                // we can't guarantee that someone is still processing it
+                // therefore we will fetch a handler from the queue and execute it
+                // note that fetched handler may be not the one that we have added
+                // even we can fetch no handlers at all :)
+                InvokeHandler(handler);
+        }
+
+        void AddHandler(Action<T> success, Action<Exception> error, Action cancel, Promise<T> medium, bool inc) {
+            if (inc)
+                Interlocked.Increment(ref m_childrenCount);
+
+            AbstractHandler handler = new HandlerDescriptor(success, error, cancel, medium);
 
             bool queued;
 
@@ -834,7 +894,7 @@
             else
                 cancelHandler = medium.Cancel;
 
-            AddHandler(
+            AddMappers(
                 resultHandler,
                 errorHandler,
                 cancelHandler,