comparison Implab/Promise.cs @ 144:8c0b95069066 v2

DRAFT: refactoring
author cin
date Fri, 06 Mar 2015 15:45:26 +0300
parents f75cfa58e3d4
children 8200ab154c8a
comparison
equal deleted inserted replaced
143:16f926ee499d 144:8c0b95069066
1 using System; 1 using System;
2 using System.Diagnostics; 2 using Implab.Parallels;
3 3
4 namespace Implab { 4 namespace Implab {
5 public class Promise : AbstractPromise<Promise.HandlerDescriptor>, IPromise, IDeferred { 5 public class Promise : AbstractPromise, IDeferred {
6 public static readonly Promise SUCCESS;
6 7
7 public struct HandlerDescriptor { 8 static Promise() {
8 readonly Action m_success; 9 SUCCESS = new Promise();
9 readonly Action<Exception> m_error; 10 SUCCESS.Resolve();
10 readonly Action<Exception> m_cancel;
11 readonly IDeferred m_deferred;
12
13 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel, IDeferred deferred) {
14 m_success = success;
15 m_error = error;
16 m_cancel = cancel;
17 m_deferred = deferred;
18 }
19
20 public void SignalSuccess() {
21 if (m_success != null) {
22 try {
23 m_success();
24 if (m_deferred != null)
25 m_deferred.Resolve();
26 } catch (Exception err) {
27 SignalError(err);
28 }
29 }
30 }
31
32 public void SignalError(Exception err) {
33 if (m_error != null) {
34 try {
35 m_error(err);
36 if (m_deferred != null)
37 m_deferred.Resolve();
38 } catch (Exception err2) {
39 if (m_deferred != null)
40 m_deferred.Reject(err2);
41 }
42 } else {
43 if (m_deferred != null)
44 m_deferred.Reject(err);
45 }
46 }
47
48 public void SignalCancel(Exception reason) {
49 if (m_cancel != null) {
50 try {
51 m_cancel(reason);
52 if (m_deferred != null)
53 m_deferred.Resolve();
54 } catch (Exception err) {
55 SignalError(err);
56 }
57 } else if (reason != null && m_error != null) {
58 try {
59 m_error(new OperationCanceledException("The operation was canceled.", reason));
60 if (m_deferred != null)
61 m_deferred.Resolve();
62 } catch (Exception err) {
63 SignalError(err);
64 }
65 } else {
66 if (m_deferred != null)
67 m_deferred.Cancel(reason);
68 }
69 }
70 } 11 }
71 12
72 public void Resolve() { 13 public void Resolve() {
73 BeginSetResult(); 14 SetResult();
74 EndSetResult();
75 } 15 }
76 16
77 public void Reject(Exception error) { 17 public void Reject(Exception error) {
78 SetError(error); 18 SetError(error);
79 } 19 }
80
81 #region implemented abstract members of AbstractPromise
82
83 protected override void SignalSuccess(HandlerDescriptor handler) {
84 handler.SignalSuccess();
85 }
86
87 protected override void SignalError(HandlerDescriptor handler, Exception error) {
88 handler.SignalError(error);
89 }
90
91 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
92 handler.SignalCancel(reason);
93 }
94
95 protected override void Listen(PromiseEventType events, Action handler) {
96 AddHandler(new HandlerDescriptor(
97 events.HasFlag(PromiseEventType.Success) ? handler : null,
98 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null,
99 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null,
100 null
101 ));
102 }
103
104 #endregion
105
106
107 public Type PromiseType {
108 get {
109 return typeof(void);
110 }
111 }
112
113 public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) {
114 var promise = new Promise();
115 if (success != null)
116 promise.On(Cancel, PromiseEventType.Cancelled);
117
118 AddHandler(new HandlerDescriptor(success, error, cancel, promise));
119
120 return promise;
121 }
122
123 public IPromise Then(Action success, Action<Exception> error) {
124 return Then(success, error, null);
125 }
126
127 public IPromise Then(Action success) {
128 return Then(success, null, null);
129 }
130
131 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
132 AddHandler(new HandlerDescriptor(success, error, cancel, null));
133 return this;
134 }
135
136 public IPromise On(Action success, Action<Exception> error) {
137 return On(success, error, null);
138 }
139
140 public IPromise On(Action success) {
141 return On(success, null, null);
142 }
143
144 public IPromise On(Action handler, PromiseEventType events) {
145 return On(
146 events.HasFlag(PromiseEventType.Success) ? handler : null,
147 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null,
148 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null
149 );
150 }
151
152 public IPromise<T> Cast<T>() {
153 throw new InvalidCastException();
154 }
155
156 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception,IPromise> cancel) {
157 var medium = new Promise();
158
159 On(
160 () => {
161 if (medium.IsCancelled)
162 return;
163 if (chained != null)
164 ConnectPromise(chained(), medium);
165 },
166 ex => {
167 if (medium.IsCancelled)
168 return;
169 if (error != null) {
170 try {
171 ConnectPromise(error(ex), medium);
172 } catch (Exception ex2) {
173 medium.Reject(ex2);
174 }
175 } else {
176 medium.Reject(ex);
177 }
178 },
179 reason => {
180 if (medium.IsCancelled)
181 return;
182 if (cancel != null)
183 ConnectPromise(cancel(reason), medium);
184 else
185 medium.Cancel(reason);
186 }
187 );
188
189 if (chained != null)
190 medium.On(Cancel, PromiseEventType.Cancelled);
191
192 return medium;
193 }
194
195 static void ConnectPromise(IPromise result, Promise medium) {
196 if (result != null) {
197 result.On(
198 medium.Resolve,
199 medium.Reject,
200 medium.Cancel
201 );
202 medium.On(null,null,result.Cancel);
203 } else {
204 medium.Reject(
205 new NullReferenceException(
206 "The chained asynchronous operation returned" +
207 " 'null' where the promise instance is expected"
208 )
209 );
210 }
211 }
212
213 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error) {
214 return Chain(chained, error, null);
215 }
216
217 public IPromise Chain(Func<IPromise> chained) {
218 return Chain(chained, null, null);
219 }
220 } 20 }
221 } 21 }
222 22