comparison Implab/AbstractPromise.cs @ 244:eee3e49dd1ff v3

working on promises
author cin
date Thu, 25 Jan 2018 19:09:16 +0300
parents b1e0ffdf3451
children fb70574741a1
comparison
equal deleted inserted replaced
243:b1e0ffdf3451 244:eee3e49dd1ff
2 using System.Diagnostics; 2 using System.Diagnostics;
3 using System.Reflection; 3 using System.Reflection;
4 using Implab.Parallels; 4 using Implab.Parallels;
5 5
6 namespace Implab { 6 namespace Implab {
7 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise { 7 public class AbstractPromise : AbstractEvent<IResolvable>, IPromise {
8 public class HandlerDescriptor {
9 readonly Action m_resolve;
10 readonly Action<Exception> m_reject;
11 8
12 readonly IDeferred m_deferred; 9 class ResolvableSignal : IResolvable {
13 public HandlerDescriptor(Action success, Action<Exception> error) { 10 public Signal Signal { get; private set; }
14 m_resolve = success; 11 public ResolvableSignal() {
15 m_reject = error; 12 Signal = new Signal();
16 } 13 }
17 14
18 public void SignalSuccess() { 15
19 try { 16 public void Reject(Exception error) {
20 if (m_resolve != null) 17 Signal.Set();
21 m_resolve();
22 m_deferred.Resolve();
23 } catch (Exception ex) {
24 m_deferred.Reject(ex);
25 }
26 } 18 }
27 19
28 public void SignalError(Exception err) { 20 public void Resolve() {
29 if (m_reject != null) { 21 Signal.Set();
30 try {
31 m_reject(err);
32 m_deferred.Resolve();
33 } catch (Exception ex) {
34 m_deferred.Reject(ex);
35 }
36 }
37 } 22 }
38 } 23 }
39 24
40 PromiseState m_state; 25 PromiseState m_state;
41 26
45 get { 30 get {
46 return m_state == PromiseState.Rejected; 31 return m_state == PromiseState.Rejected;
47 } 32 }
48 } 33 }
49 34
50 public bool IsResolved { 35 public bool IsFulfilled {
51 get { 36 get {
52 return m_state == PromiseState.Resolved; 37 return m_state == PromiseState.Fulfilled;
53 } 38 }
54 } 39 }
55 40
56 public Exception RejectReason { 41 public Exception RejectReason {
57 get { 42 get {
58 return m_error; 43 return m_error;
59 } 44 }
60 } 45 }
61 46
62 47
48 internal void Resolve() {
49 if (BeginTransit())
50 CompleteResolve();
51 }
52
53 internal void Reject(Exception reason) {
54 if (BeginTransit()) {
55 m_error = reason;
56 m_state = PromiseState.Rejected;
57 CompleteTransit();
58 }
59 }
60
61
63 #region implemented abstract members of AbstractPromise 62 #region implemented abstract members of AbstractPromise
64 63
65 protected override void SignalHandler(HandlerDescriptor handler) { 64 protected override void SignalHandler(IResolvable handler) {
66 switch (m_state) { 65 switch (m_state) {
67 case PromiseState.Resolved: 66 case PromiseState.Fulfilled:
68 handler.SignalSuccess(); 67 handler.Resolve();
69 break; 68 break;
70 case PromiseState.Rejected: 69 case PromiseState.Rejected:
71 handler.SignalError(RejectReason); 70 handler.Reject(RejectReason);
72 break; 71 break;
73 default: 72 default:
74 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state)); 73 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state));
75 } 74 }
76 } 75 }
77 76
78 protected override Signal GetFulfillSignal() { 77 protected override Signal GetFulfillSignal() {
79 var signal = new Signal(); 78 var next = new ResolvableSignal();
80 On(signal.Set, e => signal.Set()); 79 Then(next);
81 return signal; 80 return next.Signal;
82 } 81 }
83 82
84 #endregion 83 #endregion
85 84
86 protected void CompleteResolve() { 85 protected void CompleteResolve() {
87 m_state = PromiseState.Resolved; 86 m_state = PromiseState.Fulfilled;
88 CompleteTransit(); 87 CompleteTransit();
89 } 88 }
90 89
91 public Type ResultType { 90 public Type ResultType {
92 get { 91 get {
93 return typeof(void); 92 return typeof(void);
94 } 93 }
95 } 94 }
96 95
97 /// <summary>
98 /// Выполняет обещание, сообщая об ошибке
99 /// </summary>
100 /// <remarks>
101 /// Поскольку обещание должно работать в многопточной среде, при его выполнении сразу несколько потоков
102 /// могу вернуть ошибку, при этом только первая будет использована в качестве результата, остальные
103 /// будут проигнорированы.
104 /// </remarks>
105 /// <param name="error">Исключение возникшее при выполнении операции</param>
106 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
107 protected void SetError(Exception error) {
108 if (BeginTransit()) {
109 m_error = error;
110 m_state = PromiseState.Rejected;
111 CompleteTransit();
112 } else {
113 WaitTransition();
114 if (m_state == PromiseState.Resolved)
115 throw new InvalidOperationException("The promise is already resolved");
116 }
117 }
118 96
119 protected void Rethrow() { 97 protected void Rethrow() {
120 Debug.Assert(m_error != null); 98 Debug.Assert(m_error != null);
121 if (m_error is OperationCanceledException) 99 if (m_error is OperationCanceledException)
122 throw new OperationCanceledException("Operation cancelled", m_error); 100 throw new OperationCanceledException("Operation cancelled", m_error);
123 else 101 else
124 throw new TargetInvocationException(m_error); 102 throw new TargetInvocationException(m_error);
125 } 103 }
126 104
127 public void On(Action success, Action<Exception> error) { 105 public void Then(IResolvable next) {
128 AddHandler(new HandlerDescriptor(success, error)); 106 AddHandler(next);
129 } 107 }
130 108
131 public IPromise<T> Cast<T>() { 109 public IPromise<T> Cast<T>() {
132 throw new InvalidCastException(); 110 throw new InvalidCastException();
133 } 111 }