Auto status change to "Under Review"
@@ -0,0 +1,18 | |||
|
1 | using System; | |
|
2 | using System.Reflection; | |
|
3 | using System.Runtime.ExceptionServices; | |
|
4 | ||
|
5 | namespace Implab { | |
|
6 | public static class ExceptionHelpers { | |
|
7 | public static void Rethrow(this Exception that) { | |
|
8 | ExceptionDispatchInfo.Capture(that).Throw(); | |
|
9 | } | |
|
10 | ||
|
11 | public static void ThrowInvocationException(this Exception that) { | |
|
12 | if (that is OperationCanceledException) | |
|
13 | throw new OperationCanceledException("Operation cancelled", that); | |
|
14 | else | |
|
15 | throw new TargetInvocationException(that); | |
|
16 | } | |
|
17 | } | |
|
18 | } No newline at end of file |
@@ -0,0 +1,20 | |||
|
1 | using System; | |
|
2 | using System.Threading; | |
|
3 | ||
|
4 | namespace Implab { | |
|
5 | public class SyncContextDispatcher : IDispatcher { | |
|
6 | SynchronizationContext m_context; | |
|
7 | public SyncContextDispatcher(SynchronizationContext context) { | |
|
8 | Safe.ArgumentNotNull(context, nameof(context)); | |
|
9 | m_context = context; | |
|
10 | } | |
|
11 | ||
|
12 | public void Enqueue(Action job) { | |
|
13 | m_context.Post((o) => job(), null); | |
|
14 | } | |
|
15 | ||
|
16 | public void Enqueue<T>(Action<T> job, T arg) { | |
|
17 | m_context.Post((o) => job((T)o), arg); | |
|
18 | } | |
|
19 | } | |
|
20 | } No newline at end of file |
@@ -0,0 +1,20 | |||
|
1 | using System; | |
|
2 | using System.Threading; | |
|
3 | ||
|
4 | namespace Implab.Parallels { | |
|
5 | public class ThreadPoolDispatcher : IDispatcher { | |
|
6 | ||
|
7 | public static ThreadPoolDispatcher Instance { get; private set; } = new ThreadPoolDispatcher(); | |
|
8 | ||
|
9 | private ThreadPoolDispatcher() { | |
|
10 | } | |
|
11 | ||
|
12 | public void Enqueue(Action job) { | |
|
13 | ThreadPool.QueueUserWorkItem((o) => job(), null); | |
|
14 | } | |
|
15 | ||
|
16 | public void Enqueue<T>(Action<T> job, T arg) { | |
|
17 | ThreadPool.QueueUserWorkItem((o) => job((T)o), arg); | |
|
18 | } | |
|
19 | } | |
|
20 | } No newline at end of file |
@@ -0,0 +1,209 | |||
|
1 | using System; | |
|
2 | using System.Collections.Generic; | |
|
3 | using System.Diagnostics; | |
|
4 | using System.Reflection; | |
|
5 | using System.Threading.Tasks; | |
|
6 | using Implab.Parallels; | |
|
7 | ||
|
8 | namespace Implab { | |
|
9 | public class Promise : AbstractEvent<IResolvable>, IPromise { | |
|
10 | public static IDispatcher DefaultDispatcher { | |
|
11 | get { | |
|
12 | return ThreadPoolDispatcher.Instance; | |
|
13 | } | |
|
14 | } | |
|
15 | ||
|
16 | class ResolvableSignal : IResolvable { | |
|
17 | public Signal Signal { get; private set; } | |
|
18 | public ResolvableSignal() { | |
|
19 | Signal = new Signal(); | |
|
20 | } | |
|
21 | ||
|
22 | ||
|
23 | public void Reject(Exception error) { | |
|
24 | Signal.Set(); | |
|
25 | } | |
|
26 | ||
|
27 | public void Resolve() { | |
|
28 | Signal.Set(); | |
|
29 | } | |
|
30 | } | |
|
31 | ||
|
32 | PromiseState m_state; | |
|
33 | ||
|
34 | Exception m_error; | |
|
35 | ||
|
36 | public bool IsRejected { | |
|
37 | get { | |
|
38 | return m_state == PromiseState.Rejected; | |
|
39 | } | |
|
40 | } | |
|
41 | ||
|
42 | public bool IsFulfilled { | |
|
43 | get { | |
|
44 | return m_state == PromiseState.Fulfilled; | |
|
45 | } | |
|
46 | } | |
|
47 | ||
|
48 | public Exception RejectReason { | |
|
49 | get { | |
|
50 | return m_error; | |
|
51 | } | |
|
52 | } | |
|
53 | ||
|
54 | internal Promise() { | |
|
55 | ||
|
56 | } | |
|
57 | ||
|
58 | internal void ResolvePromise() { | |
|
59 | if (BeginTransit()) { | |
|
60 | m_state = PromiseState.Fulfilled; | |
|
61 | CompleteTransit(); | |
|
62 | } | |
|
63 | } | |
|
64 | ||
|
65 | internal void RejectPromise(Exception reason) { | |
|
66 | if (BeginTransit()) { | |
|
67 | m_error = reason; | |
|
68 | m_state = PromiseState.Rejected; | |
|
69 | CompleteTransit(); | |
|
70 | } | |
|
71 | } | |
|
72 | ||
|
73 | ||
|
74 | #region implemented abstract members of AbstractPromise | |
|
75 | ||
|
76 | protected override void SignalHandler(IResolvable handler) { | |
|
77 | switch (m_state) { | |
|
78 | case PromiseState.Fulfilled: | |
|
79 | handler.Resolve(); | |
|
80 | break; | |
|
81 | case PromiseState.Rejected: | |
|
82 | handler.Reject(RejectReason); | |
|
83 | break; | |
|
84 | default: | |
|
85 | throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state)); | |
|
86 | } | |
|
87 | } | |
|
88 | ||
|
89 | protected void WaitResult(int timeout) { | |
|
90 | if (!(IsResolved || GetFulfillSignal().Wait(timeout))) | |
|
91 | throw new TimeoutException(); | |
|
92 | } | |
|
93 | ||
|
94 | protected Signal GetFulfillSignal() { | |
|
95 | var next = new ResolvableSignal(); | |
|
96 | Then(next); | |
|
97 | return next.Signal; | |
|
98 | } | |
|
99 | ||
|
100 | #endregion | |
|
101 | ||
|
102 | ||
|
103 | public Type ResultType { | |
|
104 | get { | |
|
105 | return typeof(void); | |
|
106 | } | |
|
107 | } | |
|
108 | ||
|
109 | ||
|
110 | protected void Rethrow() { | |
|
111 | Debug.Assert(m_error != null); | |
|
112 | if (m_error is OperationCanceledException) | |
|
113 | throw new OperationCanceledException("Operation cancelled", m_error); | |
|
114 | else | |
|
115 | throw new TargetInvocationException(m_error); | |
|
116 | } | |
|
117 | ||
|
118 | public void Then(IResolvable next) { | |
|
119 | AddHandler(next); | |
|
120 | } | |
|
121 | ||
|
122 | public IPromise<T> Cast<T>() { | |
|
123 | throw new InvalidCastException(); | |
|
124 | } | |
|
125 | ||
|
126 | public void Join() { | |
|
127 | WaitResult(-1); | |
|
128 | if (IsRejected) | |
|
129 | Rethrow(); | |
|
130 | } | |
|
131 | ||
|
132 | public void Join(int timeout) { | |
|
133 | WaitResult(timeout); | |
|
134 | if (IsRejected) | |
|
135 | Rethrow(); | |
|
136 | } | |
|
137 | ||
|
138 | public static ResolvedPromise Resolve() { | |
|
139 | return new ResolvedPromise(); | |
|
140 | } | |
|
141 | ||
|
142 | public static ResolvedPromise<T> Resolve<T>(T result) { | |
|
143 | return new ResolvedPromise<T>(result); | |
|
144 | } | |
|
145 | ||
|
146 | public static RejectedPromise Reject(Exception reason) { | |
|
147 | return new RejectedPromise(reason); | |
|
148 | } | |
|
149 | ||
|
150 | public static RejectedPromise<T> Reject<T>(Exception reason) { | |
|
151 | return new RejectedPromise<T>(reason); | |
|
152 | } | |
|
153 | ||
|
154 | public static IPromise Create(PromiseExecutor executor) { | |
|
155 | Safe.ArgumentNotNull(executor, nameof(executor)); | |
|
156 | ||
|
157 | var p = new Promise(); | |
|
158 | var d = new Deferred(p, DefaultDispatcher); | |
|
159 | ||
|
160 | try { | |
|
161 | executor(d); | |
|
162 | } catch (Exception e) { | |
|
163 | d.Reject(e); | |
|
164 | } | |
|
165 | ||
|
166 | return d.Promise; | |
|
167 | } | |
|
168 | ||
|
169 | public static IPromise<T> Create<T>(PromiseExecutor<T> executor) { | |
|
170 | Safe.ArgumentNotNull(executor, nameof(executor)); | |
|
171 | ||
|
172 | var p = new Promise<T>(); | |
|
173 | var d = new Deferred<T>(p, DefaultDispatcher); | |
|
174 | ||
|
175 | try { | |
|
176 | executor(d); | |
|
177 | } catch (Exception e) { | |
|
178 | d.Reject(e); | |
|
179 | } | |
|
180 | ||
|
181 | return d.Promise; | |
|
182 | } | |
|
183 | ||
|
184 | public static IPromise All(IEnumerable<IPromise> promises) { | |
|
185 | var d = new Deferred(DefaultDispatcher); | |
|
186 | var all = new PromiseAll(d); | |
|
187 | foreach (var promise in promises) { | |
|
188 | all.AddPromise(promise); | |
|
189 | if (all.Done) | |
|
190 | break; | |
|
191 | } | |
|
192 | all.Complete(); | |
|
193 | return all.ResultPromise; | |
|
194 | } | |
|
195 | ||
|
196 | public static IPromise<T[]> All<T>(IEnumerable<IPromise<T>> promises, Func<T, IPromise> cleanup, Action cancel) { | |
|
197 | var d = new Deferred<T[]>(DefaultDispatcher); | |
|
198 | var all = new PromiseAll<T>(d, cleanup, cancel); | |
|
199 | foreach (var promise in promises) { | |
|
200 | all.AddPromise(promise); | |
|
201 | if (all.Done) | |
|
202 | break; | |
|
203 | } | |
|
204 | all.Complete(); | |
|
205 | return all.ResultPromise; | |
|
206 | } | |
|
207 | } | |
|
208 | } | |
|
209 |
@@ -0,0 +1,40 | |||
|
1 | using System; | |
|
2 | using System.Threading; | |
|
3 | ||
|
4 | namespace Implab | |
|
5 | { | |
|
6 | class PromiseAll : IResolvable { | |
|
7 | int m_count; | |
|
8 | ||
|
9 | readonly Deferred m_deferred; | |
|
10 | ||
|
11 | public bool Done { | |
|
12 | get { return m_deferred.Promise.IsResolved; } | |
|
13 | } | |
|
14 | ||
|
15 | public IPromise ResultPromise { | |
|
16 | get { return m_deferred.Promise; } | |
|
17 | } | |
|
18 | ||
|
19 | public void AddPromise(IPromise promise) { | |
|
20 | Interlocked.Increment(ref m_count); | |
|
21 | } | |
|
22 | ||
|
23 | public PromiseAll(Deferred deferred) { | |
|
24 | m_deferred = deferred; | |
|
25 | } | |
|
26 | ||
|
27 | public void Resolve() { | |
|
28 | if (Interlocked.Decrement(ref m_count) == 0) | |
|
29 | m_deferred.Resolve(); | |
|
30 | } | |
|
31 | ||
|
32 | public void Complete() { | |
|
33 | Resolve(); | |
|
34 | } | |
|
35 | ||
|
36 | public void Reject(Exception error) { | |
|
37 | m_deferred.Reject(error); | |
|
38 | } | |
|
39 | } | |
|
40 | } No newline at end of file |
@@ -0,0 +1,90 | |||
|
1 | using System; | |
|
2 | using System.Collections.Generic; | |
|
3 | using System.Linq; | |
|
4 | using System.Threading; | |
|
5 | ||
|
6 | namespace Implab { | |
|
7 | class PromiseAll<T> : IResolvable { | |
|
8 | ||
|
9 | int m_count; | |
|
10 | ||
|
11 | readonly List<IPromise<T>> m_promises = new List<IPromise<T>>(); | |
|
12 | ||
|
13 | readonly Deferred<T[]> m_deferred; | |
|
14 | ||
|
15 | IPromise<T[]> m_result; | |
|
16 | ||
|
17 | readonly Func<T, IPromise> m_cleanup; | |
|
18 | ||
|
19 | readonly Action m_cancel; | |
|
20 | ||
|
21 | public bool Done { | |
|
22 | get { return m_deferred.Promise.IsResolved && m_cleanup == null; } | |
|
23 | } | |
|
24 | ||
|
25 | public IPromise<T[]> ResultPromise { | |
|
26 | get { return m_result; } | |
|
27 | } | |
|
28 | ||
|
29 | public void AddPromise(IPromise<T> promise) { | |
|
30 | Interlocked.Increment(ref m_count); | |
|
31 | promise.Then(this); | |
|
32 | } | |
|
33 | ||
|
34 | public PromiseAll(Deferred<T[]> deferred, Func<T, IPromise> cleanup, Action cancel) { | |
|
35 | m_deferred = deferred; | |
|
36 | m_cancel = cancel; | |
|
37 | m_cleanup = cleanup; | |
|
38 | } | |
|
39 | ||
|
40 | public void Resolve() { | |
|
41 | if (Interlocked.Decrement(ref m_count) == 0) | |
|
42 | m_deferred.Resolve(GetResults()); | |
|
43 | } | |
|
44 | ||
|
45 | public void Reject(Exception error) { | |
|
46 | m_deferred.Reject(error); | |
|
47 | } | |
|
48 | ||
|
49 | public void Complete() { | |
|
50 | if (m_cancel != null || m_cleanup != null) | |
|
51 | m_result = m_deferred.Promise.Catch(CleanupResults); | |
|
52 | else | |
|
53 | m_result = m_deferred.Promise; | |
|
54 | } | |
|
55 | ||
|
56 | IPromise<T[]> CleanupResults(Exception reason) { | |
|
57 | var errors = new List<Exception>(); | |
|
58 | errors.Add(reason); | |
|
59 | ||
|
60 | if (m_cancel != null) | |
|
61 | try { | |
|
62 | m_cancel(); | |
|
63 | } catch (Exception e) { | |
|
64 | errors.Add(e); | |
|
65 | } | |
|
66 | ||
|
67 | if (m_cleanup != null) { | |
|
68 | return Promise.All( | |
|
69 | m_promises.Select(p => p | |
|
70 | .Then(m_cleanup, e => { }) | |
|
71 | .Catch(e => { | |
|
72 | errors.Add(e); | |
|
73 | }) | |
|
74 | ) | |
|
75 | ).Then<T[]>(new Func<T[]>(() => { | |
|
76 | throw new AggregateException(errors); | |
|
77 | }), (Func<Exception, T[]>)null); | |
|
78 | } else { | |
|
79 | return Promise.Reject<T[]>(errors.Count > 1 ? new AggregateException(errors) : reason); | |
|
80 | } | |
|
81 | } | |
|
82 | ||
|
83 | T[] GetResults() { | |
|
84 | var results = new T[m_promises.Count]; | |
|
85 | for (var i = 0; i < results.Length; i++) | |
|
86 | results[i] = m_promises[i].Join(); | |
|
87 | return results; | |
|
88 | } | |
|
89 | } | |
|
90 | } No newline at end of file |
@@ -0,0 +1,62 | |||
|
1 | using System; | |
|
2 | using System.Runtime.CompilerServices; | |
|
3 | using System.Threading; | |
|
4 | using Implab.Parallels; | |
|
5 | ||
|
6 | namespace Implab | |
|
7 | { | |
|
8 | public struct PromiseAwaiter : INotifyCompletion { | |
|
9 | class PromiseEvent : IResolvable { | |
|
10 | IDispatcher m_dispatcher; | |
|
11 | ||
|
12 | Action m_handler; | |
|
13 | ||
|
14 | public PromiseEvent(Action handler, IDispatcher dispatcher) { | |
|
15 | m_handler = handler; | |
|
16 | m_dispatcher = dispatcher; | |
|
17 | } | |
|
18 | ||
|
19 | public void Resolve() { | |
|
20 | m_dispatcher.Enqueue(m_handler); | |
|
21 | } | |
|
22 | ||
|
23 | public void Reject(Exception error) { | |
|
24 | m_dispatcher.Enqueue(m_handler); | |
|
25 | } | |
|
26 | } | |
|
27 | ||
|
28 | readonly IPromise m_promise; | |
|
29 | readonly IDispatcher m_dispatcher; | |
|
30 | ||
|
31 | public PromiseAwaiter(IPromise promise, IDispatcher dispatcher) { | |
|
32 | m_promise = promise; | |
|
33 | m_dispatcher = dispatcher; | |
|
34 | } | |
|
35 | ||
|
36 | public PromiseAwaiter(IPromise promise) { | |
|
37 | m_promise = promise; | |
|
38 | m_dispatcher = GetDispatcher(); | |
|
39 | } | |
|
40 | ||
|
41 | public void OnCompleted (Action continuation) { | |
|
42 | if (m_promise != null) | |
|
43 | m_promise.Then(new PromiseEvent(continuation, GetDispatcher())); | |
|
44 | } | |
|
45 | ||
|
46 | public void GetResult() { | |
|
47 | m_promise.Join(); | |
|
48 | } | |
|
49 | ||
|
50 | static IDispatcher GetDispatcher() { | |
|
51 | if(SynchronizationContext.Current == null) | |
|
52 | return ThreadPoolDispatcher.Instance; | |
|
53 | return new SyncContextDispatcher(SynchronizationContext.Current); | |
|
54 | } | |
|
55 | ||
|
56 | public bool IsCompleted { | |
|
57 | get { | |
|
58 | return m_promise.IsResolved; | |
|
59 | } | |
|
60 | } | |
|
61 | } | |
|
62 | } No newline at end of file |
@@ -0,0 +1,62 | |||
|
1 | using System; | |
|
2 | using System.Runtime.CompilerServices; | |
|
3 | using System.Threading; | |
|
4 | using Implab.Parallels; | |
|
5 | ||
|
6 | namespace Implab { | |
|
7 | public struct PromiseAwaiter<T> : INotifyCompletion { | |
|
8 | class PromiseEvent : IResolvable<T> { | |
|
9 | IDispatcher m_dispatcher; | |
|
10 | ||
|
11 | Action m_handler; | |
|
12 | ||
|
13 | public PromiseEvent(Action handler, IDispatcher dispatcher) { | |
|
14 | m_handler = handler; | |
|
15 | m_dispatcher = dispatcher; | |
|
16 | } | |
|
17 | ||
|
18 | public void Resolve(T result) { | |
|
19 | m_dispatcher.Enqueue(m_handler); | |
|
20 | } | |
|
21 | ||
|
22 | public void Reject(Exception error) { | |
|
23 | m_dispatcher.Enqueue(m_handler); | |
|
24 | } | |
|
25 | } | |
|
26 | ||
|
27 | readonly IPromise<T> m_promise; | |
|
28 | ||
|
29 | readonly IDispatcher m_dispatcher; | |
|
30 | ||
|
31 | public PromiseAwaiter(IPromise<T> promise) { | |
|
32 | m_promise = promise; | |
|
33 | m_dispatcher = GetDispatcher(); | |
|
34 | } | |
|
35 | ||
|
36 | public PromiseAwaiter(IPromise<T> promise, IDispatcher dispatcher) { | |
|
37 | m_promise = promise; | |
|
38 | m_dispatcher = dispatcher; | |
|
39 | } | |
|
40 | ||
|
41 | public void OnCompleted(Action continuation) { | |
|
42 | if (m_promise != null) | |
|
43 | m_promise.Then(new PromiseEvent(continuation, GetDispatcher())); | |
|
44 | } | |
|
45 | ||
|
46 | public T GetResult() { | |
|
47 | return m_promise.Join(); | |
|
48 | } | |
|
49 | ||
|
50 | static IDispatcher GetDispatcher() { | |
|
51 | if (SynchronizationContext.Current == null) | |
|
52 | return ThreadPoolDispatcher.Instance; | |
|
53 | return new SyncContextDispatcher(SynchronizationContext.Current); | |
|
54 | } | |
|
55 | ||
|
56 | public bool IsCompleted { | |
|
57 | get { | |
|
58 | return m_promise.IsResolved; | |
|
59 | } | |
|
60 | } | |
|
61 | } | |
|
62 | } No newline at end of file |
@@ -0,0 +1,3 | |||
|
1 | namespace Implab { | |
|
2 | public delegate void PromiseExecutor(Deferred deferred); | |
|
3 | } No newline at end of file |
@@ -0,0 +1,3 | |||
|
1 | namespace Implab { | |
|
2 | public delegate void PromiseExecutor<T>(Deferred<T> d); | |
|
3 | } No newline at end of file |
@@ -0,0 +1,56 | |||
|
1 | using System; | |
|
2 | using System.Diagnostics; | |
|
3 | ||
|
4 | namespace Implab { | |
|
5 | class PromiseFuncReaction<TIn, TRet> : PromiseReaction<TIn> { | |
|
6 | readonly Deferred<TRet> m_next; | |
|
7 | ||
|
8 | public IPromise<TRet> Promise { | |
|
9 | get { return m_next.Promise; } | |
|
10 | } | |
|
11 | ||
|
12 | public PromiseFuncReaction(Func<TIn, TRet> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
13 | m_next = new Deferred<TRet>(dispatcher); | |
|
14 | if (fulfilled != null) | |
|
15 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
16 | ||
|
17 | if (rejected != null) | |
|
18 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
19 | } | |
|
20 | ||
|
21 | public PromiseFuncReaction(Func<TIn, IPromise<TRet>> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
22 | m_next = new Deferred<TRet>(dispatcher); | |
|
23 | if (fulfilled != null) | |
|
24 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
25 | ||
|
26 | if (rejected != null) | |
|
27 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
28 | } | |
|
29 | ||
|
30 | public PromiseFuncReaction(Func<TIn, TRet> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
31 | m_next = new Deferred<TRet>(dispatcher); | |
|
32 | if (fulfilled != null) | |
|
33 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
34 | ||
|
35 | if (rejected != null) | |
|
36 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
37 | } | |
|
38 | ||
|
39 | public PromiseFuncReaction(Func<TIn, IPromise<TRet>> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
40 | m_next = new Deferred<TRet>(dispatcher); | |
|
41 | if (fulfilled != null) | |
|
42 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
43 | ||
|
44 | if (rejected != null) | |
|
45 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
46 | } | |
|
47 | ||
|
48 | protected override void DefaultReject(Exception reason) { | |
|
49 | m_next.Reject(reason); | |
|
50 | } | |
|
51 | ||
|
52 | protected override void DefaultResolve(TIn result) { | |
|
53 | m_next.Resolve((TRet)(object)result); | |
|
54 | } | |
|
55 | } | |
|
56 | } No newline at end of file |
@@ -0,0 +1,102 | |||
|
1 | using System; | |
|
2 | using System.Diagnostics; | |
|
3 | ||
|
4 | namespace Implab { | |
|
5 | class PromiseHandler { | |
|
6 | public static Action<T> Create<T>(Action<T> handler, Deferred next) { | |
|
7 | Debug.Assert(handler != null); | |
|
8 | ||
|
9 | return (v) => { | |
|
10 | try { | |
|
11 | handler(v); | |
|
12 | next.Resolve(); | |
|
13 | } catch (Exception err) { | |
|
14 | next.Reject(err); | |
|
15 | } | |
|
16 | }; | |
|
17 | } | |
|
18 | ||
|
19 | public static Action<T> Create<T>(Func<T, IPromise> handler, Deferred next) { | |
|
20 | Debug.Assert(handler != null); | |
|
21 | ||
|
22 | return (v) => { | |
|
23 | try { | |
|
24 | next.Resolve(handler(v)); | |
|
25 | } catch (Exception err) { | |
|
26 | next.Reject(err); | |
|
27 | } | |
|
28 | }; | |
|
29 | } | |
|
30 | ||
|
31 | public static Action<T> Create<T, T2>(Func<T, T2> handler, Deferred<T2> next) { | |
|
32 | Debug.Assert(handler != null); | |
|
33 | ||
|
34 | return (v) => { | |
|
35 | try { | |
|
36 | next.Resolve(handler(v)); | |
|
37 | } catch (Exception err) { | |
|
38 | next.Reject(err); | |
|
39 | } | |
|
40 | }; | |
|
41 | } | |
|
42 | ||
|
43 | public static Action<T> Create<T, T2>(Func<T, IPromise<T2>> handler, Deferred<T2> next) { | |
|
44 | Debug.Assert(handler != null); | |
|
45 | return (v) => { | |
|
46 | try { | |
|
47 | next.Resolve(handler(v)); | |
|
48 | } catch (Exception err) { | |
|
49 | next.Reject(err); | |
|
50 | } | |
|
51 | }; | |
|
52 | } | |
|
53 | ||
|
54 | public static Action Create(Action handler, Deferred next) { | |
|
55 | Debug.Assert(handler != null); | |
|
56 | ||
|
57 | return () => { | |
|
58 | try { | |
|
59 | handler(); | |
|
60 | next.Resolve(); | |
|
61 | } catch (Exception err) { | |
|
62 | next.Reject(err); | |
|
63 | } | |
|
64 | }; | |
|
65 | } | |
|
66 | ||
|
67 | public static Action Create(Func<IPromise> handler, Deferred next) { | |
|
68 | Debug.Assert(handler != null); | |
|
69 | ||
|
70 | return () => { | |
|
71 | try { | |
|
72 | next.Resolve(handler()); | |
|
73 | } catch (Exception err) { | |
|
74 | next.Reject(err); | |
|
75 | } | |
|
76 | }; | |
|
77 | } | |
|
78 | ||
|
79 | public static Action Create<T2>(Func<T2> handler, Deferred<T2> next) { | |
|
80 | Debug.Assert(handler != null); | |
|
81 | ||
|
82 | return () => { | |
|
83 | try { | |
|
84 | next.Resolve(handler()); | |
|
85 | } catch (Exception err) { | |
|
86 | next.Reject(err); | |
|
87 | } | |
|
88 | }; | |
|
89 | } | |
|
90 | ||
|
91 | public static Action Create<T2>(Func<IPromise<T2>> handler, Deferred<T2> next) { | |
|
92 | Debug.Assert(handler != null); | |
|
93 | return () => { | |
|
94 | try { | |
|
95 | next.Resolve(handler()); | |
|
96 | } catch (Exception err) { | |
|
97 | next.Reject(err); | |
|
98 | } | |
|
99 | }; | |
|
100 | } | |
|
101 | } | |
|
102 | } No newline at end of file |
@@ -0,0 +1,159 | |||
|
1 | using System; | |
|
2 | using System.Diagnostics; | |
|
3 | using System.Reflection; | |
|
4 | using Implab.Parallels; | |
|
5 | ||
|
6 | namespace Implab { | |
|
7 | public class Promise<T> : AbstractEvent<IResolvable<T>>, IPromise<T> { | |
|
8 | ||
|
9 | class ResolvableSignal : IResolvable<T> { | |
|
10 | public Signal Signal { get; private set; } | |
|
11 | public ResolvableSignal() { | |
|
12 | Signal = new Signal(); | |
|
13 | } | |
|
14 | ||
|
15 | ||
|
16 | public void Reject(Exception error) { | |
|
17 | Signal.Set(); | |
|
18 | } | |
|
19 | ||
|
20 | public void Resolve(T result) { | |
|
21 | Signal.Set(); | |
|
22 | } | |
|
23 | } | |
|
24 | ||
|
25 | class ResolvableWrapper : IResolvable<T> { | |
|
26 | readonly IResolvable m_resolvable; | |
|
27 | public ResolvableWrapper(IResolvable resolvable) { | |
|
28 | m_resolvable = resolvable; | |
|
29 | } | |
|
30 | ||
|
31 | public void Reject(Exception reason) { | |
|
32 | m_resolvable.Reject(reason); | |
|
33 | } | |
|
34 | ||
|
35 | public void Resolve(T value) { | |
|
36 | m_resolvable.Resolve(); | |
|
37 | } | |
|
38 | } | |
|
39 | ||
|
40 | PromiseState m_state; | |
|
41 | ||
|
42 | T m_result; | |
|
43 | ||
|
44 | Exception m_error; | |
|
45 | ||
|
46 | public bool IsRejected { | |
|
47 | get { | |
|
48 | return m_state == PromiseState.Rejected; | |
|
49 | } | |
|
50 | } | |
|
51 | ||
|
52 | public bool IsFulfilled { | |
|
53 | get { | |
|
54 | return m_state == PromiseState.Fulfilled; | |
|
55 | } | |
|
56 | } | |
|
57 | ||
|
58 | public Exception RejectReason { | |
|
59 | get { | |
|
60 | return m_error; | |
|
61 | } | |
|
62 | } | |
|
63 | ||
|
64 | ||
|
65 | internal void ResolvePromise(T result) { | |
|
66 | if (BeginTransit()) { | |
|
67 | m_result = result; | |
|
68 | m_state = PromiseState.Fulfilled; | |
|
69 | CompleteTransit(); | |
|
70 | } | |
|
71 | } | |
|
72 | ||
|
73 | internal void RejectPromise(Exception reason) { | |
|
74 | if (BeginTransit()) { | |
|
75 | m_error = reason; | |
|
76 | m_state = PromiseState.Rejected; | |
|
77 | CompleteTransit(); | |
|
78 | } | |
|
79 | } | |
|
80 | ||
|
81 | ||
|
82 | #region implemented abstract members of AbstractPromise | |
|
83 | ||
|
84 | protected override void SignalHandler(IResolvable<T> handler) { | |
|
85 | switch (m_state) { | |
|
86 | case PromiseState.Fulfilled: | |
|
87 | handler.Resolve(m_result); | |
|
88 | break; | |
|
89 | case PromiseState.Rejected: | |
|
90 | handler.Reject(RejectReason); | |
|
91 | break; | |
|
92 | default: | |
|
93 | throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state)); | |
|
94 | } | |
|
95 | } | |
|
96 | ||
|
97 | protected void WaitResult(int timeout) { | |
|
98 | if (!(IsResolved || GetFulfillSignal().Wait(timeout))) | |
|
99 | throw new TimeoutException(); | |
|
100 | } | |
|
101 | ||
|
102 | protected Signal GetFulfillSignal() { | |
|
103 | var next = new ResolvableSignal(); | |
|
104 | Then(next); | |
|
105 | return next.Signal; | |
|
106 | } | |
|
107 | ||
|
108 | #endregion | |
|
109 | ||
|
110 | public Type ResultType { | |
|
111 | get { | |
|
112 | return typeof(void); | |
|
113 | } | |
|
114 | } | |
|
115 | ||
|
116 | ||
|
117 | protected void Rethrow() { | |
|
118 | if (m_error is OperationCanceledException) | |
|
119 | throw new OperationCanceledException("Operation cancelled", m_error); | |
|
120 | else | |
|
121 | throw new TargetInvocationException(m_error); | |
|
122 | } | |
|
123 | ||
|
124 | public void Then(IResolvable<T> next) { | |
|
125 | AddHandler(next); | |
|
126 | } | |
|
127 | ||
|
128 | public void Then(IResolvable next) { | |
|
129 | AddHandler(new ResolvableWrapper(next)); | |
|
130 | } | |
|
131 | ||
|
132 | public IPromise<T2> Cast<T2>() { | |
|
133 | return (IPromise<T2>)this; | |
|
134 | } | |
|
135 | ||
|
136 | void IPromise.Join() { | |
|
137 | Join(); | |
|
138 | } | |
|
139 | ||
|
140 | void IPromise.Join(int timeout) { | |
|
141 | Join(timeout); | |
|
142 | } | |
|
143 | ||
|
144 | public T Join() { | |
|
145 | WaitResult(-1); | |
|
146 | if (IsRejected) | |
|
147 | Rethrow(); | |
|
148 | return m_result; | |
|
149 | } | |
|
150 | ||
|
151 | public T Join(int timeout) { | |
|
152 | WaitResult(timeout); | |
|
153 | if (IsRejected) | |
|
154 | Rethrow(); | |
|
155 | return m_result; | |
|
156 | } | |
|
157 | } | |
|
158 | } | |
|
159 |
@@ -0,0 +1,38 | |||
|
1 | using System; | |
|
2 | ||
|
3 | namespace Implab | |
|
4 | { | |
|
5 | public struct RejectedPromise : IPromise { | |
|
6 | readonly Exception m_reason; | |
|
7 | ||
|
8 | public Type ResultType => typeof(void); | |
|
9 | ||
|
10 | public bool IsResolved => true; | |
|
11 | ||
|
12 | public bool IsRejected => true; | |
|
13 | ||
|
14 | public bool IsFulfilled => false; | |
|
15 | ||
|
16 | public Exception RejectReason => m_reason; | |
|
17 | ||
|
18 | public RejectedPromise(Exception reason) { | |
|
19 | m_reason = reason; | |
|
20 | } | |
|
21 | ||
|
22 | public IPromise<T> Cast<T>() { | |
|
23 | throw new InvalidCastException(); | |
|
24 | } | |
|
25 | ||
|
26 | public void Join() { | |
|
27 | m_reason.ThrowInvocationException(); | |
|
28 | } | |
|
29 | ||
|
30 | public void Join(int timeout) { | |
|
31 | m_reason.ThrowInvocationException(); | |
|
32 | } | |
|
33 | ||
|
34 | public void Then(IResolvable next) { | |
|
35 | next.Reject(m_reason); | |
|
36 | } | |
|
37 | } | |
|
38 | } No newline at end of file |
@@ -0,0 +1,52 | |||
|
1 | using System; | |
|
2 | ||
|
3 | namespace Implab | |
|
4 | { | |
|
5 | public struct RejectedPromise<T> : IPromise<T> { | |
|
6 | readonly Exception m_reason; | |
|
7 | ||
|
8 | public Type ResultType => typeof(void); | |
|
9 | ||
|
10 | public bool IsResolved => true; | |
|
11 | ||
|
12 | public bool IsRejected => true; | |
|
13 | ||
|
14 | public bool IsFulfilled => false; | |
|
15 | ||
|
16 | public Exception RejectReason => m_reason; | |
|
17 | ||
|
18 | public RejectedPromise(Exception reason) { | |
|
19 | m_reason = reason; | |
|
20 | } | |
|
21 | ||
|
22 | public IPromise<T2> Cast<T2>() { | |
|
23 | return (IPromise<T2>)(IPromise<T>)this; | |
|
24 | } | |
|
25 | ||
|
26 | void IPromise.Join() { | |
|
27 | m_reason.ThrowInvocationException(); | |
|
28 | } | |
|
29 | ||
|
30 | void IPromise.Join(int timeout) { | |
|
31 | m_reason.ThrowInvocationException(); | |
|
32 | } | |
|
33 | ||
|
34 | public T Join() { | |
|
35 | m_reason.ThrowInvocationException(); | |
|
36 | throw new Exception(); // unreachable code | |
|
37 | } | |
|
38 | ||
|
39 | public T Join(int timeout) { | |
|
40 | m_reason.ThrowInvocationException(); | |
|
41 | throw new Exception(); // unreachable code | |
|
42 | } | |
|
43 | ||
|
44 | public void Then(IResolvable next) { | |
|
45 | next.Reject(m_reason); | |
|
46 | } | |
|
47 | ||
|
48 | public void Then(IResolvable<T> next) { | |
|
49 | next.Reject(m_reason); | |
|
50 | } | |
|
51 | } | |
|
52 | } No newline at end of file |
@@ -0,0 +1,30 | |||
|
1 | using System; | |
|
2 | ||
|
3 | namespace Implab | |
|
4 | { | |
|
5 | public struct ResolvedPromise : IPromise { | |
|
6 | public Type ResultType => typeof(void); | |
|
7 | ||
|
8 | public bool IsResolved => true; | |
|
9 | ||
|
10 | public bool IsRejected => false; | |
|
11 | ||
|
12 | public bool IsFulfilled => true; | |
|
13 | ||
|
14 | public Exception RejectReason => null; | |
|
15 | ||
|
16 | public IPromise<T> Cast<T>() { | |
|
17 | throw new InvalidCastException(); | |
|
18 | } | |
|
19 | ||
|
20 | public void Join() { | |
|
21 | } | |
|
22 | ||
|
23 | public void Join(int timeout) { | |
|
24 | } | |
|
25 | ||
|
26 | public void Then(IResolvable next) { | |
|
27 | next.Resolve(); | |
|
28 | } | |
|
29 | } | |
|
30 | } No newline at end of file |
@@ -0,0 +1,47 | |||
|
1 | using System; | |
|
2 | ||
|
3 | namespace Implab { | |
|
4 | public struct ResolvedPromise<T> : IPromise<T> { | |
|
5 | T m_result; | |
|
6 | ||
|
7 | public Type ResultType => typeof(T); | |
|
8 | ||
|
9 | public bool IsResolved => true; | |
|
10 | ||
|
11 | public bool IsRejected => false; | |
|
12 | ||
|
13 | public bool IsFulfilled => true; | |
|
14 | ||
|
15 | public Exception RejectReason => null; | |
|
16 | ||
|
17 | public ResolvedPromise(T result) { | |
|
18 | m_result = result; | |
|
19 | } | |
|
20 | ||
|
21 | public IPromise<T2> Cast<T2>() { | |
|
22 | return (IPromise<T2>)(IPromise<T>)this; | |
|
23 | } | |
|
24 | ||
|
25 | void IPromise.Join() { | |
|
26 | } | |
|
27 | ||
|
28 | void IPromise.Join(int timeout) { | |
|
29 | } | |
|
30 | ||
|
31 | public T Join() { | |
|
32 | return m_result; | |
|
33 | } | |
|
34 | ||
|
35 | public T Join(int timeout) { | |
|
36 | return m_result; | |
|
37 | } | |
|
38 | ||
|
39 | public void Then(IResolvable<T> next) { | |
|
40 | next.Resolve(m_result); | |
|
41 | } | |
|
42 | ||
|
43 | public void Then(IResolvable next) { | |
|
44 | next.Resolve(); | |
|
45 | } | |
|
46 | } | |
|
47 | } No newline at end of file |
@@ -69,7 +69,7 namespace Implab { | |||
|
69 | 69 | |
|
70 | 70 | protected void WaitTransition() { |
|
71 | 71 | if (m_state == TransitionalState) { |
|
72 | SpinWait spin; | |
|
72 | SpinWait spin = new SpinWait(); | |
|
73 | 73 | do { |
|
74 | 74 | spin.SpinOnce(); |
|
75 | 75 | } while (m_state == TransitionalState); |
@@ -87,17 +87,6 namespace Implab { | |||
|
87 | 87 | |
|
88 | 88 | #endregion |
|
89 | 89 | |
|
90 | protected abstract Signal GetFulfillSignal(); | |
|
91 | ||
|
92 | #region synchronization traits | |
|
93 | protected void WaitResult(int timeout) { | |
|
94 | if (!(IsResolved || GetFulfillSignal().Wait(timeout))) | |
|
95 | throw new TimeoutException(); | |
|
96 | } | |
|
97 | ||
|
98 | ||
|
99 | #endregion | |
|
100 | ||
|
101 | 90 | #region handlers managment |
|
102 | 91 | |
|
103 | 92 | protected void AddHandler(THandler handler) { |
@@ -3,63 +3,26 using System.Threading; | |||
|
3 | 3 | using Implab.Parallels; |
|
4 | 4 | |
|
5 | 5 | namespace Implab { |
|
6 | public class CancellationToken : ICancellationToken { | |
|
7 | const int CANCEL_NOT_REQUESTED = 0; | |
|
8 | const int CANCEL_REQUESTING = 1; | |
|
9 | const int CANCEL_REQUESTED = 2; | |
|
10 | ||
|
11 | volatile int m_state = CANCEL_NOT_REQUESTED; | |
|
12 | ||
|
13 | Action<Exception> m_handler; | |
|
14 | ||
|
15 | Parallels.SimpleAsyncQueue<Action<Exception>> m_handlers; | |
|
6 | /// <summary> | |
|
7 | /// The cancellation token signals to the worker that cancellation has been | |
|
8 | /// requested, after the signal is received the worker decides wheather to | |
|
9 | /// cancel its work or to continue. | |
|
10 | /// </summary> | |
|
11 | public class CancellationToken : AbstractEvent<Action<Exception>> { | |
|
12 | public CancellationToken() { | |
|
16 | 13 | |
|
17 | public bool IsCancellationRequested { | |
|
18 | get { return m_state == CANCEL_REQUESTED; } | |
|
19 | } | |
|
20 | ||
|
21 | public Exception CancellationReason { | |
|
22 | get; set; | |
|
23 | } | |
|
24 | ||
|
25 | public void CancellationRequested(Action<Exception> handler) { | |
|
26 | Safe.ArgumentNotNull(handler, nameof(handler)); | |
|
27 | if (IsCancellationRequested) { | |
|
28 | handler(CancellationReason); | |
|
29 | } else { | |
|
30 | EnqueueHandler(handler); | |
|
31 | if (IsCancellationRequested && TryDequeueHandler(out handler)) | |
|
32 | handler(CancellationReason); | |
|
33 | } | |
|
34 | 14 | } |
|
35 | 15 | |
|
36 | bool TryDequeueHandler(out Action<Exception> handler) { | |
|
37 | handler = Interlocked.Exchange(ref m_handler, null); | |
|
38 | if (handler != null) | |
|
39 | return true; | |
|
40 | else if (m_handlers != null) | |
|
41 | return m_handlers.TryDequeue(out handler); | |
|
42 | else | |
|
43 | return false; | |
|
16 | public void RequestCancellation() { | |
|
17 | ||
|
44 | 18 | } |
|
45 | 19 | |
|
46 |
void |
|
|
47 | if (Interlocked.CompareExchange(ref m_handler, handler, null) != null) { | |
|
48 | if (m_handlers == null) | |
|
49 | // compare-exchange will fprotect from loosing already created queue | |
|
50 | Interlocked.CompareExchange(ref m_handlers, new SimpleAsyncQueue<Action<Exception>>(), null); | |
|
51 | m_handlers.Enqueue(handler); | |
|
52 | } | |
|
20 | public void RequestCancellation(Exception reason) { | |
|
21 | ||
|
53 | 22 | } |
|
54 | 23 | |
|
55 | void RequestCancellation(Exception reason) { | |
|
56 | if (Interlocked.CompareExchange(ref m_state, CANCEL_REQUESTING, CANCEL_NOT_REQUESTED) == CANCEL_NOT_REQUESTED) { | |
|
57 | if (reason == null) | |
|
58 | reason = new OperationCanceledException(); | |
|
59 | CancellationReason = reason; | |
|
60 | m_state = CANCEL_REQUESTED; | |
|
24 | protected override void SignalHandler(Action<Exception> handler) { | |
|
25 | throw new NotImplementedException(); | |
|
61 | 26 |
|
|
62 | 27 |
|
|
63 | ||
|
64 | } | |
|
65 | 28 | } No newline at end of file |
@@ -7,10 +7,13 namespace Implab { | |||
|
7 | 7 | /// </summary> |
|
8 | 8 | public class Deferred : IResolvable { |
|
9 | 9 | |
|
10 |
readonly |
|
|
10 | readonly Promise m_promise; | |
|
11 | 11 | readonly IDispatcher m_dispatcher; |
|
12 | 12 | |
|
13 |
internal Deferred( |
|
|
13 | internal Deferred(IDispatcher dispatcher) : this(new Promise(), dispatcher) { | |
|
14 | } | |
|
15 | ||
|
16 | internal Deferred(Promise promise, IDispatcher dispatcher) { | |
|
14 | 17 | Debug.Assert(promise != null); |
|
15 | 18 | m_promise = promise; |
|
16 | 19 | m_dispatcher = dispatcher; |
@@ -21,11 +24,14 namespace Implab { | |||
|
21 | 24 | } |
|
22 | 25 | |
|
23 | 26 | public void Reject(Exception error) { |
|
24 | m_promise.Reject(error); | |
|
27 | if (error is PromiseTransientException) | |
|
28 | error = ((PromiseTransientException)error).InnerException; | |
|
29 | ||
|
30 | m_promise.RejectPromise(error); | |
|
25 | 31 | } |
|
26 | 32 | |
|
27 | 33 | public void Resolve() { |
|
28 | m_promise.Resolve(); | |
|
34 | m_promise.ResolvePromise(); | |
|
29 | 35 | } |
|
30 | 36 | |
|
31 | 37 | public void Resolve(IPromise thenable) { |
@@ -36,7 +42,7 namespace Implab { | |||
|
36 | 42 | |
|
37 | 43 | else if (m_dispatcher != null) |
|
38 | 44 | // dispatch (see ecma-262/6.0: 25.4.1.3.2 Promise Resolve Functions) |
|
39 |
m_dispatcher.Enqueue( |
|
|
45 | m_dispatcher.Enqueue(Chain, thenable); | |
|
40 | 46 | else |
|
41 | 47 | Chain(thenable); |
|
42 | 48 | } |
@@ -3,10 +3,13 using System.Diagnostics; | |||
|
3 | 3 | |
|
4 | 4 | namespace Implab { |
|
5 | 5 | public class Deferred<T> : IResolvable<T> { |
|
6 |
readonly |
|
|
6 | readonly Promise<T> m_promise; | |
|
7 | 7 | readonly IDispatcher m_dispatcher; |
|
8 | 8 | |
|
9 |
internal Deferred( |
|
|
9 | internal Deferred(IDispatcher dispatcher) : this(new Promise<T>(), dispatcher) { | |
|
10 | } | |
|
11 | ||
|
12 | internal Deferred(Promise<T> promise, IDispatcher dispatcher) { | |
|
10 | 13 | Debug.Assert(promise != null); |
|
11 | 14 | m_promise = promise; |
|
12 | 15 | m_dispatcher = dispatcher; |
@@ -17,11 +20,14 namespace Implab { | |||
|
17 | 20 | } |
|
18 | 21 | |
|
19 | 22 | public void Reject(Exception error) { |
|
20 | m_promise.Reject(error); | |
|
23 | if (error is PromiseTransientException) | |
|
24 | error = ((PromiseTransientException)error).InnerException; | |
|
25 | ||
|
26 | m_promise.RejectPromise(error); | |
|
21 | 27 | } |
|
22 | 28 | |
|
23 | 29 | public void Resolve(T value) { |
|
24 | m_promise.Resolve(value); | |
|
30 | m_promise.ResolvePromise(value); | |
|
25 | 31 | } |
|
26 | 32 | |
|
27 | 33 | public void Resolve(IPromise<T> thenable) { |
@@ -32,7 +38,7 namespace Implab { | |||
|
32 | 38 | |
|
33 | 39 | else if (m_dispatcher != null) |
|
34 | 40 | // dispatch (see ecma-262/6.0: 25.4.1.3.2 Promise Resolve Functions) |
|
35 |
m_dispatcher.Enqueue( |
|
|
41 | m_dispatcher.Enqueue(Chain, thenable); | |
|
36 | 42 | else |
|
37 | 43 | Chain(thenable); |
|
38 | 44 | } |
@@ -3,5 +3,7 using System; | |||
|
3 | 3 | namespace Implab { |
|
4 | 4 | public interface IDispatcher { |
|
5 | 5 | void Enqueue(Action job); |
|
6 | ||
|
7 | void Enqueue<T>(Action<T> job, T arg); | |
|
6 | 8 | } |
|
7 | 9 | } No newline at end of file |
@@ -3,63 +3,48 using System.Diagnostics; | |||
|
3 | 3 | |
|
4 | 4 | namespace Implab { |
|
5 | 5 | class PromiseActionReaction : PromiseReaction { |
|
6 | readonly Action m_fulfilled; | |
|
7 | ||
|
8 | readonly Action<Exception> m_rejected; | |
|
9 | 6 | |
|
10 | 7 | readonly Deferred m_next; |
|
11 | 8 | |
|
12 | public PromiseActionReaction(Action fulfilled, Action<Exception> rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) { | |
|
9 | public IPromise Promise { | |
|
10 | get { return m_next.Promise; } | |
|
11 | } | |
|
12 | ||
|
13 | public PromiseActionReaction(Action fulfilled, Action<Exception> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
14 | m_next = new Deferred(dispatcher); | |
|
13 | 15 | if (fulfilled != null) |
|
14 | m_fulfilled = () => { | |
|
15 | fulfilled(); | |
|
16 | next.Resolve(); | |
|
17 | }; | |
|
16 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
18 | 17 | |
|
19 | 18 | if (rejected != null) |
|
20 | m_rejected = (x) => { | |
|
21 | rejected(x); | |
|
22 | next.Resolve(); | |
|
23 | }; | |
|
24 | m_next = next; | |
|
25 | } | |
|
26 | ||
|
27 | public PromiseActionReaction(Func<IPromise> fulfilled, Func<Exception, IPromise> rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) { | |
|
28 | if (fulfilled != null) | |
|
29 | m_fulfilled = () => { next.Resolve(fulfilled()); }; | |
|
30 | if (rejected != null) | |
|
31 | m_rejected = (e) => { next.Resolve(rejected(e)); }; | |
|
32 | m_next = next; | |
|
19 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
33 | 20 | } |
|
34 | 21 | |
|
35 |
public PromiseActionReaction( |
|
|
22 | public PromiseActionReaction(Func<IPromise> fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
23 | m_next = new Deferred(dispatcher); | |
|
36 | 24 | if (fulfilled != null) |
|
37 | m_fulfilled = () => { | |
|
38 | fulfilled(); | |
|
39 | next.Resolve(); | |
|
40 | }; | |
|
25 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
41 | 26 | |
|
42 | 27 | if (rejected != null) |
|
43 |
|
|
|
44 | m_next = next; | |
|
28 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
45 | 29 | } |
|
46 | 30 | |
|
47 |
public PromiseActionReaction( |
|
|
31 | public PromiseActionReaction(Action fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
32 | m_next = new Deferred(dispatcher); | |
|
48 | 33 | if (fulfilled != null) |
|
49 |
|
|
|
34 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
50 | 35 | |
|
51 | 36 | if (rejected != null) |
|
52 | m_rejected = (x) => { | |
|
53 | rejected(x); | |
|
54 | next.Resolve(); | |
|
55 | }; | |
|
56 | m_next = next; | |
|
37 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
57 | 38 | } |
|
58 | 39 | |
|
40 | public PromiseActionReaction(Func<IPromise> fulfilled, Action<Exception> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
41 | m_next = new Deferred(dispatcher); | |
|
42 | if (fulfilled != null) | |
|
43 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
59 | 44 | |
|
60 | protected override bool HasFulfilHandler => m_fulfilled != null; | |
|
61 | ||
|
62 | protected override bool HasRejectHandler => m_rejected != null; | |
|
45 | if (rejected != null) | |
|
46 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
47 | } | |
|
63 | 48 | |
|
64 | 49 | protected override void DefaultReject(Exception reason) { |
|
65 | 50 | m_next.Reject(reason); |
@@ -68,21 +53,5 namespace Implab { | |||
|
68 | 53 | protected override void DefaultResolve() { |
|
69 | 54 | m_next.Resolve(); |
|
70 | 55 | } |
|
71 | ||
|
72 | protected override void RejectImpl(Exception reason) { | |
|
73 | try { | |
|
74 | m_rejected(reason); | |
|
75 | } catch (Exception e){ | |
|
76 | m_next.Reject(e); | |
|
77 | } | |
|
78 | } | |
|
79 | ||
|
80 | protected override void ResolveImpl() { | |
|
81 | try { | |
|
82 | m_fulfilled(); | |
|
83 | } catch (Exception e){ | |
|
84 | m_next.Reject(e); | |
|
85 | } | |
|
86 | } | |
|
87 | 56 | } |
|
88 | 57 | } No newline at end of file |
@@ -3,62 +3,47 using System.Diagnostics; | |||
|
3 | 3 | |
|
4 | 4 | namespace Implab { |
|
5 | 5 | class PromiseActionReaction<T> : PromiseReaction<T> { |
|
6 | readonly Action<T> m_fulfilled; | |
|
7 | ||
|
8 | readonly Action<Exception> m_rejected; | |
|
9 | ||
|
10 | 6 | readonly Deferred m_next; |
|
11 | 7 | |
|
12 | public PromiseActionReaction(Action<T> fulfilled, Action<Exception> rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) { | |
|
8 | public IPromise Promise { | |
|
9 | get { return m_next.Promise; } | |
|
10 | } | |
|
11 | ||
|
12 | public PromiseActionReaction(Action<T> fulfilled, Action<Exception> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
13 | m_next = new Deferred(dispatcher); | |
|
13 | 14 | if (fulfilled != null) |
|
14 | m_fulfilled = (x) => { | |
|
15 | fulfilled(x); | |
|
16 | next.Resolve(); | |
|
17 | }; | |
|
15 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
18 | 16 | |
|
19 | 17 | if (rejected != null) |
|
20 | m_rejected = (x) => { | |
|
21 | rejected(x); | |
|
22 | next.Resolve(); | |
|
23 | }; | |
|
24 | m_next = next; | |
|
18 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
25 | 19 | } |
|
26 | 20 | |
|
27 |
public PromiseActionReaction(Func<T, IPromise> fulfilled, Func<Exception, IPromise> rejected, |
|
|
21 | public PromiseActionReaction(Func<T, IPromise> fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
22 | m_next = new Deferred(dispatcher); | |
|
28 | 23 | if (fulfilled != null) |
|
29 |
|
|
|
30 | if (rejected != null) | |
|
31 | m_rejected = (e) => { next.Resolve(rejected(e)); }; | |
|
32 | m_next = next; | |
|
33 | } | |
|
34 | ||
|
35 | public PromiseActionReaction(Action<T> fulfilled, Func<Exception, IPromise> rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) { | |
|
36 | if (fulfilled != null) | |
|
37 | m_fulfilled = (x) => { | |
|
38 | fulfilled(x); | |
|
39 | next.Resolve(); | |
|
40 | }; | |
|
24 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
41 | 25 | |
|
42 | 26 | if (rejected != null) |
|
43 |
|
|
|
44 | m_next = next; | |
|
27 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
45 | 28 | } |
|
46 | 29 | |
|
47 |
public PromiseActionReaction(Func< |
|
|
30 | public PromiseActionReaction(Action<T> fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
31 | m_next = new Deferred(dispatcher); | |
|
48 | 32 | if (fulfilled != null) |
|
49 |
|
|
|
33 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
50 | 34 | |
|
51 | 35 | if (rejected != null) |
|
52 | m_rejected = (x) => { | |
|
53 | rejected(x); | |
|
54 | next.Resolve(); | |
|
55 | }; | |
|
56 | m_next = next; | |
|
36 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
57 | 37 | } |
|
58 | 38 | |
|
59 | protected override bool HasFulfilHandler => m_fulfilled != null; | |
|
39 | public PromiseActionReaction(Func<T, IPromise> fulfilled, Action<Exception> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
40 | m_next = new Deferred(dispatcher); | |
|
41 | if (fulfilled != null) | |
|
42 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
60 | 43 | |
|
61 | protected override bool HasRejectHandler => m_rejected != null; | |
|
44 | if (rejected != null) | |
|
45 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
46 | } | |
|
62 | 47 | |
|
63 | 48 | protected override void DefaultReject(Exception reason) { |
|
64 | 49 | m_next.Reject(reason); |
@@ -67,21 +52,5 namespace Implab { | |||
|
67 | 52 | protected override void DefaultResolve(T result) { |
|
68 | 53 | m_next.Resolve(); |
|
69 | 54 | } |
|
70 | ||
|
71 | protected override void RejectImpl(Exception reason) { | |
|
72 | try { | |
|
73 | m_rejected(reason); | |
|
74 | } catch (Exception e) { | |
|
75 | m_next.Reject(e); | |
|
76 | } | |
|
77 | } | |
|
78 | ||
|
79 | protected override void ResolveImpl(T result) { | |
|
80 | try { | |
|
81 | m_fulfilled(result); | |
|
82 | } catch (Exception e) { | |
|
83 | m_next.Reject(e); | |
|
84 | } | |
|
85 | } | |
|
86 | 55 | } |
|
87 | 56 | } No newline at end of file |
@@ -6,470 +6,126 using System.Linq; | |||
|
6 | 6 | |
|
7 | 7 | namespace Implab { |
|
8 | 8 | public static class PromiseExtensions { |
|
9 | public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) { | |
|
10 | Safe.ArgumentNotNull(that, "that"); | |
|
11 | var context = SynchronizationContext.Current; | |
|
12 | if (context == null) | |
|
13 | return that; | |
|
14 | 9 | |
|
15 | var p = new SyncContextPromise<T>(context); | |
|
16 | p.CancellationRequested(that.Cancel); | |
|
17 | ||
|
18 | that.On( | |
|
19 | p.Resolve, | |
|
20 | p.Reject, | |
|
21 | p.CancelOperation | |
|
22 | ); | |
|
23 | return p; | |
|
24 | } | |
|
25 | ||
|
26 | public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) { | |
|
27 | Safe.ArgumentNotNull(that, "that"); | |
|
28 | Safe.ArgumentNotNull(context, "context"); | |
|
29 | ||
|
30 | var p = new SyncContextPromise<T>(context); | |
|
31 | p.CancellationRequested(that.Cancel); | |
|
32 | ||
|
33 | that.On( | |
|
34 | p.Resolve, | |
|
35 | p.Reject, | |
|
36 | p.CancelOperation | |
|
37 | ); | |
|
38 | return p; | |
|
39 | } | |
|
40 | ||
|
41 | /// <summary> | |
|
42 | /// Ensures the dispatched. | |
|
43 | /// </summary> | |
|
44 | /// <returns>The dispatched.</returns> | |
|
45 | /// <param name="that">That.</param> | |
|
46 | /// <param name="head">Head.</param> | |
|
47 | /// <param name="cleanup">Cleanup.</param> | |
|
48 | /// <typeparam name="TPromise">The 1st type parameter.</typeparam> | |
|
49 | /// <typeparam name="T">The 2nd type parameter.</typeparam> | |
|
50 | public static TPromise EnsureDispatched<TPromise, T>(this TPromise that, IPromise<T> head, Action<T> cleanup) where TPromise : IPromise { | |
|
51 | Safe.ArgumentNotNull(that, "that"); | |
|
52 | Safe.ArgumentNotNull(head, "head"); | |
|
53 | ||
|
54 | that.On(() => head.On(cleanup), PromiseEventType.Cancelled); | |
|
55 | ||
|
56 | return that; | |
|
10 | public static IPromise Then(this IPromise that, Action fulfilled, Action<Exception> rejected) { | |
|
11 | var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
12 | that.Then(reaction); | |
|
13 | return reaction.Promise; | |
|
57 | 14 | } |
|
58 | 15 | |
|
59 | /// <summary> | |
|
60 | /// Adds a cancellation point to the chain of promises. When a cancellation request reaches the cancellation point the operation is | |
|
61 | /// cancelled immediatelly, and the request is passed towards. If the operation at the higher level can not be cancelled is't result | |
|
62 | /// will be collected with <paramref name="cleanup"/> callback. | |
|
63 | /// </summary> | |
|
64 | /// <typeparam name="T">The type of the promise result.</typeparam> | |
|
65 | /// <param name="that">The promise to which the cancellation point should be attached.</param> | |
|
66 | /// <param name="cleanup">The callback which is used to cleanup the result of the operation if the cancellation point is cancelled already.</param> | |
|
67 | /// <returns>The promise</returns> | |
|
68 | public static IPromise<T> CancellationPoint<T>(this IPromise<T> that, Action<T> cleanup) { | |
|
69 | var meduim = new Promise<T>(); | |
|
70 | ||
|
71 | that.On(meduim.Resolve, meduim.Reject, meduim.CancelOperation); | |
|
72 | ||
|
73 | meduim.CancellationRequested(that.Cancel); | |
|
74 | meduim.CancellationRequested(meduim.CancelOperation); | |
|
75 | ||
|
76 | if (cleanup != null) | |
|
77 | meduim.On((Action<T>)null, null, (e) => { | |
|
78 | that.On(cleanup); | |
|
79 | }); | |
|
80 | ||
|
81 | return meduim; | |
|
16 | public static IPromise Then(this IPromise that, Action fulfilled, Func<Exception, IPromise> rejected) { | |
|
17 | var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
18 | that.Then(reaction); | |
|
19 | return reaction.Promise; | |
|
82 | 20 | } |
|
83 | 21 | |
|
84 | public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult, T> callback) { | |
|
85 | Safe.ArgumentNotNull(that, "that"); | |
|
86 | Safe.ArgumentNotNull(callback, "callback"); | |
|
87 | var op = TraceContext.Instance.CurrentOperation; | |
|
88 | return ar => { | |
|
89 | TraceContext.Instance.EnterLogicalOperation(op, false); | |
|
90 | try { | |
|
91 | that.Resolve(callback(ar)); | |
|
92 | } catch (Exception err) { | |
|
93 | that.Reject(err); | |
|
94 | } finally { | |
|
95 | TraceContext.Instance.Leave(); | |
|
96 | } | |
|
97 | }; | |
|
22 | public static IPromise Then(this IPromise that, Func<IPromise> fulfilled, Action<Exception> rejected) { | |
|
23 | var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
24 | that.Then(reaction); | |
|
25 | return reaction.Promise; | |
|
98 | 26 | } |
|
99 | 27 | |
|
100 | static void CancelByTimeoutCallback(object cookie) { | |
|
101 | ((ICancellable)cookie).Cancel(new TimeoutException()); | |
|
102 | } | |
|
103 | ||
|
104 | /// <summary> | |
|
105 | /// Cancells promise after the specified timeout is elapsed. | |
|
106 | /// </summary> | |
|
107 | /// <param name="that">The promise to cancel on timeout.</param> | |
|
108 | /// <param name="milliseconds">The timeout in milliseconds.</param> | |
|
109 | /// <typeparam name="TPromise">The 1st type parameter.</typeparam> | |
|
110 | public static TPromise Timeout<TPromise>(this TPromise that, int milliseconds) where TPromise : IPromise { | |
|
111 | Safe.ArgumentNotNull(that, "that"); | |
|
112 | var timer = new Timer(CancelByTimeoutCallback, that, milliseconds, -1); | |
|
113 | that.On(timer.Dispose, PromiseEventType.All); | |
|
114 | return that; | |
|
115 | } | |
|
116 | ||
|
117 | public static IPromise PromiseAll(this IEnumerable<IPromise> that) { | |
|
118 | Safe.ArgumentNotNull(that, "that"); | |
|
119 | return PromiseAll(that.ToList()); | |
|
28 | public static IPromise Then(this IPromise that, Func<IPromise> fulfilled, Func<Exception, IPromise> rejected) { | |
|
29 | var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
30 | that.Then(reaction); | |
|
31 | return reaction.Promise; | |
|
120 | 32 | } |
|
121 | 33 | |
|
122 |
public static IPromise |
|
|
123 | return PromiseAll(that, null); | |
|
124 | } | |
|
125 | ||
|
126 | public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that, Action<T> cleanup) { | |
|
127 | Safe.ArgumentNotNull(that, "that"); | |
|
128 | return PromiseAll(that.ToList(), cleanup); | |
|
129 | } | |
|
130 | ||
|
131 | public static IPromise PromiseAll(this ICollection<IPromise> that) { | |
|
132 | Safe.ArgumentNotNull(that, "that"); | |
|
133 | ||
|
134 | int count = that.Count; | |
|
135 | int errors = 0; | |
|
136 | var medium = new Promise(); | |
|
137 | ||
|
138 | if (count == 0) { | |
|
139 | medium.Resolve(); | |
|
140 | return medium; | |
|
34 | public static IPromise Then<T>(this IPromise<T> that, Action<T> fulfilled, Action<Exception> rejected) { | |
|
35 | var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
36 | that.Then(reaction); | |
|
37 | return reaction.Promise; | |
|
141 | 38 |
|
|
142 | 39 | |
|
143 | medium.On(() => { | |
|
144 | foreach (var p2 in that) | |
|
145 | p2.Cancel(); | |
|
146 | }, PromiseEventType.ErrorOrCancel); | |
|
147 | ||
|
148 | foreach (var p in that) | |
|
149 | p.On( | |
|
150 | () => { | |
|
151 | if (Interlocked.Decrement(ref count) == 0) | |
|
152 | medium.Resolve(); | |
|
153 | }, | |
|
154 | error => { | |
|
155 | if (Interlocked.Increment(ref errors) == 1) | |
|
156 | medium.Reject( | |
|
157 | new Exception("The dependency promise is failed", error) | |
|
158 | ); | |
|
159 | }, | |
|
160 | reason => { | |
|
161 | if (Interlocked.Increment(ref errors) == 1) | |
|
162 | medium.Cancel( | |
|
163 | new Exception("The dependency promise is cancelled") | |
|
164 | ); | |
|
165 | } | |
|
166 | ); | |
|
167 | ||
|
168 | return medium; | |
|
169 | } | |
|
170 | ||
|
171 | public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that) { | |
|
172 | return PromiseAll(that, null); | |
|
40 | public static IPromise Then<T>(this IPromise<T> that, Action<T> fulfilled, Func<Exception, IPromise> rejected) { | |
|
41 | var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
42 | that.Then(reaction); | |
|
43 | return reaction.Promise; | |
|
173 | 44 | } |
|
174 | 45 | |
|
175 | /// <summary> | |
|
176 | /// Creates a new promise which will be satisfied when all promises are satisfied. | |
|
177 | /// </summary> | |
|
178 | /// <typeparam name="T"></typeparam> | |
|
179 | /// <param name="that"></param> | |
|
180 | /// <param name="cleanup">A callback used to cleanup already resolved promises in case of an error</param> | |
|
181 | /// <returns></returns> | |
|
182 | public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that, Action<T> cleanup) { | |
|
183 | Safe.ArgumentNotNull(that, "that"); | |
|
184 | ||
|
185 | int count = that.Count; | |
|
186 | ||
|
187 | if (count == 0) | |
|
188 | return Promise<T[]>.FromResult(new T[0]); | |
|
189 | ||
|
190 | int errors = 0; | |
|
191 | var medium = new Promise<T[]>(); | |
|
192 | var results = new T[that.Count]; | |
|
193 | ||
|
194 | medium.On(() => { | |
|
195 | foreach (var p2 in that) { | |
|
196 | p2.Cancel(); | |
|
197 | if (cleanup != null) | |
|
198 | p2.On(cleanup); | |
|
199 | } | |
|
200 | }, PromiseEventType.ErrorOrCancel); | |
|
201 | ||
|
202 | int i = 0; | |
|
203 | foreach (var p in that) { | |
|
204 | var idx = i; | |
|
205 | p.On( | |
|
206 | x => { | |
|
207 | results[idx] = x; | |
|
208 | if (Interlocked.Decrement(ref count) == 0) | |
|
209 | medium.Resolve(results); | |
|
210 | }, | |
|
211 | error => { | |
|
212 | if (Interlocked.Increment(ref errors) == 1) | |
|
213 | medium.Reject( | |
|
214 | new Exception("The dependency promise is failed", error) | |
|
215 | ); | |
|
216 | }, | |
|
217 | reason => { | |
|
218 | if (Interlocked.Increment(ref errors) == 1) | |
|
219 | medium.Cancel( | |
|
220 | new Exception("The dependency promise is cancelled", reason) | |
|
221 | ); | |
|
222 | } | |
|
223 | ); | |
|
224 | i++; | |
|
46 | public static IPromise Then<T>(this IPromise<T> that, Func<T, IPromise> fulfilled, Action<Exception> rejected) { | |
|
47 | var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
48 | that.Then(reaction); | |
|
49 | return reaction.Promise; | |
|
225 | 50 |
|
|
226 | 51 | |
|
227 | return medium; | |
|
52 | public static IPromise Then<T>(this IPromise<T> that, Func<T, IPromise> fulfilled, Func<Exception, IPromise> rejected) { | |
|
53 | var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
54 | that.Then(reaction); | |
|
55 | return reaction.Promise; | |
|
228 | 56 | } |
|
229 | 57 | |
|
230 |
public static IPromise Then(this IPromise that, |
|
|
231 | Safe.ArgumentNotNull(that, "that"); | |
|
232 | ||
|
233 | var d = new ActionTask(success, error, cancel, false); | |
|
234 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |
|
235 | d.CancellationRequested(that.Cancel); | |
|
236 | return d; | |
|
58 | public static IPromise<Tout> Then<Tout>(this IPromise that, Func<Tout> fulfilled, Func<Exception, Tout> rejected) { | |
|
59 | var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
60 | that.Then(reaction); | |
|
61 | return reaction.Promise; | |
|
237 | 62 | } |
|
238 | 63 | |
|
239 |
public static IPromise Then(this IPromise that, |
|
|
240 | return Then(that, success, error, null); | |
|
241 | } | |
|
242 | ||
|
243 | public static IPromise Then(this IPromise that, Action success) { | |
|
244 | return Then(that, success, null, null); | |
|
245 | } | |
|
246 | ||
|
247 | public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error, Func<Exception, T> cancel) { | |
|
248 | Safe.ArgumentNotNull(that, "that"); | |
|
249 | ||
|
250 | var d = new FuncTask<T>(success, error, cancel, false); | |
|
251 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |
|
252 | d.CancellationRequested(that.Cancel); | |
|
253 | return d; | |
|
254 | } | |
|
255 | ||
|
256 | public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error) { | |
|
257 | return Then(that, success, error, null); | |
|
258 | } | |
|
259 | ||
|
260 | public static IPromise<T> Then<T>(this IPromise that, Func<T> success) { | |
|
261 | return Then(that, success, null, null); | |
|
64 | public static IPromise<Tout> Then<Tout>(this IPromise that, Func<Tout> fulfilled, Func<Exception, IPromise<Tout>> rejected) { | |
|
65 | var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
66 | that.Then(reaction); | |
|
67 | return reaction.Promise; | |
|
262 | 68 | } |
|
263 | 69 | |
|
264 |
public static IPromise<T |
|
|
265 | Safe.ArgumentNotNull(that, "that"); | |
|
266 | Safe.ArgumentNotNull(success, "success"); | |
|
267 | ||
|
268 | var d = new FuncTask<T, T2>(success, error, cancel, false); | |
|
269 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |
|
270 | d.CancellationRequested(that.Cancel); | |
|
271 | return d; | |
|
272 | } | |
|
273 | ||
|
274 | public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error, Func<Exception, T> cancel) { | |
|
275 | Safe.ArgumentNotNull(that, "that"); | |
|
276 | var d = new FuncTask<T, T>( | |
|
277 | x => { | |
|
278 | success(x); | |
|
279 | return x; | |
|
280 | }, | |
|
281 | error, | |
|
282 | cancel, | |
|
283 | false | |
|
284 | ); | |
|
285 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |
|
286 | d.CancellationRequested(that.Cancel); | |
|
287 | return d; | |
|
288 | } | |
|
289 | ||
|
290 | public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error) { | |
|
291 | return Then(that, success, error, null); | |
|
70 | public static IPromise<Tout> Then<Tout>(this IPromise that, Func<IPromise<Tout>> fulfilled, Func<Exception, Tout> rejected) { | |
|
71 | var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
72 | that.Then(reaction); | |
|
73 | return reaction.Promise; | |
|
292 | 74 | } |
|
293 | 75 | |
|
294 |
public static IPromise<T> Then<T>(this IPromise |
|
|
295 | return Then(that, success, null, null); | |
|
296 | } | |
|
297 | ||
|
298 | public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error) { | |
|
299 | return Then(that, success, error, null); | |
|
300 | } | |
|
301 | ||
|
302 | public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success) { | |
|
303 | return Then(that, success, null, null); | |
|
76 | public static IPromise<Tout> Then<Tout>(this IPromise that, Func<IPromise<Tout>> fulfilled, Func<Exception, IPromise<Tout>> rejected) { | |
|
77 | var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
78 | that.Then(reaction); | |
|
79 | return reaction.Promise; | |
|
304 | 80 | } |
|
305 | 81 | |
|
306 |
public static IPromise<T> |
|
|
307 | Func<Exception, T> errorOrCancel; | |
|
308 | if (handler != null) | |
|
309 | errorOrCancel = e => { | |
|
310 | handler(); | |
|
311 | throw new PromiseTransientException(e); | |
|
312 | }; | |
|
313 | else | |
|
314 | errorOrCancel = null; | |
|
315 | ||
|
316 | return Then( | |
|
317 | that, | |
|
318 | x => { | |
|
319 | handler(); | |
|
320 | return x; | |
|
321 | }, | |
|
322 | errorOrCancel, | |
|
323 | errorOrCancel); | |
|
82 | public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, Tout> fulfilled, Func<Exception, Tout> rejected) { | |
|
83 | var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
84 | that.Then(reaction); | |
|
85 | return reaction.Promise; | |
|
324 | 86 | } |
|
325 | 87 | |
|
326 | public static IPromise Always(this IPromise that, Action handler) { | |
|
327 | Action<Exception> errorOrCancel; | |
|
328 | if (handler != null) | |
|
329 | errorOrCancel = e => { | |
|
330 | handler(); | |
|
331 | throw new PromiseTransientException(e); | |
|
332 | }; | |
|
333 | else | |
|
334 | errorOrCancel = null; | |
|
335 | ||
|
336 | return Then( | |
|
337 | that, | |
|
338 | handler, | |
|
339 | errorOrCancel, | |
|
340 | errorOrCancel); | |
|
341 | } | |
|
342 | ||
|
343 | public static IPromise Error(this IPromise that, Action<Exception> handler, bool handleCancellation) { | |
|
344 | Action<Exception> errorOrCancel; | |
|
345 | if (handler != null) | |
|
346 | errorOrCancel = e => { | |
|
347 | handler(e); | |
|
348 | throw new PromiseTransientException(e); | |
|
349 | }; | |
|
350 | else | |
|
351 | errorOrCancel = null; | |
|
352 | ||
|
353 | return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null); | |
|
88 | public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, Tout> fulfilled, Func<Exception, IPromise<Tout>> rejected) { | |
|
89 | var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
90 | that.Then(reaction); | |
|
91 | return reaction.Promise; | |
|
354 | 92 | } |
|
355 | 93 | |
|
356 |
public static IPromise |
|
|
357 | return Error(that, handler, false); | |
|
358 | } | |
|
359 | ||
|
360 | public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler, bool handleCancellation) { | |
|
361 | Func<Exception, T> errorOrCancel; | |
|
362 | if (handler != null) | |
|
363 | errorOrCancel = e => { | |
|
364 | handler(e); | |
|
365 | throw new PromiseTransientException(e); | |
|
366 | }; | |
|
367 | else | |
|
368 | errorOrCancel = null; | |
|
369 | ||
|
370 | return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null); | |
|
371 | } | |
|
372 | ||
|
373 | public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler) { | |
|
374 | return Error(that, handler, false); | |
|
94 | public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, IPromise<Tout>> fulfilled, Func<Exception, Tout> rejected) { | |
|
95 | var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
96 | that.Then(reaction); | |
|
97 | return reaction.Promise; | |
|
375 | 98 | } |
|
376 | 99 | |
|
377 | #region chain traits | |
|
378 | public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) { | |
|
379 | Safe.ArgumentNotNull(that, "that"); | |
|
380 | ||
|
381 | var d = new ActionChainTask(success, error, cancel, false); | |
|
382 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |
|
383 | d.CancellationRequested(that.Cancel); | |
|
384 | return d; | |
|
385 | } | |
|
386 | ||
|
387 | public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error) { | |
|
388 | return Chain(that, success, error, null); | |
|
100 | public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, IPromise<Tout>> fulfilled, Func<Exception, IPromise<Tout>> rejected) { | |
|
101 | var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher); | |
|
102 | that.Then(reaction); | |
|
103 | return reaction.Promise; | |
|
389 | 104 | } |
|
390 | 105 | |
|
391 |
public static IPromise C |
|
|
392 |
return |
|
|
393 | } | |
|
394 | ||
|
395 | public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error, Func<Exception, IPromise<T>> cancel) { | |
|
396 | Safe.ArgumentNotNull(that, "that"); | |
|
397 | ||
|
398 | var d = new FuncChainTask<T>(success, error, cancel, false); | |
|
399 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |
|
400 | if (success != null) | |
|
401 | d.CancellationRequested(that.Cancel); | |
|
402 | return d; | |
|
403 | } | |
|
404 | ||
|
405 | public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error) { | |
|
406 | return Chain(that, success, error, null); | |
|
407 | } | |
|
408 | ||
|
409 | public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success) { | |
|
410 | return Chain(that, success, null, null); | |
|
106 | public static IPromise Catch(this IPromise that, Action<Exception> rejected) { | |
|
107 | return Then(that, null, rejected); | |
|
411 | 108 | } |
|
412 | 109 | |
|
413 |
public static IPromise |
|
|
414 | Safe.ArgumentNotNull(that, "that"); | |
|
415 | var d = new FuncChainTask<T, T2>(success, error, cancel, false); | |
|
416 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |
|
417 | if (success != null) | |
|
418 | d.CancellationRequested(that.Cancel); | |
|
419 | return d; | |
|
420 | } | |
|
421 | ||
|
422 | public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error) { | |
|
423 | return Chain(that, success, error, null); | |
|
110 | public static IPromise Catch(this IPromise that, Func<Exception, IPromise> rejected) { | |
|
111 | return Then(that, null, rejected); | |
|
424 | 112 | } |
|
425 | 113 | |
|
426 |
public static IPromise<T |
|
|
427 |
return |
|
|
428 | } | |
|
429 | ||
|
430 | #endregion | |
|
431 | ||
|
432 | public static IPromise<T2> Guard<T, T2>(this IPromise<T> that, Func<IPromise<T>, IPromise<T2>> continuation, Action<T> cleanup) { | |
|
433 | Safe.ArgumentNotNull(that, "that"); | |
|
434 | Safe.ArgumentNotNull(continuation, "continuation"); | |
|
435 | return continuation(that).Error((err) => { | |
|
436 | that.On(cleanup); | |
|
437 | }, true); | |
|
114 | public static IPromise<Tout> Catch<Tout>(this IPromise that, Func<Exception, Tout> rejected) { | |
|
115 | return Then(that, (Func<Tout>)null, rejected); | |
|
438 | 116 | } |
|
439 | 117 | |
|
440 | #if NET_4_5 | |
|
441 | ||
|
442 | public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) { | |
|
443 | Safe.ArgumentNotNull(that, "that"); | |
|
444 | ||
|
445 | return new PromiseAwaiter<T>(that); | |
|
446 | } | |
|
447 | ||
|
448 | public static PromiseAwaiter GetAwaiter(this IPromise that) { | |
|
449 | Safe.ArgumentNotNull(that, "that"); | |
|
450 | ||
|
451 | return new PromiseAwaiter(that); | |
|
118 | public static IPromise<Tout> Catch<Tout>(this IPromise that, Func<Exception, IPromise<Tout>> rejected) { | |
|
119 | return Then(that, (Func<Tout>)null, rejected); | |
|
452 | 120 | } |
|
453 | 121 | |
|
454 |
public static IPromise |
|
|
455 | Safe.ArgumentNotNull(that, "that"); | |
|
456 | ct.Register(that.Cancel); | |
|
457 | return that.Then(null, null, (err) => { | |
|
458 | ct.ThrowIfCancellationRequested(); | |
|
459 | throw new PromiseTransientException(err); | |
|
460 | }); | |
|
122 | public static IPromise<Tout> Catch<Tin, Tout>(this IPromise<Tin> that, Func<Exception, Tout> rejected) { | |
|
123 | return Then(that, (Func<Tin, Tout>)null, rejected); | |
|
461 | 124 | } |
|
462 | 125 | |
|
463 |
public static IPromise<T> |
|
|
464 | Safe.ArgumentNotNull(that, "that"); | |
|
465 | ct.Register(that.Cancel); | |
|
466 | return that.Then(null, null, (err) => { | |
|
467 | ct.ThrowIfCancellationRequested(); | |
|
468 | throw new PromiseTransientException(err); | |
|
469 | }); | |
|
126 | public static IPromise<Tout> Catch<Tin, Tout>(this IPromise<Tin> that, Func<Exception, IPromise<Tout>> rejected) { | |
|
127 | return Then(that, (Func<Tin, Tout>)null, rejected); | |
|
470 | 128 | } |
|
471 | ||
|
472 | #endif | |
|
473 | 129 | } |
|
474 | 130 | } |
|
475 | 131 |
@@ -3,51 +3,47 using System.Diagnostics; | |||
|
3 | 3 | |
|
4 | 4 | namespace Implab { |
|
5 | 5 | class PromiseFuncReaction<TRet> : PromiseReaction { |
|
6 | readonly Action m_fulfilled; | |
|
7 | ||
|
8 | readonly Action<Exception> m_rejected; | |
|
9 | ||
|
10 | 6 | readonly Deferred<TRet> m_next; |
|
11 | 7 | |
|
12 | public PromiseFuncReaction(Func<TRet> fulfilled, Func<Exception, TRet> rejected, Deferred<TRet> next, IDispatcher dispatcher) : base(dispatcher) { | |
|
8 | public IPromise<TRet> Promise { | |
|
9 | get { return m_next.Promise; } | |
|
10 | } | |
|
11 | ||
|
12 | public PromiseFuncReaction(Func<TRet> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
13 | m_next = new Deferred<TRet>(dispatcher); | |
|
13 | 14 | if (fulfilled != null) |
|
14 |
|
|
|
15 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
15 | 16 | |
|
16 | 17 | if (rejected != null) |
|
17 |
|
|
|
18 | m_next = next; | |
|
19 | } | |
|
20 | ||
|
21 | public PromiseFuncReaction(Func<IPromise<TRet>> fulfilled, Func<Exception, IPromise<TRet>> rejected, Deferred<TRet> next, IDispatcher dispatcher) : base(dispatcher) { | |
|
22 | if (fulfilled != null) | |
|
23 | m_fulfilled = () => { next.Resolve(fulfilled()); }; | |
|
24 | if (rejected != null) | |
|
25 | m_rejected = (e) => { next.Resolve(rejected(e)); }; | |
|
26 | m_next = next; | |
|
18 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
27 | 19 | } |
|
28 | 20 | |
|
29 |
public PromiseFuncReaction(Func<TRet> fulfilled, Func<Exception, IPromise<TRet>> rejected, |
|
|
21 | public PromiseFuncReaction(Func<IPromise<TRet>> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
22 | m_next = new Deferred<TRet>(dispatcher); | |
|
30 | 23 | if (fulfilled != null) |
|
31 |
|
|
|
24 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
25 | ||
|
32 | 26 | if (rejected != null) |
|
33 |
|
|
|
34 | ||
|
35 | m_next = next; | |
|
27 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
36 | 28 | } |
|
37 | 29 | |
|
38 |
public PromiseFuncReaction(Func< |
|
|
30 | public PromiseFuncReaction(Func<TRet> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
31 | m_next = new Deferred<TRet>(dispatcher); | |
|
39 | 32 | if (fulfilled != null) |
|
40 |
|
|
|
33 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
34 | ||
|
41 | 35 | if (rejected != null) |
|
42 |
|
|
|
43 | ||
|
44 | m_next = next; | |
|
36 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
45 | 37 | } |
|
46 | 38 | |
|
39 | public PromiseFuncReaction(Func<IPromise<TRet>> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) : base(dispatcher) { | |
|
40 | m_next = new Deferred<TRet>(dispatcher); | |
|
41 | if (fulfilled != null) | |
|
42 | FulfilHandler = PromiseHandler.Create(fulfilled, m_next); | |
|
47 | 43 | |
|
48 | protected override bool HasFulfilHandler => m_fulfilled != null; | |
|
49 | ||
|
50 | protected override bool HasRejectHandler => m_rejected != null; | |
|
44 | if (rejected != null) | |
|
45 | RejectHandler = PromiseHandler.Create(rejected, m_next); | |
|
46 | } | |
|
51 | 47 | |
|
52 | 48 | protected override void DefaultReject(Exception reason) { |
|
53 | 49 | m_next.Reject(reason); |
@@ -56,21 +52,5 namespace Implab { | |||
|
56 | 52 | protected override void DefaultResolve() { |
|
57 | 53 | throw new NotImplementedException(); |
|
58 | 54 | } |
|
59 | ||
|
60 | protected override void RejectImpl(Exception reason) { | |
|
61 | try { | |
|
62 | m_rejected(reason); | |
|
63 | } catch (Exception e){ | |
|
64 | m_next.Reject(e); | |
|
65 | } | |
|
66 | } | |
|
67 | ||
|
68 | protected override void ResolveImpl() { | |
|
69 | try { | |
|
70 | m_fulfilled(); | |
|
71 | } catch (Exception e){ | |
|
72 | m_next.Reject(e); | |
|
73 | } | |
|
74 | } | |
|
75 | 55 | } |
|
76 | 56 | } No newline at end of file |
@@ -1,6 +1,11 | |||
|
1 | 1 | using System; |
|
2 | 2 | |
|
3 | 3 | namespace Implab { |
|
4 | /// <summary> | |
|
5 | /// Базовыйй класс для создания обработчиков результов выполнения обещаний. | |
|
6 | /// Данный объект связывает обработчик и обешание, при этом для выполнения | |
|
7 | /// обработчика будет использоваться диспетчер. | |
|
8 | /// </summary> | |
|
4 | 9 | abstract class PromiseReaction : IResolvable { |
|
5 | 10 | readonly IDispatcher m_dispatcher; |
|
6 | 11 | |
@@ -8,36 +13,28 namespace Implab { | |||
|
8 | 13 | m_dispatcher = dispatcher; |
|
9 | 14 | } |
|
10 | 15 | |
|
11 |
protected |
|
|
12 | get; | |
|
13 | } | |
|
16 | protected Action FulfilHandler { get; set; } | |
|
14 | 17 | |
|
15 |
protected |
|
|
16 | get; | |
|
17 | } | |
|
18 | protected Action<Exception> RejectHandler { get; set; } | |
|
18 | 19 | |
|
19 | 20 | public void Reject(Exception error) { |
|
20 |
if ( |
|
|
21 | if (RejectHandler == null) | |
|
21 | 22 | DefaultReject(error); |
|
22 | 23 | else if (m_dispatcher != null) |
|
23 |
m_dispatcher.Enqueue( |
|
|
24 | m_dispatcher.Enqueue(RejectHandler, error); | |
|
24 | 25 | else |
|
25 |
Reject |
|
|
26 | RejectHandler(error); | |
|
26 | 27 | } |
|
27 | 28 | |
|
28 | 29 | public void Resolve() { |
|
29 |
if ( |
|
|
30 | if (FulfilHandler == null) | |
|
30 | 31 | DefaultResolve(); |
|
31 | 32 | else if (m_dispatcher != null) |
|
32 |
m_dispatcher.Enqueue( |
|
|
33 | m_dispatcher.Enqueue(FulfilHandler); | |
|
33 | 34 | else |
|
34 |
|
|
|
35 | FulfilHandler(); | |
|
35 | 36 | } |
|
36 | 37 | |
|
37 | protected abstract void ResolveImpl(); | |
|
38 | ||
|
39 | protected abstract void RejectImpl(Exception reason); | |
|
40 | ||
|
41 | 38 | protected abstract void DefaultResolve(); |
|
42 | 39 | |
|
43 | 40 | protected abstract void DefaultReject(Exception reason); |
@@ -1,6 +1,11 | |||
|
1 | 1 | using System; |
|
2 | 2 | |
|
3 | 3 | namespace Implab { |
|
4 | /// <summary> | |
|
5 | /// Базовыйй класс для создания обработчиков результов выполнения обещаний. | |
|
6 | /// Данный объект связывает обработчик и обешание, при этом для выполнения | |
|
7 | /// обработчика будет использоваться диспетчер. | |
|
8 | /// </summary> | |
|
4 | 9 | abstract class PromiseReaction<T> : IResolvable<T> { |
|
5 | 10 | readonly IDispatcher m_dispatcher; |
|
6 | 11 | |
@@ -8,36 +13,28 namespace Implab { | |||
|
8 | 13 | m_dispatcher = dispatcher; |
|
9 | 14 | } |
|
10 | 15 | |
|
11 |
protected |
|
|
12 | get; | |
|
13 | } | |
|
16 | protected Action<T> FulfilHandler { get; set; } | |
|
14 | 17 | |
|
15 |
protected |
|
|
16 | get; | |
|
17 | } | |
|
18 | protected Action<Exception> RejectHandler { get; set; } | |
|
18 | 19 | |
|
19 | 20 | public void Reject(Exception error) { |
|
20 |
if ( |
|
|
21 | if (RejectHandler == null) | |
|
21 | 22 | DefaultReject(error); |
|
22 | 23 | else if (m_dispatcher != null) |
|
23 |
m_dispatcher.Enqueue( |
|
|
24 | m_dispatcher.Enqueue(RejectHandler, error); | |
|
24 | 25 | else |
|
25 |
Reject |
|
|
26 | RejectHandler(error); | |
|
26 | 27 | } |
|
27 | 28 | |
|
28 | 29 | public void Resolve(T result) { |
|
29 |
if ( |
|
|
30 | if (FulfilHandler == null) | |
|
30 | 31 | DefaultResolve(result); |
|
31 | 32 | else if (m_dispatcher != null) |
|
32 |
m_dispatcher.Enqueue( |
|
|
33 | m_dispatcher.Enqueue(FulfilHandler, result); | |
|
33 | 34 | else |
|
34 |
|
|
|
35 | FulfilHandler(result); | |
|
35 | 36 | } |
|
36 | 37 | |
|
37 | protected abstract void ResolveImpl(T result); | |
|
38 | ||
|
39 | protected abstract void RejectImpl(Exception reason); | |
|
40 | ||
|
41 | 38 | protected abstract void DefaultResolve(T result); |
|
42 | 39 | |
|
43 | 40 | protected abstract void DefaultReject(Exception reason); |
@@ -112,9 +112,9 namespace Implab | |||
|
112 | 112 | ArgumentNotNull(action, "action"); |
|
113 | 113 | |
|
114 | 114 | try { |
|
115 |
return Promise |
|
|
115 | return Promise.Resolve(action()); | |
|
116 | 116 | } catch (Exception err) { |
|
117 |
return Promise<T> |
|
|
117 | return Promise.Reject<T>(err); | |
|
118 | 118 | } |
|
119 | 119 | } |
|
120 | 120 | |
@@ -124,9 +124,9 namespace Implab | |||
|
124 | 124 | |
|
125 | 125 | try { |
|
126 | 126 | action(); |
|
127 |
return Promise. |
|
|
127 | return Promise.Resolve(); | |
|
128 | 128 | } catch (Exception err) { |
|
129 |
return |
|
|
129 | return Promise.Reject(err); | |
|
130 | 130 | } |
|
131 | 131 | } |
|
132 | 132 | |
@@ -135,9 +135,9 namespace Implab | |||
|
135 | 135 | ArgumentNotNull(action, "action"); |
|
136 | 136 | |
|
137 | 137 | try { |
|
138 |
return action() ?? |
|
|
138 | return action() ?? Promise.Reject(new Exception("The action returned null")); | |
|
139 | 139 | } catch (Exception err) { |
|
140 |
return |
|
|
140 | return Promise.Reject(err); | |
|
141 | 141 | } |
|
142 | 142 | } |
|
143 | 143 | |
@@ -149,9 +149,9 namespace Implab | |||
|
149 | 149 | ArgumentNotNull(action, "action"); |
|
150 | 150 | |
|
151 | 151 | try { |
|
152 |
return action() ?? Promise<T> |
|
|
152 | return action() ?? Promise.Reject<T>(new Exception("The action returned null")); | |
|
153 | 153 | } catch (Exception err) { |
|
154 |
return Promise<T> |
|
|
154 | return Promise.Reject<T>(err); | |
|
155 | 155 | } |
|
156 | 156 | } |
|
157 | 157 |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
General Comments 3
ok, latest stable version should be in default
You need to be logged in to leave comments.
Login now