comparison Implab/AbstractPromise.cs @ 243:b1e0ffdf3451 v3

working on promises
author cin
date Wed, 24 Jan 2018 19:24:10 +0300
parents cbe10ac0731e
children eee3e49dd1ff
comparison
equal deleted inserted replaced
242:cbe10ac0731e 243:b1e0ffdf3451
1 using System; 1 using System;
2 using System.Diagnostics;
3 using System.Reflection;
2 using Implab.Parallels; 4 using Implab.Parallels;
3 5
4 namespace Implab { 6 namespace Implab {
5 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise { 7 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise {
6 public class HandlerDescriptor { 8 public class HandlerDescriptor {
7 readonly Action m_handler; 9 readonly Action m_resolve;
8 readonly Action<Exception> m_error; 10 readonly Action<Exception> m_reject;
11
12 readonly IDeferred m_deferred;
9 public HandlerDescriptor(Action success, Action<Exception> error) { 13 public HandlerDescriptor(Action success, Action<Exception> error) {
10 m_handler = success; 14 m_resolve = success;
11 m_error = error; 15 m_reject = error;
12 } 16 }
13 17
14 public void SignalSuccess() { 18 public void SignalSuccess() {
15 if (m_handler != null) { 19 try {
16 try { 20 if (m_resolve != null)
17 m_handler(); 21 m_resolve();
18 // Analysis disable once EmptyGeneralCatchClause 22 m_deferred.Resolve();
19 } catch { 23 } catch (Exception ex) {
20 } 24 m_deferred.Reject(ex);
21 } 25 }
22 } 26 }
23 27
24 public void SignalError(Exception err) { 28 public void SignalError(Exception err) {
25 if (m_error != null) { 29 if (m_reject != null) {
26 try { 30 try {
27 m_error(err); 31 m_reject(err);
28 // Analysis disable once EmptyGeneralCatchClause 32 m_deferred.Resolve();
29 } catch { 33 } catch (Exception ex) {
34 m_deferred.Reject(ex);
30 } 35 }
31 } 36 }
37 }
38 }
39
40 PromiseState m_state;
41
42 Exception m_error;
43
44 public bool IsRejected {
45 get {
46 return m_state == PromiseState.Rejected;
47 }
48 }
49
50 public bool IsResolved {
51 get {
52 return m_state == PromiseState.Resolved;
53 }
54 }
55
56 public Exception RejectReason {
57 get {
58 return m_error;
32 } 59 }
33 } 60 }
34 61
35 62
36 #region implemented abstract members of AbstractPromise 63 #region implemented abstract members of AbstractPromise
37 64
38 protected override void SignalHandler(HandlerDescriptor handler, int signal) { 65 protected override void SignalHandler(HandlerDescriptor handler) {
39 switch (signal) { 66 switch (m_state) {
40 case SUCCEEDED_STATE: 67 case PromiseState.Resolved:
41 handler.SignalSuccess(); 68 handler.SignalSuccess();
42 break; 69 break;
43 case REJECTED_STATE: 70 case PromiseState.Rejected:
44 handler.SignalError(RejectReason); 71 handler.SignalError(RejectReason);
45 break; 72 break;
46 default: 73 default:
47 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", signal)); 74 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state));
48 } 75 }
49 } 76 }
50 77
51 protected override Signal GetFulfillSignal() { 78 protected override Signal GetFulfillSignal() {
52 var signal = new Signal(); 79 var signal = new Signal();
54 return signal; 81 return signal;
55 } 82 }
56 83
57 #endregion 84 #endregion
58 85
86 protected void CompleteResolve() {
87 m_state = PromiseState.Resolved;
88 CompleteTransit();
89 }
90
59 public Type ResultType { 91 public Type ResultType {
60 get { 92 get {
61 return typeof(void); 93 return typeof(void);
62 } 94 }
95 }
96
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
119 protected void Rethrow() {
120 Debug.Assert(m_error != null);
121 if (m_error is OperationCanceledException)
122 throw new OperationCanceledException("Operation cancelled", m_error);
123 else
124 throw new TargetInvocationException(m_error);
63 } 125 }
64 126
65 public void On(Action success, Action<Exception> error) { 127 public void On(Action success, Action<Exception> error) {
66 AddHandler(new HandlerDescriptor(success, error)); 128 AddHandler(new HandlerDescriptor(success, error));
67 } 129 }
70 throw new InvalidCastException(); 132 throw new InvalidCastException();
71 } 133 }
72 134
73 public void Join() { 135 public void Join() {
74 WaitResult(-1); 136 WaitResult(-1);
137 if (IsRejected)
138 Rethrow();
75 } 139 }
76 140
77 public void Join(int timeout) { 141 public void Join(int timeout) {
78 WaitResult(timeout); 142 WaitResult(timeout);
79 } 143 }
80
81 protected void SetResult() {
82 if(BeginSetResult())
83 EndSetResult();
84 }
85 } 144 }
86 } 145 }
87 146