Auto status change to "Under Review"
@@ -0,0 +1,9 | |||||
|
1 | namespace Implab { | |||
|
2 | public enum PromiseState { | |||
|
3 | Pending, | |||
|
4 | ||||
|
5 | Resolved, | |||
|
6 | ||||
|
7 | Rejected | |||
|
8 | } | |||
|
9 | } No newline at end of file |
@@ -1,170 +1,141 | |||||
1 | using System; |
|
1 | using System; | |
2 | using Implab.Parallels; |
|
2 | using Implab.Parallels; | |
3 | using System.Threading; |
|
3 | using System.Threading; | |
4 | using System.Reflection; |
|
4 | using System.Reflection; | |
5 | using System.Diagnostics; |
|
5 | using System.Diagnostics; | |
6 |
|
6 | |||
7 | namespace Implab { |
|
7 | namespace Implab { | |
|
8 | /// <summary> | |||
|
9 | /// Abstract class for creation of custom one-shot thread safe events. | |||
|
10 | /// </summary> | |||
|
11 | /// <remarks> | |||
|
12 | /// <para> | |||
|
13 | /// An event is something that should happen in the future and the | |||
|
14 | /// triggering of the event causes execution of some pending actions | |||
|
15 | /// which are formely event handlers. One-shot events occur only once | |||
|
16 | /// and any handler added after the event is triggered should run | |||
|
17 | /// without a delay. | |||
|
18 | /// </para> | |||
|
19 | /// <para> | |||
|
20 | /// The lifecycle of the one-shot event is tipically consists of following | |||
|
21 | /// phases. | |||
|
22 | /// <list> | |||
|
23 | /// <description>Pending state. This is the initial state of the event. Any | |||
|
24 | /// handler added to the event will be queued for the future execution. | |||
|
25 | /// </description> | |||
|
26 | /// <description>Transitional state. This is intermediate state between pending | |||
|
27 | /// and fulfilled states, during this state internal initialization and storing | |||
|
28 | /// of the result occurs. | |||
|
29 | /// </description> | |||
|
30 | /// <description>Fulfilled state. The event contains the result, all queued | |||
|
31 | /// handlers are signalled to run and newly added handlers are executed | |||
|
32 | /// immediatelly. | |||
|
33 | /// </description> | |||
|
34 | /// </list> | |||
|
35 | /// </para> | |||
|
36 | /// </remarks> | |||
8 | public abstract class AbstractEvent<THandler> where THandler : class { |
|
37 | public abstract class AbstractEvent<THandler> where THandler : class { | |
9 |
|
||||
10 | const int PENDING_SATE = 0; |
|
38 | const int PENDING_SATE = 0; | |
11 | protected const int TRANSITIONAL_STATE = 1; |
|
|||
12 |
|
39 | |||
13 |
|
|
40 | const int TRANSITIONAL_STATE = 1; | |
14 | protected const int REJECTED_STATE = 3; |
|
41 | ||
|
42 | const int FULFILLED_STATE = 2; | |||
15 |
|
43 | |||
16 | volatile int m_state; |
|
44 | volatile int m_state; | |
17 | Exception m_error; |
|
|||
18 |
|
45 | |||
19 | THandler m_handler; |
|
46 | THandler m_handler; | |
20 | SimpleAsyncQueue<THandler> m_extraHandlers; |
|
47 | SimpleAsyncQueue<THandler> m_extraHandlers; | |
21 |
|
48 | |||
|
49 | public bool IsFulfilled { | |||
|
50 | get { | |||
|
51 | return m_state > TRANSITIONAL_STATE; | |||
|
52 | } | |||
|
53 | } | |||
|
54 | ||||
22 | #region state managment |
|
55 | #region state managment | |
23 | protected bool BeginTransit() { |
|
56 | protected bool BeginTransit() { | |
24 | return PENDING_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, PENDING_SATE); |
|
57 | return PENDING_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, PENDING_SATE); | |
25 | } |
|
58 | } | |
26 |
|
59 | |||
27 |
protected void CompleteTransit( |
|
60 | protected void CompleteTransit() { | |
28 | #if DEBUG |
|
61 | #if DEBUG | |
29 |
if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, |
|
62 | if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, FULFILLED_STATE, TRANSITIONAL_STATE)) | |
30 | throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state"); |
|
63 | throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state"); | |
31 | #else |
|
64 | #else | |
32 | m_state = state; |
|
65 | m_state = state; | |
33 | #endif |
|
66 | #endif | |
34 | Signal(); |
|
67 | Signal(); | |
35 | } |
|
68 | } | |
36 |
|
69 | |||
37 | protected void WaitTransition() { |
|
70 | protected void WaitTransition() { | |
38 | if (m_state == TRANSITIONAL_STATE) { |
|
71 | if (m_state == TRANSITIONAL_STATE) { | |
39 | SpinWait spin; |
|
72 | SpinWait spin; | |
40 | do { |
|
73 | do { | |
41 | spin.SpinOnce(); |
|
74 | spin.SpinOnce(); | |
42 | } while (m_state == TRANSITIONAL_STATE); |
|
75 | } while (m_state == TRANSITIONAL_STATE); | |
43 | } |
|
76 | } | |
44 | } |
|
77 | } | |
45 |
|
78 | |||
46 | protected bool BeginSetResult() { |
|
|||
47 | if (!BeginTransit()) { |
|
|||
48 | WaitTransition(); |
|
|||
49 | return false; |
|
|||
50 | } |
|
|||
51 | return true; |
|
|||
52 | } |
|
|||
53 |
|
79 | |||
54 | protected void EndSetResult() { |
|
80 | protected abstract void SignalHandler(THandler handler); | |
55 | CompleteTransit(SUCCEEDED_STATE); |
|
|||
56 | } |
|
|||
57 |
|
||||
58 |
|
||||
59 |
|
||||
60 | /// <summary> |
|
|||
61 | /// ΠΡΠΏΠΎΠ»Π½ΡΠ΅Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅, ΡΠΎΠΎΠ±ΡΠ°Ρ ΠΎΠ± ΠΎΡΠΈΠ±ΠΊΠ΅ |
|
|||
62 | /// </summary> |
|
|||
63 | /// <remarks> |
|
|||
64 | /// ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΠ°Π±ΠΎΡΠ°ΡΡ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡΠΎΡΠ½ΠΎΠΉ ΡΡΠ΅Π΄Π΅, ΠΏΡΠΈ Π΅Π³ΠΎ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΡΡΠ°Π·Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΡΠΎΠΊΠΎΠ² |
|
|||
65 | /// ΠΌΠΎΠ³Ρ Π²Π΅ΡΠ½ΡΡΡ ΠΎΡΠΈΠ±ΠΊΡ, ΠΏΡΠΈ ΡΡΠΎΠΌ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠ΅ΡΠ²Π°Ρ Π±ΡΠ΄Π΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½Π° Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ°, ΠΎΡΡΠ°Π»ΡΠ½ΡΠ΅ |
|
|||
66 | /// Π±ΡΠ΄ΡΡ ΠΏΡΠΎΠΈΠ³Π½ΠΎΡΠΈΡΠΎΠ²Π°Π½Ρ. |
|
|||
67 | /// </remarks> |
|
|||
68 | /// <param name="error">ΠΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π²ΠΎΠ·Π½ΠΈΠΊΡΠ΅Π΅ ΠΏΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ</param> |
|
|||
69 | /// <exception cref="InvalidOperationException">ΠΠ°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΡΠΆΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception> |
|
|||
70 | protected void SetError(Exception error) { |
|
|||
71 | if (BeginTransit()) { |
|
|||
72 | m_error = error; |
|
|||
73 | CompleteTransit(REJECTED_STATE); |
|
|||
74 | } else { |
|
|||
75 | WaitTransition(); |
|
|||
76 | if (m_state == SUCCEEDED_STATE) |
|
|||
77 | throw new InvalidOperationException("The promise is already resolved"); |
|
|||
78 | } |
|
|||
79 | } |
|
|||
80 |
|
||||
81 | protected abstract void SignalHandler(THandler handler, int signal); |
|
|||
82 |
|
81 | |||
83 | void Signal() { |
|
82 | void Signal() { | |
84 | THandler handler; |
|
83 | THandler handler; | |
85 | while (TryDequeueHandler(out handler)) |
|
84 | while (TryDequeueHandler(out handler)) | |
86 |
SignalHandler(handler |
|
85 | SignalHandler(handler); | |
87 | } |
|
86 | } | |
88 |
|
87 | |||
89 | #endregion |
|
88 | #endregion | |
90 |
|
89 | |||
91 | protected abstract Signal GetFulfillSignal(); |
|
90 | protected abstract Signal GetFulfillSignal(); | |
92 |
|
91 | |||
93 | #region synchronization traits |
|
92 | #region synchronization traits | |
94 | protected void WaitResult(int timeout) { |
|
93 | protected void WaitResult(int timeout) { | |
95 | if (!(IsFulfilled || GetFulfillSignal().Wait(timeout))) |
|
94 | if (!(IsFulfilled || GetFulfillSignal().Wait(timeout))) | |
96 | throw new TimeoutException(); |
|
95 | throw new TimeoutException(); | |
97 |
|
||||
98 | if (IsRejected) |
|
|||
99 | Rethrow(); |
|
|||
100 | } |
|
96 | } | |
101 |
|
97 | |||
102 | protected void Rethrow() { |
|
98 | ||
103 | Debug.Assert(m_error != null); |
|
|||
104 | if (m_error is OperationCanceledException) |
|
|||
105 | throw new OperationCanceledException("Operation cancelled", m_error); |
|
|||
106 | else |
|
|||
107 | throw new TargetInvocationException(m_error); |
|
|||
108 | } |
|
|||
109 | #endregion |
|
99 | #endregion | |
110 |
|
100 | |||
111 | #region handlers managment |
|
101 | #region handlers managment | |
112 |
|
102 | |||
113 | protected void AddHandler(THandler handler) { |
|
103 | protected void AddHandler(THandler handler) { | |
114 |
|
104 | |||
115 |
if ( |
|
105 | if (IsFulfilled) { | |
116 | // the promise is in the resolved state, just invoke the handler |
|
106 | // the promise is in the resolved state, just invoke the handler | |
117 |
SignalHandler(handler |
|
107 | SignalHandler(handler); | |
118 | } else { |
|
108 | } else { | |
119 | if (Interlocked.CompareExchange(ref m_handler, handler, null) != null) { |
|
109 | EnqueueHandler(handler); | |
120 | if (m_extraHandlers == null) |
|
|||
121 | // compare-exchange will fprotect from loosing already created queue |
|
|||
122 | Interlocked.CompareExchange(ref m_extraHandlers, new SimpleAsyncQueue<THandler>(), null); |
|
|||
123 | m_extraHandlers.Enqueue(handler); |
|
|||
124 | } |
|
|||
125 |
|
110 | |||
126 |
if ( |
|
111 | if (IsFulfilled && TryDequeueHandler(out handler)) | |
127 | // if the promise have been resolved while we was adding the handler to the queue |
|
112 | // if the promise have been resolved while we was adding the handler to the queue | |
128 | // we can't guarantee that someone is still processing it |
|
113 | // we can't guarantee that someone is still processing it | |
129 | // therefore we need to fetch a handler from the queue and execute it |
|
114 | // therefore we need to fetch a handler from the queue and execute it | |
130 | // note that fetched handler may be not the one that we have added |
|
115 | // note that fetched handler may be not the one that we have added | |
131 | // even we can fetch no handlers at all :) |
|
116 | // even we can fetch no handlers at all :) | |
132 |
SignalHandler(handler |
|
117 | SignalHandler(handler); | |
133 | } |
|
118 | } | |
134 |
|
119 | |||
135 | } |
|
120 | } | |
136 |
|
121 | |||
|
122 | void EnqueueHandler(THandler handler) { | |||
|
123 | if (Interlocked.CompareExchange(ref m_handler, handler, null) != null) { | |||
|
124 | if (m_extraHandlers == null) | |||
|
125 | // compare-exchange will protect from loosing already created queue | |||
|
126 | Interlocked.CompareExchange(ref m_extraHandlers, new SimpleAsyncQueue<THandler>(), null); | |||
|
127 | m_extraHandlers.Enqueue(handler); | |||
|
128 | } | |||
|
129 | } | |||
|
130 | ||||
137 | bool TryDequeueHandler(out THandler handler) { |
|
131 | bool TryDequeueHandler(out THandler handler) { | |
138 | handler = Interlocked.Exchange(ref m_handler, null); |
|
132 | handler = Interlocked.Exchange(ref m_handler, null); | |
139 | if (handler != null) |
|
133 | if (handler != null) | |
140 | return true; |
|
134 | return true; | |
141 | return m_extraHandlers != null && m_extraHandlers.TryDequeue(out handler); |
|
135 | return m_extraHandlers != null && m_extraHandlers.TryDequeue(out handler); | |
142 | } |
|
136 | } | |
143 |
|
137 | |||
144 | #endregion |
|
138 | #endregion | |
145 |
|
||||
146 | #region IPromise implementation |
|
|||
147 |
|
||||
148 | public bool IsFulfilled { |
|
|||
149 | get { |
|
|||
150 | return m_state > TRANSITIONAL_STATE; |
|
|||
151 | } |
|
|||
152 | } |
|
|||
153 |
|
||||
154 | public bool IsRejected { |
|
|||
155 | get { |
|
|||
156 | return m_state == REJECTED_STATE; |
|
|||
157 | } |
|
|||
158 | } |
|
|||
159 |
|
||||
160 | #endregion |
|
|||
161 |
|
||||
162 | public Exception RejectReason { |
|
|||
163 | get { |
|
|||
164 | return m_error; |
|
|||
165 | } |
|
|||
166 | } |
|
|||
167 |
|
||||
168 | } |
|
139 | } | |
169 | } |
|
140 | } | |
170 |
|
141 |
@@ -1,87 +1,146 | |||||
1 | using System; |
|
1 | using System; | |
|
2 | using System.Diagnostics; | |||
|
3 | using System.Reflection; | |||
2 | using Implab.Parallels; |
|
4 | using Implab.Parallels; | |
3 |
|
5 | |||
4 | namespace Implab { |
|
6 | namespace Implab { | |
5 | public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise { |
|
7 | public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise { | |
6 | public class HandlerDescriptor { |
|
8 | public class HandlerDescriptor { | |
7 |
readonly Action m_ |
|
9 | readonly Action m_resolve; | |
8 |
readonly Action<Exception> m_ |
|
10 | readonly Action<Exception> m_reject; | |
|
11 | ||||
|
12 | readonly IDeferred m_deferred; | |||
9 | public HandlerDescriptor(Action success, Action<Exception> error) { |
|
13 | public HandlerDescriptor(Action success, Action<Exception> error) { | |
10 |
m_ |
|
14 | m_resolve = success; | |
11 |
m_ |
|
15 | m_reject = error; | |
12 | } |
|
16 | } | |
13 |
|
17 | |||
14 | public void SignalSuccess() { |
|
18 | public void SignalSuccess() { | |
15 |
|
|
19 | try { | |
16 |
|
|
20 | if (m_resolve != null) | |
17 |
m_ |
|
21 | m_resolve(); | |
18 | // Analysis disable once EmptyGeneralCatchClause |
|
22 | m_deferred.Resolve(); | |
19 |
|
|
23 | } catch (Exception ex) { | |
20 |
|
|
24 | m_deferred.Reject(ex); | |
21 | } |
|
25 | } | |
22 | } |
|
26 | } | |
23 |
|
27 | |||
24 | public void SignalError(Exception err) { |
|
28 | public void SignalError(Exception err) { | |
25 |
if (m_ |
|
29 | if (m_reject != null) { | |
26 | try { |
|
30 | try { | |
27 |
m_ |
|
31 | m_reject(err); | |
28 | // Analysis disable once EmptyGeneralCatchClause |
|
32 | m_deferred.Resolve(); | |
29 | } catch { |
|
33 | } catch (Exception ex) { | |
|
34 | m_deferred.Reject(ex); | |||
30 | } |
|
35 | } | |
31 | } |
|
36 | } | |
32 | } |
|
37 | } | |
33 | } |
|
38 | } | |
34 |
|
39 | |||
|
40 | PromiseState m_state; | |||
|
41 | ||||
|
42 | Exception m_error; | |||
|
43 | ||||
|
44 | public bool IsRejected { | |||
|
45 | get { | |||
|
46 | return m_state == PromiseState.Rejected; | |||
|
47 | } | |||
|
48 | } | |||
|
49 | ||||
|
50 | public bool IsResolved { | |||
|
51 | get { | |||
|
52 | return m_state == PromiseState.Resolved; | |||
|
53 | } | |||
|
54 | } | |||
|
55 | ||||
|
56 | public Exception RejectReason { | |||
|
57 | get { | |||
|
58 | return m_error; | |||
|
59 | } | |||
|
60 | } | |||
|
61 | ||||
35 |
|
62 | |||
36 | #region implemented abstract members of AbstractPromise |
|
63 | #region implemented abstract members of AbstractPromise | |
37 |
|
64 | |||
38 |
protected override void SignalHandler(HandlerDescriptor handler |
|
65 | protected override void SignalHandler(HandlerDescriptor handler) { | |
39 |
switch ( |
|
66 | switch (m_state) { | |
40 | case SUCCEEDED_STATE: |
|
67 | case PromiseState.Resolved: | |
41 | handler.SignalSuccess(); |
|
68 | handler.SignalSuccess(); | |
42 | break; |
|
69 | break; | |
43 | case REJECTED_STATE: |
|
70 | case PromiseState.Rejected: | |
44 | handler.SignalError(RejectReason); |
|
71 | handler.SignalError(RejectReason); | |
45 | break; |
|
72 | break; | |
46 | default: |
|
73 | default: | |
47 |
throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", |
|
74 | throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state)); | |
48 | } |
|
75 | } | |
49 | } |
|
76 | } | |
50 |
|
77 | |||
51 | protected override Signal GetFulfillSignal() { |
|
78 | protected override Signal GetFulfillSignal() { | |
52 | var signal = new Signal(); |
|
79 | var signal = new Signal(); | |
53 | On(signal.Set, e => signal.Set()); |
|
80 | On(signal.Set, e => signal.Set()); | |
54 | return signal; |
|
81 | return signal; | |
55 | } |
|
82 | } | |
56 |
|
83 | |||
57 | #endregion |
|
84 | #endregion | |
58 |
|
85 | |||
|
86 | protected void CompleteResolve() { | |||
|
87 | m_state = PromiseState.Resolved; | |||
|
88 | CompleteTransit(); | |||
|
89 | } | |||
|
90 | ||||
59 | public Type ResultType { |
|
91 | public Type ResultType { | |
60 | get { |
|
92 | get { | |
61 | return typeof(void); |
|
93 | return typeof(void); | |
62 | } |
|
94 | } | |
63 | } |
|
95 | } | |
64 |
|
96 | |||
|
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 | ||||
|
119 | protected void Rethrow() { | |||
|
120 | Debug.Assert(m_error != null); | |||
|
121 | if (m_error is OperationCanceledException) | |||
|
122 | throw new OperationCanceledException("Operation cancelled", m_error); | |||
|
123 | else | |||
|
124 | throw new TargetInvocationException(m_error); | |||
|
125 | } | |||
|
126 | ||||
65 | public void On(Action success, Action<Exception> error) { |
|
127 | public void On(Action success, Action<Exception> error) { | |
66 | AddHandler(new HandlerDescriptor(success, error)); |
|
128 | AddHandler(new HandlerDescriptor(success, error)); | |
67 | } |
|
129 | } | |
68 |
|
130 | |||
69 | public IPromise<T> Cast<T>() { |
|
131 | public IPromise<T> Cast<T>() { | |
70 | throw new InvalidCastException(); |
|
132 | throw new InvalidCastException(); | |
71 | } |
|
133 | } | |
72 |
|
134 | |||
73 | public void Join() { |
|
135 | public void Join() { | |
74 | WaitResult(-1); |
|
136 | WaitResult(-1); | |
|
137 | if (IsRejected) | |||
|
138 | Rethrow(); | |||
75 | } |
|
139 | } | |
76 |
|
140 | |||
77 | public void Join(int timeout) { |
|
141 | public void Join(int timeout) { | |
78 | WaitResult(timeout); |
|
142 | WaitResult(timeout); | |
79 | } |
|
143 | } | |
80 |
|
||||
81 | protected void SetResult() { |
|
|||
82 | if(BeginSetResult()) |
|
|||
83 | EndSetResult(); |
|
|||
84 | } |
|
|||
85 | } |
|
144 | } | |
86 | } |
|
145 | } | |
87 |
|
146 |
@@ -1,53 +1,53 | |||||
1 | using System; |
|
1 | using System; | |
2 | using System.Collections.Generic; |
|
2 | using System.Collections.Generic; | |
3 | using System.Linq; |
|
3 | using System.Linq; | |
4 | using System.Text; |
|
4 | using System.Text; | |
5 |
|
5 | |||
6 | namespace Implab { |
|
6 | namespace Implab { | |
7 |
public interface IPromise |
|
7 | public interface IPromise { | |
8 |
|
8 | |||
9 | /// <summary> |
|
9 | /// <summary> | |
10 | /// Π’ΠΈΠΏ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ°, ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌΠΎΠ³ΠΎ ΡΠ΅ΡΠ΅Π· Π΄Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅. |
|
10 | /// Π’ΠΈΠΏ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ°, ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌΠΎΠ³ΠΎ ΡΠ΅ΡΠ΅Π· Π΄Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅. | |
11 | /// </summary> |
|
11 | /// </summary> | |
12 | Type ResultType { get; } |
|
12 | Type ResultType { get; } | |
13 |
|
13 | |||
14 | /// <summary> |
|
14 | /// <summary> | |
15 | /// ΠΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΡΠ²Π»ΡΠ΅ΡΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΡΠΌ, Π»ΠΈΠ±ΠΎ ΡΡΠΏΠ΅ΡΠ½ΠΎ, Π»ΠΈΠ±ΠΎ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ, Π»ΠΈΠ±ΠΎ ΠΎΡΠΌΠ΅Π½Π΅Π½ΠΎ. |
|
15 | /// ΠΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΡΠ²Π»ΡΠ΅ΡΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΡΠΌ, Π»ΠΈΠ±ΠΎ ΡΡΠΏΠ΅ΡΠ½ΠΎ, Π»ΠΈΠ±ΠΎ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ, Π»ΠΈΠ±ΠΎ ΠΎΡΠΌΠ΅Π½Π΅Π½ΠΎ. | |
16 | /// </summary> |
|
16 | /// </summary> | |
17 | bool IsFulfilled { get; } |
|
17 | bool IsFulfilled { get; } | |
18 |
|
18 | |||
19 | bool IsRejected { get; } |
|
19 | bool IsRejected { get; } | |
20 |
|
20 | |||
21 | bool IsResolved { get; } |
|
21 | bool IsResolved { get; } | |
22 |
|
22 | |||
23 | /// <summary> |
|
23 | /// <summary> | |
24 | /// ΠΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π²ΠΎΠ·Π½ΠΈΠΊΡΠ΅Π΅ Π² ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ, Π»ΠΈΠ±ΠΎ ΠΏΡΠΈΡΠΈΠ½Π° ΠΎΡΠΌΠ΅Π½Ρ. |
|
24 | /// ΠΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π²ΠΎΠ·Π½ΠΈΠΊΡΠ΅Π΅ Π² ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ, Π»ΠΈΠ±ΠΎ ΠΏΡΠΈΡΠΈΠ½Π° ΠΎΡΠΌΠ΅Π½Ρ. | |
25 | /// </summary> |
|
25 | /// </summary> | |
26 | Exception RejectReason { get; } |
|
26 | Exception RejectReason { get; } | |
27 |
|
27 | |||
28 | /// <summary> |
|
28 | /// <summary> | |
29 | /// Adds specified listeners to the current promise. |
|
29 | /// Adds specified listeners to the current promise. | |
30 | /// </summary> |
|
30 | /// </summary> | |
31 | /// <param name="success">The handler called on the successful promise completion.</param> |
|
31 | /// <param name="success">The handler called on the successful promise completion.</param> | |
32 | /// <param name="error">The handler is called if an error while completing the promise occurred.</param> |
|
32 | /// <param name="error">The handler is called if an error while completing the promise occurred.</param> | |
33 | /// <returns>The current promise.</returns> |
|
33 | /// <returns>The current promise.</returns> | |
34 | void On(Action success, Action<Exception> error); |
|
34 | void On(Action success, Action<Exception> error); | |
35 |
|
35 | |||
36 | /// <summary> |
|
36 | /// <summary> | |
37 | /// ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ΅Ρ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ ΠΊ Π·Π°Π΄Π°Π½Π½ΠΎΠΌΡ ΡΠΈΠΏΡ ΠΈ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅. |
|
37 | /// ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ΅Ρ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ ΠΊ Π·Π°Π΄Π°Π½Π½ΠΎΠΌΡ ΡΠΈΠΏΡ ΠΈ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅. | |
38 | /// </summary> |
|
38 | /// </summary> | |
39 | IPromise<T> Cast<T>(); |
|
39 | IPromise<T> Cast<T>(); | |
40 |
|
40 | |||
41 | /// <summary> |
|
41 | /// <summary> | |
42 | /// Π‘ΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·ΠΈΡΡΠ΅Ρ ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΏΠΎΡΠΎΠΊ Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ΠΌ. |
|
42 | /// Π‘ΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·ΠΈΡΡΠ΅Ρ ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΏΠΎΡΠΎΠΊ Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ΠΌ. | |
43 | /// </summary> |
|
43 | /// </summary> | |
44 | void Join(); |
|
44 | void Join(); | |
45 | /// <summary> |
|
45 | /// <summary> | |
46 | /// Π‘ΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·ΠΈΡΡΠ΅Ρ ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΏΠΎΡΠΎΠΊ Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ΠΌ. |
|
46 | /// Π‘ΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·ΠΈΡΡΠ΅Ρ ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΏΠΎΡΠΎΠΊ Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ΠΌ. | |
47 | /// </summary> |
|
47 | /// </summary> | |
48 | /// <param name="timeout">ΠΡΠ΅ΠΌΡ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ, ΠΏΠΎ Π΅Π³ΠΎ ΠΈΡΡΠ΅ΡΠ΅Π½ΠΈΡ Π²ΠΎΠ·Π½ΠΈΠΊΠ½Π΅Ρ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅.</param> |
|
48 | /// <param name="timeout">ΠΡΠ΅ΠΌΡ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ, ΠΏΠΎ Π΅Π³ΠΎ ΠΈΡΡΠ΅ΡΠ΅Π½ΠΈΡ Π²ΠΎΠ·Π½ΠΈΠΊΠ½Π΅Ρ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅.</param> | |
49 | /// <exception cref="TimeoutException">ΠΡΠ΅Π²ΡΡΠ΅Π½ΠΎ Π²ΡΠ΅ΠΌΡ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ.</exception> |
|
49 | /// <exception cref="TimeoutException">ΠΡΠ΅Π²ΡΡΠ΅Π½ΠΎ Π²ΡΠ΅ΠΌΡ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ.</exception> | |
50 | void Join(int timeout); |
|
50 | void Join(int timeout); | |
51 |
|
51 | |||
52 | } |
|
52 | } | |
53 | } |
|
53 | } |
@@ -1,25 +1,25 | |||||
1 | using System; |
|
1 | using System; | |
2 | using Implab.Parallels; |
|
2 | using Implab.Parallels; | |
3 |
|
3 | |||
4 | namespace Implab { |
|
4 | namespace Implab { | |
5 |
public class Promise : AbstractPromise |
|
5 | public class Promise : AbstractPromise { | |
6 | public static readonly IPromise Success; |
|
6 | public static readonly IPromise Success; | |
7 |
|
7 | |||
8 | static Promise() { |
|
8 | static Promise() { | |
9 | Success = new SuccessPromise(); |
|
9 | Success = new SuccessPromise(); | |
10 | } |
|
10 | } | |
11 |
|
11 | |||
12 |
|
|
12 | internal void ResolvePromise() { | |
13 | SetResult(); |
|
13 | SetResult(); | |
14 | } |
|
14 | } | |
15 |
|
15 | |||
16 |
|
|
16 | internal void RejectPromise(Exception error) { | |
17 | SetError(error); |
|
17 | SetError(error); | |
18 | } |
|
18 | } | |
19 |
|
19 | |||
20 |
public static IPromise |
|
20 | public static IPromise Reject(Exception exception) { | |
21 | return new FailedPromise(exception); |
|
21 | return new FailedPromise(exception); | |
22 | } |
|
22 | } | |
23 | } |
|
23 | } | |
24 | } |
|
24 | } | |
25 |
|
25 |
General Comments 3
ok, latest stable version should be in default
You need to be logged in to leave comments.
Login now