diff --git a/Implab.Fx/PromiseHelpers.cs b/Implab.Fx/PromiseHelpers.cs --- a/Implab.Fx/PromiseHelpers.cs +++ b/Implab.Fx/PromiseHelpers.cs @@ -29,7 +29,7 @@ namespace Implab.Fx var directed = new ControlBoundPromise(ctl,that); - that.Last( + that.On( directed.Resolve, directed.Reject, directed.Cancel diff --git a/Implab/IPromise.cs b/Implab/IPromise.cs --- a/Implab/IPromise.cs +++ b/Implab/IPromise.cs @@ -41,9 +41,10 @@ namespace Implab { /// Success. /// Error. /// Cancel. - void Last(Action success, Action error, Action cancel); - void Last(Action success, Action error); - void Last(Action success); + void On(Action success, Action error, Action cancel); + void On(Action success, Action error); + void On(Action success); + void On(Action success, PromiseEventType events); IPromise Error(Action error); /// diff --git a/Implab/IPromiseT.cs b/Implab/IPromiseT.cs --- a/Implab/IPromiseT.cs +++ b/Implab/IPromiseT.cs @@ -7,11 +7,11 @@ namespace Implab { new T Join(int timeout); - void Last(Action success, Action error, Action cancel); + void On(Action success, Action error, Action cancel); - void Last(Action success, Action error); + void On(Action success, Action error); - void Last(Action success); + void On(Action success); IPromise Then(Action success, Func error, Action cancel); diff --git a/Implab/Implab.csproj b/Implab/Implab.csproj --- a/Implab/Implab.csproj +++ b/Implab/Implab.csproj @@ -147,6 +147,7 @@ + diff --git a/Implab/Parallels/ArrayTraits.cs b/Implab/Parallels/ArrayTraits.cs --- a/Implab/Parallels/ArrayTraits.cs +++ b/Implab/Parallels/ArrayTraits.cs @@ -183,7 +183,7 @@ namespace Implab.Parallels { Monitor.Pulse(locker); } }) - .Last( + .On( x => { res[idx] = x; var left = Interlocked.Decrement(ref pending); diff --git a/Implab/Promise.cs b/Implab/Promise.cs --- a/Implab/Promise.cs +++ b/Implab/Promise.cs @@ -117,7 +117,8 @@ namespace Implab { if (parent.IsExclusive) parent.Cancel(); }, - null + null, + false ); } @@ -220,7 +221,7 @@ namespace Implab { var medium = new Promise(this); - AddHandler(success, error, cancel, medium); + AddHandler(success, error, cancel, medium, true); return medium; } @@ -238,7 +239,7 @@ namespace Implab { var medium = new Promise(this); - AddHandler(success, error, null, medium); + AddHandler(success, error, null, medium, true); return medium; } @@ -252,7 +253,7 @@ namespace Implab { var medium = new Promise(this); - AddHandler(success, null, null, medium); + AddHandler(success, null, null, medium, true); return medium; } @@ -274,7 +275,7 @@ namespace Implab { /// всей цепи обещаний снизу (с самого последнего обещания). /// /// - public void Last(Action success, Action error, Action cancel) { + public void On(Action success, Action error, Action cancel) { if (success == null && error == null && cancel == null) return; @@ -284,15 +285,28 @@ namespace Implab { error(err); return default(T); }; - AddHandler(success, errorHandler, cancel, null); + AddHandler(success, errorHandler, cancel, null, false); + } + + public void On(Action success, Action error) { + On(success, error, null); + } + + public void On(Action success) { + On(success, null, null); } - public void Last(Action success, Action error) { - Last(success, error, null); - } + public void On(Action handler, PromiseEventType events) { + Safe.ArgumentNotNull(handler, "handler"); - public void Last(Action success) { - Last(success, null, null); + Action success = events.HasFlag(PromiseEventType.Success) ? new Action(x => handler()) : null; + Func error = events.HasFlag(PromiseEventType.Error) ? new Func(e => { + handler(); + return default(T); + }) : null; + Action cancel = events.HasFlag(PromiseEventType.Cancelled) ? handler : null; + + AddHandler(success, error, cancel, null, false); } public IPromise Error(Action error) { @@ -308,7 +322,8 @@ namespace Implab { return default(T); }, null, - medium + medium, + true ); return medium; @@ -328,7 +343,7 @@ namespace Implab { var medium = new Promise(this); - AddHandler(null, handler, null, medium); + AddHandler(null, handler, null, medium, true); return medium; } @@ -380,7 +395,8 @@ namespace Implab { resultHandler, errorHandler, cancelHandler, - null + null, + true ); return medium; @@ -421,7 +437,7 @@ namespace Implab { var promise = chained(result); - promise.Last( + promise.On( medium.Resolve, medium.Reject, () => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка @@ -430,7 +446,7 @@ namespace Implab { // notify chained operation that it's not needed anymore // порядок вызова Then, Cancelled важен, поскольку от этого // зависит IsExclusive - medium.Last( + medium.On( null, null, () => { @@ -447,7 +463,7 @@ namespace Implab { try { var promise = error(e); - promise.Last( + promise.On( medium.Resolve, medium.Reject, () => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка @@ -486,7 +502,8 @@ namespace Implab { resultHandler, errorHandler, cancelHandler, - null + null, + true ); return medium; @@ -502,7 +519,7 @@ namespace Implab { public IPromise Cancelled(Action handler) { var medium = new Promise(this); - AddHandler(null, null, handler, medium); + AddHandler(null, null, handler, medium, false); return medium; } @@ -513,7 +530,9 @@ namespace Implab { /// self public IPromise Anyway(Action handler) { Safe.ArgumentNotNull(handler, "handler"); - + + var medium = new Promise(this); + AddHandler( x => handler(), e => { @@ -521,9 +540,11 @@ namespace Implab { throw new TransientPromiseException(e); }, handler, - null + medium, + true ); - return this; + + return medium; } /// @@ -579,8 +600,8 @@ namespace Implab { return Join(Timeout.Infinite); } - void AddHandler(Action success, Func error, Action cancel, Promise medium) { - if (success != null || error != null) + void AddHandler(Action success, Func error, Action cancel, Promise medium, bool inc) { + if (inc) Interlocked.Increment(ref m_childrenCount); var handler = new HandlerDescriptor { @@ -784,39 +805,39 @@ namespace Implab { } IPromise ChainNoResult(Func chained, Func error, Action cancel) { - Safe.ArgumentNotNull(chained, "chained"); + Safe.ArgumentNotNull(chained, "chained"); var medium = new Promise(this); Action resultHandler = delegate { - if (medium.IsCancelled) - return; + if (medium.IsCancelled) + return; - var promise = chained(); + var promise = chained(); - promise.Last( - medium.Resolve, - medium.Reject, - () => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка - ); + promise.On( + medium.Resolve, + medium.Reject, + () => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка + ); - // notify chained operation that it's not needed anymore - // порядок вызова Then, Cancelled важен, поскольку от этого - // зависит IsExclusive - medium.Cancelled(() => { - if (promise.IsExclusive) - promise.Cancel(); - }); - }; + // notify chained operation that it's not needed anymore + // порядок вызова Then, Cancelled важен, поскольку от этого + // зависит IsExclusive + medium.Cancelled(() => { + if (promise.IsExclusive) + promise.Cancel(); + }); + }; Func errorHandler; - if (error != null) - errorHandler = delegate(Exception e) { + if (error != null) + errorHandler = delegate(Exception e) { try { var promise = error(e); - promise.Last( + promise.On( medium.Resolve, medium.Reject, () => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка @@ -834,50 +855,53 @@ namespace Implab { } return default(T); }; - else - errorHandler = err => { + else + errorHandler = err => { medium.Reject(err); return default(T); }; - Action cancelHandler; - if (cancel != null) - cancelHandler = () => { + Action cancelHandler; + if (cancel != null) + cancelHandler = () => { if (cancel != null) cancel(); medium.Cancel(); }; - else - cancelHandler = medium.Cancel; + else + cancelHandler = medium.Cancel; - AddHandler( - resultHandler, - errorHandler, - cancelHandler, - null - ); + AddHandler( + resultHandler, + errorHandler, + cancelHandler, + null, + true + ); - return medium; + return medium; } + IPromise IPromise.Chain(Func chained, Func error) { return ChainNoResult(chained, error, null); } + IPromise IPromise.Chain(Func chained) { return ChainNoResult(chained, null, null); - } + } - void IPromise.Last(Action success, Action error, Action cancel) { - Last(x => success(), error, cancel); + void IPromise.On(Action success, Action error, Action cancel) { + On(x => success(), error, cancel); } - void IPromise.Last(Action success, Action error) { - Last(x => success(), error, null); + void IPromise.On(Action success, Action error) { + On(x => success(), error, null); } - void IPromise.Last(Action success) { - Last(x => success(), null, null); + void IPromise.On(Action success) { + On(x => success(), null, null); } IPromise IPromise.Error(Action error) { diff --git a/Implab/PromiseEventType.cs b/Implab/PromiseEventType.cs new file mode 100644 --- /dev/null +++ b/Implab/PromiseEventType.cs @@ -0,0 +1,19 @@ +using System; + +namespace Implab { + [Flags] + public enum PromiseEventType { + Success = 1, + Error = 2, + Cancelled = 4, + /// + /// Завершено успешно, либо возникла ошибка, + /// + All = 7, + /// + /// Заврешено успешно, либо возникла ошибка. + /// + Complete = 3 + } +} + diff --git a/Implab/PromiseExtensions.cs b/Implab/PromiseExtensions.cs --- a/Implab/PromiseExtensions.cs +++ b/Implab/PromiseExtensions.cs @@ -14,7 +14,7 @@ namespace Implab { var p = new SyncContextPromise(context, that); - that.Last( + that.On( p.Resolve, p.Reject, p.Cancel @@ -28,7 +28,7 @@ namespace Implab { var p = new SyncContextPromise(context, that); - that.Last( + that.On( p.Resolve, p.Reject, p.Cancel @@ -49,7 +49,7 @@ namespace Implab { Safe.ArgumentNotNull(that, "that"); Safe.ArgumentNotNull(head, "head"); - that.Last(null,null,() => head.Last(cleanup)); + that.On(null,null,() => head.On(cleanup)); return that; } @@ -72,7 +72,7 @@ namespace Implab { Safe.ArgumentNotNull(that, "that"); var tcs = new TaskCompletionSource(); - that.Last(tcs.SetResult, tcs.SetException, tcs.SetCanceled); + that.On(tcs.SetResult, tcs.SetException, tcs.SetCanceled); return tcs.Task; } diff --git a/MonoPlay/Program.cs b/MonoPlay/Program.cs --- a/MonoPlay/Program.cs +++ b/MonoPlay/Program.cs @@ -12,7 +12,7 @@ namespace MonoPlay { throw new ArgumentNullException("args"); var q1 = new MTQueue(); - var q2 = new ConcurrentQueue(); + var q2 = new Queue(); const int count = 10000000; @@ -32,7 +32,7 @@ namespace MonoPlay { t2 = Environment.TickCount; Console.WriteLine("LinkedList: {0} ms", t2 - t1); - q2 = new ConcurrentQueue(); + q2 = new Queue(); t1 = Environment.TickCount;