##// END OF EJS Templates
Added 'Fail' method to RunnableComponent which allows component to move from...
cin -
r203:4d9830a9bbb8 v2
parent child
Show More
@@ -0,0 +1,71
1 using System;
2 using Implab.Components;
3
4 namespace Implab.Test.Mock {
5 class MockPollingComponent : PollingComponent {
6 public MockPollingComponent(TimeSpan interval, Func<Func<ICancellationToken, IPromise>, IPromise> dispatcher, bool initialized) : base(interval, dispatcher, initialized) {
7 }
8
9 public Action MockInit {
10 get;
11 set;
12 }
13
14 public Action<Exception> MockOnError {
15 get;
16 set;
17 }
18
19 public Action<Exception> MockOnCancel {
20 get;
21 set;
22 }
23
24 public Func<IPromise> MockStart {
25 get;
26 set;
27 }
28
29 public Func<IPromise> MockStop {
30 get;
31 set;
32 }
33
34 public Func<ICancellationToken, IPromise> MockTick {
35 get;
36 set;
37 }
38
39 protected override IPromise OnStart() {
40 return MockStart != null ? Safe.Run(MockStart).Chain(base.OnStart) : Safe.Run(base.OnStart);
41 }
42
43 protected override IPromise OnStop() {
44 return MockStop != null ? Safe.Run(MockStop).Chain(base.OnStop) : Safe.Run(base.OnStop);
45 }
46
47 protected override void OnInitialize() {
48 if (MockInit != null)
49 MockInit();
50 }
51
52 protected override IPromise OnTick(ICancellationToken cancellationToken) {
53 return MockTick != null ? Safe.Run(() => MockTick(cancellationToken)) : Promise.SUCCESS;
54 }
55
56 protected override void OnTickCancel(Exception error) {
57 if (MockOnCancel != null)
58 MockOnCancel(error);
59 }
60
61 protected override void OnTickError(Exception error) {
62 if (MockOnError != null)
63 MockOnError(error);
64 }
65
66 public void CallComponentFail(Exception error) {
67 Fail(error);
68 }
69 }
70 }
71
@@ -0,0 +1,38
1 using System;
2 using Implab.Components;
3
4 namespace Implab.Test.Mock {
5 class MockRunnableComponent : RunnableComponent {
6 public MockRunnableComponent(bool initialized) : base(initialized) {
7 }
8
9 public Action MockInit {
10 get;
11 set;
12 }
13
14 public Func<IPromise> MockStart {
15 get;
16 set;
17 }
18
19 public Func<IPromise> MockStop {
20 get;
21 set;
22 }
23
24 protected override IPromise OnStart() {
25 return MockStart != null ? Safe.Run(MockStart).Chain(base.OnStart) : Safe.Run(base.OnStart);
26 }
27
28 protected override IPromise OnStop() {
29 return MockStop != null ? Safe.Run(MockStop).Chain(base.OnStop) : Safe.Run(base.OnStop);
30 }
31
32 protected override void OnInitialize() {
33 if (MockInit != null)
34 MockInit();
35 }
36 }
37 }
38
@@ -0,0 +1,230
1 using System;
2 using System.Reflection;
3 using System.Threading;
4 using Implab.Parallels;
5 using Implab.Components;
6 using Implab.Test.Mock;
7
8 #if MONO
9
10 using NUnit.Framework;
11 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
12 using TestMethodAttribute = NUnit.Framework.TestAttribute;
13 using AssertFailedException = NUnit.Framework.AssertionException;
14 #else
15
16 using Microsoft.VisualStudio.TestTools.UnitTesting;
17
18 #endif
19
20 namespace Implab.Test {
21 [TestClass]
22 public class PollingComponentTests {
23 static void ShouldThrow(Action action) {
24 try {
25 action();
26 Assert.Fail();
27 } catch (AssertFailedException) {
28 throw;
29 } catch {
30 }
31 }
32
33 [TestMethod]
34 public void NormalFlowTest() {
35 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, false);
36
37 Assert.AreEqual(ExecutionState.Created, comp.State);
38
39 comp.Init();
40
41 Assert.AreEqual(ExecutionState.Ready, comp.State);
42
43 comp.Start().Join(1000);
44
45 Assert.AreEqual(ExecutionState.Running, comp.State);
46
47 comp.Stop().Join(1000);
48
49 Assert.AreEqual(ExecutionState.Disposed, comp.State);
50
51 }
52
53 [TestMethod]
54 public void ShouldStartTicks() {
55 var signal = new Signal();
56
57 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
58 comp.MockTick = ct => {
59 signal.Set();
60 return Promise.SUCCESS;
61 };
62
63 comp.Start().Join(1000);
64 signal.Wait(1000);
65 comp.Stop().Join(1000);
66 }
67
68 [TestMethod]
69 public void StopShouldWaitForTickToComplete() {
70 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
71 var signal = new Signal();
72 var promise = new Promise();
73
74 // timer should tick once
75 comp.MockTick = ct => {
76 signal.Set();
77 return promise;
78 };
79
80 // start timer
81 comp.Start().Join(1000);
82
83 signal.Wait(); // wait for tick
84
85 // try to stop component
86 var stopping = comp.Stop();
87
88 Assert.AreEqual(ExecutionState.Stopping, comp.State);
89 ShouldThrow(() => stopping.Join(100));
90 Assert.AreEqual(ExecutionState.Stopping, comp.State);
91
92 // complete operation
93 promise.Resolve();
94
95 // the component should stop normally
96 stopping.Join(1000);
97
98 Assert.AreEqual(ExecutionState.Disposed, comp.State);
99 }
100
101 [TestMethod]
102 public void ShouldRecoverAfterTickError() {
103 var ticks = 0;
104
105 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
106 var signal = new Signal(); // will signal when timer fires 10 times
107
108 comp.MockTick = ct => {
109 ticks++;
110 if (ticks == 10)
111 signal.Set();
112 // each time handler dies
113 throw new Exception("tainted handler");
114 };
115
116 comp.Start();
117
118 signal.Wait(1000);
119
120 comp.Stop().Join(1000);
121
122 Assert.AreEqual(ExecutionState.Disposed, comp.State);
123 }
124
125 [TestMethod]
126 public void StopCancelHandlerOnStop() {
127 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
128 var started = new Signal();
129 bool cancelled = false;
130
131 // timer should tick once
132 comp.MockTick = ct => {
133 started.Set();
134
135 while(!ct.IsCancellationRequested) {
136 Thread.Sleep(1);
137 }
138
139 cancelled = true;
140
141 throw new OperationCanceledException();
142 };
143
144 // start timer
145 comp.Start().Join(1000);
146
147 started.Wait(); // wait for tick
148
149 // try to stop component
150 comp.Stop().Join(1000);
151
152 Assert.AreEqual(true, cancelled);
153
154 Assert.AreEqual(ExecutionState.Disposed, comp.State);
155 }
156
157 [TestMethod]
158 public void FailTickOnStopShouldBeIgnored() {
159 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
160 var started = new Signal();
161 var finish = new Signal();
162
163 // timer should tick once
164 comp.MockTick = ct => {
165 started.Set();
166 finish.Wait();
167 // component is in stopping state here
168 throw new Exception("Die, die, die!!!");
169 };
170
171
172 comp.MockOnError = comp.CallComponentFail;
173
174 // start timer
175 comp.Start().Join(1000);
176
177 started.Wait(); // wait for tick
178
179 // try to stop component
180 var stopping = comp.Stop();
181
182 // the component is in stopping state but it is waiting for the tick handler to complete
183 finish.Set(); // signal the tick handler to finish
184
185 // tick handler should stop rather soon
186 stopping.Join(1000);
187
188 // validate the component is disposed
189 Assert.AreEqual(ExecutionState.Disposed, comp.State);
190 }
191
192 [TestMethod]
193 public void FailTickShouldFailComponent() {
194 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
195 var started = new Signal();
196 var finish = new Signal();
197
198 // timer should tick once
199 comp.MockTick = ct => {
200 started.Set();
201 throw new Exception("Die, die, die!!!");
202 };
203
204
205 comp.MockOnError = err => {
206 comp.CallComponentFail(err);
207 finish.Set();
208 };
209
210 // start timer
211 comp.Start().Join(1000);
212
213 started.Wait(); // wait for tick
214
215 finish.Wait();
216
217 // try to stop component
218 ShouldThrow(() => comp.Stop());
219
220 Assert.AreEqual(ExecutionState.Failed, comp.State);
221 Assert.IsNotNull(comp.LastError);
222 Assert.AreEqual("Die, die, die!!!", comp.LastError.Message);
223
224 comp.Dispose();
225 Assert.AreEqual(ExecutionState.Disposed, comp.State);
226 }
227
228 }
229 }
230
@@ -0,0 +1,155
1 using System;
2 using System.Threading;
3 using Implab.Diagnostics;
4
5 namespace Implab.Components {
6 public class PollingComponent : RunnableComponent {
7 readonly Timer m_timer;
8 readonly Func<Func<ICancellationToken, IPromise>, IPromise> m_dispatcher;
9 readonly TimeSpan m_interval;
10
11 readonly object m_lock = new object();
12
13 ActionTask m_pending;
14
15 protected PollingComponent(TimeSpan interval, Func<Func<ICancellationToken, IPromise>, IPromise> dispatcher, bool initialized) : base(initialized) {
16 m_timer = new Timer(OnInternalTick);
17
18 m_interval = interval;
19 m_dispatcher = dispatcher;
20 }
21
22 protected override IPromise OnStart() {
23 m_timer.Change(TimeSpan.Zero, m_interval);
24
25 return base.OnStart();
26 }
27
28 void OnInternalTick(object state) {
29 if (StartTick()) {
30 try {
31 if (m_dispatcher != null) {
32 var result = m_dispatcher(OnTick);
33 m_pending.CancellationRequested(result.Cancel);
34 AwaitTick(result);
35 } else {
36 AwaitTick(OnTick(m_pending));
37 }
38 } catch (Exception error) {
39 HandleTickError(error);
40 }
41 }
42 }
43
44 /// <summary>
45 /// Checks wheather there is no running handler in the component and marks that the handler is starting.
46 /// </summary>
47 /// <returns>boolean value, true - the new tick handler may be invoked, false - a tick handler is already running or a component isn't running.</returns>
48 /// <remarks>
49 /// If the component is stopping no new handlers can be run. Every successful call to this method must be completed with either AwaitTick or HandleTickError handlers.
50 /// </remarks>
51 protected virtual bool StartTick() {
52 lock (m_lock) {
53 if (State != ExecutionState.Running || m_pending != null)
54 return false;
55 // actually the component may be in a not running state here (stopping, disposed or what ever),
56 // but OnStop method also locks on the same object and will handle operation in m_pending
57 m_pending = new ActionTask(
58 () => {
59 // only one operation is running, it's safe to assing m_pending from it
60 m_pending = null;
61 },
62 ex => {
63 try {
64 OnTickError(ex);
65 // Analysis disable once EmptyGeneralCatchClause
66 } catch {
67 } finally {
68 m_pending = null;
69 }
70 // suppress error
71 },
72 ex => {
73 try {
74 OnTickCancel(ex);
75 // Analysis disable once EmptyGeneralCatchClause
76 } catch {
77 } finally {
78 m_pending = null;
79 }
80 // supress cancellation
81 },
82 false
83 );
84 return true;
85 }
86 }
87
88 /// <summary>
89 /// Awaits the tick.
90 /// </summary>
91 /// <param name="tick">Tick.</param>
92 /// <remarks>
93 /// This method is called only after StartTick method and m_pending will hold the promise which should be fulfilled.
94 /// </remarks>
95 void AwaitTick(IPromise tick) {
96 if (tick == null) {
97 m_pending.Resolve();
98 } else {
99 tick.On(
100 m_pending.Resolve,
101 m_pending.Reject,
102 m_pending.CancelOperation
103 );
104 }
105 }
106
107 /// <summary>
108 /// Handles the tick error.
109 /// </summary>
110 /// <remarks>
111 /// This method is called only after StartTick method and m_pending will hold the promise which should be fulfilled.
112 /// </remarks>
113 void HandleTickError(Exception error) {
114 m_pending.Reject(error);
115 }
116
117 protected virtual void OnTickError(Exception error) {
118 }
119
120 protected virtual void OnTickCancel(Exception error) {
121 }
122
123 /// <summary>
124 /// Invoked when the timer ticks, use this method to implement your logic
125 /// </summary>
126 protected virtual IPromise OnTick(ICancellationToken cancellationToken) {
127 return Promise.SUCCESS;
128 }
129
130 protected override IPromise OnStop() {
131 m_timer.Change(-1, -1);
132
133 // the component is in the stopping state
134 lock (m_lock) {
135 // after this lock no more pending operations could be created
136 var pending = m_pending;
137 // m_pending could be fulfilled and set to null already
138 if (pending != null) {
139 pending.Cancel();
140 return pending.Then(base.OnStop);
141 }
142 }
143
144 return base.OnStop();
145 }
146
147 protected override void Dispose(bool disposing, Exception lastError) {
148 if (disposing)
149 Safe.Dispose(m_timer);
150
151 base.Dispose(disposing, lastError);
152 }
153 }
154 }
155
@@ -0,0 +1,100
1 using System;
2 using System.Reflection;
3
4 namespace Implab {
5 public class FailedPromise : IPromise {
6 readonly Exception m_error;
7 public FailedPromise(Exception error) {
8 Safe.ArgumentNotNull(error, "error");
9 m_error = error;
10 }
11
12 #region IPromise implementation
13
14 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
15 if (error != null) {
16 try {
17 error(m_error);
18 // Analysis disable once EmptyGeneralCatchClause
19 } catch {
20 }
21 }
22 return this;
23 }
24
25 public IPromise On(Action success, Action<Exception> error) {
26 if (error != null) {
27 try {
28 error(m_error);
29 // Analysis disable once EmptyGeneralCatchClause
30 } catch {
31 }
32 }
33 return this;
34 }
35
36 public IPromise On(Action success) {
37 return this;
38 }
39
40 public IPromise On(Action handler, PromiseEventType events) {
41 if ((events & PromiseEventType.Error) != 0) {
42 try {
43 handler();
44 // Analysis disable once EmptyGeneralCatchClause
45 } catch {
46 }
47 }
48 return this;
49 }
50
51 public IPromise<T> Cast<T>() {
52 return (IPromise<T>)this;
53 }
54
55 public void Join() {
56 throw new TargetInvocationException(Error);
57 }
58
59 public void Join(int timeout) {
60 throw new TargetInvocationException(Error);
61 }
62
63 public virtual Type PromiseType {
64 get {
65 return typeof(void);
66 }
67 }
68
69 public bool IsResolved {
70 get {
71 return true;
72 }
73 }
74
75 public bool IsCancelled {
76 get {
77 return false;
78 }
79 }
80
81 public Exception Error {
82 get {
83 return m_error;
84 }
85 }
86
87 #endregion
88
89 #region ICancellable implementation
90
91 public void Cancel() {
92 }
93
94 public void Cancel(Exception reason) {
95 }
96
97 #endregion
98 }
99 }
100
@@ -0,0 +1,65
1 using System;
2 using System.Reflection;
3
4 namespace Implab {
5 public class FailedPromise<T> : FailedPromise, IPromise<T> {
6 public FailedPromise(Exception error) : base(error) {
7 }
8
9 public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
10 if (error != null) {
11 try {
12 error(Error);
13 // Analysis disable once EmptyGeneralCatchClause
14 } catch {
15 }
16 }
17 return this;
18 }
19
20 public IPromise<T> On(Action<T> success, Action<Exception> error) {
21 if (error != null) {
22 try {
23 error(Error);
24 // Analysis disable once EmptyGeneralCatchClause
25 } catch {
26 }
27 }
28 return this;
29 }
30
31 public IPromise<T> On(Action<T> success) {
32 return this;
33 }
34
35 T IPromise<T>.Join() {
36 throw new TargetInvocationException(Error);
37 }
38
39 T IPromise<T>.Join(int timeout) {
40 throw new TargetInvocationException(Error);
41 }
42
43
44 IPromise<T> IPromise<T>.On(Action success, Action<Exception> error, Action<Exception> cancel) {
45 On(success, error, cancel);
46 return this;
47 }
48
49 IPromise<T> IPromise<T>.On(Action success, Action<Exception> error) {
50 On(success, error);
51 return this;
52 }
53
54 IPromise<T> IPromise<T>.On(Action success) {
55 On(success);
56 return this;
57 }
58
59 IPromise<T> IPromise<T>.On(Action handler, PromiseEventType events) {
60 On(handler, events);
61 return this;
62 }
63 }
64 }
65
@@ -1,69 +1,75
1 1 <?xml version="1.0" encoding="utf-8"?>
2 2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 3 <PropertyGroup>
4 4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 6 <ProductVersion>8.0.30703</ProductVersion>
7 7 <SchemaVersion>2.0</SchemaVersion>
8 8 <ProjectGuid>{2BD05F84-E067-4B87-9477-FDC2676A21C6}</ProjectGuid>
9 9 <OutputType>Library</OutputType>
10 10 <RootNamespace>Implab.Test</RootNamespace>
11 11 <AssemblyName>Implab.Test</AssemblyName>
12 12 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13 13 <ReleaseVersion>0.2</ReleaseVersion>
14 14 </PropertyGroup>
15 15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 16 <DebugSymbols>true</DebugSymbols>
17 17 <DebugType>full</DebugType>
18 18 <Optimize>false</Optimize>
19 19 <OutputPath>bin\Debug</OutputPath>
20 20 <DefineConstants>DEBUG;MONO</DefineConstants>
21 21 <ErrorReport>prompt</ErrorReport>
22 22 <WarningLevel>4</WarningLevel>
23 23 <ConsolePause>false</ConsolePause>
24 24 </PropertyGroup>
25 25 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26 26 <Optimize>true</Optimize>
27 27 <OutputPath>bin\Release</OutputPath>
28 28 <ErrorReport>prompt</ErrorReport>
29 29 <WarningLevel>4</WarningLevel>
30 30 <ConsolePause>false</ConsolePause>
31 31 <DefineConstants>MONO</DefineConstants>
32 32 </PropertyGroup>
33 33 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
34 34 <DebugSymbols>true</DebugSymbols>
35 35 <DebugType>full</DebugType>
36 36 <Optimize>false</Optimize>
37 37 <OutputPath>bin\Debug</OutputPath>
38 38 <DefineConstants>DEBUG;TRACE;NET_4_5;MONO</DefineConstants>
39 39 <ErrorReport>prompt</ErrorReport>
40 40 <WarningLevel>4</WarningLevel>
41 41 <ConsolePause>false</ConsolePause>
42 42 </PropertyGroup>
43 43 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
44 44 <Optimize>true</Optimize>
45 45 <OutputPath>bin\Release</OutputPath>
46 46 <DefineConstants>NET_4_5;MONO</DefineConstants>
47 47 <ErrorReport>prompt</ErrorReport>
48 48 <WarningLevel>4</WarningLevel>
49 49 <ConsolePause>false</ConsolePause>
50 50 </PropertyGroup>
51 51 <ItemGroup>
52 52 <Reference Include="System" />
53 53 <Reference Include="nunit.framework" />
54 54 </ItemGroup>
55 55 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
56 56 <ItemGroup>
57 57 <Compile Include="AsyncTests.cs" />
58 58 <Compile Include="PromiseHelper.cs" />
59 59 <Compile Include="Properties\AssemblyInfo.cs" />
60 60 <Compile Include="CancelationTests.cs" />
61 61 <Compile Include="RunnableComponentTests.cs" />
62 <Compile Include="PollingComponentTests.cs" />
63 <Compile Include="Mock\MockRunnableComponent.cs" />
64 <Compile Include="Mock\MockPollingComponent.cs" />
62 65 </ItemGroup>
63 66 <ItemGroup>
64 67 <ProjectReference Include="..\Implab\Implab.csproj">
65 68 <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project>
66 69 <Name>Implab</Name>
67 70 </ProjectReference>
68 71 </ItemGroup>
72 <ItemGroup>
73 <Folder Include="Mock\" />
74 </ItemGroup>
69 75 </Project> No newline at end of file
@@ -1,14 +1,22
1 1 using Implab.Parallels;
2 2 using System.Threading;
3 3
4 4 namespace Implab.Test {
5 5 static class PromiseHelper {
6 6 public static IPromise<T> Sleep<T>(int timeout, T retVal) {
7 7 return AsyncPool.Invoke((ct) => {
8 8 ct.CancellationRequested(ct.CancelOperation);
9 9 Thread.Sleep(timeout);
10 10 return retVal;
11 11 });
12 12 }
13
14 public static IPromise Sleep(int timeout) {
15 return AsyncPool.Invoke((ct) => {
16 ct.CancellationRequested(ct.CancelOperation);
17 Thread.Sleep(timeout);
18 return 0;
19 });
13 20 }
14 21 }
22 }
@@ -1,195 +1,165
1 1 using System;
2 2 using System.Reflection;
3 3 using System.Threading;
4 4 using Implab.Parallels;
5 5 using Implab.Components;
6 using Implab.Test.Mock;
6 7
7 8 #if MONO
8 9
9 10 using NUnit.Framework;
10 11 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
11 12 using TestMethodAttribute = NUnit.Framework.TestAttribute;
12 13 using AssertFailedException = NUnit.Framework.AssertionException;
13 14 #else
14 15
15 16 using Microsoft.VisualStudio.TestTools.UnitTesting;
16 17
17 18 #endif
18 19
19 20 namespace Implab.Test {
20 21 [TestClass]
21 22 public class RunnableComponentTests {
22 23
23 24 static void ShouldThrow(Action action) {
24 25 try {
25 26 action();
26 27 Assert.Fail();
27 28 } catch (AssertFailedException) {
28 29 throw;
29 30 } catch {
30 31 }
31 32 }
32 33
33 class Runnable : RunnableComponent {
34 public Runnable(bool initialized) : base(initialized) {
35 }
36 34
37 public Action MockInit {
38 get;
39 set;
40 }
41
42 public Func<IPromise> MockStart {
43 get;
44 set;
45 }
46
47 public Func<IPromise> MockStop {
48 get;
49 set;
50 }
51
52 protected override IPromise OnStart() {
53 return MockStart != null ? MockStart() : base.OnStart();
54 }
55
56 protected override IPromise OnStop() {
57 return MockStop != null ? MockStop() : base.OnStart();
58 }
59
60 protected override void OnInitialize() {
61 if (MockInit != null)
62 MockInit();
63 }
64 }
65 35
66 36 [TestMethod]
67 37 public void NormalFlowTest() {
68 var comp = new Runnable(false);
38 var comp = new MockRunnableComponent(false);
69 39
70 40 Assert.AreEqual(ExecutionState.Created, comp.State);
71 41
72 42 comp.Init();
73 43
74 44 Assert.AreEqual(ExecutionState.Ready, comp.State);
75 45
76 46 comp.Start().Join(1000);
77 47
78 48 Assert.AreEqual(ExecutionState.Running, comp.State);
79 49
80 50 comp.Stop().Join(1000);
81 51
82 52 Assert.AreEqual(ExecutionState.Disposed, comp.State);
83 53
84 54 }
85 55
86 56 [TestMethod]
87 57 public void InitFailTest() {
88 var comp = new Runnable(false) {
58 var comp = new MockRunnableComponent(false) {
89 59 MockInit = () => {
90 60 throw new Exception("BAD");
91 61 }
92 62 };
93 63
94 64 ShouldThrow(() => comp.Start());
95 65 ShouldThrow(() => comp.Stop());
96 66 Assert.AreEqual(ExecutionState.Created, comp.State);
97 67
98 68 ShouldThrow(comp.Init);
99 69
100 70 Assert.AreEqual(ExecutionState.Failed, comp.State);
101 71
102 72 ShouldThrow(() => comp.Start());
103 73 ShouldThrow(() => comp.Stop());
104 74 Assert.AreEqual(ExecutionState.Failed, comp.State);
105 75
106 76 comp.Dispose();
107 77 Assert.AreEqual(ExecutionState.Disposed, comp.State);
108 78 }
109 79
110 80 [TestMethod]
111 81 public void DisposedTest() {
112 82
113 var comp = new Runnable(false);
83 var comp = new MockRunnableComponent(false);
114 84 comp.Dispose();
115 85
116 86 ShouldThrow(() => comp.Start());
117 87 ShouldThrow(() => comp.Stop());
118 88 ShouldThrow(comp.Init);
119 89
120 90 Assert.AreEqual(ExecutionState.Disposed, comp.State);
121 91 }
122 92
123 93 [TestMethod]
124 94 public void StartCancelTest() {
125 var comp = new Runnable(true) {
95 var comp = new MockRunnableComponent(true) {
126 96 MockStart = () => PromiseHelper.Sleep(100000, 0)
127 97 };
128 98
129 99 var p = comp.Start();
130 100 Assert.AreEqual(ExecutionState.Starting, comp.State);
131 101 p.Cancel();
132 102 ShouldThrow(() => p.Join(1000));
133 103 Assert.AreEqual(ExecutionState.Failed, comp.State);
134 104
135 105 Assert.IsTrue(comp.LastError is OperationCanceledException);
136 106
137 107 comp.Dispose();
138 108 }
139 109
140 110 [TestMethod]
141 111 public void StartStopTest() {
142 112 var stop = new Signal();
143 var comp = new Runnable(true) {
113 var comp = new MockRunnableComponent(true) {
144 114 MockStart = () => PromiseHelper.Sleep(100000, 0),
145 115 MockStop = () => AsyncPool.RunThread(stop.Wait)
146 116 };
147 117
148 118 var p1 = comp.Start();
149 119 var p2 = comp.Stop();
150 120 // should enter stopping state
151 121
152 122 ShouldThrow(p1.Join);
153 123 Assert.IsTrue(p1.IsCancelled);
154 124 Assert.AreEqual(ExecutionState.Stopping, comp.State);
155 125
156 126 stop.Set();
157 127 p2.Join(1000);
158 128 Assert.AreEqual(ExecutionState.Disposed, comp.State);
159 129 }
160 130
161 131 [TestMethod]
162 132 public void StartStopFailTest() {
163 var comp = new Runnable(true) {
133 var comp = new MockRunnableComponent(true) {
164 134 MockStart = () => PromiseHelper.Sleep(100000, 0).Then(null,null,x => { throw new Exception("I'm dead"); })
165 135 };
166 136
167 137 comp.Start();
168 138 var p = comp.Stop();
169 139 // if Start fails to cancel, should fail to stop
170 140 ShouldThrow(() => p.Join(1000));
171 141 Assert.AreEqual(ExecutionState.Failed, comp.State);
172 142 Assert.IsNotNull(comp.LastError);
173 143 Assert.AreEqual("I'm dead", comp.LastError.Message);
174 144 }
175 145
176 146 [TestMethod]
177 147 public void StopCancelTest() {
178 var comp = new Runnable(true) {
148 var comp = new MockRunnableComponent(true) {
179 149 MockStop = () => PromiseHelper.Sleep(100000, 0)
180 150 };
181 151
182 152 comp.Start();
183 153 var p = comp.Stop();
184 154 Assert.AreEqual(ExecutionState.Stopping, comp.State);
185 155 p.Cancel();
186 156 ShouldThrow(() => p.Join(1000));
187 157 Assert.AreEqual(ExecutionState.Failed, comp.State);
188 158 Assert.IsTrue(comp.LastError is OperationCanceledException);
189 159
190 160 comp.Dispose();
191 161 }
192 162
193 163 }
194 164 }
195 165
@@ -1,14 +1,20
1 1 using System;
2 2
3 3 namespace Implab.Components {
4 4 public interface IRunnable {
5 /// <summary>
6 /// Starts this instance.
7 /// </summary>
5 8 IPromise Start();
6 9
10 /// <summary>
11 /// Stops this instance. After the instance is stopped it can't be started again, stopping should be treated as gracefull and async dispose.
12 /// </summary>
7 13 IPromise Stop();
8 14
9 15 ExecutionState State { get; }
10 16
11 17 Exception LastError { get; }
12 18 }
13 19 }
14 20
@@ -1,265 +1,296
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 DisposeTimeout = 10000;
74 75 }
75 76
76 protected virtual int DisposeTimeout {
77 get {
78 return 10000;
79 }
77 /// <summary>
78 /// Gets or sets the timeout to wait for the pending operation to complete. If the pending operation doesn't finish than the component will be disposed anyway.
79 /// </summary>
80 protected int DisposeTimeout {
81 get;
82 set;
80 83 }
81 84
82 85 void ThrowInvalidCommand(Commands cmd) {
83 86 if (m_stateMachine.State == ExecutionState.Disposed)
84 87 throw new ObjectDisposedException(ToString());
85 88
86 89 throw new InvalidOperationException(String.Format("Commnd {0} is not allowed in the state {1}", cmd, m_stateMachine.State));
87 90 }
88 91
89 92 void Move(Commands cmd) {
90 93 if (!m_stateMachine.Move(cmd))
91 94 ThrowInvalidCommand(cmd);
92 95 }
93 96
97 /// <summary>
98 /// Moves the component from running to failed state.
99 /// </summary>
100 /// <param name="error">The exception which is describing the error.</param>
101 /// <returns>Returns true if the component is set to the failed state, false - otherwise.
102 /// This method works only for the running state, in any other state it will return false.</returns>
103 protected bool Fail(Exception error) {
104 lock (m_stateMachine) {
105 if(m_stateMachine.State == ExecutionState.Running) {
106 m_stateMachine.Move(Commands.Fail);
107 m_lastError = error;
108 return true;
109 }
110 }
111 return false;
112 }
113
94 114 void Invoke(Commands cmd, Action action) {
95 115 lock (m_stateMachine)
96 116 Move(cmd);
97 117
98 118 try {
99 119 action();
100 120 lock(m_stateMachine)
101 121 Move(Commands.Ok);
102 122
103 123 } catch (Exception err) {
104 124 lock (m_stateMachine) {
105 125 Move(Commands.Fail);
106 126 m_lastError = err;
107 127 }
108 128 throw;
109 129 }
110 130 }
111 131
112 132 IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IDeferred> chain) {
113 133 IPromise promise = null;
114 134 IPromise prev;
115 135
116 136 var task = new ActionChainTask(action, null, null, true);
117 137
118 138 lock (m_stateMachine) {
119 139 Move(cmd);
120 140
121 141 prev = m_pending;
122 142
123 143 Action<Exception> errorOrCancel = e => {
124 144 if (e == null)
125 145 e = new OperationCanceledException();
126 146
127 147 lock (m_stateMachine) {
128 148 if (m_pending == promise) {
129 149 Move(Commands.Fail);
130 150 m_pending = null;
131 151 m_lastError = e;
132 152 }
133 153 }
134 154 throw new PromiseTransientException(e);
135 155 };
136 156
137 157 promise = task.Then(
138 158 () => {
139 159 lock(m_stateMachine) {
140 160 if (m_pending == promise) {
141 161 Move(Commands.Ok);
142 162 m_pending = null;
143 163 }
144 164 }
145 165 },
146 166 errorOrCancel,
147 167 errorOrCancel
148 168 );
149 169
150 170 m_pending = promise;
151 171 }
152 172
153 173 if (prev == null)
154 174 task.Resolve();
155 175 else
156 176 chain(prev, task);
157 177
158 178 return promise;
159 179 }
160 180
161 181
162 182 #region IInitializable implementation
163 183
164 184 public void Init() {
165 185 Invoke(Commands.Init, OnInitialize);
166 186 }
167 187
168 188 protected virtual void OnInitialize() {
169 189 }
170 190
171 191 #endregion
172 192
173 193 #region IRunnable implementation
174 194
175 195 public IPromise Start() {
176 196 return InvokeAsync(Commands.Start, OnStart, null);
177 197 }
178 198
179 199 protected virtual IPromise OnStart() {
180 200 return Promise.SUCCESS;
181 201 }
182 202
183 203 public IPromise Stop() {
184 204 return InvokeAsync(Commands.Stop, OnStop, StopPending).Then(Dispose);
185 205 }
186 206
187 207 protected virtual IPromise OnStop() {
188 208 return Promise.SUCCESS;
189 209 }
190 210
191 211 /// <summary>
192 212 /// Stops the current operation if one exists.
193 213 /// </summary>
194 214 /// <param name="current">Current.</param>
195 215 /// <param name="stop">Stop.</param>
196 216 protected virtual void StopPending(IPromise current, IDeferred stop) {
197 217 if (current == null) {
198 218 stop.Resolve();
199 219 } else {
200 220 // связваем текущую операцию с операцией остановки
201 221 current.On(
202 222 stop.Resolve, // если текущая операция заверщилась, то можно начинать остановку
203 223 stop.Reject, // если текущая операция дала ошибку - то все плохо, нельзя продолжать
204 224 e => stop.Resolve() // если текущая отменилась, то можно начинать остановку
205 225 );
206 226 // посылаем текущей операции сигнал остановки
207 227 current.Cancel();
208 228 }
209 229 }
210 230
211 231 public ExecutionState State {
212 232 get {
213 lock (m_stateMachine)
214 233 return m_stateMachine.State;
215 234 }
216 235 }
217 236
218 237 public Exception LastError {
219 238 get {
220 239 return m_lastError;
221 240 }
222 241 }
223 242
224 243 #endregion
225 244
226 245 #region IDisposable implementation
227 246
247 /// <summary>
248 /// Releases all resource used by the <see cref="Implab.Components.RunnableComponent"/> object.
249 /// </summary>
250 /// <remarks>
251 /// <para>Will not try to stop the component, it will just release all resources.
252 /// To cleanup the component gracefully use <see cref="Stop()"/> method.</para>
253 /// <para>
254 /// In normal cases the <see cref="Dispose()"/> method shouldn't be called, the call to the <see cref="Stop()"/>
255 /// method is sufficient to cleanup the component. Call <see cref="Dispose()"/> only to cleanup after errors,
256 /// especially if <see cref="Stop"/> method is failed. Using this method insted of <see cref="Stop()"/> may
257 /// lead to the data loss by the component.
258 /// </para></remarks>
228 259 public void Dispose() {
229 260 IPromise pending;
230 261 lock (m_stateMachine) {
231 262 if (m_stateMachine.State == ExecutionState.Disposed)
232 263 return;
233 264
234 265 Move(Commands.Dispose);
235 266
236 267 GC.SuppressFinalize(this);
237 268
238 269 pending = m_pending;
239 270 m_pending = null;
240 271 }
241 272 if (pending != null) {
242 273 pending.Cancel();
243 274 pending.Timeout(DisposeTimeout).On(
244 275 () => Dispose(true, null),
245 276 err => Dispose(true, err),
246 277 reason => Dispose(true, new OperationCanceledException("The operation is cancelled", reason))
247 278 );
248 279 } else {
249 280 Dispose(true, m_lastError);
250 281 }
251 282 }
252 283
253 284 ~RunnableComponent() {
254 285 Dispose(false, null);
255 286 }
256 287
257 288 #endregion
258 289
259 290 protected virtual void Dispose(bool disposing, Exception lastError) {
260 291
261 292 }
262 293
263 294 }
264 295 }
265 296
@@ -1,276 +1,278
1 1 <?xml version="1.0" encoding="utf-8"?>
2 2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 3 <PropertyGroup>
4 4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
7 7 <OutputType>Library</OutputType>
8 8 <RootNamespace>Implab</RootNamespace>
9 9 <AssemblyName>Implab</AssemblyName>
10 10 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
11 11 <ReleaseVersion>0.2</ReleaseVersion>
12 12 <ProductVersion>8.0.30703</ProductVersion>
13 13 <SchemaVersion>2.0</SchemaVersion>
14 14 </PropertyGroup>
15 15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 16 <DebugSymbols>true</DebugSymbols>
17 17 <DebugType>full</DebugType>
18 18 <Optimize>false</Optimize>
19 19 <OutputPath>bin\Debug</OutputPath>
20 20 <DefineConstants>TRACE;DEBUG;</DefineConstants>
21 21 <ErrorReport>prompt</ErrorReport>
22 22 <WarningLevel>4</WarningLevel>
23 23 <ConsolePause>false</ConsolePause>
24 24 <RunCodeAnalysis>true</RunCodeAnalysis>
25 25 </PropertyGroup>
26 26 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
27 27 <DebugType>full</DebugType>
28 28 <Optimize>true</Optimize>
29 29 <OutputPath>bin\Release</OutputPath>
30 30 <ErrorReport>prompt</ErrorReport>
31 31 <WarningLevel>4</WarningLevel>
32 32 <ConsolePause>false</ConsolePause>
33 33 </PropertyGroup>
34 34 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
35 35 <DebugSymbols>true</DebugSymbols>
36 36 <DebugType>full</DebugType>
37 37 <Optimize>false</Optimize>
38 38 <OutputPath>bin\Debug</OutputPath>
39 39 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
40 40 <ErrorReport>prompt</ErrorReport>
41 41 <WarningLevel>4</WarningLevel>
42 42 <RunCodeAnalysis>true</RunCodeAnalysis>
43 43 <ConsolePause>false</ConsolePause>
44 44 </PropertyGroup>
45 45 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
46 46 <Optimize>true</Optimize>
47 47 <OutputPath>bin\Release</OutputPath>
48 48 <ErrorReport>prompt</ErrorReport>
49 49 <WarningLevel>4</WarningLevel>
50 50 <ConsolePause>false</ConsolePause>
51 51 <DefineConstants>NET_4_5</DefineConstants>
52 52 </PropertyGroup>
53 53 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
54 54 <DebugSymbols>true</DebugSymbols>
55 55 <DebugType>full</DebugType>
56 56 <Optimize>false</Optimize>
57 57 <OutputPath>bin\Debug</OutputPath>
58 58 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
59 59 <ErrorReport>prompt</ErrorReport>
60 60 <WarningLevel>4</WarningLevel>
61 61 <RunCodeAnalysis>true</RunCodeAnalysis>
62 62 <ConsolePause>false</ConsolePause>
63 63 </PropertyGroup>
64 64 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
65 65 <Optimize>true</Optimize>
66 66 <OutputPath>bin\Release</OutputPath>
67 67 <DefineConstants>NET_4_5;MONO;</DefineConstants>
68 68 <ErrorReport>prompt</ErrorReport>
69 69 <WarningLevel>4</WarningLevel>
70 70 <ConsolePause>false</ConsolePause>
71 71 </PropertyGroup>
72 72 <ItemGroup>
73 73 <Reference Include="System" />
74 74 <Reference Include="System.Xml" />
75 75 <Reference Include="mscorlib" />
76 76 </ItemGroup>
77 77 <ItemGroup>
78 78 <Compile Include="CustomEqualityComparer.cs" />
79 79 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
80 80 <Compile Include="Diagnostics\LogChannel.cs" />
81 81 <Compile Include="Diagnostics\LogicalOperation.cs" />
82 82 <Compile Include="Diagnostics\TextFileListener.cs" />
83 83 <Compile Include="Diagnostics\TraceLog.cs" />
84 84 <Compile Include="Diagnostics\TraceEvent.cs" />
85 85 <Compile Include="Diagnostics\TraceEventType.cs" />
86 86 <Compile Include="ICancellable.cs" />
87 87 <Compile Include="IProgressHandler.cs" />
88 88 <Compile Include="IProgressNotifier.cs" />
89 89 <Compile Include="IPromiseT.cs" />
90 90 <Compile Include="IPromise.cs" />
91 91 <Compile Include="IServiceLocator.cs" />
92 92 <Compile Include="ITaskController.cs" />
93 93 <Compile Include="Parallels\DispatchPool.cs" />
94 94 <Compile Include="Parallels\ArrayTraits.cs" />
95 95 <Compile Include="Parallels\MTQueue.cs" />
96 96 <Compile Include="Parallels\WorkerPool.cs" />
97 97 <Compile Include="ProgressInitEventArgs.cs" />
98 98 <Compile Include="Properties\AssemblyInfo.cs" />
99 99 <Compile Include="Parallels\AsyncPool.cs" />
100 100 <Compile Include="Safe.cs" />
101 101 <Compile Include="ValueEventArgs.cs" />
102 102 <Compile Include="PromiseExtensions.cs" />
103 103 <Compile Include="SyncContextPromise.cs" />
104 104 <Compile Include="Diagnostics\OperationContext.cs" />
105 105 <Compile Include="Diagnostics\TraceContext.cs" />
106 106 <Compile Include="Diagnostics\LogEventArgs.cs" />
107 107 <Compile Include="Diagnostics\LogEventArgsT.cs" />
108 108 <Compile Include="Diagnostics\Extensions.cs" />
109 109 <Compile Include="PromiseEventType.cs" />
110 110 <Compile Include="Parallels\AsyncQueue.cs" />
111 111 <Compile Include="PromiseT.cs" />
112 112 <Compile Include="IDeferred.cs" />
113 113 <Compile Include="IDeferredT.cs" />
114 114 <Compile Include="Promise.cs" />
115 115 <Compile Include="PromiseTransientException.cs" />
116 116 <Compile Include="Parallels\Signal.cs" />
117 117 <Compile Include="Parallels\SharedLock.cs" />
118 118 <Compile Include="Diagnostics\ILogWriter.cs" />
119 119 <Compile Include="Diagnostics\ListenerBase.cs" />
120 120 <Compile Include="Parallels\BlockingQueue.cs" />
121 121 <Compile Include="AbstractEvent.cs" />
122 122 <Compile Include="AbstractPromise.cs" />
123 123 <Compile Include="AbstractPromiseT.cs" />
124 124 <Compile Include="FuncTask.cs" />
125 125 <Compile Include="FuncTaskBase.cs" />
126 126 <Compile Include="FuncTaskT.cs" />
127 127 <Compile Include="ActionChainTaskBase.cs" />
128 128 <Compile Include="ActionChainTask.cs" />
129 129 <Compile Include="ActionChainTaskT.cs" />
130 130 <Compile Include="FuncChainTaskBase.cs" />
131 131 <Compile Include="FuncChainTask.cs" />
132 132 <Compile Include="FuncChainTaskT.cs" />
133 133 <Compile Include="ActionTaskBase.cs" />
134 134 <Compile Include="ActionTask.cs" />
135 135 <Compile Include="ActionTaskT.cs" />
136 136 <Compile Include="ICancellationToken.cs" />
137 137 <Compile Include="SuccessPromise.cs" />
138 138 <Compile Include="SuccessPromiseT.cs" />
139 139 <Compile Include="PromiseAwaiterT.cs" />
140 140 <Compile Include="PromiseAwaiter.cs" />
141 141 <Compile Include="Components\ComponentContainer.cs" />
142 142 <Compile Include="Components\Disposable.cs" />
143 143 <Compile Include="Components\DisposablePool.cs" />
144 144 <Compile Include="Components\ObjectPool.cs" />
145 145 <Compile Include="Components\ServiceLocator.cs" />
146 146 <Compile Include="Components\IInitializable.cs" />
147 147 <Compile Include="TaskController.cs" />
148 148 <Compile Include="Components\App.cs" />
149 149 <Compile Include="Components\IRunnable.cs" />
150 150 <Compile Include="Components\ExecutionState.cs" />
151 151 <Compile Include="Components\RunnableComponent.cs" />
152 152 <Compile Include="Components\IFactory.cs" />
153 153 <Compile Include="Automaton\IAlphabet.cs" />
154 154 <Compile Include="Automaton\ParserException.cs" />
155 155 <Compile Include="Automaton\IndexedAlphabetBase.cs" />
156 156 <Compile Include="Automaton\IAlphabetBuilder.cs" />
157 157 <Compile Include="Automaton\RegularExpressions\AltToken.cs" />
158 158 <Compile Include="Automaton\RegularExpressions\BinaryToken.cs" />
159 159 <Compile Include="Automaton\RegularExpressions\CatToken.cs" />
160 160 <Compile Include="Automaton\RegularExpressions\StarToken.cs" />
161 161 <Compile Include="Automaton\RegularExpressions\SymbolToken.cs" />
162 162 <Compile Include="Automaton\RegularExpressions\EmptyToken.cs" />
163 163 <Compile Include="Automaton\RegularExpressions\Token.cs" />
164 164 <Compile Include="Automaton\RegularExpressions\IVisitor.cs" />
165 165 <Compile Include="Automaton\AutomatonTransition.cs" />
166 166 <Compile Include="Formats\JSON\JSONElementContext.cs" />
167 167 <Compile Include="Formats\JSON\JSONElementType.cs" />
168 168 <Compile Include="Formats\JSON\JSONGrammar.cs" />
169 169 <Compile Include="Formats\JSON\JSONParser.cs" />
170 170 <Compile Include="Formats\JSON\JSONScanner.cs" />
171 171 <Compile Include="Formats\JSON\JsonTokenType.cs" />
172 172 <Compile Include="Formats\JSON\JSONWriter.cs" />
173 173 <Compile Include="Formats\JSON\JSONXmlReader.cs" />
174 174 <Compile Include="Formats\JSON\JSONXmlReaderOptions.cs" />
175 175 <Compile Include="Formats\JSON\StringTranslator.cs" />
176 176 <Compile Include="Automaton\MapAlphabet.cs" />
177 177 <Compile Include="Formats\CharAlphabet.cs" />
178 178 <Compile Include="Formats\ByteAlphabet.cs" />
179 179 <Compile Include="Automaton\IDFATable.cs" />
180 180 <Compile Include="Automaton\IDFATableBuilder.cs" />
181 181 <Compile Include="Automaton\DFATable.cs" />
182 182 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitor.cs" />
183 183 <Compile Include="Automaton\RegularExpressions\ITaggedDFABuilder.cs" />
184 184 <Compile Include="Formats\TextScanner.cs" />
185 185 <Compile Include="Formats\StringScanner.cs" />
186 186 <Compile Include="Formats\ReaderScanner.cs" />
187 187 <Compile Include="Formats\ScannerContext.cs" />
188 188 <Compile Include="Formats\Grammar.cs" />
189 189 <Compile Include="Automaton\RegularExpressions\EndTokenT.cs" />
190 190 <Compile Include="Automaton\RegularExpressions\EndToken.cs" />
191 191 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitorT.cs" />
192 192 <Compile Include="Automaton\AutomatonConst.cs" />
193 193 <Compile Include="Automaton\RegularExpressions\RegularDFA.cs" />
194 194 <Compile Include="Components\LazyAndWeak.cs" />
195 195 <Compile Include="AbstractTask.cs" />
196 196 <Compile Include="AbstractTaskT.cs" />
197 <Compile Include="Components\PollingRunnableComponent.cs" />
197 <Compile Include="FailedPromise.cs" />
198 <Compile Include="FailedPromiseT.cs" />
199 <Compile Include="Components\PollingComponent.cs" />
198 200 </ItemGroup>
199 201 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
200 202 <ItemGroup />
201 203 <ProjectExtensions>
202 204 <MonoDevelop>
203 205 <Properties>
204 206 <Policies>
205 207 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
206 208 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
207 209 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
208 210 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
209 211 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
210 212 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
211 213 <NameConventionPolicy>
212 214 <Rules>
213 215 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
214 216 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
215 217 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
216 218 <RequiredPrefixes>
217 219 <String>I</String>
218 220 </RequiredPrefixes>
219 221 </NamingRule>
220 222 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
221 223 <RequiredSuffixes>
222 224 <String>Attribute</String>
223 225 </RequiredSuffixes>
224 226 </NamingRule>
225 227 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
226 228 <RequiredSuffixes>
227 229 <String>EventArgs</String>
228 230 </RequiredSuffixes>
229 231 </NamingRule>
230 232 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
231 233 <RequiredSuffixes>
232 234 <String>Exception</String>
233 235 </RequiredSuffixes>
234 236 </NamingRule>
235 237 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
236 238 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
237 239 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
238 240 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
239 241 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
240 242 <RequiredPrefixes>
241 243 <String>m_</String>
242 244 </RequiredPrefixes>
243 245 </NamingRule>
244 246 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
245 247 <RequiredPrefixes>
246 248 <String>_</String>
247 249 </RequiredPrefixes>
248 250 </NamingRule>
249 251 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
250 252 <RequiredPrefixes>
251 253 <String>m_</String>
252 254 </RequiredPrefixes>
253 255 </NamingRule>
254 256 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
255 257 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
256 258 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
257 259 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
258 260 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
259 261 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
260 262 <RequiredPrefixes>
261 263 <String>T</String>
262 264 </RequiredPrefixes>
263 265 </NamingRule>
264 266 </Rules>
265 267 </NameConventionPolicy>
266 268 </Policies>
267 269 </Properties>
268 270 </MonoDevelop>
269 271 </ProjectExtensions>
270 272 <ItemGroup>
271 273 <Folder Include="Components\" />
272 274 <Folder Include="Automaton\RegularExpressions\" />
273 275 <Folder Include="Formats\" />
274 276 <Folder Include="Formats\JSON\" />
275 277 </ItemGroup>
276 278 </Project> No newline at end of file
@@ -1,61 +1,59
1 1 using System;
2 2 using System.Diagnostics;
3 3 using Implab.Parallels;
4 4
5 5 namespace Implab {
6 6
7 7 /// <summary>
8 8 /// Класс для асинхронного получения результатов. Так называемое "обещание".
9 9 /// </summary>
10 10 /// <typeparam name="T">Тип получаемого результата</typeparam>
11 11 /// <remarks>
12 12 /// <para>Сервис при обращении к его методу дает обещаиние о выполнении операции,
13 13 /// клиент получив такое обещание может установить ряд обратных вызово для получения
14 14 /// событий выполнения обещания, тоесть завершения операции и предоставлении результатов.</para>
15 15 /// <para>
16 16 /// Обещение может быть как выполнено, так и выполнено с ошибкой. Для подписки на
17 17 /// данные события клиент должен использовать методы <c>Then</c>.
18 18 /// </para>
19 19 /// <para>
20 20 /// Сервис, в свою очередь, по окончанию выполнения операции (возможно с ошибкой),
21 21 /// использует методы <c>Resolve</c> либо <c>Reject</c> для оповещения клиетна о
22 22 /// выполнении обещания.
23 23 /// </para>
24 24 /// <para>
25 25 /// Если сервер успел выполнить обещание еще до того, как клиент на него подписался,
26 26 /// то в момент подписки клиента будут вызваны соответсвующие события в синхронном
27 27 /// режиме и клиент будет оповещен в любом случае. Иначе, обработчики добавляются в
28 28 /// список в порядке подписания и в этом же порядке они будут вызваны при выполнении
29 29 /// обещания.
30 30 /// </para>
31 31 /// <para>
32 32 /// Обрабатывая результаты обещания можно преобразовывать результаты либо инициировать
33 33 /// связанные асинхронные операции, которые также возвращают обещания. Для этого следует
34 34 /// использовать соответствующую форму методе <c>Then</c>.
35 35 /// </para>
36 36 /// <para>
37 37 /// Также хорошим правилом является то, что <c>Resolve</c> и <c>Reject</c> должен вызывать
38 38 /// только инициатор обещания иначе могут возникнуть противоречия.
39 39 /// </para>
40 40 /// </remarks>
41 41 public class Promise<T> : AbstractPromise<T>, IDeferred<T> {
42 42
43 43 public static IPromise<T> FromResult(T value) {
44 44 return new SuccessPromise<T>(value);
45 45 }
46 46
47 47 public static IPromise<T> FromException(Exception error) {
48 var p = new Promise<T>();
49 p.Reject(error);
50 return p;
48 return new FailedPromise<T>(error);
51 49 }
52 50
53 51 public virtual void Resolve(T value) {
54 52 SetResult(value);
55 53 }
56 54
57 55 public void Reject(Exception error) {
58 56 SetError(error);
59 57 }
60 58 }
61 59 }
@@ -1,128 +1,114
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5 using System.Text.RegularExpressions;
6 6 using System.Diagnostics;
7 7
8 8 namespace Implab
9 9 {
10 10 public static class Safe
11 11 {
12 12 public static void ArgumentAssert(bool condition, string paramName) {
13 13 if (!condition)
14 14 throw new ArgumentException("The parameter is invalid", paramName);
15 15 }
16 16
17 17 public static void ArgumentMatch(string value, string paramName, Regex rx) {
18 18 if (rx == null)
19 19 throw new ArgumentNullException("rx");
20 20 if (!rx.IsMatch(value))
21 21 throw new ArgumentException(String.Format("The prameter value must match {0}", rx), paramName);
22 22 }
23 23
24 24 public static void ArgumentNotEmpty(string value, string paramName) {
25 25 if (String.IsNullOrEmpty(value))
26 26 throw new ArgumentException("The parameter can't be empty", paramName);
27 27 }
28 28
29 29 public static void ArgumentNotEmpty<T>(T[] value, string paramName) {
30 30 if (value == null || value.Length == 0)
31 31 throw new ArgumentException("The array must be not emty", paramName);
32 32 }
33 33
34 34 public static void ArgumentNotNull(object value, string paramName) {
35 35 if (value == null)
36 36 throw new ArgumentNullException(paramName);
37 37 }
38 38
39 39 public static void ArgumentInRange(int value, int min, int max, string paramName) {
40 40 if (value < min || value > max)
41 41 throw new ArgumentOutOfRangeException(paramName);
42 42 }
43 43
44 44 public static void ArgumentOfType(object value, Type type, string paramName) {
45 45 if (!type.IsInstanceOfType(value))
46 46 throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName);
47 47 }
48 48
49 49 public static void Dispose(params IDisposable[] objects) {
50 50 foreach (var d in objects)
51 51 if (d != null)
52 52 d.Dispose();
53 53 }
54 54
55 55 public static void Dispose(params object[] objects) {
56 56 foreach (var obj in objects) {
57 57 var d = obj as IDisposable;
58 58 if (d != null)
59 59 d.Dispose();
60 60 }
61 61 }
62 62
63 63 public static void Dispose(object obj) {
64 64 var d = obj as IDisposable;
65 65 if (d != null)
66 66 d.Dispose();
67 67 }
68 68
69 69 [DebuggerStepThrough]
70 public static IPromise<T> WrapPromise<T>(Func<T> action) {
71 ArgumentNotNull(action, "action");
72
73 var p = new Promise<T>();
74 try {
75 p.Resolve(action());
76 } catch (Exception err) {
77 p.Reject(err);
78 }
79
80 return p;
81 }
82
83 [DebuggerStepThrough]
84 public static IPromise WrapPromise(Action action) {
85 ArgumentNotNull(action, "action");
86
87 var p = new Promise();
88 try {
89 action();
90 p.Resolve();
91 } catch (Exception err) {
92 p.Reject(err);
93 }
94
95 return p;
96 }
97
98 [DebuggerStepThrough]
99 public static IPromise InvokePromise(Func<IPromise> action) {
70 public static IPromise<T> Run<T>(Func<T> action) {
100 71 ArgumentNotNull(action, "action");
101 72
102 73 try {
103 var p = action();
104 if (p == null) {
105 var d = new Promise();
106 d.Reject(new Exception("The action returned null"));
107 p = d;
108 }
109 return p;
74 return Promise<T>.FromResult(action());
110 75 } catch (Exception err) {
111 var p = new Promise();
112 p.Reject(err);
113 return p;
76 return Promise<T>.FromException(err);
114 77 }
115 78 }
116 79
117 80 [DebuggerStepThrough]
118 public static IPromise<T> InvokePromise<T>(Func<IPromise<T>> action) {
81 public static IPromise Run(Action action) {
82 ArgumentNotNull(action, "action");
83
84 try {
85 action();
86 return Promise.SUCCESS;
87 } catch (Exception err) {
88 return new FailedPromise(err);
89 }
90 }
91
92 [DebuggerStepThrough]
93 public static IPromise Run(Func<IPromise> action) {
94 ArgumentNotNull(action, "action");
95
96 try {
97 return action() ?? new FailedPromise(new Exception("The action returned null"));
98 } catch (Exception err) {
99 return new FailedPromise(err);
100 }
101 }
102
103 [DebuggerStepThrough]
104 public static IPromise<T> Run<T>(Func<IPromise<T>> action) {
119 105 ArgumentNotNull(action, "action");
120 106
121 107 try {
122 108 return action() ?? Promise<T>.FromException(new Exception("The action returned null"));
123 109 } catch (Exception err) {
124 110 return Promise<T>.FromException(err);
125 111 }
126 112 }
127 113 }
128 114 }
@@ -1,111 +1,99
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class SuccessPromise : IPromise {
5 5 #region IPromise implementation
6 6
7 7 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
8 8 if (success != null) {
9 9 try {
10 10 success();
11 } catch(Exception err) {
12 if (error != null) {
13 try {
14 error(err);
15 11 // Analysis disable once EmptyGeneralCatchClause
16 12 } catch {
17 13 }
18 14 }
19 }
20 }
21 15 return this;
22 16 }
23 17
24 18 public IPromise On(Action success, Action<Exception> error) {
25 19 if (success != null) {
26 20 try {
27 21 success();
28 } catch(Exception err) {
29 if (error != null) {
30 try {
31 error(err);
32 22 // Analysis disable once EmptyGeneralCatchClause
33 23 } catch {
34 24 }
35 25 }
36 }
37 }
38 26 return this;
39 27 }
40 28
41 29 public IPromise On(Action success) {
42 30 if (success != null) {
43 31 try {
44 32 success();
45 33 // Analysis disable once EmptyGeneralCatchClause
46 34 } catch {
47 35 }
48 36 }
49 37 return this;
50 38 }
51 39
52 40 public IPromise On(Action handler, PromiseEventType events) {
53 41 if (handler != null && events.HasFlag(PromiseEventType.Success)) {
54 42 try {
55 43 handler();
56 44 // Analysis disable once EmptyGeneralCatchClause
57 45 } catch {
58 46 }
59 47 }
60 48 return this;
61 49 }
62 50
63 51 public IPromise<T> Cast<T>() {
64 52 throw new InvalidCastException();
65 53 }
66 54
67 55 public void Join() {
68 56 }
69 57
70 58 public void Join(int timeout) {
71 59 }
72 60
73 61 public Type PromiseType {
74 62 get {
75 63 return typeof(void);
76 64 }
77 65 }
78 66
79 67 public bool IsResolved {
80 68 get {
81 69 return true;
82 70 }
83 71 }
84 72
85 73 public bool IsCancelled {
86 74 get {
87 75 return false;
88 76 }
89 77 }
90 78
91 79 public Exception Error {
92 80 get {
93 81 return null;
94 82 }
95 83 }
96 84
97 85 #endregion
98 86
99 87 #region ICancellable implementation
100 88
101 89 public void Cancel() {
102 90 }
103 91
104 92 public void Cancel(Exception reason) {
105 93 }
106 94
107 95 #endregion
108 96
109 97 }
110 98 }
111 99
@@ -1,177 +1,153
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public class SuccessPromise<T> : IPromise<T> {
5 5 readonly T m_value;
6 6
7 7 public SuccessPromise(T value){
8 8 m_value = value;
9 9 }
10 10
11 11 public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
12 12 if (success != null) {
13 13 try {
14 14 success(m_value);
15 } catch(Exception err) {
16 if (error != null) {
17 try {
18 error(err);
19 15 // Analysis disable once EmptyGeneralCatchClause
20 16 } catch {
21 17 }
22 18 }
23 }
24 }
25 19 return this;
26 20 }
27 21
28 22 public IPromise<T> On(Action<T> success, Action<Exception> error) {
29 23 if (success != null) {
30 24 try {
31 25 success(m_value);
32 } catch(Exception err) {
33 if (error != null) {
34 try {
35 error(err);
36 26 // Analysis disable once EmptyGeneralCatchClause
37 27 } catch {
38 28 }
39 29 }
40 }
41 }
42 30 return this;
43 31 }
44 32
45 33 public IPromise<T> On(Action<T> success) {
46 34 if (success != null) {
47 35 try {
48 36 success(m_value);
49 37 // Analysis disable once EmptyGeneralCatchClause
50 38 } catch {
51 39 }
52 40 }
53 41 return this;
54 42 }
55 43
56 44 public T Join() {
57 45 return m_value;
58 46 }
59 47
60 48 public T Join(int timeout) {
61 49 return m_value;
62 50 }
63 51
64 52 public IPromise<T> On(Action success, Action<Exception> error, Action<Exception> cancel) {
65 53 if (success != null) {
66 54 try {
67 55 success();
68 } catch(Exception err) {
69 if (error != null) {
70 try {
71 error(err);
72 56 // Analysis disable once EmptyGeneralCatchClause
73 57 } catch {
74 58 }
75 59 }
76 }
77 }
78 60 return this;
79 61 }
80 62
81 63 public IPromise<T> On(Action success, Action<Exception> error) {
82 64 if (success != null) {
83 65 try {
84 66 success();
85 } catch(Exception err) {
86 if (error != null) {
87 try {
88 error(err);
89 67 // Analysis disable once EmptyGeneralCatchClause
90 68 } catch {
91 69 }
92 70 }
93 }
94 }
95 71 return this;
96 72 }
97 73
98 74 public IPromise<T> On(Action success) {
99 75 if (success != null) {
100 76 try {
101 77 success();
102 78 // Analysis disable once EmptyGeneralCatchClause
103 79 } catch {
104 80 }
105 81 }
106 82 return this;
107 83 }
108 84
109 85 public IPromise<T> On(Action handler, PromiseEventType events) {
110 86 if (handler != null && events.HasFlag(PromiseEventType.Success)) {
111 87 try {
112 88 handler();
113 89 // Analysis disable once EmptyGeneralCatchClause
114 90 } catch {
115 91 }
116 92 }
117 93 return this;
118 94 }
119 95
120 96 IPromise IPromise.On(Action success, Action<Exception> error, Action<Exception> cancel) {
121 97 return On(success, error, cancel);
122 98 }
123 99
124 100 IPromise IPromise.On(Action success, Action<Exception> error) {
125 101 return On(success, error);
126 102 }
127 103
128 104 IPromise IPromise.On(Action success) {
129 105 return On(success);
130 106 }
131 107
132 108 IPromise IPromise.On(Action handler, PromiseEventType events) {
133 109 return On(handler, events);
134 110 }
135 111
136 112 public IPromise<T2> Cast<T2>() {
137 113 return new SuccessPromise<T2>((T2)(object)m_value);
138 114 }
139 115
140 116 void IPromise.Join() {
141 117 }
142 118
143 119 void IPromise.Join(int timeout) {
144 120 }
145 121
146 122 public Type PromiseType {
147 123 get {
148 124 return typeof(T);
149 125 }
150 126 }
151 127
152 128 public bool IsResolved {
153 129 get {
154 130 return true;
155 131 }
156 132 }
157 133
158 134 public bool IsCancelled {
159 135 get {
160 136 return false;
161 137 }
162 138 }
163 139
164 140 public Exception Error {
165 141 get {
166 142 return null;
167 143 }
168 144 }
169 145
170 146 public void Cancel() {
171 147 }
172 148
173 149 public void Cancel(Exception reason) {
174 150 }
175 151 }
176 152 }
177 153
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