##// END OF EJS Templates
promises refactoring
promises refactoring

File last commit:

r72:d67b95eddaf4 v2
r72:d67b95eddaf4 v2
Show More
Promise.cs
731 lines | 30.7 KiB | text/x-csharp | CSharpLexer
cin
small fixes
r2 using System;
using System.Collections.Generic;
using System.Reflection;
using System.Diagnostics;
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 public delegate void ErrorHandler(Exception e);
cin
refactoring
r11 public delegate T ErrorHandler<out T>(Exception e);
cin
implemeted new cancellable promises concept
r10 public delegate void ResultHandler<in T>(T result);
cin
promises refactoring
r72 public delegate TNew ResultMapper<in TSrc,out TNew>(TSrc result);
public delegate IPromise<TNew> ChainedOperation<in TSrc,TNew>(TSrc result);
cin
small fixes
r2
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
fixes
r28 protected struct HandlerDescriptor {
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 public ResultHandler<T> resultHandler;
cin
promises refactoring
r72 public ErrorHandler<T> errorHandler;
cin
Promise is rewritten to use interlocked operations instead of locks
r19 public Action cancellHandler;
cin
promises refactoring
r72 public Promise<T> medium;
cin
Promise is rewritten to use interlocked operations instead of locks
r19
public void Resolve(T result) {
cin
promises refactoring
r72 if (resultHandler != null) {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 try {
resultHandler(result);
} catch (Exception e) {
Reject(e);
cin
promises refactoring
r72 return;
cin
Promise is rewritten to use interlocked operations instead of locks
r19 }
cin
promises refactoring
r72 }
if (medium != null)
medium.Resolve(result);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 }
public void Reject(Exception err) {
cin
promises refactoring
r72 if (errorHandler != null) {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 try {
cin
promises refactoring
r72 var res = errorHandler(err);
if (medium != null)
medium.Resolve(res);
} catch (TransientPromiseException err2) {
if (medium != null)
medium.Reject(err2.InnerException);
} catch (Exception err2) {
if (medium != null)
medium.Reject(err2);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 }
cin
promises refactoring
r72 } else if (medium != null)
medium.Reject(err);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 }
public void Cancel() {
cin
promises refactoring
r72 if (cancellHandler != null) {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 try {
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 }
if (medium != null)
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
readonly bool m_cancellable;
cin
sync
r9
cin
implemeted new cancellable promises concept
r10 int m_childrenCount = 0;
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
Promise is rewritten to use interlocked operations instead of locks
r19 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 public Promise() {
m_cancellable = true;
}
cin
small fixes
r2
cin
Refactoring
r66 public Promise(IPromise parent, bool cancellable) {
cin
inital progress handling
r7 m_cancellable = cancellable;
cin
removed the reference to the parent from the promise object this allows...
r33 if (parent != null)
cin
promises refactoring
r72 Cancelled(() => {
if (parent.IsExclusive)
parent.Cancel();
});
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
refactoring
r25 /* noop */
}
}
cin
Promise is rewritten to use interlocked operations instead of locks
r19 public bool IsResolved {
get {
return m_state > 1;
}
}
public bool IsCancelled {
get {
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
*refactoring: Promise.Then now returns a new chained promise...
r6 m_error = 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>
/// <returns><c>true</c> Операция была отменена, обработчики не будут вызваны.<c>false</c> отмена не возможна, поскольку обещание уже выполнено и обработчики отработали.</returns>
public bool Cancel() {
cin
promises refactoring
r72 if (m_cancellable && BeginTransit()) {
cin
code cleanup
r71 CompleteTransit(CANCELLED_STATE);
cin
removed the reference to the parent from the promise object this allows...
r33 OnStateChanged();
return true;
}
cin
promises refactoring
r72 return false;
cin
removed the reference to the parent from the promise object this allows...
r33 }
// сделано для возвращаемого типа void
protected void InternalCancel() {
Cancel();
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
refactoring
r11 /// Adds new handlers to this promise.
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 /// </summary>
cin
refactoring
r11 /// <param name="success">The handler of the successfully completed operation.
/// This handler will recieve an operation result as a parameter.</param>
/// <param name="error">Handles an exception that may occur during the operation and returns the value which will be used as the result of the operation.</param>
/// <returns>The new promise chained to this one.</returns>
cin
refactoring
r26 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
cin
refactoring
r11 if (success == null && error == null)
return this;
var medium = new Promise<T>(this, true);
cin
promises refactoring
r72 AddHandler(success, error, null, medium);
cin
refactoring
r11
return medium;
}
cin
promises refactoring
r72 public IPromise Then(Action success, ErrorHandler error) {
return Then(
x => success(),
e => {
error(e);
return default(T);
}
);
}
public IPromise Then(Action success) {
return Then(x => success());
}
cin
refactoring
r11
cin
refactoring
r26 public IPromise<T> Then(ResultHandler<T> success) {
cin
refactoring
r11 if (success == null)
return this;
var medium = new Promise<T>(this, true);
cin
promises refactoring
r72 AddHandler(success, null, null, medium);
cin
refactoring
r11
return medium;
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 }
cin
small fixes
r2
cin
promises refactoring
r72 public IPromise Error(ErrorHandler error) {
if (error == null)
return this;
var medium = new Promise<T>(this, true);
AddHandler(
null,
e => {
error(e);
return default(T);
},
null,
medium
);
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
refactoring
r26 public IPromise<T> Error(ErrorHandler<T> handler) {
cin
refactoring
r11 if (handler == null)
return this;
var medium = new Promise<T>(this, true);
cin
promises refactoring
r72 AddHandler(null, handler, null, medium);
cin
refactoring
r11
return medium;
}
cin
refactoring
r26 public IPromise<T> Anyway(Action handler) {
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 if (handler == null)
return this;
cin
promises refactoring
r72 var medium = new Promise<T>(this, true);
cin
small fixes
r2
cin
Promise is rewritten to use interlocked operations instead of locks
r19 AddHandler(
cin
promises refactoring
r72 x => handler(),
e => {
handler();
throw new TransientPromiseException(e);
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 },
cin
promises refactoring
r72 null,
medium
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
small fixes
r2
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
promises refactoring
r72 public IPromise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<T> error) {
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 if (mapper == null)
throw new ArgumentNullException("mapper");
cin
small fixes
r2
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 // создаем прицепленное обещание
cin
promises refactoring
r72 var chained = new Promise<TNew>(this, true);
cin
small fixes
r2
cin
Promise is rewritten to use interlocked operations instead of locks
r19 ResultHandler<T> resultHandler = result => chained.Resolve(mapper(result));
cin
promises refactoring
r72 ErrorHandler<T> errorHandler;
if (error != null)
errorHandler = e => {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 try {
cin
promises refactoring
r72 return error(e);
} catch (Exception e2) {
// в случае ошибки нужно передать исключение дальше по цепочке
chained.Reject(e2);
}
return default(T);
};
else
errorHandler = e => {
chained.Reject(e);
return default(T);
};
cin
Promise is rewritten to use interlocked operations instead of locks
r19
AddHandler(
resultHandler,
errorHandler,
cin
promises refactoring
r72 chained.InternalCancel,
null
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 chained;
}
cin
refactoring
r26 public IPromise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper) {
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 return Map(mapper, null);
}
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
promises refactoring
r72 public IPromise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler<T> error) {
cin
*refactoring: Promise.Then now returns a new chained promise...
r6
// проблема в том, что на момент связывания еще не начата асинхронная операция, поэтому нужно
// создать посредника, к которому будут подвызяваться следующие обработчики.
// когда будет выполнена реальная асинхронная операция, она обратиться к посреднику, чтобы
// передать через него результаты работы.
cin
implemeted new cancellable promises concept
r10 var medium = new Promise<TNew>(this, true);
cin
small fixes
r2
cin
Promise is rewritten to use interlocked operations instead of locks
r19 ResultHandler<T> resultHandler = delegate(T result) {
if (medium.IsCancelled)
return;
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
Promise is rewritten to use interlocked operations instead of locks
r19 promise.Then(
cin
promises refactoring
r72 medium.Resolve,
err => {
medium.Reject(err);
throw new TransientPromiseException(err);
}
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
medium.Cancelled(() => {
cin
promises refactoring
r72 if (promise.IsExclusive)
cin
removed the reference to the parent from the promise object this allows...
r33 promise.Cancel();
});
// внешняя отмена связанной операции рассматривается как ошибка
promise.Cancelled(() => medium.Reject(new OperationCanceledException()));
cin
Promise is rewritten to use interlocked operations instead of locks
r19 };
cin
promises refactoring
r72 ErrorHandler<T> errorHandler = delegate(Exception e) {
if (error != null) {
try {
return error(e);
} catch (Exception e2) {
medium.Reject(e2);
return default(T);
}
}
cin
Promise is rewritten to use interlocked operations instead of locks
r19 // в случае ошибки нужно передать исключение дальше по цепочке
medium.Reject(e);
cin
promises refactoring
r72 return default(T);
cin
Promise is rewritten to use interlocked operations instead of locks
r19 };
AddHandler(
resultHandler,
errorHandler,
cin
promises refactoring
r72 medium.InternalCancel,
null
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
refactoring
r26 public IPromise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained) {
cin
*refactoring: Promise.Then now returns a new chained promise...
r6 return Chain(chained, null);
}
cin
small fixes
r2
cin
refactoring
r26 public IPromise<T> Cancelled(Action handler) {
cin
promises refactoring
r72 AddHandler(null, null, handler, null);
cin
implemeted new cancellable promises concept
r10 return this;
}
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
r26 public IPromise<T> Finally(Action handler) {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 if (handler == null)
throw new ArgumentNullException("handler");
AddHandler(
x => handler(),
cin
promises refactoring
r72 e => {
handler();
throw new TransientPromiseException(e);
},
handler,
null
cin
Promise is rewritten to use interlocked operations instead of locks
r19 );
return this;
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>() {
return Map(x => (T2)(object)x, null);
}
/// <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: Promise.Then now returns a new chained promise...
r6 Anyway(() => evt.Set());
cin
implemeted new cancellable promises concept
r10 Cancelled(() => 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
promises refactoring
r72 void AddHandler(ResultHandler<T> success, ErrorHandler<T> error, Action cancel, Promise<T> medium) {
cin
removed the reference to the parent from the promise object this allows...
r33 if (success != null || error != null)
Interlocked.Increment(ref m_childrenCount);
cin
Promise is rewritten to use interlocked operations instead of locks
r19
cin
promises refactoring
r72 var handler = new HandlerDescriptor {
cin
Promise is rewritten to use interlocked operations instead of locks
r19 resultHandler = success,
errorHandler = error,
cin
promises refactoring
r72 cancellHandler = cancel,
medium = medium
cin
Promise is rewritten to use interlocked operations instead of locks
r19 };
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
fixes
r27 protected virtual void InvokeHandler(HandlerDescriptor 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
Promise is rewritten to use interlocked operations instead of locks
r19 HandlerDescriptor handler;
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) {
promises[i].Then(
x => {
result[dest] = x;
if (Interlocked.Decrement(ref pending) == 0)
promise.Resolve(result);
},
cin
promises refactoring
r72 e => {
promise.Reject(e);
return default(T);
}
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
Refactoring
r66 IPromise IPromise.Error(ErrorHandler error) {
cin
removed the reference to the parent from the promise object this allows...
r33 return Error(error);
}
cin
Refactoring
r66 IPromise IPromise.Anyway(Action handler) {
cin
removed the reference to the parent from the promise object this allows...
r33 return Anyway(handler);
}
cin
Refactoring
r66 IPromise IPromise.Finally(Action handler) {
cin
removed the reference to the parent from the promise object this allows...
r33 return Finally(handler);
}
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 }