annotate Implab/AbstractPromise.cs @ 243:b1e0ffdf3451 v3

working on promises
author cin
date Wed, 24 Jan 2018 19:24:10 +0300
parents cbe10ac0731e
children eee3e49dd1ff
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
1 using System;
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
2 using System.Diagnostics;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
3 using System.Reflection;
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
4 using Implab.Parallels;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
5
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
6 namespace Implab {
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
7 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise {
242
cbe10ac0731e Working on promises
cin
parents: 197
diff changeset
8 public class HandlerDescriptor {
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
9 readonly Action m_resolve;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
10 readonly Action<Exception> m_reject;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
11
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
12 readonly IDeferred m_deferred;
242
cbe10ac0731e Working on promises
cin
parents: 197
diff changeset
13 public HandlerDescriptor(Action success, Action<Exception> error) {
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
14 m_resolve = success;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
15 m_reject = error;
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
16 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
17
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
18 public void SignalSuccess() {
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
19 try {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
20 if (m_resolve != null)
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
21 m_resolve();
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
22 m_deferred.Resolve();
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
23 } catch (Exception ex) {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
24 m_deferred.Reject(ex);
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
25 }
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
26 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
27
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
28 public void SignalError(Exception err) {
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
29 if (m_reject != null) {
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
30 try {
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
31 m_reject(err);
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
32 m_deferred.Resolve();
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
33 } catch (Exception ex) {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
34 m_deferred.Reject(ex);
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
35 }
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
36 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
37 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
38 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
39
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
40 PromiseState m_state;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
41
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
42 Exception m_error;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
43
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
44 public bool IsRejected {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
45 get {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
46 return m_state == PromiseState.Rejected;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
47 }
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
48 }
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
49
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
50 public bool IsResolved {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
51 get {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
52 return m_state == PromiseState.Resolved;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
53 }
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
54 }
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
55
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
56 public Exception RejectReason {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
57 get {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
58 return m_error;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
59 }
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
60 }
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
61
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
62
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
63 #region implemented abstract members of AbstractPromise
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
64
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
65 protected override void SignalHandler(HandlerDescriptor handler) {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
66 switch (m_state) {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
67 case PromiseState.Resolved:
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
68 handler.SignalSuccess();
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
69 break;
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
70 case PromiseState.Rejected:
242
cbe10ac0731e Working on promises
cin
parents: 197
diff changeset
71 handler.SignalError(RejectReason);
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
72 break;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
73 default:
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
74 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state));
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
75 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
76 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
77
242
cbe10ac0731e Working on promises
cin
parents: 197
diff changeset
78 protected override Signal GetFulfillSignal() {
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
79 var signal = new Signal();
242
cbe10ac0731e Working on promises
cin
parents: 197
diff changeset
80 On(signal.Set, e => signal.Set());
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
81 return signal;
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
82 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
83
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
84 #endregion
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
85
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
86 protected void CompleteResolve() {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
87 m_state = PromiseState.Resolved;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
88 CompleteTransit();
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
89 }
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
90
242
cbe10ac0731e Working on promises
cin
parents: 197
diff changeset
91 public Type ResultType {
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
92 get {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
93 return typeof(void);
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
94 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
95 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
96
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
97 /// <summary>
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
98 /// Выполняет обещание, сообщая об ошибке
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
99 /// </summary>
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
100 /// <remarks>
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
101 /// Поскольку обещание должно работать в многопточной среде, при его выполнении сразу несколько потоков
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
102 /// могу вернуть ошибку, при этом только первая будет использована в качестве результата, остальные
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
103 /// будут проигнорированы.
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
104 /// </remarks>
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
105 /// <param name="error">Исключение возникшее при выполнении операции</param>
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
106 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
107 protected void SetError(Exception error) {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
108 if (BeginTransit()) {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
109 m_error = error;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
110 m_state = PromiseState.Rejected;
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
111 CompleteTransit();
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
112 } else {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
113 WaitTransition();
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
114 if (m_state == PromiseState.Resolved)
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
115 throw new InvalidOperationException("The promise is already resolved");
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
116 }
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
117 }
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
118
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
119 protected void Rethrow() {
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
120 Debug.Assert(m_error != null);
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
121 if (m_error is OperationCanceledException)
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
122 throw new OperationCanceledException("Operation cancelled", m_error);
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
123 else
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
124 throw new TargetInvocationException(m_error);
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
125 }
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
126
242
cbe10ac0731e Working on promises
cin
parents: 197
diff changeset
127 public void On(Action success, Action<Exception> error) {
cbe10ac0731e Working on promises
cin
parents: 197
diff changeset
128 AddHandler(new HandlerDescriptor(success, error));
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
129 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
130
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
131 public IPromise<T> Cast<T>() {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
132 throw new InvalidCastException();
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
133 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
134
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
135 public void Join() {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
136 WaitResult(-1);
243
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
137 if (IsRejected)
b1e0ffdf3451 working on promises
cin
parents: 242
diff changeset
138 Rethrow();
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
139 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
140
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
141 public void Join(int timeout) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
142 WaitResult(timeout);
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
143 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
144 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
145 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
146