##// END OF EJS Templates
fixed Promise.Error handler
fixed Promise.Error handler

File last commit:

r112:38d6a4db35d7 v2
r112:38d6a4db35d7 v2
Show More
Promise.cs
954 lines | 39.7 KiB | text/x-csharp | CSharpLexer
cin
small fixes
r2 using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
cin
Promise is rewritten to use interlocked operations instead of locks
r19 using Implab.Parallels;
cin
small fixes
r2
namespace Implab {
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 /// <summary>
/// Класс для асинхронного получения результатов. Так называемое "обещание".
/// </summary>
/// <typeparam name="T">Тип получаемого результата</typeparam>
/// <remarks>
/// <para>Сервис при обращении к его методу дает обещаиние о выполнении операции,
/// клиент получив такое обещание может установить ряд обратных вызово для получения
/// событий выполнения обещания, тоесть завершения операции и предоставлении результатов.</para>
/// <para>
/// Обещение может быть как выполнено, так и выполнено с ошибкой. Для подписки на
/// данные события клиент должен использовать методы <c>Then</c>.
/// </para>
/// <para>
/// Сервис, в свою очередь, по окончанию выполнения операции (возможно с ошибкой),
/// использует методы <c>Resolve</c> либо <c>Reject</c> для оповещения клиетна о
/// выполнении обещания.
/// </para>
/// <para>
/// Если сервер успел выполнить обещание еще до того, как клиент на него подписался,
/// то в момент подписки клиента будут вызваны соответсвующие события в синхронном
/// режиме и клиент будет оповещен в любом случае. Иначе, обработчики добавляются в
/// список в порядке подписания и в этом же порядке они будут вызваны при выполнении
/// обещания.
/// </para>
/// <para>
/// Обрабатывая результаты обещания можно преобразовывать результаты либо инициировать
/// связанные асинхронные операции, которые также возвращают обещания. Для этого следует
/// использовать соответствующую форму методе <c>Then</c>.
/// </para>
/// <para>
/// Также хорошим правилом является то, что <c>Resolve</c> и <c>Reject</c> должен вызывать
/// только инициатор обещания иначе могут возникнуть противоречия.
/// </para>
/// </remarks>
cin
refactoring
r25 public class Promise<T> : IPromise<T> {
cin
small fixes
r2
cin
promises refactoring
r106 protected abstract class AbstractHandler : MTCustomQueueNode<AbstractHandler> {
public abstract void Resolve(T result);
public abstract void Reject(Exception error);
public abstract void Cancel();
}
cin
minor fixes and optimizations
r107 protected class RemapDescriptor<T2> : AbstractHandler {
cin
promises refactoring
r106
readonly Func<T,T2> m_resultHandler;
readonly Func<Exception,T2> m_errorHandler;
readonly Action m_cancellHandler;
readonly Promise<T2> m_medium;
cin
Promise is rewritten to use interlocked operations instead of locks
r19
cin
minor fixes and optimizations
r107 public RemapDescriptor(Func<T,T2> resultHandler, Func<Exception,T2> errorHandler, Action cancelHandler, Promise<T2> medium) {
cin
promises refactoring
r106 m_resultHandler = resultHandler;
m_errorHandler = errorHandler;
m_cancellHandler = cancelHandler;
m_medium = medium;
}
public override void Resolve(T result) {
if (m_resultHandler != null) {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 try {
cin
promises refactoring
r106 if (m_medium != null)
m_medium.Resolve(m_resultHandler(result));
else
m_resultHandler(result);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 } catch (Exception e) {
Reject(e);
}
cin
promises refactoring
r106 } else if(m_medium != null)
m_medium.Resolve(default(T2));
cin
Promise is rewritten to use interlocked operations instead of locks
r19 }
cin
promises refactoring
r106 public override void Reject(Exception error) {
if (m_errorHandler != null) {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 try {
cin
promises refactoring
r106 var res = m_errorHandler(error);
if (m_medium != null)
m_medium.Resolve(res);
cin
minor fixes and optimizations
r107 } 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));
cin
promises refactoring
r72 } catch (Exception err2) {
cin
promises refactoring
r106 if (m_medium != null)
m_medium.Reject(err2);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 }
cin
promises refactoring
r106 } else if (m_medium != null)
m_medium.Reject(error);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 }
cin
promises refactoring
r106 public override void Cancel() {
if (m_cancellHandler != null) {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 try {
cin
promises refactoring
r106 m_cancellHandler();
cin
promises refactoring
r72 } catch (Exception err) {
Reject(err);
return;
cin
Promise is rewritten to use interlocked operations instead of locks
r19 }
cin
promises refactoring
r72 }
cin
promises refactoring
r106 if (m_medium != null)
m_medium.Cancel();
cin
Promise is rewritten to use interlocked operations instead of locks
r19 }
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
cin
code cleanup
r71 const int UNRESOLVED_SATE = 0;
const int TRANSITIONAL_STATE = 1;
const int SUCCEEDED_STATE = 2;
const int REJECTED_STATE = 3;
const int CANCELLED_STATE = 4;
cin
Promise is rewritten to use interlocked operations instead of locks
r19
cin
code cleanup...
r101 int m_childrenCount;
cin
Promise is rewritten to use interlocked operations instead of locks
r19 int m_state;
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 T m_result;
Exception m_error;
cin
sync
r9
cin
promises refactoring
r106 readonly MTCustomQueue<AbstractHandler> m_handlers = new MTCustomQueue<AbstractHandler>();
//readonly MTQueue<AbstractHandler> m_handlers = new MTQueue<AbstractHandler>();
cin
Promise is rewritten to use interlocked operations instead of locks
r19
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 public Promise() {
}
cin
small fixes
r2
cin
code cleanup...
r101 public Promise(IPromise parent) {
cin
removed the reference to the parent from the promise object this allows...
r33 if (parent != null)
cin
fixed Promise.Error handler
r112 AddHandler(
cin
Refactoring of the IPromise<T> interface...
r76 null,
null,
() => {
if (parent.IsExclusive)
parent.Cancel();
},
cin
renamed Promise.Last -> Promise.On...
r104 null,
false
cin
Refactoring of the IPromise<T> interface...
r76 );
cin
implemeted new cancellable promises concept
r10 }
cin
small fixes
r2
cin
Promise is rewritten to use interlocked operations instead of locks
r19 bool BeginTransit() {
cin
code cleanup
r71 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 }
void CompleteTransit(int state) {
cin
code cleanup
r71 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
cin
Promise is rewritten to use interlocked operations instead of locks
r19 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
}
cin
refactoring
r25 void WaitTransition() {
cin
code cleanup
r71 while (m_state == TRANSITIONAL_STATE) {
cin
added memory barriers
r80 Thread.MemoryBarrier();
cin
refactoring
r25 }
}
cin
Promise is rewritten to use interlocked operations instead of locks
r19 public bool IsResolved {
get {
cin
added memory barriers
r80 Thread.MemoryBarrier();
cin
Promise is rewritten to use interlocked operations instead of locks
r19 return m_state > 1;
}
}
public bool IsCancelled {
get {
cin
added memory barriers
r80 Thread.MemoryBarrier();
cin
code cleanup
r71 return m_state == CANCELLED_STATE;
cin
Promise is rewritten to use interlocked operations instead of locks
r19 }
}
cin
Added a casting method for promises.
r29 public Type PromiseType {
get { return typeof(T); }
}
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 /// <summary>
/// Выполняет обещание, сообщая об успешном выполнении.
/// </summary>
/// <param name="result">Результат выполнения.</param>
/// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
public void Resolve(T result) {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 if (BeginTransit()) {
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 m_result = result;
cin
code cleanup
r71 CompleteTransit(SUCCEEDED_STATE);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 OnStateChanged();
cin
refactoring
r25 } else {
WaitTransition();
cin
code cleanup
r71 if (m_state != CANCELLED_STATE)
cin
refactoring
r25 throw new InvalidOperationException("The promise is already resolved");
}
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
cin
small fixes
r2
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 /// <summary>
cin
removed the reference to the parent from the promise object this allows...
r33 /// Выполняет обещание, сообщая об успешном выполнении. Результатом выполнения будет пустое значения.
/// </summary>
/// <remarks>
/// Данный вариант удобен в случаях, когда интересен факт выполнения операции, нежели полученное значение.
/// </remarks>
public void Resolve() {
Resolve(default(T));
}
/// <summary>
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 /// Выполняет обещание, сообщая об ошибке
/// </summary>
cin
sync
r16 /// <remarks>
/// Поскольку обещание должно работать в многопточной среде, при его выполнении сразу несколько потоков
/// могу вернуть ошибку, при этом только первая будет использована в качестве результата, остальные
/// будут проигнорированы.
/// </remarks>
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 /// <param name="error">Исключение возникшее при выполнении операции</param>
/// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
public void Reject(Exception error) {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 if (BeginTransit()) {
cin
fixed TransientPromiseException handling
r99 m_error = error is TransientPromiseException ? error.InnerException : error;
cin
code cleanup
r71 CompleteTransit(REJECTED_STATE);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 OnStateChanged();
cin
refactoring
r25 } else {
WaitTransition();
cin
code cleanup
r71 if (m_state == SUCCEEDED_STATE)
cin
refactoring
r25 throw new InvalidOperationException("The promise is already resolved");
}
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
cin
small fixes
r2
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 /// <summary>
/// Отменяет операцию, если это возможно.
/// </summary>
cin
Refactoring of the IPromise<T> interface...
r76 /// <remarks>Для определения была ли операция отменена следует использовать свойство <see cref="IsCancelled"/>.</remarks>
public void Cancel() {
cin
code cleanup...
r101 if (BeginTransit()) {
cin
code cleanup
r71 CompleteTransit(CANCELLED_STATE);
cin
removed the reference to the parent from the promise object this allows...
r33 OnStateChanged();
}
}
cin
Refactoring of the IPromise<T> interface...
r76 /// <summary>
/// Последний обработчик в цепочки обещаний.
/// </summary>
/// <param name="success"></param>
/// <param name="error"></param>
/// <param name="cancel"></param>
/// <remarks>
/// <para>
/// Данный метод не создает связанного с текущим обещания и предназначен для окончания
/// фсинхронной цепочки.
/// </para>
/// <para>
/// Если данный метод вызвать несколько раз, либо добавить другие обработчики, то цепочка
/// не будет одиночной <see cref="IsExclusive"/> и, как следствие, будет невозможна отмена
/// всей цепи обещаний снизу (с самого последнего обещания).
/// </para>
/// </remarks>
cin
renamed Promise.Last -> Promise.On...
r104 public void On(Action<T> success, Action<Exception> error, Action cancel) {
cin
major refactoring, added tasks support
r75 if (success == null && error == null && cancel == null)
return;
cin
minor fixes and optimizations
r107 AddHandler(success, error, cancel, null, false);
cin
renamed Promise.Last -> Promise.On...
r104 }
public void On(Action<T> success, Action<Exception> error) {
cin
minor fixes and optimizations
r107 AddHandler(success, error, null, null, false);
cin
renamed Promise.Last -> Promise.On...
r104 }
public void On(Action<T> success) {
cin
minor fixes and optimizations
r107 AddHandler(success, null, null, null, false);
cin
major refactoring, added tasks support
r75 }
cin
renamed Promise.Last -> Promise.On...
r104 public void On(Action handler, PromiseEventType events) {
Safe.ArgumentNotNull(handler, "handler");
cin
major refactoring, added tasks support
r75
cin
renamed Promise.Last -> Promise.On...
r104
cin
minor fixes and optimizations
r107 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
);
cin
major refactoring, added tasks support
r75 }
cin
code cleanup...
r101 public IPromise Error(Action<Exception> error) {
cin
promises refactoring
r72 if (error == null)
return this;
cin
code cleanup...
r101 var medium = new Promise<T>(this);
cin
promises refactoring
r72
cin
minor fixes and optimizations
r107 AddMappers(
cin
fixed Promise.Error handler
r112 x => x,
cin
promises refactoring
r72 e => {
error(e);
return default(T);
},
null,
cin
renamed Promise.Last -> Promise.On...
r104 medium,
true
cin
promises refactoring
r72 );
return medium;
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
cin
small fixes
r2
cin
refactoring
r11 /// <summary>
/// Handles error and allows to keep the promise.
/// </summary>
/// <remarks>
/// If the specified handler throws an exception, this exception will be used to reject the promise.
/// </remarks>
/// <param name="handler">The error handler which returns the result of the promise.</param>
/// <returns>New promise.</returns>
cin
code cleanup...
r101 public IPromise<T> Error(Func<Exception,T> handler) {
cin
refactoring
r11 if (handler == null)
return this;
cin
code cleanup...
r101 var medium = new Promise<T>(this);
cin
refactoring
r11
cin
fixed Promise.Error handler
r112 AddMappers(x => x, handler, null, medium, true);
cin
refactoring
r11
return medium;
}
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 /// <summary>
/// Позволяет преобразовать результат выполения операции к новому типу.
/// </summary>
/// <typeparam name="TNew">Новый тип результата.</typeparam>
/// <param name="mapper">Преобразование результата к новому типу.</param>
/// <param name="error">Обработчик ошибки. Данный обработчик получит
/// исключение возникшее при выполнении операции.</param>
/// <returns>Новое обещание, которое будет выполнено при выполнении исходного обещания.</returns>
cin
Added the chaining method to the non-generic IPromise
r96 /// <param name = "cancel"></param>
cin
code cleanup...
r101 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error, Action cancel) {
cin
Refactoring of the IPromise<T> interface...
r76 Safe.ArgumentNotNull(mapper, "mapper");
// создаем прицепленное обещание
cin
code cleanup...
r101 var medium = new Promise<TNew>(this);
cin
small fixes
r2
cin
minor fixes and optimizations
r107 AddMappers(
cin
promises refactoring
r106 mapper,
error,
cancel,
medium,
cin
renamed Promise.Last -> Promise.On...
r104 true
cin
Promise is rewritten to use interlocked operations instead of locks
r19 );
cin
small fixes
r2
cin
Refactoring of the IPromise<T> interface...
r76 return medium;
}
cin
code cleanup...
r101 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error) {
cin
Refactoring of the IPromise<T> interface...
r76 return Then(mapper, error, null);
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
cin
code cleanup...
r101 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper) {
cin
Refactoring of the IPromise<T> interface...
r76 return Then(mapper, null, null);
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
cin
small fixes
r2
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 /// <summary>
/// Сцепляет несколько аснхронных операций. Указанная асинхронная операция будет вызвана после
/// выполнения текущей, а результат текущей операции может быть использован для инициализации
/// новой операции.
/// </summary>
/// <typeparam name="TNew">Тип результата указанной асинхронной операции.</typeparam>
/// <param name="chained">Асинхронная операция, которая должна будет начаться после выполнения текущей.</param>
/// <param name="error">Обработчик ошибки. Данный обработчик получит
/// исключение возникшее при выполнении текуещй операции.</param>
/// <returns>Новое обещание, которое будет выполнено по окончанию указанной аснхронной операции.</returns>
cin
Added the chaining method to the non-generic IPromise
r96 /// <param name = "cancel"></param>
cin
code cleanup...
r101 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error, Action cancel) {
cin
Refactoring of the IPromise<T> interface...
r76
Safe.ArgumentNotNull(chained, "chained");
cin
*refactoring: Promise.Then now returns a new chained promise...
r6
// проблема в том, что на момент связывания еще не начата асинхронная операция, поэтому нужно
// создать посредника, к которому будут подвызяваться следующие обработчики.
// когда будет выполнена реальная асинхронная операция, она обратиться к посреднику, чтобы
// передать через него результаты работы.
cin
code cleanup...
r101 var medium = new Promise<TNew>(this);
cin
small fixes
r2
cin
promises refactoring
r106 Func<T,T> resultHandler = delegate(T result) {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 if (medium.IsCancelled)
cin
promises refactoring
r106 return default(T);
cin
implemeted new cancellable promises concept
r10
cin
Promise is rewritten to use interlocked operations instead of locks
r19 var promise = chained(result);
cin
implemeted new cancellable promises concept
r10
cin
renamed Promise.Last -> Promise.On...
r104 promise.On(
cin
promises refactoring
r72 medium.Resolve,
cin
Refactoring of the IPromise<T> interface...
r76 medium.Reject,
() => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка
cin
Promise is rewritten to use interlocked operations instead of locks
r19 );
cin
removed the reference to the parent from the promise object this allows...
r33
// notify chained operation that it's not needed anymore
// порядок вызова Then, Cancelled важен, поскольку от этого
// зависит IsExclusive
cin
renamed Promise.Last -> Promise.On...
r104 medium.On(
cin
code cleanup...
r101 null,
null,
() => {
if (promise.IsExclusive)
promise.Cancel();
}
);
cin
promises refactoring
r106
return default(T);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 };
cin
code cleanup...
r101 Func<Exception,T> errorHandler;
cin
Refactoring of the IPromise<T> interface...
r76
if (error != null)
errorHandler = delegate(Exception e) {
cin
promises refactoring
r72 try {
cin
Refactoring of the IPromise<T> interface...
r76 var promise = error(e);
cin
renamed Promise.Last -> Promise.On...
r104 promise.On(
cin
Refactoring of the IPromise<T> interface...
r76 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();
});
cin
promises refactoring
r72 } catch (Exception e2) {
medium.Reject(e2);
}
cin
Refactoring of the IPromise<T> interface...
r76 return default(T);
};
else
errorHandler = err => {
medium.Reject(err);
return default(T);
};
Action cancelHandler;
if (cancel != null)
cancelHandler = () => {
if (cancel != null)
cancel();
medium.Cancel();
};
else
cancelHandler = medium.Cancel;
cin
Promise is rewritten to use interlocked operations instead of locks
r19
cin
minor fixes and optimizations
r107 AddMappers(
cin
Promise is rewritten to use interlocked operations instead of locks
r19 resultHandler,
errorHandler,
cin
Refactoring of the IPromise<T> interface...
r76 cancelHandler,
cin
renamed Promise.Last -> Promise.On...
r104 null,
true
cin
Promise is rewritten to use interlocked operations instead of locks
r19 );
cin
small fixes
r2
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 return medium;
}
cin
code cleanup...
r101 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error) {
cin
Refactoring of the IPromise<T> interface...
r76 return Chain(chained, error, null);
}
cin
code cleanup...
r101 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained) {
cin
Refactoring of the IPromise<T> interface...
r76 return Chain(chained, null, null);
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
cin
small fixes
r2
cin
refactoring
r26 public IPromise<T> Cancelled(Action handler) {
cin
code cleanup...
r101 var medium = new Promise<T>(this);
cin
renamed Promise.Last -> Promise.On...
r104 AddHandler(null, null, handler, medium, false);
cin
minor fixes
r74 return medium;
cin
implemeted new cancellable promises concept
r10 }
cin
refactoring
r25 /// <summary>
/// Adds the specified handler for all cases (success, error, cancel)
/// </summary>
/// <param name="handler">The handler that will be called anyway</param>
/// <returns>self</returns>
cin
Refactoring of the IPromise<T> interface...
r76 public IPromise<T> Anyway(Action handler) {
Safe.ArgumentNotNull(handler, "handler");
cin
renamed Promise.Last -> Promise.On...
r104
var medium = new Promise<T>(this);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 AddHandler(
cin
minor fixes and optimizations
r107 x => handler(),
cin
promises refactoring
r72 e => {
handler();
throw new TransientPromiseException(e);
},
handler,
cin
renamed Promise.Last -> Promise.On...
r104 medium,
true
cin
Promise is rewritten to use interlocked operations instead of locks
r19 );
cin
renamed Promise.Last -> Promise.On...
r104
return medium;
cin
implemeted new cancellable promises concept
r10 }
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 /// <summary>
cin
Added a casting method for promises.
r29 /// Преобразует результат обещания к нужному типу
/// </summary>
/// <typeparam name="T2"></typeparam>
/// <returns></returns>
public IPromise<T2> Cast<T2>() {
cin
major refactoring, added tasks support
r75 return Then(x => (T2)(object)x, null);
cin
Added a casting method for promises.
r29 }
/// <summary>
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 /// Дожидается отложенного обещания и в случае успеха, возвращает
/// его, результат, в противном случае бросает исключение.
/// </summary>
/// <remarks>
/// <para>
/// Если ожидание обещания было прервано по таймауту, это не значит,
/// что обещание было отменено или что-то в этом роде, это только
/// означает, что мы его не дождались, однако все зарегистрированные
/// обработчики, как были так остались и они будут вызваны, когда
/// обещание будет выполнено.
/// </para>
/// <para>
/// Такое поведение вполне оправдано поскольку таймаут может истечь
/// в тот момент, когда началась обработка цепочки обработчиков, и
/// к тому же текущее обещание может стоять в цепочке обещаний и его
/// отклонение может привести к непрогнозируемому результату.
/// </para>
/// </remarks>
/// <param name="timeout">Время ожидания</param>
/// <returns>Результат выполнения обещания</returns>
public T Join(int timeout) {
cin
implemeted new cancellable promises concept
r10 var evt = new ManualResetEvent(false);
cin
Refactoring of the IPromise<T> interface...
r76 Anyway(() => evt.Set());
cin
small fixes
r2
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 if (!evt.WaitOne(timeout, true))
throw new TimeoutException();
cin
small fixes
r2
cin
Promise is rewritten to use interlocked operations instead of locks
r19 switch (m_state) {
cin
code cleanup
r71 case SUCCEEDED_STATE:
cin
implemeted new cancellable promises concept
r10 return m_result;
cin
code cleanup
r71 case CANCELLED_STATE:
cin
implemeted new cancellable promises concept
r10 throw new OperationCanceledException();
cin
code cleanup
r71 case REJECTED_STATE:
cin
implemeted new cancellable promises concept
r10 throw new TargetInvocationException(m_error);
default:
cin
Promise is rewritten to use interlocked operations instead of locks
r19 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
cin
implemeted new cancellable promises concept
r10 }
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
public T Join() {
return Join(Timeout.Infinite);
}
cin
small fixes
r2
cin
minor fixes and optimizations
r107 void AddMappers<T2>(Func<T,T2> success, Func<Exception,T2> error, Action cancel, Promise<T2> medium, bool inc) {
cin
renamed Promise.Last -> Promise.On...
r104 if (inc)
cin
removed the reference to the parent from the promise object this allows...
r33 Interlocked.Increment(ref m_childrenCount);
cin
Promise is rewritten to use interlocked operations instead of locks
r19
cin
minor fixes and optimizations
r107 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);
cin
small fixes
r2
cin
Promise is rewritten to use interlocked operations instead of locks
r19 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);
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
cin
small fixes
r2
cin
Promise is rewritten to use interlocked operations instead of locks
r19 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
cin
fixes
r27 // note that fetched handler may be not the one that we have added
// even we can fetch no handlers at all :)
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 InvokeHandler(handler);
}
cin
small fixes
r2
cin
promises refactoring
r106 protected virtual void InvokeHandler(AbstractHandler handler) {
cin
implemeted new cancellable promises concept
r10 switch (m_state) {
cin
code cleanup
r71 case SUCCEEDED_STATE:
cin
Promise is rewritten to use interlocked operations instead of locks
r19 handler.Resolve(m_result);
cin
implemeted new cancellable promises concept
r10 break;
cin
code cleanup
r71 case REJECTED_STATE:
cin
Promise is rewritten to use interlocked operations instead of locks
r19 handler.Reject(m_error);
break;
cin
code cleanup
r71 case CANCELLED_STATE:
cin
Promise is rewritten to use interlocked operations instead of locks
r19 handler.Cancel();
cin
implemeted new cancellable promises concept
r10 break;
default:
// do nothing
return;
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
}
cin
small fixes
r2
cin
minor changes
r65 void OnStateChanged() {
cin
promises refactoring
r106 AbstractHandler handler;
cin
Promise is rewritten to use interlocked operations instead of locks
r19 while (m_handlers.TryDequeue(out handler))
InvokeHandler(handler);
cin
refactoring
r11 }
cin
sync
r9 public bool IsExclusive {
get {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 return m_childrenCount <= 1;
cin
sync
r9 }
}
cin
refactoring
r25 /// <summary>
/// Объединяет несколько обещаний в одно, результатом которого является массив результатов других обещаний.
/// Если хотябы одно из переданных обещаний не будет выполнено, то новое обещение тоже не будет выполнено.
/// При отмене нового обещания, переданные обещания также будут отменены, если никто больше на них не подписан.
/// </summary>
/// <param name="promises">Список обещаний. Если список пустой, то результирующее обещание возвращается уже выполненным.</param>
/// <returns>Обещание объединяющее в себе результат переданных обещаний.</returns>
/// <exception cref="ArgumentNullException"><paramref name="promises"/> не может быть null</exception>
cin
small refactoring, cleanup.
r30 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
cin
refactoring
r25 if (promises == null)
throw new ArgumentNullException();
// создаем аккумулятор для результатов и результирующее обещание
var result = new T[promises.Count];
var promise = new Promise<T[]>();
// special case
if (promises.Count == 0) {
promise.Resolve(result);
return promise;
}
int pending = promises.Count;
for (int i = 0; i < promises.Count; i++) {
var dest = i;
cin
removed the reference to the parent from the promise object this allows...
r33 if (promises[i] != null) {
cin
promises refactoring
r106 promises[i].On(
cin
removed the reference to the parent from the promise object this allows...
r33 x => {
result[dest] = x;
if (Interlocked.Decrement(ref pending) == 0)
promise.Resolve(result);
},
cin
promises refactoring
r106 promise.Reject
cin
removed the reference to the parent from the promise object this allows...
r33 );
} else {
if (Interlocked.Decrement(ref pending) == 0)
promise.Resolve(result);
}
cin
refactoring
r25 }
promise.Cancelled(
() => {
cin
removed the reference to the parent from the promise object this allows...
r33 foreach (var d in promises)
if (d != null && d.IsExclusive)
cin
refactoring
r25 d.Cancel();
}
);
return promise;
}
cin
removed the reference to the parent from the promise object this allows...
r33 /// <summary>
/// Объединяет несколько обещаний в одно. Результирующее обещание будет выполнено при
/// выполнении всех указанных обещаний. При этом возвращаемые значения первичных обещаний
/// игнорируются.
/// </summary>
/// <param name="promises">Коллекция первичных обещаний, которые будут объеденены в одно.</param>
/// <returns>Новое обещание, объединяющее в себе переданные.</returns>
/// <remarks>
/// Если в коллекции встречаюься <c>null</c>, то они воспринимаются как выполненные обещания.
/// </remarks>
cin
Refactoring
r66 public static IPromise CreateComposite(ICollection<IPromise> promises) {
cin
removed the reference to the parent from the promise object this allows...
r33 if (promises == null)
throw new ArgumentNullException();
if (promises.Count == 0)
return Promise<object>.ResultToPromise(null);
int countdown = promises.Count;
var result = new Promise<object>();
foreach (var d in promises) {
if (d == null) {
if (Interlocked.Decrement(ref countdown) == 0)
result.Resolve(null);
} else {
d.Then(() => {
if (Interlocked.Decrement(ref countdown) == 0)
result.Resolve(null);
});
}
}
result.Cancelled(() => {
foreach (var d in promises)
if (d != null && d.IsExclusive)
d.Cancel();
});
return result;
}
cin
refactoring
r25 public static Promise<T> ResultToPromise(T result) {
var p = new Promise<T>();
p.Resolve(result);
return p;
}
public static Promise<T> ExceptionToPromise(Exception error) {
if (error == null)
throw new ArgumentNullException();
var p = new Promise<T>();
p.Reject(error);
return p;
}
cin
removed the reference to the parent from the promise object this allows...
r33 #region IPromiseBase explicit implementation
cin
code cleanup...
r101 IPromise IPromise.Then(Action success, Action<Exception> error, Action cancel) {
cin
Refactoring of the IPromise<T> interface...
r76 return Then(
cin
promises refactoring
r106 success != null ? new Func<T,T>(x => {
success();
return x;
}) : null,
cin
code cleanup...
r101 error != null ? new Func<Exception,T>(e => {
cin
Refactoring of the IPromise<T> interface...
r76 error(e);
return default(T);
cin
Added the chaining method to the non-generic IPromise
r96 }) : null,
cin
Refactoring of the IPromise<T> interface...
r76 cancel
);
}
cin
code cleanup...
r101 IPromise IPromise.Then(Action success, Action<Exception> error) {
cin
Refactoring of the IPromise<T> interface...
r76 return Then(
cin
promises refactoring
r106 success != null ? new Func<T,T>(x => {
success();
return x;
}) : null,
cin
code cleanup...
r101 error != null ? new Func<Exception,T>(e => {
cin
Refactoring of the IPromise<T> interface...
r76 error(e);
return default(T);
cin
Added the chaining method to the non-generic IPromise
r96 }) : null
cin
Refactoring of the IPromise<T> interface...
r76 );
}
IPromise IPromise.Then(Action success) {
cin
Added the chaining method to the non-generic IPromise
r96 Safe.ArgumentNotNull(success, "success");
cin
promises refactoring
r106 return Then(x => {
success();
return x;
});
cin
Refactoring of the IPromise<T> interface...
r76 }
cin
code cleanup...
r101 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
cin
Added the chaining method to the non-generic IPromise
r96 return ChainNoResult(chained, error, cancel);
}
cin
code cleanup...
r101 IPromise ChainNoResult(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
cin
renamed Promise.Last -> Promise.On...
r104 Safe.ArgumentNotNull(chained, "chained");
cin
Added the chaining method to the non-generic IPromise
r96
cin
code cleanup...
r101 var medium = new Promise<object>(this);
cin
Added the chaining method to the non-generic IPromise
r96
cin
promises refactoring
r106 Func<T,T> resultHandler = delegate {
cin
renamed Promise.Last -> Promise.On...
r104 if (medium.IsCancelled)
cin
promises refactoring
r106 return default(T);
cin
Added the chaining method to the non-generic IPromise
r96
cin
renamed Promise.Last -> Promise.On...
r104 var promise = chained();
cin
Added the chaining method to the non-generic IPromise
r96
cin
renamed Promise.Last -> Promise.On...
r104 promise.On(
medium.Resolve,
medium.Reject,
() => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка
);
cin
Added the chaining method to the non-generic IPromise
r96
cin
renamed Promise.Last -> Promise.On...
r104 // notify chained operation that it's not needed anymore
// порядок вызова Then, Cancelled важен, поскольку от этого
// зависит IsExclusive
medium.Cancelled(() => {
if (promise.IsExclusive)
promise.Cancel();
});
cin
promises refactoring
r106
return default(T);
cin
renamed Promise.Last -> Promise.On...
r104 };
cin
Added the chaining method to the non-generic IPromise
r96
cin
code cleanup...
r101 Func<Exception,T> errorHandler;
cin
Added the chaining method to the non-generic IPromise
r96
cin
renamed Promise.Last -> Promise.On...
r104 if (error != null)
errorHandler = delegate(Exception e) {
cin
Added the chaining method to the non-generic IPromise
r96 try {
var promise = error(e);
cin
renamed Promise.Last -> Promise.On...
r104 promise.On(
cin
Added the chaining method to the non-generic IPromise
r96 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();
});
} catch (Exception e2) {
medium.Reject(e2);
}
return default(T);
};
cin
renamed Promise.Last -> Promise.On...
r104 else
errorHandler = err => {
cin
Added the chaining method to the non-generic IPromise
r96 medium.Reject(err);
return default(T);
};
cin
renamed Promise.Last -> Promise.On...
r104 Action cancelHandler;
if (cancel != null)
cancelHandler = () => {
cin
Added the chaining method to the non-generic IPromise
r96 if (cancel != null)
cancel();
medium.Cancel();
};
cin
renamed Promise.Last -> Promise.On...
r104 else
cancelHandler = medium.Cancel;
cin
Added the chaining method to the non-generic IPromise
r96
cin
minor fixes and optimizations
r107 AddMappers(
cin
renamed Promise.Last -> Promise.On...
r104 resultHandler,
errorHandler,
cancelHandler,
null,
true
);
cin
Added the chaining method to the non-generic IPromise
r96
cin
renamed Promise.Last -> Promise.On...
r104 return medium;
cin
Added the chaining method to the non-generic IPromise
r96 }
cin
renamed Promise.Last -> Promise.On...
r104
cin
code cleanup...
r101 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error) {
cin
Added the chaining method to the non-generic IPromise
r96 return ChainNoResult(chained, error, null);
}
cin
renamed Promise.Last -> Promise.On...
r104
cin
Added the chaining method to the non-generic IPromise
r96 IPromise IPromise.Chain(Func<IPromise> chained) {
return ChainNoResult(chained, null, null);
cin
renamed Promise.Last -> Promise.On...
r104 }
cin
Added the chaining method to the non-generic IPromise
r96
cin
renamed Promise.Last -> Promise.On...
r104 void IPromise.On(Action success, Action<Exception> error, Action cancel) {
cin
minor fixes
r105 On(success != null ? new Action<T>(x => success()) : null, error, cancel);
cin
Refactoring of the IPromise<T> interface...
r76 }
cin
renamed Promise.Last -> Promise.On...
r104 void IPromise.On(Action success, Action<Exception> error) {
On(x => success(), error, null);
cin
Refactoring of the IPromise<T> interface...
r76 }
cin
renamed Promise.Last -> Promise.On...
r104 void IPromise.On(Action success) {
On(x => success(), null, null);
cin
Refactoring of the IPromise<T> interface...
r76 }
cin
code cleanup...
r101 IPromise IPromise.Error(Action<Exception> error) {
cin
removed the reference to the parent from the promise object this allows...
r33 return Error(error);
}
cin
Refactoring of the IPromise<T> interface...
r76 IPromise IPromise.Anyway(Action handler) {
return Anyway(handler);
cin
removed the reference to the parent from the promise object this allows...
r33 }
cin
Refactoring
r66 IPromise IPromise.Cancelled(Action handler) {
cin
removed the reference to the parent from the promise object this allows...
r33 return Cancelled(handler);
}
cin
Refactoring
r66 void IPromise.Join() {
cin
removed the reference to the parent from the promise object this allows...
r33 Join();
}
cin
Refactoring
r66 void IPromise.Join(int timeout) {
cin
removed the reference to the parent from the promise object this allows...
r33 Join(timeout);
}
#endregion
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
cin
small fixes
r2 }