Mercurial > pub > ImplabNet
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,