@@ -0,0 +1,45 | |||
|
1 | using System; | |
|
2 | using System.Threading; | |
|
3 | ||
|
4 | namespace Implab { | |
|
5 | /// <summary> | |
|
6 | /// Базовый класс для реализации задачь. Задача представляет собой некторое | |
|
7 | /// действие, которое можно иницировать и обработать результат его выполнения | |
|
8 | /// в виде обещания, для этого оно реализует интерфейс <see cref="IPromise"/>. | |
|
9 | /// </summary> | |
|
10 | /// <remarks> | |
|
11 | /// Данный класс определяет стандартное поведение при обработки результатов, в частности | |
|
12 | /// обработку <see cref="System.OperationCanceledException"/> и <see cref="PromiseTransientException"/> | |
|
13 | /// </remarks> | |
|
14 | public abstract class AbstractTask : AbstractPromise { | |
|
15 | int m_cancelationLock; | |
|
16 | ||
|
17 | /// <summary> | |
|
18 | /// Получает эксклюзивное право отмены задания, используется для отмены задания до начала его выполнения. | |
|
19 | /// </summary> | |
|
20 | /// <returns><c>true</c>, if cancelation was locked, <c>false</c> otherwise.</returns> | |
|
21 | protected bool LockCancelation() { | |
|
22 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | |
|
23 | } | |
|
24 | ||
|
25 | ||
|
26 | ||
|
27 | protected void SetErrorInternal(Exception error) { | |
|
28 | // unwrap | |
|
29 | while (error is PromiseTransientException && error.InnerException != null) | |
|
30 | error = error.InnerException; | |
|
31 | ||
|
32 | if (error is OperationCanceledException) | |
|
33 | SetCancelled(error); | |
|
34 | else | |
|
35 | SetError(error); | |
|
36 | } | |
|
37 | ||
|
38 | protected void SetCancelledInternal(Exception reason) { | |
|
39 | SetCancelled( | |
|
40 | reason == null ? new OperationCanceledException() : reason is OperationCanceledException ? reason : new OperationCanceledException(null, reason) | |
|
41 | ); | |
|
42 | } | |
|
43 | } | |
|
44 | } | |
|
45 |
@@ -0,0 +1,36 | |||
|
1 | using System; | |
|
2 | using System.Threading; | |
|
3 | ||
|
4 | namespace Implab { | |
|
5 | public abstract class AbstractTask<T> : AbstractPromise<T> { | |
|
6 | int m_cancelationLock; | |
|
7 | ||
|
8 | /// <summary> | |
|
9 | /// Получает эксклюзивное право отмены задания, используется для отмены задания до начала его выполнения. | |
|
10 | /// </summary> | |
|
11 | /// <returns><c>true</c>, if cancelation was locked, <c>false</c> otherwise.</returns> | |
|
12 | protected bool LockCancelation() { | |
|
13 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | |
|
14 | } | |
|
15 | ||
|
16 | ||
|
17 | ||
|
18 | protected void SetErrorInternal(Exception error) { | |
|
19 | // unwrap | |
|
20 | while (error is PromiseTransientException && error.InnerException != null) | |
|
21 | error = error.InnerException; | |
|
22 | ||
|
23 | if (error is OperationCanceledException) | |
|
24 | SetCancelled(error); | |
|
25 | else | |
|
26 | SetError(error); | |
|
27 | } | |
|
28 | ||
|
29 | protected void SetCancelledInternal(Exception reason) { | |
|
30 | SetCancelled( | |
|
31 | reason == null ? new OperationCanceledException() : reason is OperationCanceledException ? reason : new OperationCanceledException(null, reason) | |
|
32 | ); | |
|
33 | } | |
|
34 | } | |
|
35 | } | |
|
36 |
@@ -21,8 +21,10 namespace Implab { | |||
|
21 | 21 | if (m_task != null && LockCancelation()) { |
|
22 | 22 | try { |
|
23 | 23 | var p = m_task(); |
|
24 |
p.On(SetResult, HandleErrorInternal, |
|
|
24 | p.On(SetResult, HandleErrorInternal, HandleCancelInternal); | |
|
25 | 25 | CancellationRequested(p.Cancel); |
|
26 | } catch (OperationCanceledException reason){ | |
|
27 | HandleCancelInternal(reason); | |
|
26 | 28 | } catch(Exception err) { |
|
27 | 29 | HandleErrorInternal(err); |
|
28 | 30 | } |
@@ -2,12 +2,10 | |||
|
2 | 2 | using System.Threading; |
|
3 | 3 | |
|
4 | 4 | namespace Implab { |
|
5 |
public class ActionChainTaskBase : Abstract |
|
|
5 | public class ActionChainTaskBase : AbstractTask { | |
|
6 | 6 | readonly Func<Exception, IPromise> m_error; |
|
7 | 7 | readonly Func<Exception, IPromise> m_cancel; |
|
8 | 8 | |
|
9 | int m_cancelationLock; | |
|
10 | ||
|
11 | 9 | protected ActionChainTaskBase(Func<Exception, IPromise> error, Func<Exception, IPromise> cancel, bool autoCancellable) { |
|
12 | 10 | m_error = error; |
|
13 | 11 | m_cancel = cancel; |
@@ -21,55 +19,44 namespace Implab { | |||
|
21 | 19 | } |
|
22 | 20 | |
|
23 | 21 | public override void CancelOperation(Exception reason) { |
|
24 |
if (LockCancelation()) |
|
|
25 | if (!(reason is OperationCanceledException)) | |
|
26 | reason = reason != null ? new OperationCanceledException(null, reason) : new OperationCanceledException(); | |
|
27 |
|
|
|
28 | if (m_cancel != null) { | |
|
29 | try { | |
|
30 | m_cancel(reason).On(SetResult, HandleErrorInternal, HandleCancelInternal); | |
|
31 |
|
|
|
32 | HandleErrorInternal(err); | |
|
33 |
|
|
|
34 | } else { | |
|
35 | HandleErrorInternal(reason); | |
|
22 | if (LockCancelation()) | |
|
23 | // отмена вызвана до начала выполнения задачи | |
|
24 | HandleCancelInternal(reason); | |
|
25 | } | |
|
26 | ||
|
27 | protected void HandleCancelInternal(Exception reason) { | |
|
28 | if (m_cancel != null) { | |
|
29 | try { | |
|
30 | // вызываем обработчик отмены | |
|
31 | var p = m_cancel(reason); | |
|
32 | p.On(SetResult, HandleErrorInternal, SetCancelledInternal); | |
|
33 | // сообщаем асинхронной операции, что клиент уже не хочет получать результат | |
|
34 | // т.е. если он инициировал отмену, задача отменилась, вызвался обрабочик отмены | |
|
35 | // отбработчику сообщили, что результат уже не нужен и уже сам обработчик решает | |
|
36 | // отдавать ли результат или подтвердить отмену (или вернуть ошибку). | |
|
37 | CancellationRequested(p.Cancel); | |
|
38 | } catch (Exception err) { | |
|
39 | HandleErrorInternal(err); | |
|
36 | 40 | } |
|
41 | } else { | |
|
42 | HandleErrorInternal(reason ?? new OperationCanceledException()); | |
|
37 | 43 | } |
|
38 | 44 | } |
|
39 | 45 | |
|
40 |
void Handle |
|
|
41 | if (!(reason is OperationCanceledException)) | |
|
42 | reason = reason != null ? new OperationCanceledException(null, reason) : new OperationCanceledException(); | |
|
43 | HandleErrorInternal(reason); | |
|
44 | } | |
|
45 | ||
|
46 | void HandleErrorInternal(Exception error) { | |
|
46 | protected void HandleErrorInternal(Exception error) { | |
|
47 | 47 | if (m_error != null) { |
|
48 | 48 | try { |
|
49 | 49 | var p = m_error(error); |
|
50 | p.On(SetResult, SetError, SetCancelled); | |
|
50 | p.On(SetResult, SetErrorInternal, SetCancelledInternal); | |
|
51 | 51 | CancellationRequested(p.Cancel); |
|
52 | 52 | } catch (Exception err) { |
|
53 |
error |
|
|
53 | SetErrorInternal(error); | |
|
54 | 54 | } |
|
55 | 55 | } else { |
|
56 | 56 | SetErrorInternal(error); |
|
57 | 57 | } |
|
58 | 58 | } |
|
59 | 59 | |
|
60 | void SetErrorInternal(Exception error) { | |
|
61 | while (error is PromiseTransientException) | |
|
62 | error = error.InnerException; | |
|
63 | ||
|
64 | if (error is OperationCanceledException) | |
|
65 | SetCancelled(error); | |
|
66 | else | |
|
67 | SetError(error); | |
|
68 | } | |
|
69 | ||
|
70 | protected bool LockCancelation() { | |
|
71 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | |
|
72 | } | |
|
73 | 60 | } |
|
74 | 61 | } |
|
75 | 62 |
@@ -12,8 +12,10 namespace Implab { | |||
|
12 | 12 | if (m_task != null && LockCancelation()) { |
|
13 | 13 | try { |
|
14 | 14 | var p = m_task(value); |
|
15 |
p.On(SetResult, HandleErrorInternal, |
|
|
15 | p.On(SetResult, HandleErrorInternal, HandleCancelInternal); | |
|
16 | 16 | CancellationRequested(p.Cancel); |
|
17 | } catch (OperationCanceledException reason) { | |
|
18 | HandleCancelInternal(reason); | |
|
17 | 19 | } catch(Exception err) { |
|
18 | 20 | HandleErrorInternal(err); |
|
19 | 21 | } |
@@ -12,6 +12,8 namespace Implab { | |||
|
12 | 12 | try { |
|
13 | 13 | m_task(); |
|
14 | 14 | SetResult(); |
|
15 | } catch(OperationCanceledException reason) { | |
|
16 | HandleCancelInternal(reason); | |
|
15 | 17 | } catch(Exception err) { |
|
16 | 18 | HandleErrorInternal(err); |
|
17 | 19 | } |
@@ -1,13 +1,10 | |||
|
1 | 1 | using System; |
|
2 | using System.Threading; | |
|
3 | 2 | |
|
4 | 3 | namespace Implab { |
|
5 |
public class ActionTaskBase : Abstract |
|
|
4 | public class ActionTaskBase : AbstractTask { | |
|
6 | 5 | readonly Action<Exception> m_cancel; |
|
7 | 6 | readonly Action<Exception> m_error; |
|
8 | 7 | |
|
9 | int m_cancelationLock; | |
|
10 | ||
|
11 | 8 | protected ActionTaskBase( Action<Exception> error, Action<Exception> cancel, bool autoCancellable) { |
|
12 | 9 | m_error = error; |
|
13 | 10 | m_cancel = cancel; |
@@ -21,37 +18,36 namespace Implab { | |||
|
21 | 18 | HandleErrorInternal(error); |
|
22 | 19 | } |
|
23 | 20 | |
|
21 | public override void CancelOperation(Exception reason) { | |
|
22 | if (LockCancelation()) | |
|
23 | HandleCancelInternal(reason); | |
|
24 | } | |
|
25 | ||
|
24 | 26 | protected void HandleErrorInternal(Exception error) { |
|
25 | 27 | if (m_error != null) { |
|
26 | 28 | try { |
|
27 | 29 | m_error(error); |
|
28 | 30 | SetResult(); |
|
29 | 31 | } catch(Exception err) { |
|
30 | SetError(err); | |
|
32 | SetErrorInternal(err); | |
|
31 | 33 | } |
|
32 | 34 | } else { |
|
33 | SetError(error); | |
|
35 | SetErrorInternal(error); | |
|
34 | 36 | } |
|
35 | 37 | } |
|
36 | 38 | |
|
37 |
p |
|
|
38 |
if ( |
|
|
39 |
|
|
|
40 |
|
|
|
41 |
|
|
|
42 | SetResult(); | |
|
43 |
|
|
|
44 | HandleErrorInternal(err); | |
|
45 | } | |
|
46 | } else { | |
|
47 | SetCancelled(reason); | |
|
39 | protected void HandleCancelInternal(Exception error) { | |
|
40 | if (m_cancel != null) { | |
|
41 | try { | |
|
42 | m_cancel(error); | |
|
43 | SetResult(); | |
|
44 | } catch(Exception err) { | |
|
45 | HandleErrorInternal(err); | |
|
48 | 46 | } |
|
47 | } else { | |
|
48 | HandleErrorInternal(error ?? new OperationCanceledException()); | |
|
49 | 49 | } |
|
50 | 50 | } |
|
51 | ||
|
52 | protected bool LockCancelation() { | |
|
53 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | |
|
54 | } | |
|
55 | 51 | } |
|
56 | 52 | } |
|
57 | 53 |
@@ -12,6 +12,8 namespace Implab { | |||
|
12 | 12 | try { |
|
13 | 13 | m_task(value); |
|
14 | 14 | SetResult(); |
|
15 | } catch(OperationCanceledException reason) { | |
|
16 | HandleCancelInternal(reason); | |
|
15 | 17 | } catch(Exception err) { |
|
16 | 18 | HandleErrorInternal(err); |
|
17 | 19 | } |
@@ -137,10 +137,6 namespace Implab.Components { | |||
|
137 | 137 | } |
|
138 | 138 | } |
|
139 | 139 | throw new PromiseTransientException(e); |
|
140 | }, | |
|
141 | r => { | |
|
142 | // handle cancellation as exception | |
|
143 | throw new OperationCanceledException("The operation has been cancelled", r); | |
|
144 | 140 | } |
|
145 | 141 | ); |
|
146 | 142 | |
@@ -194,7 +190,13 namespace Implab.Components { | |||
|
194 | 190 | if (current == null) { |
|
195 | 191 | stop.Resolve(); |
|
196 | 192 | } else { |
|
197 | current.On(stop.Resolve, stop.Reject, e => stop.Resolve()); | |
|
193 | // связваем текущую операцию с операцией остановки | |
|
194 | current.On( | |
|
195 | stop.Resolve, // если текущая операция заверщилась, то можно начинать остановку | |
|
196 | stop.Reject, // если текущая операция дала ошибку - то все плохо, нельзя продолжать | |
|
197 | e => stop.Resolve() // если текущая отменилась, то можно начинать остановку | |
|
198 | ); | |
|
199 | // посылаем текущей операции сигнал остановки | |
|
198 | 200 | current.Cancel(); |
|
199 | 201 | } |
|
200 | 202 | } |
@@ -13,8 +13,10 namespace Implab { | |||
|
13 | 13 | if (m_task != null && LockCancelation()) { |
|
14 | 14 | try { |
|
15 | 15 | var operation = m_task(); |
|
16 |
operation.On(SetResult, HandleErrorInternal, |
|
|
16 | operation.On(SetResult, HandleErrorInternal, HandleCancelInternal); | |
|
17 | 17 | CancellationRequested(operation.Cancel); |
|
18 | } catch (OperationCanceledException reason) { | |
|
19 | HandleCancelInternal(reason); | |
|
18 | 20 | } catch (Exception err) { |
|
19 | 21 | HandleErrorInternal(err); |
|
20 | 22 | } |
@@ -1,13 +1,10 | |||
|
1 | 1 | using System; |
|
2 | using System.Threading; | |
|
3 | 2 | |
|
4 | 3 | namespace Implab { |
|
5 |
public class FuncChainTaskBase<TResult> : Abstract |
|
|
4 | public class FuncChainTaskBase<TResult> : AbstractTask<TResult> { | |
|
6 | 5 | readonly Func<Exception, IPromise<TResult>> m_error; |
|
7 | 6 | readonly Func<Exception, IPromise<TResult>> m_cancel; |
|
8 | 7 | |
|
9 | int m_cancelationLock; | |
|
10 | ||
|
11 | 8 | protected FuncChainTaskBase( Func<Exception, IPromise<TResult>> error, Func<Exception, IPromise<TResult>> cancel, bool autoCancellable) { |
|
12 | 9 | m_error = error; |
|
13 | 10 | m_cancel = cancel; |
@@ -21,37 +18,36 namespace Implab { | |||
|
21 | 18 | } |
|
22 | 19 | |
|
23 | 20 | public override void CancelOperation(Exception reason) { |
|
24 |
if (LockCancelation()) |
|
|
25 | if (m_cancel != null) { | |
|
26 | try { | |
|
27 | m_cancel(reason).On(SetResult, HandleErrorInternal, SetCancelled); | |
|
28 | } catch (Exception err) { | |
|
29 | HandleErrorInternal(err); | |
|
30 | } | |
|
31 | } else { | |
|
32 | SetCancelled(reason); | |
|
33 | } | |
|
34 | } | |
|
35 | ||
|
21 | if (LockCancelation()) | |
|
22 | HandleCancelInternal(reason); | |
|
36 | 23 | } |
|
37 | 24 | |
|
38 | 25 | protected void HandleErrorInternal(Exception error) { |
|
39 | 26 | if (m_error != null) { |
|
40 | 27 | try { |
|
41 |
var |
|
|
42 | ||
|
43 | operation.On(SetResult, SetError, SetCancelled); | |
|
44 | CancellationRequested(operation.Cancel); | |
|
28 | var p = m_error(error); | |
|
29 | p.On(SetResult, SetErrorInternal, SetCancelledInternal); | |
|
30 | CancellationRequested(p.Cancel); | |
|
45 | 31 | } catch(Exception err) { |
|
46 | SetError(err); | |
|
32 | SetErrorInternal(err); | |
|
47 | 33 | } |
|
48 | 34 | } else { |
|
49 | SetError(error); | |
|
35 | SetErrorInternal(error); | |
|
50 | 36 | } |
|
51 | 37 | } |
|
52 | 38 | |
|
53 |
protected |
|
|
54 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | |
|
39 | protected void HandleCancelInternal(Exception reason) { | |
|
40 | if (m_cancel != null) { | |
|
41 | try { | |
|
42 | var p = m_cancel(reason); | |
|
43 | p.On(SetResult, HandleErrorInternal, SetCancelledInternal); | |
|
44 | CancellationRequested(p.Cancel); | |
|
45 | } catch (Exception err) { | |
|
46 | HandleErrorInternal(err); | |
|
47 | } | |
|
48 | } else { | |
|
49 | HandleErrorInternal(reason ?? new OperationCanceledException()); | |
|
50 | } | |
|
55 | 51 | } |
|
56 | 52 | } |
|
57 | 53 | } |
@@ -14,6 +14,8 namespace Implab { | |||
|
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); | |
|
17 | 19 | } catch (Exception err) { |
|
18 | 20 | HandleErrorInternal(err); |
|
19 | 21 | } |
@@ -13,6 +13,8 namespace Implab { | |||
|
13 | 13 | if (m_task != null && LockCancelation()) { |
|
14 | 14 | try { |
|
15 | 15 | SetResult(m_task()); |
|
16 | } catch(OperationCanceledException reason) { | |
|
17 | HandleCancelInternal(reason); | |
|
16 | 18 | } catch(Exception err) { |
|
17 | 19 | HandleErrorInternal(err); |
|
18 | 20 | } |
@@ -1,13 +1,10 | |||
|
1 | 1 | using System; |
|
2 | using System.Threading; | |
|
3 | 2 | |
|
4 | 3 | namespace Implab { |
|
5 |
public class FuncTaskBase<TResult> : Abstract |
|
|
4 | public class FuncTaskBase<TResult> : AbstractTask<TResult> { | |
|
6 | 5 | readonly Func<Exception, TResult> m_cancel; |
|
7 | 6 | readonly Func<Exception, TResult> m_error; |
|
8 | 7 | |
|
9 | int m_cancelationLock; | |
|
10 | ||
|
11 | 8 | protected FuncTaskBase( Func<Exception, TResult> error, Func<Exception, TResult> cancel, bool autoCancellable) { |
|
12 | 9 | m_error = error; |
|
13 | 10 | m_cancel = cancel; |
@@ -26,30 +23,30 namespace Implab { | |||
|
26 | 23 | try { |
|
27 | 24 | SetResult(m_error(error)); |
|
28 | 25 | } catch(Exception err) { |
|
29 | SetError(err); | |
|
26 | SetErrorInternal(err); | |
|
30 | 27 | } |
|
31 | 28 | } else { |
|
32 | SetError(error); | |
|
29 | SetErrorInternal(error); | |
|
33 | 30 | } |
|
34 | 31 | } |
|
35 | 32 | |
|
36 | 33 | public override void CancelOperation(Exception reason) { |
|
37 |
if (LockCancelation()) |
|
|
38 | if (m_cancel != null) { | |
|
39 | try { | |
|
40 | SetResult(m_cancel(reason)); | |
|
41 | } catch (Exception err) { | |
|
42 | HandleErrorInternal(err); | |
|
43 |
|
|
|
44 | } else { | |
|
45 | SetCancelled(reason); | |
|
34 | if (LockCancelation()) | |
|
35 | HandleCancelInternal(reason); | |
|
36 | } | |
|
37 | ||
|
38 | protected void HandleCancelInternal(Exception reason) { | |
|
39 | if (m_cancel != null) { | |
|
40 | try { | |
|
41 | SetResult(m_cancel(reason)); | |
|
42 | } catch (Exception err) { | |
|
43 | HandleErrorInternal(err); | |
|
46 | 44 | } |
|
45 | } else { | |
|
46 | HandleErrorInternal(reason ?? new OperationCanceledException()); | |
|
47 | 47 | } |
|
48 | 48 | } |
|
49 | 49 | |
|
50 | protected bool LockCancelation() { | |
|
51 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | |
|
52 | } | |
|
53 | 50 | } |
|
54 | 51 | } |
|
55 | 52 |
@@ -12,7 +12,9 namespace Implab { | |||
|
12 | 12 | if (m_task != null && LockCancelation()) { |
|
13 | 13 | try { |
|
14 | 14 | SetResult(m_task(value)); |
|
15 |
} catch |
|
|
15 | } catch(OperationCanceledException reason) { | |
|
16 | HandleCancelInternal(reason); | |
|
17 | } catch(Exception err) { | |
|
16 | 18 | HandleErrorInternal(err); |
|
17 | 19 | } |
|
18 | 20 | } |
@@ -193,6 +193,8 | |||
|
193 | 193 | <Compile Include="Automaton\AutomatonConst.cs" /> |
|
194 | 194 | <Compile Include="Automaton\RegularExpressions\RegularDFA.cs" /> |
|
195 | 195 | <Compile Include="Components\LazyAndWeak.cs" /> |
|
196 | <Compile Include="AbstractTask.cs" /> | |
|
197 | <Compile Include="AbstractTaskT.cs" /> | |
|
196 | 198 | </ItemGroup> |
|
197 | 199 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> |
|
198 | 200 | <ItemGroup /> |
General Comments 0
You need to be logged in to leave comments.
Login now