##// END OF EJS Templates
Слияние с default
cin -
r199:43b1017ce100 merge v2
parent child
Show More
@@ -0,0 +1,1
1 f1da3afc3521e0e1631ac19e09690bc0a241841a release v2.1
@@ -1,142 +1,140
1 1 using System;
2 2 using Implab.Parallels;
3 3
4 4 namespace Implab {
5 5 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise {
6 6 public struct HandlerDescriptor {
7 7 readonly Action m_handler;
8 8 readonly Action<Exception> m_error;
9 9 readonly Action<Exception> m_cancel;
10 10 readonly PromiseEventType m_mask;
11 11
12 12 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
13 13 m_handler = success;
14 14 m_error = error;
15 15 m_cancel = cancel;
16 16 m_mask = PromiseEventType.Success;
17 17 }
18 18
19 19 public HandlerDescriptor(Action handler, PromiseEventType mask) {
20 20 m_handler = handler;
21 21 m_error = null;
22 22 m_cancel = null;
23 23 m_mask = mask;
24 24 }
25 25
26 26 public void SignalSuccess() {
27 27 if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) {
28 28 try {
29 29 m_handler();
30 } catch (Exception err) {
31 // avoid calling handler twice in case of error
32 if (m_error != null)
33 SignalError(err);
30 // Analysis disable once EmptyGeneralCatchClause
31 } catch {
34 32 }
35 33 }
36 34 }
37 35
38 36 public void SignalError(Exception err) {
39 37 if (m_error != null) {
40 38 try {
41 39 m_error(err);
42 40 // Analysis disable once EmptyGeneralCatchClause
43 41 } catch {
44 42 }
45 43 } else if ((m_mask & PromiseEventType.Error ) != 0 && m_handler != null) {
46 44 try {
47 45 m_handler();
48 46 // Analysis disable once EmptyGeneralCatchClause
49 47 } catch {
50 48 }
51 49 }
52 50 }
53 51
54 52 public void SignalCancel(Exception reason) {
55 53 if (m_cancel != null) {
56 54 try {
57 55 m_cancel(reason);
58 } catch (Exception err) {
59 SignalError(err);
56 // Analysis disable once EmptyGeneralCatchClause
57 } catch {
60 58 }
61 59 } else if ( (m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) {
62 60 try {
63 61 m_handler();
64 62 // Analysis disable once EmptyGeneralCatchClause
65 63 } catch {
66 64 }
67 65 }
68 66 }
69 67 }
70 68
71 69
72 70 #region implemented abstract members of AbstractPromise
73 71
74 72 protected override void SignalHandler(HandlerDescriptor handler, int signal) {
75 73 switch (signal) {
76 74 case SUCCEEDED_STATE:
77 75 handler.SignalSuccess();
78 76 break;
79 77 case REJECTED_STATE:
80 78 handler.SignalError(Error);
81 79 break;
82 80 case CANCELLED_STATE:
83 81 handler.SignalCancel(CancellationReason);
84 82 break;
85 83 default:
86 84 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", signal));
87 85 }
88 86 }
89 87
90 88 protected override Signal GetResolveSignal() {
91 89 var signal = new Signal();
92 90 On(signal.Set, PromiseEventType.All);
93 91 return signal;
94 92 }
95 93
96 94 #endregion
97 95
98 96 public Type PromiseType {
99 97 get {
100 98 return typeof(void);
101 99 }
102 100 }
103 101
104 102 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
105 103 AddHandler(new HandlerDescriptor(success, error, cancel));
106 104 return this;
107 105 }
108 106
109 107 public IPromise On(Action success, Action<Exception> error) {
110 108 AddHandler(new HandlerDescriptor(success, error, null));
111 109 return this;
112 110 }
113 111
114 112 public IPromise On(Action success) {
115 113 AddHandler(new HandlerDescriptor(success, null, null));
116 114 return this;
117 115 }
118 116
119 117 public IPromise On(Action handler, PromiseEventType events) {
120 118 AddHandler(new HandlerDescriptor(handler,events));
121 119 return this;
122 120 }
123 121
124 122 public IPromise<T> Cast<T>() {
125 123 throw new InvalidCastException();
126 124 }
127 125
128 126 public void Join() {
129 127 WaitResult(-1);
130 128 }
131 129
132 130 public void Join(int timeout) {
133 131 WaitResult(timeout);
134 132 }
135 133
136 134 protected void SetResult() {
137 135 if(BeginSetResult())
138 136 EndSetResult();
139 137 }
140 138 }
141 139 }
142 140
@@ -1,206 +1,204
1 1 using System;
2 2 using Implab.Parallels;
3 3
4 4 namespace Implab {
5 5 public abstract class AbstractPromise<T> : AbstractEvent<AbstractPromise<T>.HandlerDescriptor>, IPromise<T> {
6 6 public struct HandlerDescriptor {
7 7 readonly Action m_handler;
8 8 readonly Action<T> m_success;
9 9 readonly Action<Exception> m_error;
10 10 readonly Action<Exception> m_cancel;
11 11 readonly PromiseEventType m_mask;
12 12
13 13 public HandlerDescriptor(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
14 14 m_success = success;
15 15 m_error = error;
16 16 m_cancel = cancel;
17 17
18 18 m_handler = null;
19 19 m_mask = 0;
20 20 }
21 21
22 22 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
23 23 m_handler = success;
24 24 m_success = null;
25 25 m_error = error;
26 26 m_cancel = cancel;
27 27 m_mask = PromiseEventType.Success;
28 28 }
29 29
30 30 public HandlerDescriptor(Action handler, PromiseEventType mask) {
31 31 m_handler = handler;
32 32 m_mask = mask;
33 33 m_success = null;
34 34 m_error = null;
35 35 m_cancel = null;
36 36 }
37 37
38 38 public void SignalSuccess(T result) {
39 39 if (m_success != null) {
40 40 try {
41 41 m_success(result);
42 } catch(Exception err) {
43 SignalError(err);
42 // Analysis disable once EmptyGeneralCatchClause
43 } catch {
44 44 }
45 45 } else if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) {
46 46 try {
47 47 m_handler();
48 } catch(Exception err) {
49 // avoid calling handler twice in case of error
50 if (m_error != null)
51 SignalError(err);
48 // Analysis disable once EmptyGeneralCatchClause
49 } catch {
52 50 }
53 51 }
54 52 }
55 53
56 54 public void SignalError(Exception err) {
57 55 if (m_error != null) {
58 56 try {
59 57 m_error(err);
60 58 // Analysis disable once EmptyGeneralCatchClause
61 59 } catch {
62 60 }
63 61 } else if ((m_mask & PromiseEventType.Error) != 0 && m_handler != null) {
64 62 try {
65 63 m_handler();
66 64 // Analysis disable once EmptyGeneralCatchClause
67 65 } catch {
68 66 }
69 67 }
70 68 }
71 69
72 70 public void SignalCancel(Exception reason) {
73 71 if (m_cancel != null) {
74 72 try {
75 73 m_cancel(reason);
76 } catch (Exception err) {
77 SignalError(err);
74 // Analysis disable once EmptyGeneralCatchClause
75 } catch {
78 76 }
79 77 } else if ((m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) {
80 78 try {
81 79 m_handler();
82 80 // Analysis disable once EmptyGeneralCatchClause
83 81 } catch {
84 82 }
85 83 }
86 84 }
87 85 }
88 86
89 87 public Type PromiseType {
90 88 get {
91 89 return typeof(T);
92 90 }
93 91 }
94 92
95 93 public T Join() {
96 94 WaitResult(-1);
97 95 return m_result;
98 96 }
99 97 public T Join(int timeout) {
100 98 WaitResult(timeout);
101 99 return m_result;
102 100 }
103 101
104 102 void IPromise.Join() {
105 103 WaitResult(-1);
106 104 }
107 105 void IPromise.Join(int timeout) {
108 106 WaitResult(timeout);
109 107 }
110 108
111 109 public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
112 110 AddHandler(new HandlerDescriptor(success, error, cancel));
113 111 return this;
114 112 }
115 113
116 114 public IPromise<T> On(Action<T> success, Action<Exception> error) {
117 115 AddHandler(new HandlerDescriptor(success, error, null));
118 116 return this;
119 117 }
120 118
121 119 public IPromise<T> On(Action<T> success) {
122 120 AddHandler(new HandlerDescriptor(success, null, null));
123 121 return this;
124 122 }
125 123
126 124 public IPromise<T> On(Action handler, PromiseEventType events) {
127 125 AddHandler(new HandlerDescriptor(handler, events));
128 126 return this;
129 127 }
130 128
131 129 public IPromise<T> On(Action success, Action<Exception> error, Action<Exception> cancel) {
132 130 AddHandler(new HandlerDescriptor(success, error, cancel));
133 131 return this;
134 132 }
135 133
136 134 public IPromise<T> On(Action success, Action<Exception> error) {
137 135 AddHandler(new HandlerDescriptor(success, error, null));
138 136 return this;
139 137 }
140 138
141 139 public IPromise<T> On(Action success) {
142 140 AddHandler(new HandlerDescriptor(success, null, null));
143 141 return this;
144 142 }
145 143
146 144 IPromise IPromise.On(Action success, Action<Exception> error, Action<Exception> cancel) {
147 145 AddHandler(new HandlerDescriptor(success, error, cancel));
148 146 return this;
149 147 }
150 148
151 149 IPromise IPromise.On(Action success, Action<Exception> error) {
152 150 AddHandler(new HandlerDescriptor(success, error, null));
153 151 return this;
154 152 }
155 153
156 154 IPromise IPromise.On(Action success) {
157 155 AddHandler(new HandlerDescriptor(success, null, null));
158 156 return this;
159 157 }
160 158
161 159 IPromise IPromise.On(Action handler, PromiseEventType events) {
162 160 AddHandler(new HandlerDescriptor(handler, events));
163 161 return this;
164 162 }
165 163
166 164 public IPromise<T2> Cast<T2>() {
167 165 return (IPromise<T2>)this;
168 166 }
169 167
170 168 #region implemented abstract members of AbstractPromise
171 169
172 170 protected override Signal GetResolveSignal() {
173 171 var signal = new Signal();
174 172 AddHandler(new HandlerDescriptor(signal.Set, PromiseEventType.All));
175 173 return signal;
176 174 }
177 175
178 176 protected override void SignalHandler(HandlerDescriptor handler, int signal) {
179 177 switch (signal) {
180 178 case SUCCEEDED_STATE:
181 179 handler.SignalSuccess(m_result);
182 180 break;
183 181 case REJECTED_STATE:
184 182 handler.SignalError(Error);
185 183 break;
186 184 case CANCELLED_STATE:
187 185 handler.SignalCancel(CancellationReason);
188 186 break;
189 187 default:
190 188 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", signal));
191 189 }
192 190 }
193 191
194 192 #endregion
195 193
196 194 T m_result;
197 195
198 196 protected void SetResult(T value) {
199 197 if (BeginSetResult()) {
200 198 m_result = value;
201 199 EndSetResult();
202 200 }
203 201 }
204 202 }
205 203 }
206 204
@@ -1,36 +1,34
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class ActionChainTask : ActionChainTaskBase, IDeferred {
5 5 readonly Func<IPromise> m_task;
6 6
7 7 /// <summary>
8 8 /// Initializes a new instance of the <see cref="Implab.ActionChainTask"/> class.
9 9 /// </summary>
10 10 /// <param name="task">The operation which will be performed when the <see cref="Resolve()"/> is called.</param>
11 11 /// <param name="error">The error handler which will invoke when the <see cref="Reject(Exception)"/> is called or when the task fails with an error.</param>
12 12 /// <param name="cancel">The cancellation handler.</param>
13 13 /// <param name="autoCancellable">If set to <c>true</c> will automatically accept
14 14 /// all cancel requests before the task is started with <see cref="Resolve()"/>,
15 15 /// after that all requests are directed to the task.</param>
16 16 public ActionChainTask(Func<IPromise> task, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel, bool autoCancellable) : base(error,cancel, autoCancellable) {
17 17 m_task = task;
18 18 }
19 19
20 20 public void Resolve() {
21 21 if (m_task != null && LockCancelation()) {
22 22 try {
23 23 var p = m_task();
24 24 p.On(SetResult, HandleErrorInternal, HandleCancelInternal);
25 25 CancellationRequested(p.Cancel);
26 } catch (OperationCanceledException reason){
27 HandleCancelInternal(reason);
28 26 } catch(Exception err) {
29 HandleErrorInternal(err);
27 SetErrorInternal(err);
30 28 }
31 29 }
32 30 }
33 31
34 32 }
35 33 }
36 34
@@ -1,62 +1,62
1 1 using System;
2 2 using System.Threading;
3 3
4 4 namespace Implab {
5 5 public class ActionChainTaskBase : AbstractTask {
6 6 readonly Func<Exception, IPromise> m_error;
7 7 readonly Func<Exception, IPromise> m_cancel;
8 8
9 9 protected ActionChainTaskBase(Func<Exception, IPromise> error, Func<Exception, IPromise> cancel, bool autoCancellable) {
10 10 m_error = error;
11 11 m_cancel = cancel;
12 12 if (autoCancellable)
13 13 CancellationRequested(CancelOperation);
14 14 }
15 15
16 16 public void Reject(Exception error) {
17 17 if (LockCancelation())
18 18 HandleErrorInternal(error);
19 19 }
20 20
21 21 public override void CancelOperation(Exception reason) {
22 22 if (LockCancelation())
23 23 // отмена вызвана до начала выполнения задачи
24 24 HandleCancelInternal(reason);
25 25 }
26 26
27 27 protected void HandleCancelInternal(Exception reason) {
28 28 if (m_cancel != null) {
29 29 try {
30 30 // вызываем обработчик отмены
31 31 var p = m_cancel(reason);
32 32 p.On(SetResult, HandleErrorInternal, SetCancelledInternal);
33 33 // сообщаем асинхронной операции, что клиент уже не хочет получать результат
34 34 // т.е. если он инициировал отмену, задача отменилась, вызвался обрабочик отмены
35 35 // отбработчику сообщили, что результат уже не нужен и уже сам обработчик решает
36 36 // отдавать ли результат или подтвердить отмену (или вернуть ошибку).
37 37 CancellationRequested(p.Cancel);
38 38 } catch (Exception err) {
39 HandleErrorInternal(err);
39 SetErrorInternal(err);
40 40 }
41 41 } else {
42 HandleErrorInternal(reason ?? new OperationCanceledException());
42 SetCancelledInternal(reason);
43 43 }
44 44 }
45 45
46 46 protected void HandleErrorInternal(Exception error) {
47 47 if (m_error != null) {
48 48 try {
49 49 var p = m_error(error);
50 50 p.On(SetResult, SetErrorInternal, SetCancelledInternal);
51 51 CancellationRequested(p.Cancel);
52 52 } catch (Exception err) {
53 SetErrorInternal(error);
53 SetErrorInternal(err);
54 54 }
55 55 } else {
56 56 SetErrorInternal(error);
57 57 }
58 58 }
59 59
60 60 }
61 61 }
62 62
@@ -1,27 +1,25
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class ActionChainTask<T> : ActionChainTaskBase, IDeferred<T> {
5 5 readonly Func<T, IPromise> m_task;
6 6
7 7 public ActionChainTask(Func<T, IPromise> task, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel, bool autoCancellable) : base(error,cancel, autoCancellable) {
8 8 m_task = task;
9 9 }
10 10
11 11 public void Resolve(T value) {
12 12 if (m_task != null && LockCancelation()) {
13 13 try {
14 14 var p = m_task(value);
15 15 p.On(SetResult, HandleErrorInternal, HandleCancelInternal);
16 16 CancellationRequested(p.Cancel);
17 } catch (OperationCanceledException reason) {
18 HandleCancelInternal(reason);
19 17 } catch(Exception err) {
20 HandleErrorInternal(err);
18 SetErrorInternal(err);
21 19 }
22 20 }
23 21 }
24 22
25 23 }
26 24 }
27 25
@@ -1,24 +1,22
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class ActionTask : ActionTaskBase, IDeferred {
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;
8 8 }
9 9
10 10 public void Resolve() {
11 11 if (m_task != null && LockCancelation()) {
12 12 try {
13 13 m_task();
14 14 SetResult();
15 } catch(OperationCanceledException reason) {
16 HandleCancelInternal(reason);
17 15 } catch(Exception err) {
18 HandleErrorInternal(err);
16 SetErrorInternal(err);
19 17 }
20 18 }
21 19 }
22 20 }
23 21 }
24 22
@@ -1,53 +1,53
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class ActionTaskBase : AbstractTask {
5 5 readonly Action<Exception> m_cancel;
6 6 readonly Action<Exception> m_error;
7 7
8 8 protected ActionTaskBase( Action<Exception> error, Action<Exception> cancel, bool autoCancellable) {
9 9 m_error = error;
10 10 m_cancel = cancel;
11 11 if (autoCancellable)
12 12 CancellationRequested(CancelOperation);
13 13 }
14 14
15 15 public void Reject(Exception error) {
16 16 Safe.ArgumentNotNull(error, "error");
17 17 if (LockCancelation())
18 18 HandleErrorInternal(error);
19 19 }
20 20
21 21 public override void CancelOperation(Exception reason) {
22 22 if (LockCancelation())
23 23 HandleCancelInternal(reason);
24 24 }
25 25
26 26 protected void HandleErrorInternal(Exception error) {
27 27 if (m_error != null) {
28 28 try {
29 29 m_error(error);
30 30 SetResult();
31 31 } catch(Exception err) {
32 32 SetErrorInternal(err);
33 33 }
34 34 } else {
35 35 SetErrorInternal(error);
36 36 }
37 37 }
38 38
39 39 protected void HandleCancelInternal(Exception error) {
40 40 if (m_cancel != null) {
41 41 try {
42 42 m_cancel(error);
43 43 SetResult();
44 44 } catch(Exception err) {
45 HandleErrorInternal(err);
45 SetErrorInternal(err);
46 46 }
47 47 } else {
48 HandleErrorInternal(error ?? new OperationCanceledException());
48 SetCancelledInternal(error);
49 49 }
50 50 }
51 51 }
52 52 }
53 53
@@ -1,24 +1,22
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class ActionTask<T> : ActionTaskBase, IDeferred<T> {
5 5 readonly Action<T> m_task;
6 6 public ActionTask(Action<T> task, Action<Exception> error, Action<Exception> cancel, bool autoCancellable) : base(error,cancel, autoCancellable) {
7 7 m_task = task;
8 8 }
9 9
10 10 public void Resolve(T value) {
11 11 if (m_task != null && LockCancelation()) {
12 12 try {
13 13 m_task(value);
14 14 SetResult();
15 } catch(OperationCanceledException reason) {
16 HandleCancelInternal(reason);
17 15 } catch(Exception err) {
18 HandleErrorInternal(err);
16 SetErrorInternal(err);
19 17 }
20 18 }
21 19 }
22 20 }
23 21 }
24 22
@@ -1,257 +1,264
1 1 using System;
2 2
3 3 namespace Implab.Components {
4 4 public abstract class RunnableComponent : IDisposable, IRunnable, IInitializable {
5 5 enum Commands {
6 6 Ok = 0,
7 7 Fail,
8 8 Init,
9 9 Start,
10 10 Stop,
11 11 Dispose,
12 12 Last = Dispose
13 13 }
14 14
15 15 class StateMachine {
16 16 static readonly ExecutionState[,] _transitions;
17 17
18 18 static StateMachine() {
19 19 _transitions = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1];
20 20
21 21 Edge(ExecutionState.Created, ExecutionState.Initializing, Commands.Init);
22 22 Edge(ExecutionState.Created, ExecutionState.Disposed, Commands.Dispose);
23 23
24 24 Edge(ExecutionState.Initializing, ExecutionState.Ready, Commands.Ok);
25 25 Edge(ExecutionState.Initializing, ExecutionState.Failed, Commands.Fail);
26 26
27 27 Edge(ExecutionState.Ready, ExecutionState.Starting, Commands.Start);
28 28 Edge(ExecutionState.Ready, ExecutionState.Disposed, Commands.Dispose);
29 29
30 30 Edge(ExecutionState.Starting, ExecutionState.Running, Commands.Ok);
31 31 Edge(ExecutionState.Starting, ExecutionState.Failed, Commands.Fail);
32 32 Edge(ExecutionState.Starting, ExecutionState.Stopping, Commands.Stop);
33 33 Edge(ExecutionState.Starting, ExecutionState.Disposed, Commands.Dispose);
34 34
35 35 Edge(ExecutionState.Running, ExecutionState.Failed, Commands.Fail);
36 36 Edge(ExecutionState.Running, ExecutionState.Stopping, Commands.Stop);
37 37 Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose);
38 38
39 39 Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail);
40 40 Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok);
41 41
42 42 Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose);
43 43 }
44 44
45 45 static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) {
46 46 _transitions[(int)s1, (int)cmd] = s2;
47 47 }
48 48
49 49 public ExecutionState State {
50 50 get;
51 51 private set;
52 52 }
53 53
54 54 public StateMachine(ExecutionState initial) {
55 55 State = initial;
56 56 }
57 57
58 58 public bool Move(Commands cmd) {
59 59 var next = _transitions[(int)State, (int)cmd];
60 60 if (next == ExecutionState.Undefined)
61 61 return false;
62 62 State = next;
63 63 return true;
64 64 }
65 65 }
66 66
67 67 IPromise m_pending;
68 68 Exception m_lastError;
69 69
70 70 readonly StateMachine m_stateMachine;
71 71
72 72 protected RunnableComponent(bool initialized) {
73 73 m_stateMachine = new StateMachine(initialized ? ExecutionState.Ready : ExecutionState.Created);
74 74 }
75 75
76 76 protected virtual int DisposeTimeout {
77 77 get {
78 78 return 10000;
79 79 }
80 80 }
81 81
82 82 void ThrowInvalidCommand(Commands cmd) {
83 83 if (m_stateMachine.State == ExecutionState.Disposed)
84 84 throw new ObjectDisposedException(ToString());
85 85
86 86 throw new InvalidOperationException(String.Format("Commnd {0} is not allowed in the state {1}", cmd, m_stateMachine.State));
87 87 }
88 88
89 89 void Move(Commands cmd) {
90 90 if (!m_stateMachine.Move(cmd))
91 91 ThrowInvalidCommand(cmd);
92 92 }
93 93
94 94 void Invoke(Commands cmd, Action action) {
95 95 lock (m_stateMachine)
96 96 Move(cmd);
97 97
98 98 try {
99 99 action();
100 100 lock(m_stateMachine)
101 101 Move(Commands.Ok);
102 102
103 103 } catch (Exception err) {
104 104 lock (m_stateMachine) {
105 105 Move(Commands.Fail);
106 106 m_lastError = err;
107 107 }
108 108 throw;
109 109 }
110 110 }
111 111
112 112 IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IDeferred> chain) {
113 113 IPromise promise = null;
114 114 IPromise prev;
115 115
116 116 var task = new ActionChainTask(action, null, null, true);
117 117
118 118 lock (m_stateMachine) {
119 119 Move(cmd);
120 120
121 121 prev = m_pending;
122 122
123 Action<Exception> errorOrCancel = e => {
124 if (e == null)
125 e = new OperationCanceledException();
126
127 lock (m_stateMachine) {
128 if (m_pending == promise) {
129 Move(Commands.Fail);
130 m_pending = null;
131 m_lastError = e;
132 }
133 }
134 throw new PromiseTransientException(e);
135 };
136
123 137 promise = task.Then(
124 138 () => {
125 139 lock(m_stateMachine) {
126 140 if (m_pending == promise) {
127 141 Move(Commands.Ok);
128 142 m_pending = null;
129 143 }
130 144 }
131 }, e => {
132 lock(m_stateMachine) {
133 if (m_pending == promise) {
134 Move(Commands.Fail);
135 m_pending = null;
136 m_lastError = e;
137 }
138 }
139 throw new PromiseTransientException(e);
140 }
145 },
146 errorOrCancel,
147 errorOrCancel
141 148 );
142 149
143 150 m_pending = promise;
144 151 }
145 152
146 153 if (prev == null)
147 154 task.Resolve();
148 155 else
149 156 chain(prev, task);
150 157
151 158 return promise;
152 159 }
153 160
154 161
155 162 #region IInitializable implementation
156 163
157 164 public void Init() {
158 165 Invoke(Commands.Init, OnInitialize);
159 166 }
160 167
161 168 protected virtual void OnInitialize() {
162 169 }
163 170
164 171 #endregion
165 172
166 173 #region IRunnable implementation
167 174
168 175 public IPromise Start() {
169 176 return InvokeAsync(Commands.Start, OnStart, null);
170 177 }
171 178
172 179 protected virtual IPromise OnStart() {
173 180 return Promise.SUCCESS;
174 181 }
175 182
176 183 public IPromise Stop() {
177 184 return InvokeAsync(Commands.Stop, OnStop, StopPending).Then(Dispose);
178 185 }
179 186
180 187 protected virtual IPromise OnStop() {
181 188 return Promise.SUCCESS;
182 189 }
183 190
184 191 /// <summary>
185 192 /// Stops the current operation if one exists.
186 193 /// </summary>
187 194 /// <param name="current">Current.</param>
188 195 /// <param name="stop">Stop.</param>
189 196 protected virtual void StopPending(IPromise current, IDeferred stop) {
190 197 if (current == null) {
191 198 stop.Resolve();
192 199 } else {
193 200 // связваем текущую операцию с операцией остановки
194 201 current.On(
195 202 stop.Resolve, // если текущая операция заверщилась, то можно начинать остановку
196 203 stop.Reject, // если текущая операция дала ошибку - то все плохо, нельзя продолжать
197 204 e => stop.Resolve() // если текущая отменилась, то можно начинать остановку
198 205 );
199 206 // посылаем текущей операции сигнал остановки
200 207 current.Cancel();
201 208 }
202 209 }
203 210
204 211 public ExecutionState State {
205 212 get {
206 213 return m_stateMachine.State;
207 214 }
208 215 }
209 216
210 217 public Exception LastError {
211 218 get {
212 219 return m_lastError;
213 220 }
214 221 }
215 222
216 223 #endregion
217 224
218 225 #region IDisposable implementation
219 226
220 227 public void Dispose() {
221 228 IPromise pending;
222 229 lock (m_stateMachine) {
223 230 if (m_stateMachine.State == ExecutionState.Disposed)
224 231 return;
225 232
226 233 Move(Commands.Dispose);
227 234
228 235 GC.SuppressFinalize(this);
229 236
230 237 pending = m_pending;
231 238 m_pending = null;
232 239 }
233 240 if (pending != null) {
234 241 pending.Cancel();
235 242 pending.Timeout(DisposeTimeout).On(
236 243 () => Dispose(true, null),
237 244 err => Dispose(true, err),
238 245 reason => Dispose(true, new OperationCanceledException("The operation is cancelled", reason))
239 246 );
240 247 } else {
241 248 Dispose(true, m_lastError);
242 249 }
243 250 }
244 251
245 252 ~RunnableComponent() {
246 253 Dispose(false, null);
247 254 }
248 255
249 256 #endregion
250 257
251 258 protected virtual void Dispose(bool disposing, Exception lastError) {
252 259
253 260 }
254 261
255 262 }
256 263 }
257 264
@@ -1,26 +1,24
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class FuncChainTask<TResult> : FuncChainTaskBase<TResult>, IDeferred {
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)
8 8 : base(error, cancel, autoCancellable) {
9 9 m_task = task;
10 10 }
11 11
12 12 public void Resolve() {
13 13 if (m_task != null && LockCancelation()) {
14 14 try {
15 15 var operation = m_task();
16 16 operation.On(SetResult, HandleErrorInternal, HandleCancelInternal);
17 17 CancellationRequested(operation.Cancel);
18 } catch (OperationCanceledException reason) {
19 HandleCancelInternal(reason);
20 18 } catch (Exception err) {
21 HandleErrorInternal(err);
19 SetErrorInternal(err);
22 20 }
23 21 }
24 22 }
25 23 }
26 24 } No newline at end of file
@@ -1,54 +1,54
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class FuncChainTaskBase<TResult> : AbstractTask<TResult> {
5 5 readonly Func<Exception, IPromise<TResult>> m_error;
6 6 readonly Func<Exception, IPromise<TResult>> m_cancel;
7 7
8 8 protected FuncChainTaskBase( Func<Exception, IPromise<TResult>> error, Func<Exception, IPromise<TResult>> cancel, bool autoCancellable) {
9 9 m_error = error;
10 10 m_cancel = cancel;
11 11 if (autoCancellable)
12 12 CancellationRequested(CancelOperation);
13 13 }
14 14
15 15 public void Reject(Exception error) {
16 16 if (LockCancelation())
17 17 HandleErrorInternal(error);
18 18 }
19 19
20 20 public override void CancelOperation(Exception reason) {
21 21 if (LockCancelation())
22 22 HandleCancelInternal(reason);
23 23 }
24 24
25 25 protected void HandleErrorInternal(Exception error) {
26 26 if (m_error != null) {
27 27 try {
28 28 var p = m_error(error);
29 29 p.On(SetResult, SetErrorInternal, SetCancelledInternal);
30 30 CancellationRequested(p.Cancel);
31 31 } catch(Exception err) {
32 32 SetErrorInternal(err);
33 33 }
34 34 } else {
35 35 SetErrorInternal(error);
36 36 }
37 37 }
38 38
39 39 protected void HandleCancelInternal(Exception reason) {
40 40 if (m_cancel != null) {
41 41 try {
42 42 var p = m_cancel(reason);
43 43 p.On(SetResult, HandleErrorInternal, SetCancelledInternal);
44 44 CancellationRequested(p.Cancel);
45 45 } catch (Exception err) {
46 HandleErrorInternal(err);
46 SetErrorInternal(err);
47 47 }
48 48 } else {
49 HandleErrorInternal(reason ?? new OperationCanceledException());
49 SetCancelledInternal(reason);
50 50 }
51 51 }
52 52 }
53 53 }
54 54
@@ -1,25 +1,23
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class FuncChainTask<TArg,TResult> : FuncChainTaskBase<TResult>, IDeferred<TArg> {
5 5 readonly Func<TArg, IPromise<TResult>> m_task;
6 6
7 7 public FuncChainTask(Func<TArg, IPromise<TResult>> task, Func<Exception, IPromise<TResult>> error, Func<Exception, IPromise<TResult>> cancel, bool autoCancellable) : base(error, cancel, autoCancellable){
8 8 m_task = task;
9 9 }
10 10
11 11 public void Resolve(TArg value) {
12 12 if (m_task != null && LockCancelation()) {
13 13 try {
14 14 var operation = m_task(value);
15 15 operation.On(SetResult, HandleErrorInternal, SetCancelled);
16 16 CancellationRequested(operation.Cancel);
17 } catch (OperationCanceledException reason) {
18 HandleCancelInternal(reason);
19 17 } catch (Exception err) {
20 HandleErrorInternal(err);
18 SetErrorInternal(err);
21 19 }
22 20 }
23 21 }
24 22 }
25 23 } No newline at end of file
@@ -1,25 +1,23
1 1 using System;
2 2 using System.Threading;
3 3
4 4 namespace Implab {
5 5 public class FuncTask<T> : FuncTaskBase<T>, IDeferred {
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) {
9 9 m_task = task;
10 10 }
11 11
12 12 public void Resolve() {
13 13 if (m_task != null && LockCancelation()) {
14 14 try {
15 15 SetResult(m_task());
16 } catch(OperationCanceledException reason) {
17 HandleCancelInternal(reason);
18 16 } catch(Exception err) {
19 HandleErrorInternal(err);
17 SetErrorInternal(err);
20 18 }
21 19 }
22 20 }
23 21 }
24 22 }
25 23
@@ -1,52 +1,52
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class FuncTaskBase<TResult> : AbstractTask<TResult> {
5 5 readonly Func<Exception, TResult> m_cancel;
6 6 readonly Func<Exception, TResult> m_error;
7 7
8 8 protected FuncTaskBase( Func<Exception, TResult> error, Func<Exception, TResult> cancel, bool autoCancellable) {
9 9 m_error = error;
10 10 m_cancel = cancel;
11 11 if (autoCancellable)
12 12 CancellationRequested(CancelOperation);
13 13 }
14 14
15 15 public void Reject(Exception error) {
16 16 Safe.ArgumentNotNull(error, "error");
17 17 if (LockCancelation())
18 18 HandleErrorInternal(error);
19 19 }
20 20
21 21 protected void HandleErrorInternal(Exception error) {
22 22 if (m_error != null) {
23 23 try {
24 24 SetResult(m_error(error));
25 25 } catch(Exception err) {
26 26 SetErrorInternal(err);
27 27 }
28 28 } else {
29 29 SetErrorInternal(error);
30 30 }
31 31 }
32 32
33 33 public override void CancelOperation(Exception reason) {
34 34 if (LockCancelation())
35 35 HandleCancelInternal(reason);
36 36 }
37 37
38 38 protected void HandleCancelInternal(Exception reason) {
39 39 if (m_cancel != null) {
40 40 try {
41 41 SetResult(m_cancel(reason));
42 42 } catch (Exception err) {
43 HandleErrorInternal(err);
43 SetErrorInternal(err);
44 44 }
45 45 } else {
46 HandleErrorInternal(reason ?? new OperationCanceledException());
46 SetCancelledInternal(reason);
47 47 }
48 48 }
49 49
50 50 }
51 51 }
52 52
@@ -1,24 +1,22
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class FuncTask<TArg, TResult> : FuncTaskBase<TResult>, IDeferred<TArg> {
5 5 readonly Func<TArg, TResult> m_task;
6 6
7 7 public FuncTask(Func<TArg, TResult> task, Func<Exception, TResult> error,Func<Exception, TResult> cancel, bool autoCancellable) : base(error,cancel, autoCancellable) {
8 8 m_task = task;
9 9 }
10 10
11 11 public void Resolve(TArg value) {
12 12 if (m_task != null && LockCancelation()) {
13 13 try {
14 14 SetResult(m_task(value));
15 } catch(OperationCanceledException reason) {
16 HandleCancelInternal(reason);
17 15 } catch(Exception err) {
18 HandleErrorInternal(err);
16 SetErrorInternal(err);
19 17 }
20 18 }
21 19 }
22 20 }
23 21 }
24 22
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