##// END OF EJS Templates
working on promises
cin -
r244:eee3e49dd1ff v3
parent child
Show More
@@ -0,0 +1,52
1 using System;
2 using System.Diagnostics;
3
4 namespace Implab {
5 /// <summary>
6 /// This class is responsible for the promise resolution, dispatching and chaining
7 /// </summary>
8 public class Deferred : IResolvable {
9
10 readonly AbstractPromise m_promise;
11 readonly IDispatcher m_dispatcher;
12
13 internal Deferred(AbstractPromise promise, IDispatcher dispatcher) {
14 Debug.Assert(promise != null);
15 m_promise = promise;
16 m_dispatcher = dispatcher;
17 }
18
19 public IPromise Promise {
20 get { return m_promise; }
21 }
22
23 public void Reject(Exception error) {
24 m_promise.Reject(error);
25 }
26
27 public void Resolve() {
28 m_promise.Resolve();
29 }
30
31 public void Resolve(IPromise thenable) {
32 if (thenable == null)
33 Reject(new Exception("The promise or task are expected"));
34 if (thenable == m_promise)
35 Reject(new Exception("The promise cannot be resolved with oneself"));
36
37 else if (m_dispatcher != null)
38 // dispatch (see ecma-262/6.0: 25.4.1.3.2 Promise Resolve Functions)
39 m_dispatcher.Enqueue(() => thenable.Then(this));
40 else
41 thenable.Then(this);
42 }
43
44 void Chain(IPromise thenable) {
45 try {
46 thenable.Then(this);
47 } catch (Exception err) {
48 Reject(err);
49 }
50 }
51 }
52 } No newline at end of file
@@ -0,0 +1,7
1 using System;
2
3 namespace Implab {
4 public interface IDispatcher {
5 void Enqueue(Action job);
6 }
7 } No newline at end of file
@@ -0,0 +1,26
1 using System;
2
3 namespace Implab {
4 /// <summary>
5 /// Deferred result, usually used by asynchronous services as the service part of the promise.
6 /// </summary>
7 public interface IResolvable {
8
9 void Resolve();
10
11 void Resolve(IPromise thenable);
12
13 /// <summary>
14 /// Reject the promise with the specified error.
15 /// </summary>
16 /// <param name="error">The reason why the promise is rejected.</param>
17 /// <remarks>
18 /// Some exceptions are treated in a special case:
19 /// <see cref="OperationCanceledException"/> is interpreted as call to <see cref="Cancel()"/> method,
20 /// and <see cref="PromiseTransientException"/> is always unwrapped and its
21 /// <see cref="PromiseTransientException.InnerException"> is used as the reason to reject promise.
22 /// </remarks>
23 void Reject(Exception error);
24 }
25 }
26
@@ -35,31 +35,31 namespace Implab {
35 35 /// </para>
36 36 /// </remarks>
37 37 public abstract class AbstractEvent<THandler> where THandler : class {
38 const int PENDING_SATE = 0;
38 const int PendingState = 0;
39 39
40 const int TRANSITIONAL_STATE = 1;
40 const int TransitionalState = 1;
41 41
42 const int FULFILLED_STATE = 2;
42 const int ResolvedState = 2;
43 43
44 44 volatile int m_state;
45 45
46 46 THandler m_handler;
47 47 SimpleAsyncQueue<THandler> m_extraHandlers;
48 48
49 public bool IsFulfilled {
49 public bool IsResolved {
50 50 get {
51 return m_state > TRANSITIONAL_STATE;
51 return m_state > TransitionalState;
52 52 }
53 53 }
54 54
55 55 #region state managment
56 56 protected bool BeginTransit() {
57 return PENDING_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, PENDING_SATE);
57 return PendingState == Interlocked.CompareExchange(ref m_state, TransitionalState, PendingState);
58 58 }
59 59
60 60 protected void CompleteTransit() {
61 61 #if DEBUG
62 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, FULFILLED_STATE, TRANSITIONAL_STATE))
62 if (TransitionalState != Interlocked.CompareExchange(ref m_state, ResolvedState, TransitionalState))
63 63 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
64 64 #else
65 65 m_state = state;
@@ -68,11 +68,11 namespace Implab {
68 68 }
69 69
70 70 protected void WaitTransition() {
71 if (m_state == TRANSITIONAL_STATE) {
71 if (m_state == TransitionalState) {
72 72 SpinWait spin;
73 73 do {
74 74 spin.SpinOnce();
75 } while (m_state == TRANSITIONAL_STATE);
75 } while (m_state == TransitionalState);
76 76 }
77 77 }
78 78
@@ -91,7 +91,7 namespace Implab {
91 91
92 92 #region synchronization traits
93 93 protected void WaitResult(int timeout) {
94 if (!(IsFulfilled || GetFulfillSignal().Wait(timeout)))
94 if (!(IsResolved || GetFulfillSignal().Wait(timeout)))
95 95 throw new TimeoutException();
96 96 }
97 97
@@ -102,13 +102,13 namespace Implab {
102 102
103 103 protected void AddHandler(THandler handler) {
104 104
105 if (IsFulfilled) {
105 if (IsResolved) {
106 106 // the promise is in the resolved state, just invoke the handler
107 107 SignalHandler(handler);
108 108 } else {
109 109 EnqueueHandler(handler);
110 110
111 if (IsFulfilled && TryDequeueHandler(out handler))
111 if (IsResolved && TryDequeueHandler(out handler))
112 112 // if the promise have been resolved while we was adding the handler to the queue
113 113 // we can't guarantee that someone is still processing it
114 114 // therefore we need to fetch a handler from the queue and execute it
@@ -4,36 +4,21 using System.Reflection;
4 4 using Implab.Parallels;
5 5
6 6 namespace Implab {
7 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise {
8 public class HandlerDescriptor {
9 readonly Action m_resolve;
10 readonly Action<Exception> m_reject;
7 public class AbstractPromise : AbstractEvent<IResolvable>, IPromise {
11 8
12 readonly IDeferred m_deferred;
13 public HandlerDescriptor(Action success, Action<Exception> error) {
14 m_resolve = success;
15 m_reject = error;
9 class ResolvableSignal : IResolvable {
10 public Signal Signal { get; private set; }
11 public ResolvableSignal() {
12 Signal = new Signal();
16 13 }
17 14
18 public void SignalSuccess() {
19 try {
20 if (m_resolve != null)
21 m_resolve();
22 m_deferred.Resolve();
23 } catch (Exception ex) {
24 m_deferred.Reject(ex);
25 }
15
16 public void Reject(Exception error) {
17 Signal.Set();
26 18 }
27 19
28 public void SignalError(Exception err) {
29 if (m_reject != null) {
30 try {
31 m_reject(err);
32 m_deferred.Resolve();
33 } catch (Exception ex) {
34 m_deferred.Reject(ex);
35 }
36 }
20 public void Resolve() {
21 Signal.Set();
37 22 }
38 23 }
39 24
@@ -47,9 +32,9 namespace Implab {
47 32 }
48 33 }
49 34
50 public bool IsResolved {
35 public bool IsFulfilled {
51 36 get {
52 return m_state == PromiseState.Resolved;
37 return m_state == PromiseState.Fulfilled;
53 38 }
54 39 }
55 40
@@ -60,15 +45,29 namespace Implab {
60 45 }
61 46
62 47
48 internal void Resolve() {
49 if (BeginTransit())
50 CompleteResolve();
51 }
52
53 internal void Reject(Exception reason) {
54 if (BeginTransit()) {
55 m_error = reason;
56 m_state = PromiseState.Rejected;
57 CompleteTransit();
58 }
59 }
60
61
63 62 #region implemented abstract members of AbstractPromise
64 63
65 protected override void SignalHandler(HandlerDescriptor handler) {
64 protected override void SignalHandler(IResolvable handler) {
66 65 switch (m_state) {
67 case PromiseState.Resolved:
68 handler.SignalSuccess();
66 case PromiseState.Fulfilled:
67 handler.Resolve();
69 68 break;
70 69 case PromiseState.Rejected:
71 handler.SignalError(RejectReason);
70 handler.Reject(RejectReason);
72 71 break;
73 72 default:
74 73 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state));
@@ -76,15 +75,15 namespace Implab {
76 75 }
77 76
78 77 protected override Signal GetFulfillSignal() {
79 var signal = new Signal();
80 On(signal.Set, e => signal.Set());
81 return signal;
78 var next = new ResolvableSignal();
79 Then(next);
80 return next.Signal;
82 81 }
83 82
84 83 #endregion
85 84
86 85 protected void CompleteResolve() {
87 m_state = PromiseState.Resolved;
86 m_state = PromiseState.Fulfilled;
88 87 CompleteTransit();
89 88 }
90 89
@@ -94,27 +93,6 namespace Implab {
94 93 }
95 94 }
96 95
97 /// <summary>
98 /// Выполняет обещание, сообщая об ошибке
99 /// </summary>
100 /// <remarks>
101 /// Поскольку обещание должно работать в многопточной среде, при его выполнении сразу несколько потоков
102 /// могу вернуть ошибку, при этом только первая будет использована в качестве результата, остальные
103 /// будут проигнорированы.
104 /// </remarks>
105 /// <param name="error">Исключение возникшее при выполнении операции</param>
106 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
107 protected void SetError(Exception error) {
108 if (BeginTransit()) {
109 m_error = error;
110 m_state = PromiseState.Rejected;
111 CompleteTransit();
112 } else {
113 WaitTransition();
114 if (m_state == PromiseState.Resolved)
115 throw new InvalidOperationException("The promise is already resolved");
116 }
117 }
118 96
119 97 protected void Rethrow() {
120 98 Debug.Assert(m_error != null);
@@ -124,8 +102,8 namespace Implab {
124 102 throw new TargetInvocationException(m_error);
125 103 }
126 104
127 public void On(Action success, Action<Exception> error) {
128 AddHandler(new HandlerDescriptor(success, error));
105 public void Then(IResolvable next) {
106 AddHandler(next);
129 107 }
130 108
131 109 public IPromise<T> Cast<T>() {
@@ -1,7 +1,7
1 1 using System;
2 2
3 3 namespace Implab {
4 public class ActionChainTask : ActionChainTaskBase, IDeferred {
4 public class ActionChainTask : ActionChainTaskBase, IResolvable {
5 5 readonly Func<IPromise> m_task;
6 6
7 7 /// <summary>
@@ -1,7 +1,7
1 1 using System;
2 2
3 3 namespace Implab {
4 public class ActionTask : ActionTaskBase, IDeferred {
4 public class ActionTask : ActionTaskBase, IResolvable {
5 5 readonly Action m_task;
6 6 public ActionTask(Action task, Action<Exception> error, Action<Exception> cancel, bool autoCancellable) : base(error,cancel, autoCancellable) {
7 7 m_task = task;
@@ -1,6 +1,6
1 1 using System;
2 using System.Diagnostics.CodeAnalysis;
3
2 using System.Diagnostics.CodeAnalysis;
3
4 4 namespace Implab.Components {
5 5 public abstract class RunnableComponent : IDisposable, IRunnable, IInitializable {
6 6 enum Commands {
@@ -18,28 +18,28 namespace Implab.Components {
18 18 public static readonly ExecutionState[,] ReusableTransitions;
19 19 public static readonly ExecutionState[,] NonreusableTransitions;
20 20
21 class StateBuilder {
22 readonly ExecutionState[,] m_states;
23
24 public ExecutionState[,] States {
25 get { return m_states; }
26 }
27 public StateBuilder(ExecutionState[,] states) {
28 m_states = states;
29 }
30
31 public StateBuilder() {
32 m_states = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1];
33 }
34
35 public StateBuilder Edge(ExecutionState s1, ExecutionState s2, Commands cmd) {
36 m_states[(int)s1, (int)cmd] = s2;
37 return this;
38 }
39
40 public StateBuilder Clone() {
41 return new StateBuilder((ExecutionState[,])m_states.Clone());
42 }
21 class StateBuilder {
22 readonly ExecutionState[,] m_states;
23
24 public ExecutionState[,] States {
25 get { return m_states; }
26 }
27 public StateBuilder(ExecutionState[,] states) {
28 m_states = states;
29 }
30
31 public StateBuilder() {
32 m_states = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1];
33 }
34
35 public StateBuilder Edge(ExecutionState s1, ExecutionState s2, Commands cmd) {
36 m_states[(int)s1, (int)cmd] = s2;
37 return this;
38 }
39
40 public StateBuilder Clone() {
41 return new StateBuilder((ExecutionState[,])m_states.Clone());
42 }
43 43 }
44 44
45 45 static StateMachine() {
@@ -65,8 +65,8 namespace Implab.Components {
65 65 .Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose)
66 66
67 67 .Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose)
68 .Edge(ExecutionState.Failed, ExecutionState.Initializing, Commands.Reset)
69
68 .Edge(ExecutionState.Failed, ExecutionState.Initializing, Commands.Reset)
69
70 70 .Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail)
71 71 .Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Dispose)
72 72
@@ -74,11 +74,11 namespace Implab.Components {
74 74
75 75 var reusable = common
76 76 .Clone()
77 .Edge(ExecutionState.Stopping, ExecutionState.Ready, Commands.Ok);
78
79 var nonreusable = common
80 .Clone()
81 .Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok);
77 .Edge(ExecutionState.Stopping, ExecutionState.Ready, Commands.Ok);
78
79 var nonreusable = common
80 .Clone()
81 .Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok);
82 82
83 83 NonreusableTransitions = nonreusable.States;
84 84 ReusableTransitions = reusable.States;
@@ -109,45 +109,45 namespace Implab.Components {
109 109 IPromise m_pending;
110 110 Exception m_lastError;
111 111
112 readonly StateMachine m_stateMachine;
113 readonly bool m_reusable;
114 public event EventHandler<StateChangeEventArgs> StateChanged;
115
116 /// <summary>
117 /// Initializes component state.
118 /// </summary>
119 /// <param name="initialized">If set, the component initial state is <see cref="ExecutionState.Ready"/> and the component is ready to start, otherwise initialization is required.</param>
120 /// <param name="reusable">If set, the component may start after it has been stopped, otherwise the component is disposed after being stopped.</param>
121 protected RunnableComponent(bool initialized, bool reusable) {
112 readonly StateMachine m_stateMachine;
113 readonly bool m_reusable;
114 public event EventHandler<StateChangeEventArgs> StateChanged;
115
116 /// <summary>
117 /// Initializes component state.
118 /// </summary>
119 /// <param name="initialized">If set, the component initial state is <see cref="ExecutionState.Ready"/> and the component is ready to start, otherwise initialization is required.</param>
120 /// <param name="reusable">If set, the component may start after it has been stopped, otherwise the component is disposed after being stopped.</param>
121 protected RunnableComponent(bool initialized, bool reusable) {
122 122 m_stateMachine = new StateMachine(
123 123 reusable ? StateMachine.ReusableTransitions : StateMachine.NonreusableTransitions,
124 124 initialized ? ExecutionState.Ready : ExecutionState.Created
125 125 );
126 126 m_reusable = reusable;
127 }
128
129 /// <summary>
130 /// Initializes component state. The component created with this constructor is not reusable, i.e. it will be disposed after stop.
131 /// </summary>
132 /// <param name="initialized">If set, the component initial state is <see cref="ExecutionState.Ready"/> and the component is ready to start, otherwise initialization is required.</param>
127 }
128
129 /// <summary>
130 /// Initializes component state. The component created with this constructor is not reusable, i.e. it will be disposed after stop.
131 /// </summary>
132 /// <param name="initialized">If set, the component initial state is <see cref="ExecutionState.Ready"/> and the component is ready to start, otherwise initialization is required.</param>
133 133 protected RunnableComponent(bool initialized) : this(initialized, false) {
134 134 }
135 135
136 136 void ThrowInvalidCommand(Commands cmd) {
137 137 if (m_stateMachine.State == ExecutionState.Disposed)
138 throw new ObjectDisposedException(ToString());
139
138 throw new ObjectDisposedException(ToString());
139
140 140 throw new InvalidOperationException(String.Format("Command {0} is not allowed in the state {1}", cmd, m_stateMachine.State));
141 141 }
142 142
143 143 bool MoveIfInState(Commands cmd, IPromise pending, Exception error, ExecutionState state) {
144 144 ExecutionState prev, current;
145 lock (m_stateMachine) {
146 if (m_stateMachine.State != state)
147 return false;
148
149 prev = m_stateMachine.State;
150 if (!m_stateMachine.Move(cmd))
145 lock (m_stateMachine) {
146 if (m_stateMachine.State != state)
147 return false;
148
149 prev = m_stateMachine.State;
150 if (!m_stateMachine.Move(cmd))
151 151 ThrowInvalidCommand(cmd);
152 152 current = m_stateMachine.State;
153 153
@@ -161,46 +161,46 namespace Implab.Components {
161 161
162 162 bool MoveIfPending(Commands cmd, IPromise pending, Exception error, IPromise expected) {
163 163 ExecutionState prev, current;
164 lock (m_stateMachine) {
165 if (m_pending != expected)
166 return false;
167 prev = m_stateMachine.State;
168 if (!m_stateMachine.Move(cmd))
164 lock (m_stateMachine) {
165 if (m_pending != expected)
166 return false;
167 prev = m_stateMachine.State;
168 if (!m_stateMachine.Move(cmd))
169 169 ThrowInvalidCommand(cmd);
170 170 current = m_stateMachine.State;
171 171 m_pending = pending;
172 172 m_lastError = error;
173 }
173 }
174 174 if (prev != current)
175 OnStateChanged(prev, current, error);
175 OnStateChanged(prev, current, error);
176 176 return true;
177 177 }
178 178
179 179 IPromise Move(Commands cmd, IPromise pending, Exception error) {
180 180 ExecutionState prev, current;
181 181 IPromise ret;
182 lock (m_stateMachine) {
183 prev = m_stateMachine.State;
184 if (!m_stateMachine.Move(cmd))
182 lock (m_stateMachine) {
183 prev = m_stateMachine.State;
184 if (!m_stateMachine.Move(cmd))
185 185 ThrowInvalidCommand(cmd);
186 186 current = m_stateMachine.State;
187 187
188 188 ret = m_pending;
189 189 m_pending = pending;
190 m_lastError = error;
191
190 m_lastError = error;
191
192 192 }
193 193 if (prev != current)
194 194 OnStateChanged(prev, current, error);
195 195 return ret;
196 196 }
197 197
198 /// <summary>
199 /// Handles the state of the component change event, raises the <see cref="StateChanged"/> event, handles
200 /// the transition to the <see cref="ExecutionState.Disposed"/> state (calls <see cref="Dispose(bool)"/> method).
201 /// </summary>
202 /// <param name="previous">The previous state</param>
203 /// <param name="current">The current state</param>
198 /// <summary>
199 /// Handles the state of the component change event, raises the <see cref="StateChanged"/> event, handles
200 /// the transition to the <see cref="ExecutionState.Disposed"/> state (calls <see cref="Dispose(bool)"/> method).
201 /// </summary>
202 /// <param name="previous">The previous state</param>
203 /// <param name="current">The current state</param>
204 204 /// <param name="error">The last error if any.</param>
205 205 /// <remarks>
206 206 /// <para>
@@ -212,31 +212,31 namespace Implab.Components {
212 212 /// the wrong behavior of the component.
213 213 /// </para>
214 214 /// </remarks>
215 protected virtual void OnStateChanged(ExecutionState previous, ExecutionState current, Exception error) {
216 StateChanged.DispatchEvent(
217 this,
218 new StateChangeEventArgs {
219 State = current,
220 LastError = error
221 }
222 );
223 if (current == ExecutionState.Disposed) {
224 GC.SuppressFinalize(this);
225 Dispose(true);
226 }
215 protected virtual void OnStateChanged(ExecutionState previous, ExecutionState current, Exception error) {
216 StateChanged.DispatchEvent(
217 this,
218 new StateChangeEventArgs {
219 State = current,
220 LastError = error
221 }
222 );
223 if (current == ExecutionState.Disposed) {
224 GC.SuppressFinalize(this);
225 Dispose(true);
226 }
227 227 }
228 228
229 229 /// <summary>
230 230 /// Moves the component from running to failed state.
231 231 /// </summary>
232 232 /// <param name="error">The exception which is describing the error.</param>
233 protected bool Fail(Exception error) {
234 return MoveIfInState(Commands.Fail, null, error, ExecutionState.Running);
233 protected bool Fail(Exception error) {
234 return MoveIfInState(Commands.Fail, null, error, ExecutionState.Running);
235 235 }
236 236
237 /// <summary>
238 /// Tries to reset <see cref="ExecutionState.Failed"/> state to <see cref="ExecutionState.Ready"/>.
239 /// </summary>
237 /// <summary>
238 /// Tries to reset <see cref="ExecutionState.Failed"/> state to <see cref="ExecutionState.Ready"/>.
239 /// </summary>
240 240 /// <returns>True if component is reset to <see cref="ExecutionState.Ready"/>, false if the componet wasn't
241 241 /// in <see cref="ExecutionState.Failed"/> state.</returns>
242 242 /// <remarks>
@@ -246,10 +246,10 namespace Implab.Components {
246 246 /// to <see cref="ExecutionState.Ready"/> state, otherwise the component is moved to <see cref="ExecutionState.Failed"/>
247 247 /// state. If <see cref="OnResetState()"/> throws an exception it will be propagated by this method to the caller.
248 248 /// </remarks>
249 protected bool ResetState() {
250 if (!MoveIfInState(Commands.Reset, null, null, ExecutionState.Failed))
251 return false;
252
249 protected bool ResetState() {
250 if (!MoveIfInState(Commands.Reset, null, null, ExecutionState.Failed))
251 return false;
252
253 253 try {
254 254 OnResetState();
255 255 Move(Commands.Ok, null, null);
@@ -257,38 +257,38 namespace Implab.Components {
257 257 } catch (Exception err) {
258 258 Move(Commands.Fail, null, err);
259 259 throw;
260 }
260 }
261 261 }
262 262
263 /// <summary>
264 /// This method is called by <see cref="ResetState"/> to reinitialize component in the failed state.
263 /// <summary>
264 /// This method is called by <see cref="ResetState"/> to reinitialize component in the failed state.
265 265 /// </summary>
266 266 /// <remarks>
267 267 /// Default implementation throws <see cref="NotImplementedException"/> which will cause the component
268 268 /// fail to reset it's state and it left in <see cref="ExecutionState.Failed"/> state.
269 269 /// If this method doesn't throw exceptions the component is moved to <see cref="ExecutionState.Ready"/> state.
270 270 /// </remarks>
271 protected virtual void OnResetState() {
272 throw new NotImplementedException();
271 protected virtual void OnResetState() {
272 throw new NotImplementedException();
273 273 }
274 274
275 IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IDeferred> chain) {
275 IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IResolvable> chain) {
276 276 IPromise promise = null;
277 277 IPromise prev;
278 278
279 279 var task = new ActionChainTask(action, null, null, true);
280 280
281 Action<Exception> errorOrCancel = e => {
282 if (e == null)
283 e = new OperationCanceledException();
284 MoveIfPending(Commands.Fail, null, e, promise);
285 throw new PromiseTransientException(e);
281 Action<Exception> errorOrCancel = e => {
282 if (e == null)
283 e = new OperationCanceledException();
284 MoveIfPending(Commands.Fail, null, e, promise);
285 throw new PromiseTransientException(e);
286 286 };
287 287
288 288 promise = task.Then(
289 289 () => MoveIfPending(Commands.Ok, null, null, promise),
290 290 errorOrCancel,
291 errorOrCancel
291 errorOrCancel
292 292 );
293 293
294 294 prev = Move(cmd, promise, null);
@@ -305,8 +305,8 namespace Implab.Components {
305 305 #region IInitializable implementation
306 306
307 307 public void Initialize() {
308 Move(Commands.Init, null, null);
309
308 Move(Commands.Init, null, null);
309
310 310 try {
311 311 OnInitialize();
312 312 Move(Commands.Ok, null, null);
@@ -344,7 +344,7 namespace Implab.Components {
344 344 /// </summary>
345 345 /// <param name="current">Current.</param>
346 346 /// <param name="stop">Stop.</param>
347 protected virtual void StopPending(IPromise current, IDeferred stop) {
347 protected virtual void StopPending(IPromise current, IResolvable stop) {
348 348 if (current == null) {
349 349 stop.Resolve();
350 350 } else {
@@ -398,11 +398,11 namespace Implab.Components {
398 398
399 399 #endregion
400 400
401 /// <summary>
402 /// Releases all resources used by the component, called automatically, override this method to implement your cleanup.
403 /// </summary>
404 /// <param name="disposing">true if this method is called during normal dispose process.</param>
405 /// <param name="pending">The operation which is currenty pending</param>
401 /// <summary>
402 /// Releases all resources used by the component, called automatically, override this method to implement your cleanup.
403 /// </summary>
404 /// <param name="disposing">true if this method is called during normal dispose process.</param>
405 /// <param name="pending">The operation which is currenty pending</param>
406 406 protected virtual void Dispose(bool disposing) {
407 407 }
408 408
@@ -1,7 +1,7
1 1 using System;
2 2
3 3 namespace Implab {
4 public class FuncChainTask<TResult> : FuncChainTaskBase<TResult>, IDeferred {
4 public class FuncChainTask<TResult> : FuncChainTaskBase<TResult>, IResolvable {
5 5 readonly Func<IPromise<TResult>> m_task;
6 6
7 7 public FuncChainTask(Func<IPromise<TResult>> task, Func<Exception, IPromise<TResult>> error, Func<Exception, IPromise<TResult>> cancel, bool autoCancellable)
@@ -2,7 +2,7
2 2 using System.Threading;
3 3
4 4 namespace Implab {
5 public class FuncTask<T> : FuncTaskBase<T>, IDeferred {
5 public class FuncTask<T> : FuncTaskBase<T>, IResolvable {
6 6 readonly Func<T> m_task;
7 7
8 8 public FuncTask(Func<T> task, Func<Exception, T> error, Func<Exception, T> cancel, bool autoCancellable) : base(error, cancel, autoCancellable) {
@@ -14,11 +14,11 namespace Implab {
14 14 /// <summary>
15 15 /// Обещание является выполненым, либо успешно, либо с ошибкой, либо отменено.
16 16 /// </summary>
17 bool IsFulfilled { get; }
17 bool IsResolved { get; }
18 18
19 19 bool IsRejected { get; }
20 20
21 bool IsResolved { get; }
21 bool IsFulfilled { get; }
22 22
23 23 /// <summary>
24 24 /// Исключение возникшее в результате выполнения обещания, либо причина отмены.
@@ -31,23 +31,11 namespace Implab {
31 31 /// <param name="success">The handler called on the successful promise completion.</param>
32 32 /// <param name="error">The handler is called if an error while completing the promise occurred.</param>
33 33 /// <returns>The current promise.</returns>
34 void On(Action success, Action<Exception> error);
34 void Then(IResolvable next);
35 35
36 36 /// <summary>
37 37 /// Преобразует результат обещания к заданному типу и возвращает новое обещание.
38 38 /// </summary>
39 39 IPromise<T> Cast<T>();
40
41 /// <summary>
42 /// Синхронизирует текущий поток с обещанием.
43 /// </summary>
44 void Join();
45 /// <summary>
46 /// Синхронизирует текущий поток с обещанием.
47 /// </summary>
48 /// <param name="timeout">Время ожидания, по его истечению возникнет исключение.</param>
49 /// <exception cref="TimeoutException">Превышено время ожидания.</exception>
50 void Join(int timeout);
51
52 40 }
53 41 }
@@ -2,7 +2,7 namespace Implab {
2 2 public enum PromiseState {
3 3 Pending,
4 4
5 Resolved,
5 Fulfilled,
6 6
7 7 Rejected
8 8 }
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now