##// END OF EJS Templates
Implab.Test moved to xunit...
cin -
r249:d82909310094 v3
parent child
Show More
@@ -0,0 +1,17
1 using System;
2 using System.Threading;
3 using Xunit;
4
5 namespace Implab.Test
6 {
7 public class UnitTest1
8 {
9 [Fact]
10 public void Test1()
11 {
12 using(var cts = new CancellationTokenSource(1000)) {
13 PromiseHelper.Sleep(10000, cts.Token).Join();
14 }
15 }
16 }
17 }
@@ -1,88 +1,16
1 <?xml version="1.0" encoding="utf-8"?>
1 <Project Sdk="Microsoft.NET.Sdk">
2 <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2
3 <PropertyGroup>
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4 <TargetFramework>netcoreapp2.0</TargetFramework>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
5
6 <ProductVersion>8.0.30703</ProductVersion>
6 <IsPackable>false</IsPackable>
7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{63F92C0C-61BF-48C0-A377-8D67C3C661D0}</ProjectGuid>
9 <OutputType>Library</OutputType>
10 <AppDesignerFolder>Properties</AppDesignerFolder>
11 <RootNamespace>Implab.Test</RootNamespace>
12 <AssemblyName>Implab.Test</AssemblyName>
13 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
14 <FileAlignment>512</FileAlignment>
15 <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
16 <TargetFrameworkProfile />
17 </PropertyGroup>
18 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
19 <DebugSymbols>true</DebugSymbols>
20 <DebugType>full</DebugType>
21 <Optimize>false</Optimize>
22 <OutputPath>bin\Debug\</OutputPath>
23 <DefineConstants>DEBUG;TRACE</DefineConstants>
24 <ErrorReport>prompt</ErrorReport>
25 <WarningLevel>4</WarningLevel>
26 <Prefer32Bit>false</Prefer32Bit>
27 </PropertyGroup>
28 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
29 <DebugType>pdbonly</DebugType>
30 <Optimize>true</Optimize>
31 <OutputPath>bin\Release\</OutputPath>
32 <DefineConstants>TRACE</DefineConstants>
33 <ErrorReport>prompt</ErrorReport>
34 <WarningLevel>4</WarningLevel>
35 <Prefer32Bit>false</Prefer32Bit>
36 </PropertyGroup>
37 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
38 <DebugSymbols>true</DebugSymbols>
39 <DebugType>full</DebugType>
40 <Optimize>false</Optimize>
41 <OutputPath>bin\Debug\</OutputPath>
42 <DefineConstants>DEBUG;TRACE</DefineConstants>
43 <ErrorReport>prompt</ErrorReport>
44 <WarningLevel>4</WarningLevel>
45 <Prefer32Bit>false</Prefer32Bit>
46 </PropertyGroup>
47 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
48 <DebugType>pdbonly</DebugType>
49 <Optimize>true</Optimize>
50 <OutputPath>bin\Release\</OutputPath>
51 <DefineConstants>TRACE</DefineConstants>
52 <ErrorReport>prompt</ErrorReport>
53 <WarningLevel>4</WarningLevel>
54 <Prefer32Bit>false</Prefer32Bit>
55 </PropertyGroup>
7 </PropertyGroup>
56 <ItemGroup>
8 <ItemGroup>
57 <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
9 <ProjectReference Include="../Implab/Implab.csproj"/>
58 <Reference Include="System" />
10 <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
59 <Reference Include="System.Core">
11 <PackageReference Include="xunit" Version="2.3.1" />
60 <RequiredTargetFramework>3.5</RequiredTargetFramework>
12 <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
61 </Reference>
13 <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
62 </ItemGroup>
63 <ItemGroup>
64 <Compile Include="AsyncTests.cs" />
65 <Compile Include="CancelationTests.cs" />
66 <Compile Include="Mock\MockPollingComponent.cs" />
67 <Compile Include="Mock\MockRunnableComponent.cs" />
68 <Compile Include="PollingComponentTests.cs" />
69 <Compile Include="PromiseHelper.cs" />
70 <Compile Include="Properties\AssemblyInfo.cs" />
71 <Compile Include="RunnableComponentTests.cs" />
72 </ItemGroup>
14 </ItemGroup>
73 <ItemGroup>
15
74 <ProjectReference Include="..\Implab\Implab.csproj">
16 </Project>
75 <Project>{99B95D0D-9CF9-4F70-8ADF-F4D0AA5CB0D9}</Project>
76 <Name>Implab</Name>
77 </ProjectReference>
78 </ItemGroup>
79 <ItemGroup />
80 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
81 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
82 Other similar extension points exist, see Microsoft.Common.targets.
83 <Target Name="BeforeBuild">
84 </Target>
85 <Target Name="AfterBuild">
86 </Target>
87 -->
88 </Project> No newline at end of file
@@ -1,22 +1,40
1 using Implab.Parallels;
1 using Implab;
2 using System;
2 using System.Threading;
3 using System.Threading;
3
4
4 namespace Implab.Test {
5 namespace Implab.Test {
5 static class PromiseHelper {
6 static class PromiseHelper {
6 public static IPromise<T> Sleep<T>(int timeout, T retVal) {
7 public static IPromise<T> Sleep<T>(int timeout, T retVal, CancellationToken ct = default(CancellationToken)) {
7 return AsyncPool.Invoke((ct) => {
8
8 ct.CancellationRequested(ct.CancelOperation);
9 Timer timer = null;
9 Thread.Sleep(timeout);
10
10 return retVal;
11 return Promise.Create<T>((d) => {
12 timer = new Timer(x => {
13 d.Resolve(retVal);
14 }, null, timeout, Timeout.Infinite);
15
16 if(ct.CanBeCanceled)
17 ct.Register(d.Cancel);
18
19 }).Finally(() => {
20 Safe.Dispose(timer);
11 });
21 });
12 }
22 }
13
23
14 public static IPromise Sleep(int timeout) {
24 public static IPromise Sleep(int timeout, CancellationToken ct = default(CancellationToken)) {
15 return AsyncPool.Invoke((ct) => {
25 Timer timer = null;
16 ct.CancellationRequested(ct.CancelOperation);
26
17 Thread.Sleep(timeout);
27 return Promise.Create((d) => {
18 return 0;
28 timer = new Timer(x => {
29 d.Resolve();
30 }, null, timeout, Timeout.Infinite);
31
32 if(ct.CanBeCanceled)
33 ct.Register(d.Cancel);
34
35 }).Finally(() => {
36 Safe.Dispose(timer);
19 });
37 });
20 }
38 }
21 }
39 }
22 }
40 }
@@ -1,58 +1,53
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3
3
4 namespace Implab {
4 namespace Implab {
5 /// <summary>
5 /// <summary>
6 /// This class is responsible for the promise resolution, dispatching and chaining
6 /// This class is responsible for the promise resolution, dispatching and chaining
7 /// </summary>
7 /// </summary>
8 public class Deferred : IResolvable {
8 public class Deferred : IResolvable {
9
9
10 readonly Promise m_promise;
10 readonly Promise m_promise;
11 readonly IDispatcher m_dispatcher;
11 internal Deferred() {
12
12 m_promise = new Promise();
13 internal Deferred(IDispatcher dispatcher) : this(new Promise(), dispatcher) {
14 }
13 }
15
14
16 internal Deferred(Promise promise, IDispatcher dispatcher) {
15 internal Deferred(Promise promise, IDispatcher dispatcher) {
17 Debug.Assert(promise != null);
16 Debug.Assert(promise != null);
18 m_promise = promise;
17 m_promise = promise;
19 m_dispatcher = dispatcher;
20 }
18 }
21
19
22 public IPromise Promise {
20 public IPromise Promise {
23 get { return m_promise; }
21 get { return m_promise; }
24 }
22 }
25
23
26 public void Reject(Exception error) {
24 public void Cancel() {
25 Reject(new OperationCanceledException());
26 }
27
28 public virtual void Reject(Exception error) {
27 if (error is PromiseTransientException)
29 if (error is PromiseTransientException)
28 error = ((PromiseTransientException)error).InnerException;
30 error = ((PromiseTransientException)error).InnerException;
29
31
30 m_promise.RejectPromise(error);
32 m_promise.RejectPromise(error);
31 }
33 }
32
34
33 public void Resolve() {
35 public virtual void Resolve() {
34 m_promise.ResolvePromise();
36 m_promise.ResolvePromise();
35 }
37 }
36
38
37 public void Resolve(IPromise thenable) {
39 public virtual void Resolve(IPromise thenable) {
38 if (thenable == null)
40 if (thenable == null)
39 Reject(new Exception("The promise or task are expected"));
41 Reject(new Exception("The promise or task are expected"));
40 if (thenable == m_promise)
42 if (thenable == m_promise)
41 Reject(new Exception("The promise cannot be resolved with oneself"));
43 Reject(new Exception("The promise cannot be resolved with oneself"));
42
44
43 else if (m_dispatcher != null)
44 // dispatch (see ecma-262/6.0: 25.4.1.3.2 Promise Resolve Functions)
45 m_dispatcher.Enqueue(Chain, thenable);
46 else
47 Chain(thenable);
48 }
49
50 void Chain(IPromise thenable) {
51 try {
45 try {
52 thenable.Then(this);
46 thenable.Then(this);
53 } catch (Exception err) {
47 } catch (Exception err) {
54 Reject(err);
48 Reject(err);
55 }
49 }
56 }
50 }
51
57 }
52 }
58 } No newline at end of file
53 }
@@ -1,54 +1,49
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3
3
4 namespace Implab {
4 namespace Implab {
5 public class Deferred<T> : IResolvable<T> {
5 public class Deferred<T> : IResolvable<T> {
6 readonly Promise<T> m_promise;
6 readonly Promise<T> m_promise;
7 readonly IDispatcher m_dispatcher;
8
7
9 internal Deferred(IDispatcher dispatcher) : this(new Promise<T>(), dispatcher) {
8 internal Deferred() {
9 m_promise = new Promise<T>();
10 }
10 }
11
11
12 internal Deferred(Promise<T> promise, IDispatcher dispatcher) {
12 protected Deferred(Promise<T> promise) {
13 Debug.Assert(promise != null);
13 Debug.Assert(promise != null);
14 m_promise = promise;
14 m_promise = promise;
15 m_dispatcher = dispatcher;
16 }
15 }
17
16
18 public IPromise<T> Promise {
17 public IPromise<T> Promise {
19 get { return m_promise; }
18 get { return m_promise; }
20 }
19 }
21
20
22 public void Reject(Exception error) {
21 public void Cancel() {
22 Reject(new OperationCanceledException());
23 }
24
25 public virtual void Reject(Exception error) {
23 if (error is PromiseTransientException)
26 if (error is PromiseTransientException)
24 error = ((PromiseTransientException)error).InnerException;
27 error = ((PromiseTransientException)error).InnerException;
25
28
26 m_promise.RejectPromise(error);
29 m_promise.RejectPromise(error);
27 }
30 }
28
31
29 public void Resolve(T value) {
32 public virtual void Resolve(T value) {
30 m_promise.ResolvePromise(value);
33 m_promise.ResolvePromise(value);
31 }
34 }
32
35
33 public void Resolve(IPromise<T> thenable) {
36 public virtual void Resolve(IPromise<T> thenable) {
34 if (thenable == null)
37 if (thenable == null)
35 Reject(new Exception("The promise or task are expected"));
38 Reject(new Exception("The promise or task are expected"));
36 if (thenable == m_promise)
39 if (thenable == m_promise)
37 Reject(new Exception("The promise cannot be resolved with oneself"));
40 Reject(new Exception("The promise cannot be resolved with oneself"));
38
41
39 else if (m_dispatcher != null)
40 // dispatch (see ecma-262/6.0: 25.4.1.3.2 Promise Resolve Functions)
41 m_dispatcher.Enqueue(Chain, thenable);
42 else
43 Chain(thenable);
44 }
45
46 void Chain(IPromise<T> thenable) {
47 try {
42 try {
48 thenable.Then(this);
43 thenable.Then(this);
49 } catch (Exception err) {
44 } catch (Exception err) {
50 Reject(err);
45 Reject(err);
51 }
46 }
52 }
47 }
53 }
48 }
54 } No newline at end of file
49 }
@@ -1,18 +1,21
1 using System;
1 using System;
2 using System.Reflection;
2 using System.Reflection;
3 using System.Runtime.ExceptionServices;
3 using System.Runtime.ExceptionServices;
4
4
5 namespace Implab {
5 namespace Implab {
6 public static class ExceptionHelpers {
6 static class ExceptionHelpers {
7 public static void Rethrow(this Exception that) {
7 public static Exception Rethrow(this Exception that) {
8 ExceptionDispatchInfo.Capture(that).Throw();
8 ExceptionDispatchInfo.Capture(that).Throw();
9 return new TargetInvocationException(that);
9 }
10 }
10
11
11 public static void ThrowInvocationException(this Exception that) {
12 public static Exception Wrap(this Exception that) {
12 if (that is OperationCanceledException)
13 if (that == null)
13 throw new OperationCanceledException("Operation cancelled", that);
14 return new Exception();
15 else if (that is OperationCanceledException)
16 return new OperationCanceledException("The operation has been cancelled", that);
14 else
17 else
15 throw new TargetInvocationException(that);
18 return new TargetInvocationException(that);
16 }
19 }
17 }
20 }
18 } No newline at end of file
21 }
@@ -1,209 +1,208
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Diagnostics;
3 using System.Diagnostics;
4 using System.Reflection;
4 using System.Reflection;
5 using System.Threading.Tasks;
5 using System.Threading.Tasks;
6 using Implab.Parallels;
6 using Implab.Parallels;
7
7
8 namespace Implab {
8 namespace Implab {
9 public class Promise : AbstractEvent<IResolvable>, IPromise {
9 public class Promise : AbstractEvent<IResolvable>, IPromise {
10 public static IDispatcher DefaultDispatcher {
10 public static IDispatcher DefaultDispatcher {
11 get {
11 get {
12 return ThreadPoolDispatcher.Instance;
12 return ThreadPoolDispatcher.Instance;
13 }
13 }
14 }
14 }
15
15
16 class ResolvableSignal : IResolvable {
16 class ResolvableSignal : IResolvable {
17 public Signal Signal { get; private set; }
17 public Signal Signal { get; private set; }
18 public ResolvableSignal() {
18 public ResolvableSignal() {
19 Signal = new Signal();
19 Signal = new Signal();
20 }
20 }
21
21
22
22
23 public void Reject(Exception error) {
23 public void Reject(Exception error) {
24 Signal.Set();
24 Signal.Set();
25 }
25 }
26
26
27 public void Resolve() {
27 public void Resolve() {
28 Signal.Set();
28 Signal.Set();
29 }
29 }
30 }
30 }
31
31
32 PromiseState m_state;
32 PromiseState m_state;
33
33
34 Exception m_error;
34 Exception m_error;
35
35
36 public bool IsRejected {
36 public bool IsRejected {
37 get {
37 get {
38 return m_state == PromiseState.Rejected;
38 return m_state == PromiseState.Rejected;
39 }
39 }
40 }
40 }
41
41
42 public bool IsFulfilled {
42 public bool IsFulfilled {
43 get {
43 get {
44 return m_state == PromiseState.Fulfilled;
44 return m_state == PromiseState.Fulfilled;
45 }
45 }
46 }
46 }
47
47
48 public Exception RejectReason {
48 public Exception RejectReason {
49 get {
49 get {
50 return m_error;
50 return m_error;
51 }
51 }
52 }
52 }
53
53
54 internal Promise() {
54 internal Promise() {
55
55
56 }
56 }
57
57
58 internal void ResolvePromise() {
58 internal void ResolvePromise() {
59 if (BeginTransit()) {
59 if (BeginTransit()) {
60 m_state = PromiseState.Fulfilled;
60 m_state = PromiseState.Fulfilled;
61 CompleteTransit();
61 CompleteTransit();
62 }
62 }
63 }
63 }
64
64
65 internal void RejectPromise(Exception reason) {
65 internal void RejectPromise(Exception reason) {
66 if (BeginTransit()) {
66 if (BeginTransit()) {
67 m_error = reason;
67 m_error = reason;
68 m_state = PromiseState.Rejected;
68 m_state = PromiseState.Rejected;
69 CompleteTransit();
69 CompleteTransit();
70 }
70 }
71 }
71 }
72
72
73
73
74 #region implemented abstract members of AbstractPromise
74 #region implemented abstract members of AbstractPromise
75
75
76 protected override void SignalHandler(IResolvable handler) {
76 protected override void SignalHandler(IResolvable handler) {
77 switch (m_state) {
77 switch (m_state) {
78 case PromiseState.Fulfilled:
78 case PromiseState.Fulfilled:
79 handler.Resolve();
79 handler.Resolve();
80 break;
80 break;
81 case PromiseState.Rejected:
81 case PromiseState.Rejected:
82 handler.Reject(RejectReason);
82 handler.Reject(RejectReason);
83 break;
83 break;
84 default:
84 default:
85 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state));
85 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state));
86 }
86 }
87 }
87 }
88
88
89 protected void WaitResult(int timeout) {
89 protected void WaitResult(int timeout) {
90 if (!(IsResolved || GetFulfillSignal().Wait(timeout)))
90 if (!(IsResolved || GetFulfillSignal().Wait(timeout)))
91 throw new TimeoutException();
91 throw new TimeoutException();
92 }
92 }
93
93
94 protected Signal GetFulfillSignal() {
94 protected Signal GetFulfillSignal() {
95 var next = new ResolvableSignal();
95 var next = new ResolvableSignal();
96 Then(next);
96 Then(next);
97 return next.Signal;
97 return next.Signal;
98 }
98 }
99
99
100 #endregion
100 #endregion
101
101
102
102
103 public Type ResultType {
103 public Type ResultType {
104 get {
104 get {
105 return typeof(void);
105 return typeof(void);
106 }
106 }
107 }
107 }
108
108
109
109
110 protected void Rethrow() {
110 protected void Rethrow() {
111 Debug.Assert(m_error != null);
111 Debug.Assert(m_error != null);
112 if (m_error is OperationCanceledException)
112 if (m_error is OperationCanceledException)
113 throw new OperationCanceledException("Operation cancelled", m_error);
113 throw new OperationCanceledException("Operation cancelled", m_error);
114 else
114 else
115 throw new TargetInvocationException(m_error);
115 throw new TargetInvocationException(m_error);
116 }
116 }
117
117
118 public void Then(IResolvable next) {
118 public void Then(IResolvable next) {
119 AddHandler(next);
119 AddHandler(next);
120 }
120 }
121
121
122 public IPromise<T> Cast<T>() {
122 public IPromise<T> Cast<T>() {
123 throw new InvalidCastException();
123 throw new InvalidCastException();
124 }
124 }
125
125
126 public void Join() {
126 public void Join() {
127 WaitResult(-1);
127 WaitResult(-1);
128 if (IsRejected)
128 if (IsRejected)
129 Rethrow();
129 Rethrow();
130 }
130 }
131
131
132 public void Join(int timeout) {
132 public void Join(int timeout) {
133 WaitResult(timeout);
133 WaitResult(timeout);
134 if (IsRejected)
134 if (IsRejected)
135 Rethrow();
135 Rethrow();
136 }
136 }
137
137
138 public static ResolvedPromise Resolve() {
138 public static ResolvedPromise Resolve() {
139 return new ResolvedPromise();
139 return new ResolvedPromise();
140 }
140 }
141
141
142 public static ResolvedPromise<T> Resolve<T>(T result) {
142 public static ResolvedPromise<T> Resolve<T>(T result) {
143 return new ResolvedPromise<T>(result);
143 return new ResolvedPromise<T>(result);
144 }
144 }
145
145
146 public static RejectedPromise Reject(Exception reason) {
146 public static RejectedPromise Reject(Exception reason) {
147 return new RejectedPromise(reason);
147 return new RejectedPromise(reason);
148 }
148 }
149
149
150 public static RejectedPromise<T> Reject<T>(Exception reason) {
150 public static RejectedPromise<T> Reject<T>(Exception reason) {
151 return new RejectedPromise<T>(reason);
151 return new RejectedPromise<T>(reason);
152 }
152 }
153
153
154 public static IPromise Create(PromiseExecutor executor) {
154 public static IPromise Create(PromiseExecutor executor) {
155 Safe.ArgumentNotNull(executor, nameof(executor));
155 Safe.ArgumentNotNull(executor, nameof(executor));
156
156
157 var p = new Promise();
157 var p = new Promise();
158 var d = new Deferred(p, DefaultDispatcher);
158 var d = new Deferred(p, DefaultDispatcher);
159
159
160 try {
160 try {
161 executor(d);
161 executor(d);
162 } catch (Exception e) {
162 } catch (Exception e) {
163 d.Reject(e);
163 d.Reject(e);
164 }
164 }
165
165
166 return d.Promise;
166 return d.Promise;
167 }
167 }
168
168
169 public static IPromise<T> Create<T>(PromiseExecutor<T> executor) {
169 public static IPromise<T> Create<T>(PromiseExecutor<T> executor) {
170 Safe.ArgumentNotNull(executor, nameof(executor));
170 Safe.ArgumentNotNull(executor, nameof(executor));
171
171
172 var p = new Promise<T>();
172 var d = new Deferred<T>();
173 var d = new Deferred<T>(p, DefaultDispatcher);
174
173
175 try {
174 try {
176 executor(d);
175 executor(d);
177 } catch (Exception e) {
176 } catch (Exception e) {
178 d.Reject(e);
177 d.Reject(e);
179 }
178 }
180
179
181 return d.Promise;
180 return d.Promise;
182 }
181 }
183
182
184 public static IPromise All(IEnumerable<IPromise> promises) {
183 public static IPromise All(IEnumerable<IPromise> promises) {
185 var d = new Deferred(DefaultDispatcher);
184 var d = new Deferred();
186 var all = new PromiseAll(d);
185 var all = new PromiseAll(d);
187 foreach (var promise in promises) {
186 foreach (var promise in promises) {
188 all.AddPromise(promise);
187 all.AddPromise(promise);
189 if (all.Done)
188 if (all.Done)
190 break;
189 break;
191 }
190 }
192 all.Complete();
191 all.Complete();
193 return all.ResultPromise;
192 return all.ResultPromise;
194 }
193 }
195
194
196 public static IPromise<T[]> All<T>(IEnumerable<IPromise<T>> promises, Func<T, IPromise> cleanup, Action cancel) {
195 public static IPromise<T[]> All<T>(IEnumerable<IPromise<T>> promises, Func<T, IPromise> cleanup = null, Action cancel = null) {
197 var d = new Deferred<T[]>(DefaultDispatcher);
196 var d = new Deferred<T[]>();
198 var all = new PromiseAll<T>(d, cleanup, cancel);
197 var all = new PromiseAll<T>(d, cleanup, cancel);
199 foreach (var promise in promises) {
198 foreach (var promise in promises) {
200 all.AddPromise(promise);
199 all.AddPromise(promise);
201 if (all.Done)
200 if (all.Done)
202 break;
201 break;
203 }
202 }
204 all.Complete();
203 all.Complete();
205 return all.ResultPromise;
204 return all.ResultPromise;
206 }
205 }
207 }
206 }
208 }
207 }
209
208
@@ -1,57 +1,92
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3
3
4 namespace Implab {
4 namespace Implab {
5 class PromiseActionReaction : PromiseReaction {
5 class PromiseActionReaction : IResolvable {
6
6
7 readonly Deferred m_next;
7 readonly Deferred m_next;
8
8
9 readonly IDispatcher m_dispatcher;
10
11 readonly Action<Deferred> m_fulfilled;
12
13 readonly Action<Exception, Deferred> m_rejected;
14
9 public IPromise Promise {
15 public IPromise Promise {
10 get { return m_next.Promise; }
16 get { return m_next.Promise; }
11 }
17 }
12
18
13 public PromiseActionReaction(Action fulfilled, Action<Exception> rejected, IDispatcher dispatcher) : base(dispatcher) {
19 public PromiseActionReaction(Action<Deferred> fulfilled, Action<Exception, Deferred> rejected, Deferred next, IDispatcher dispatcher) {
14 m_next = new Deferred(dispatcher);
20 m_next = next;
15 if (fulfilled != null)
21 m_fulfilled = fulfilled;
16 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
22 m_rejected = rejected;
17
23 m_dispatcher = dispatcher;
18 if (rejected != null)
19 RejectHandler = PromiseHandler.Create(rejected, m_next);
20 }
21
22 public PromiseActionReaction(Func<IPromise> fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) : base(dispatcher) {
23 m_next = new Deferred(dispatcher);
24 if (fulfilled != null)
25 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
26
27 if (rejected != null)
28 RejectHandler = PromiseHandler.Create(rejected, m_next);
29 }
24 }
30
25
31 public PromiseActionReaction(Action fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) : base(dispatcher) {
26 public void Resolve() {
32 m_next = new Deferred(dispatcher);
27 if (m_fulfilled != null) {
33 if (fulfilled != null)
28 if (m_dispatcher != null)
34 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
29 m_dispatcher.Enqueue(ResolveImpl);
35
30 else
36 if (rejected != null)
31 ResolveImpl();
37 RejectHandler = PromiseHandler.Create(rejected, m_next);
32 } else {
38 }
39
40 public PromiseActionReaction(Func<IPromise> fulfilled, Action<Exception> rejected, IDispatcher dispatcher) : base(dispatcher) {
41 m_next = new Deferred(dispatcher);
42 if (fulfilled != null)
43 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
44
45 if (rejected != null)
46 RejectHandler = PromiseHandler.Create(rejected, m_next);
47 }
48
49 protected override void DefaultReject(Exception reason) {
50 m_next.Reject(reason);
51 }
52
53 protected override void DefaultResolve() {
54 m_next.Resolve();
33 m_next.Resolve();
55 }
34 }
56 }
35 }
36
37 void ResolveImpl() {
38 m_fulfilled(m_next);
39 }
40
41 public void Reject(Exception error) {
42 if (m_fulfilled != null) {
43 if (m_dispatcher != null)
44 m_dispatcher.Enqueue(RejectImpl, error);
45 else
46 RejectImpl(error);
47 } else {
48 m_next.Reject(error);
49 }
50 }
51
52 void RejectImpl(Exception error) {
53 m_rejected(error, m_next);
54 }
55
56 public static PromiseActionReaction Create(Action fulfilled, Action<Exception> rejected, IDispatcher dispatcher) {
57 return new PromiseActionReaction(
58 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
59 rejected != null ? PromiseHandler.Create(rejected) : null,
60 new Deferred(),
61 dispatcher
62 );
63 }
64
65 public static PromiseActionReaction Create(Func<IPromise> fulfilled, Action<Exception> rejected, IDispatcher dispatcher) {
66 return new PromiseActionReaction(
67 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
68 rejected != null ? PromiseHandler.Create(rejected) : null,
69 new Deferred(),
70 dispatcher
71 );
72 }
73
74 public static PromiseActionReaction Create(Action fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) {
75 return new PromiseActionReaction(
76 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
77 rejected != null ? PromiseHandler.Create(rejected) : null,
78 new Deferred(),
79 dispatcher
80 );
81 }
82
83 public static PromiseActionReaction Create(Func<IPromise> fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) {
84 return new PromiseActionReaction(
85 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
86 rejected != null ? PromiseHandler.Create(rejected) : null,
87 new Deferred(),
88 dispatcher
89 );
90 }
91 }
57 } No newline at end of file
92 }
@@ -1,56 +1,91
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3
3
4 namespace Implab {
4 namespace Implab {
5 class PromiseActionReaction<T> : PromiseReaction<T> {
5 class PromiseActionReaction<T> : IResolvable<T> {
6 readonly Deferred m_next;
6 readonly Deferred m_next;
7
7
8 readonly IDispatcher m_dispatcher;
9
10 readonly Action<T, Deferred> m_fulfilled;
11
12 readonly Action<Exception, Deferred> m_rejected;
13
8 public IPromise Promise {
14 public IPromise Promise {
9 get { return m_next.Promise; }
15 get { return m_next.Promise; }
10 }
16 }
11
17
12 public PromiseActionReaction(Action<T> fulfilled, Action<Exception> rejected, IDispatcher dispatcher) : base(dispatcher) {
18 public PromiseActionReaction(Action<T, Deferred> fulfilled, Action<Exception, Deferred> rejected, Deferred next, IDispatcher dispatcher) {
13 m_next = new Deferred(dispatcher);
19 m_next = next;
14 if (fulfilled != null)
20 m_fulfilled = fulfilled;
15 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
21 m_rejected = rejected;
16
22 m_dispatcher = dispatcher;
17 if (rejected != null)
18 RejectHandler = PromiseHandler.Create(rejected, m_next);
19 }
20
21 public PromiseActionReaction(Func<T, IPromise> fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) : base(dispatcher) {
22 m_next = new Deferred(dispatcher);
23 if (fulfilled != null)
24 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
25
26 if (rejected != null)
27 RejectHandler = PromiseHandler.Create(rejected, m_next);
28 }
23 }
29
24
30 public PromiseActionReaction(Action<T> fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) : base(dispatcher) {
25 public void Resolve(T result) {
31 m_next = new Deferred(dispatcher);
26 if (m_fulfilled != null) {
32 if (fulfilled != null)
27 if (m_dispatcher != null)
33 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
28 m_dispatcher.Enqueue(ResolveImpl, result);
34
29 else
35 if (rejected != null)
30 ResolveImpl(result);
36 RejectHandler = PromiseHandler.Create(rejected, m_next);
31 } else {
37 }
38
39 public PromiseActionReaction(Func<T, IPromise> fulfilled, Action<Exception> rejected, IDispatcher dispatcher) : base(dispatcher) {
40 m_next = new Deferred(dispatcher);
41 if (fulfilled != null)
42 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
43
44 if (rejected != null)
45 RejectHandler = PromiseHandler.Create(rejected, m_next);
46 }
47
48 protected override void DefaultReject(Exception reason) {
49 m_next.Reject(reason);
50 }
51
52 protected override void DefaultResolve(T result) {
53 m_next.Resolve();
32 m_next.Resolve();
54 }
33 }
55 }
34 }
35
36 void ResolveImpl (T result) {
37 m_fulfilled(result, m_next);
38 }
39
40 public void Reject(Exception error) {
41 if (m_fulfilled != null) {
42 if (m_dispatcher != null)
43 m_dispatcher.Enqueue(RejectImpl, error);
44 else
45 RejectImpl(error);
46 } else {
47 m_next.Reject(error);
48 }
49 }
50
51 void RejectImpl(Exception error) {
52 m_rejected(error, m_next);
53 }
54
55 public static PromiseActionReaction<T> Create(Action<T> fulfilled, Action<Exception> rejected, IDispatcher dispatcher) {
56 return new PromiseActionReaction<T>(
57 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
58 rejected != null ? PromiseHandler.Create(rejected) : null,
59 new Deferred(),
60 dispatcher
61 );
62 }
63
64 public static PromiseActionReaction<T> Create(Func<T,IPromise> fulfilled, Action<Exception> rejected, IDispatcher dispatcher) {
65 return new PromiseActionReaction<T>(
66 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
67 rejected != null ? PromiseHandler.Create(rejected) : null,
68 new Deferred(),
69 dispatcher
70 );
71 }
72
73 public static PromiseActionReaction<T> Create(Action<T> fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) {
74 return new PromiseActionReaction<T>(
75 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
76 rejected != null ? PromiseHandler.Create(rejected) : null,
77 new Deferred(),
78 dispatcher
79 );
80 }
81
82 public static PromiseActionReaction<T> Create(Func<T,IPromise> fulfilled, Func<Exception, IPromise> rejected, IDispatcher dispatcher) {
83 return new PromiseActionReaction<T>(
84 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
85 rejected != null ? PromiseHandler.Create(rejected) : null,
86 new Deferred(),
87 dispatcher
88 );
89 }
90 }
56 } No newline at end of file
91 }
@@ -1,131 +1,217
1 using System.Threading;
1 using System.Threading;
2 using System;
2 using System;
3 using Implab.Diagnostics;
3 using Implab.Diagnostics;
4 using System.Collections.Generic;
4 using System.Collections.Generic;
5 using System.Linq;
5 using System.Linq;
6
6
7 namespace Implab {
7 namespace Implab {
8 public static class PromiseExtensions {
8 public static class PromiseExtensions {
9
9
10 public static IPromise Then(this IPromise that, Action fulfilled, Action<Exception> rejected) {
10 public static IPromise Then(this IPromise that, Action fulfilled, Action<Exception> rejected) {
11 var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher);
11 var reaction = PromiseActionReaction.Create(fulfilled, rejected, Promise.DefaultDispatcher);
12 that.Then(reaction);
13 return reaction.Promise;
14 }
15
16 public static IPromise Then(this IPromise that, Action fulfilled) {
17 var reaction = PromiseActionReaction.Create(fulfilled, null, Promise.DefaultDispatcher);
12 that.Then(reaction);
18 that.Then(reaction);
13 return reaction.Promise;
19 return reaction.Promise;
14 }
20 }
15
21
16 public static IPromise Then(this IPromise that, Action fulfilled, Func<Exception, IPromise> rejected) {
22 public static IPromise Then(this IPromise that, Action fulfilled, Func<Exception, IPromise> rejected) {
17 var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher);
23 var reaction = PromiseActionReaction.Create(fulfilled, rejected, Promise.DefaultDispatcher);
18 that.Then(reaction);
24 that.Then(reaction);
19 return reaction.Promise;
25 return reaction.Promise;
20 }
26 }
21
27
22 public static IPromise Then(this IPromise that, Func<IPromise> fulfilled, Action<Exception> rejected) {
28 public static IPromise Then(this IPromise that, Func<IPromise> fulfilled, Action<Exception> rejected) {
23 var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher);
29 var reaction = PromiseActionReaction.Create(fulfilled, rejected, Promise.DefaultDispatcher);
30 that.Then(reaction);
31 return reaction.Promise;
32 }
33
34 public static IPromise Then(this IPromise that, Func<IPromise> fulfilled) {
35 var reaction = PromiseActionReaction.Create(fulfilled, null, Promise.DefaultDispatcher);
24 that.Then(reaction);
36 that.Then(reaction);
25 return reaction.Promise;
37 return reaction.Promise;
26 }
38 }
27
39
28 public static IPromise Then(this IPromise that, Func<IPromise> fulfilled, Func<Exception, IPromise> rejected) {
40 public static IPromise Then(this IPromise that, Func<IPromise> fulfilled, Func<Exception, IPromise> rejected) {
29 var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher);
41 var reaction = PromiseActionReaction.Create(fulfilled, rejected, Promise.DefaultDispatcher);
30 that.Then(reaction);
42 that.Then(reaction);
31 return reaction.Promise;
43 return reaction.Promise;
32 }
44 }
33
45
34 public static IPromise Then<T>(this IPromise<T> that, Action<T> fulfilled, Action<Exception> rejected) {
46 public static IPromise Then<T>(this IPromise<T> that, Action<T> fulfilled, Action<Exception> rejected) {
35 var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher);
47 var reaction = PromiseActionReaction<T>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
48 that.Then(reaction);
49 return reaction.Promise;
50 }
51
52 public static IPromise Then<T>(this IPromise<T> that, Action<T> fulfilled) {
53 var reaction = PromiseActionReaction<T>.Create(fulfilled, null, Promise.DefaultDispatcher);
36 that.Then(reaction);
54 that.Then(reaction);
37 return reaction.Promise;
55 return reaction.Promise;
38 }
56 }
39
57
40 public static IPromise Then<T>(this IPromise<T> that, Action<T> fulfilled, Func<Exception, IPromise> rejected) {
58 public static IPromise Then<T>(this IPromise<T> that, Action<T> fulfilled, Func<Exception, IPromise> rejected) {
41 var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher);
59 var reaction = PromiseActionReaction<T>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
42 that.Then(reaction);
60 that.Then(reaction);
43 return reaction.Promise;
61 return reaction.Promise;
44 }
62 }
45
63
46 public static IPromise Then<T>(this IPromise<T> that, Func<T, IPromise> fulfilled, Action<Exception> rejected) {
64 public static IPromise Then<T>(this IPromise<T> that, Func<T, IPromise> fulfilled, Action<Exception> rejected) {
47 var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher);
65 var reaction = PromiseActionReaction<T>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
66 that.Then(reaction);
67 return reaction.Promise;
68 }
69
70 public static IPromise Then<T>(this IPromise<T> that, Func<T, IPromise> fulfilled) {
71 var reaction = PromiseActionReaction<T>.Create(fulfilled, null, Promise.DefaultDispatcher);
48 that.Then(reaction);
72 that.Then(reaction);
49 return reaction.Promise;
73 return reaction.Promise;
50 }
74 }
51
75
52 public static IPromise Then<T>(this IPromise<T> that, Func<T, IPromise> fulfilled, Func<Exception, IPromise> rejected) {
76 public static IPromise Then<T>(this IPromise<T> that, Func<T, IPromise> fulfilled, Func<Exception, IPromise> rejected) {
53 var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher);
77 var reaction = PromiseActionReaction<T>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
54 that.Then(reaction);
78 that.Then(reaction);
55 return reaction.Promise;
79 return reaction.Promise;
56 }
80 }
57
81
58 public static IPromise<Tout> Then<Tout>(this IPromise that, Func<Tout> fulfilled, Func<Exception, Tout> rejected) {
82 public static IPromise<Tout> Then<Tout>(this IPromise that, Func<Tout> fulfilled, Func<Exception, Tout> rejected) {
59 var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher);
83 var reaction = PromiseFuncReaction<Tout>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
84 that.Then(reaction);
85 return reaction.Promise;
86 }
87
88 public static IPromise<Tout> Then<Tout>(this IPromise that, Func<Tout> fulfilled) {
89 var reaction = PromiseFuncReaction<Tout>.Create(fulfilled, (Func<Exception, Tout>)null, Promise.DefaultDispatcher);
60 that.Then(reaction);
90 that.Then(reaction);
61 return reaction.Promise;
91 return reaction.Promise;
62 }
92 }
63
93
64 public static IPromise<Tout> Then<Tout>(this IPromise that, Func<Tout> fulfilled, Func<Exception, IPromise<Tout>> rejected) {
94 public static IPromise<Tout> Then<Tout>(this IPromise that, Func<Tout> fulfilled, Func<Exception, IPromise<Tout>> rejected) {
65 var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher);
95 var reaction = PromiseFuncReaction<Tout>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
66 that.Then(reaction);
96 that.Then(reaction);
67 return reaction.Promise;
97 return reaction.Promise;
68 }
98 }
69
99
70 public static IPromise<Tout> Then<Tout>(this IPromise that, Func<IPromise<Tout>> fulfilled, Func<Exception, Tout> rejected) {
100 public static IPromise<Tout> Then<Tout>(this IPromise that, Func<IPromise<Tout>> fulfilled, Func<Exception, Tout> rejected) {
71 var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher);
101 var reaction = PromiseFuncReaction<Tout>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
102 that.Then(reaction);
103 return reaction.Promise;
104 }
105
106 public static IPromise<Tout> Then<Tout>(this IPromise that, Func<IPromise<Tout>> fulfilled) {
107 var reaction = PromiseFuncReaction<Tout>.Create(fulfilled, (Func<Exception, Tout>)null, Promise.DefaultDispatcher);
72 that.Then(reaction);
108 that.Then(reaction);
73 return reaction.Promise;
109 return reaction.Promise;
74 }
110 }
75
111
76 public static IPromise<Tout> Then<Tout>(this IPromise that, Func<IPromise<Tout>> fulfilled, Func<Exception, IPromise<Tout>> rejected) {
112 public static IPromise<Tout> Then<Tout>(this IPromise that, Func<IPromise<Tout>> fulfilled, Func<Exception, IPromise<Tout>> rejected) {
77 var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher);
113 var reaction = PromiseFuncReaction<Tout>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
78 that.Then(reaction);
114 that.Then(reaction);
79 return reaction.Promise;
115 return reaction.Promise;
80 }
116 }
81
117
82 public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, Tout> fulfilled, Func<Exception, Tout> rejected) {
118 public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, Tout> fulfilled, Func<Exception, Tout> rejected) {
83 var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher);
119 var reaction = PromiseFuncReaction<Tin, Tout>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
120 that.Then(reaction);
121 return reaction.Promise;
122 }
123
124 public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, Tout> fulfilled) {
125 var reaction = PromiseFuncReaction<Tin, Tout>.Create(fulfilled, (Func<Exception, Tout>)null, Promise.DefaultDispatcher);
84 that.Then(reaction);
126 that.Then(reaction);
85 return reaction.Promise;
127 return reaction.Promise;
86 }
128 }
87
129
88 public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, Tout> fulfilled, Func<Exception, IPromise<Tout>> rejected) {
130 public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, Tout> fulfilled, Func<Exception, IPromise<Tout>> rejected) {
89 var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher);
131 var reaction = PromiseFuncReaction<Tin, Tout>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
90 that.Then(reaction);
132 that.Then(reaction);
91 return reaction.Promise;
133 return reaction.Promise;
92 }
134 }
93
135
94 public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, IPromise<Tout>> fulfilled, Func<Exception, Tout> rejected) {
136 public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, IPromise<Tout>> fulfilled, Func<Exception, Tout> rejected) {
95 var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher);
137 var reaction = PromiseFuncReaction<Tin, Tout>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
138 that.Then(reaction);
139 return reaction.Promise;
140 }
141
142 public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, IPromise<Tout>> fulfilled) {
143 var reaction = PromiseFuncReaction<Tin, Tout>.Create(fulfilled, (Func<Exception, Tout>)null, Promise.DefaultDispatcher);
96 that.Then(reaction);
144 that.Then(reaction);
97 return reaction.Promise;
145 return reaction.Promise;
98 }
146 }
99
147
100 public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, IPromise<Tout>> fulfilled, Func<Exception, IPromise<Tout>> rejected) {
148 public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, IPromise<Tout>> fulfilled, Func<Exception, IPromise<Tout>> rejected) {
101 var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher);
149 var reaction = PromiseFuncReaction<Tin, Tout>.Create(fulfilled, rejected, Promise.DefaultDispatcher);
102 that.Then(reaction);
150 that.Then(reaction);
103 return reaction.Promise;
151 return reaction.Promise;
104 }
152 }
105
153
106 public static IPromise Catch(this IPromise that, Action<Exception> rejected) {
154 public static IPromise Catch(this IPromise that, Action<Exception> rejected) {
107 return Then(that, null, rejected);
155 return Then(that, null, rejected);
108 }
156 }
109
157
110 public static IPromise Catch(this IPromise that, Func<Exception, IPromise> rejected) {
158 public static IPromise Catch(this IPromise that, Func<Exception, IPromise> rejected) {
111 return Then(that, null, rejected);
159 return Then(that, null, rejected);
112 }
160 }
113
161
114 public static IPromise<Tout> Catch<Tout>(this IPromise that, Func<Exception, Tout> rejected) {
162 public static IPromise<Tout> Catch<Tout>(this IPromise that, Func<Exception, Tout> rejected) {
115 return Then(that, (Func<Tout>)null, rejected);
163 return Then(that, (Func<Tout>)null, rejected);
116 }
164 }
117
165
118 public static IPromise<Tout> Catch<Tout>(this IPromise that, Func<Exception, IPromise<Tout>> rejected) {
166 public static IPromise<Tout> Catch<Tout>(this IPromise that, Func<Exception, IPromise<Tout>> rejected) {
119 return Then(that, (Func<Tout>)null, rejected);
167 return Then(that, (Func<Tout>)null, rejected);
120 }
168 }
121
169
122 public static IPromise<Tout> Catch<Tin, Tout>(this IPromise<Tin> that, Func<Exception, Tout> rejected) {
170 public static IPromise<Tout> Catch<Tin, Tout>(this IPromise<Tin> that, Func<Exception, Tout> rejected) {
123 return Then(that, (Func<Tin, Tout>)null, rejected);
171 return Then(that, (Func<Tin, Tout>)null, rejected);
124 }
172 }
125
173
126 public static IPromise<Tout> Catch<Tin, Tout>(this IPromise<Tin> that, Func<Exception, IPromise<Tout>> rejected) {
174 public static IPromise<Tout> Catch<Tin, Tout>(this IPromise<Tin> that, Func<Exception, IPromise<Tout>> rejected) {
127 return Then(that, (Func<Tin, Tout>)null, rejected);
175 return Then(that, (Func<Tin, Tout>)null, rejected);
128 }
176 }
177
178 public static IPromise Finally(this IPromise that, Action final) {
179 return Then(that, final, e => {
180 final();
181 throw e.Rethrow();
182 });
183 }
184
185 public static IPromise Finally(this IPromise that, Func<IPromise> final) {
186 return Then(that, final, e => {
187 final();
188 throw e.Rethrow();
189 });
190 }
191
192 public static IPromise<T> Finally<T>(this IPromise<T> that, Action final) {
193 return Then<T, T>(that, x => {
194 final();
195 return x;
196 }, new Func<Exception, T>(e => {
197 final();
198 throw e.Rethrow();
199 }));
200 }
201
202 public static IPromise<T> Finally<T>(this IPromise<T> that, Func<IPromise> final) {
203 return Then<T, T>(that, x => {
204 return final()
205 .Then(() => x);
206 }, new Func<Exception, IPromise<T>>(e => {
207 return final()
208 .Then(new Func<T>(() => {
209 throw e.Rethrow();
210 }));
211 }));
212 }
213
214
129 }
215 }
130 }
216 }
131
217
@@ -1,56 +1,91
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3
3
4 namespace Implab {
4 namespace Implab {
5 class PromiseFuncReaction<TRet> : PromiseReaction {
5 class PromiseFuncReaction<TRet> : IResolvable {
6 readonly Deferred<TRet> m_next;
6 readonly Deferred<TRet> m_next;
7
7
8 readonly IDispatcher m_dispatcher;
9
10 readonly Action<Deferred<TRet>> m_fulfilled;
11
12 readonly Action<Exception, Deferred<TRet>> m_rejected;
13
8 public IPromise<TRet> Promise {
14 public IPromise<TRet> Promise {
9 get { return m_next.Promise; }
15 get { return m_next.Promise; }
10 }
16 }
11
17
12 public PromiseFuncReaction(Func<TRet> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) : base(dispatcher) {
18 public PromiseFuncReaction(Action<Deferred<TRet>> fulfilled, Action<Exception, Deferred<TRet>> rejected, Deferred<TRet> next, IDispatcher dispatcher) {
13 m_next = new Deferred<TRet>(dispatcher);
19 m_next = next;
14 if (fulfilled != null)
20 m_fulfilled = fulfilled;
15 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
21 m_rejected = rejected;
16
22 m_dispatcher = dispatcher;
17 if (rejected != null)
18 RejectHandler = PromiseHandler.Create(rejected, m_next);
19 }
23 }
20
24
21 public PromiseFuncReaction(Func<IPromise<TRet>> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) : base(dispatcher) {
25 public void Resolve() {
22 m_next = new Deferred<TRet>(dispatcher);
26 if (m_fulfilled != null) {
23 if (fulfilled != null)
27 if (m_dispatcher != null)
24 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
28 m_dispatcher.Enqueue(ResolveImpl);
29 else
30 ResolveImpl();
31 } else {
32 m_next.Resolve(default(TRet));
33 }
34 }
25
35
26 if (rejected != null)
36 void ResolveImpl () {
27 RejectHandler = PromiseHandler.Create(rejected, m_next);
37 m_fulfilled(m_next);
38 }
39
40 public void Reject(Exception error) {
41 if (m_fulfilled != null) {
42 if (m_dispatcher != null)
43 m_dispatcher.Enqueue(RejectImpl, error);
44 else
45 RejectImpl(error);
46 } else {
47 m_next.Reject(error);
48 }
28 }
49 }
29
50
30 public PromiseFuncReaction(Func<TRet> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) : base(dispatcher) {
51 void RejectImpl(Exception error) {
31 m_next = new Deferred<TRet>(dispatcher);
52 m_rejected(error, m_next);
32 if (fulfilled != null)
53 }
33 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
34
54
35 if (rejected != null)
55 public static PromiseFuncReaction<TRet> Create(Func<TRet> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) {
36 RejectHandler = PromiseHandler.Create(rejected, m_next);
56 return new PromiseFuncReaction<TRet>(
57 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
58 rejected != null ? PromiseHandler.Create(rejected) : null,
59 new Deferred<TRet>(),
60 dispatcher
61 );
37 }
62 }
38
63
39 public PromiseFuncReaction(Func<IPromise<TRet>> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) : base(dispatcher) {
64 public static PromiseFuncReaction<TRet> Create(Func<IPromise<TRet>> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) {
40 m_next = new Deferred<TRet>(dispatcher);
65 return new PromiseFuncReaction<TRet>(
41 if (fulfilled != null)
66 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
42 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
67 rejected != null ? PromiseHandler.Create(rejected) : null,
43
68 new Deferred<TRet>(),
44 if (rejected != null)
69 dispatcher
45 RejectHandler = PromiseHandler.Create(rejected, m_next);
70 );
46 }
71 }
47
72
48 protected override void DefaultReject(Exception reason) {
73 public static PromiseFuncReaction<TRet> Create(Func<TRet> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) {
49 m_next.Reject(reason);
74 return new PromiseFuncReaction<TRet>(
75 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
76 rejected != null ? PromiseHandler.Create(rejected) : null,
77 new Deferred<TRet>(),
78 dispatcher
79 );
50 }
80 }
51
81
52 protected override void DefaultResolve() {
82 public static PromiseFuncReaction<TRet> Create(Func<IPromise<TRet>> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) {
53 throw new NotImplementedException();
83 return new PromiseFuncReaction<TRet>(
84 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
85 rejected != null ? PromiseHandler.Create(rejected) : null,
86 new Deferred<TRet>(),
87 dispatcher
88 );
54 }
89 }
55 }
90 }
56 } No newline at end of file
91 }
@@ -1,56 +1,97
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3
3
4 namespace Implab {
4 namespace Implab {
5 class PromiseFuncReaction<TIn, TRet> : PromiseReaction<TIn> {
5 class PromiseFuncReaction<TIn, TRet> : IResolvable<TIn> {
6 readonly Deferred<TRet> m_next;
6 readonly Deferred<TRet> m_next;
7
7
8 readonly IDispatcher m_dispatcher;
9
10 readonly Action<TIn, Deferred<TRet>> m_fulfilled;
11
12 readonly Action<Exception, Deferred<TRet>> m_rejected;
13
8 public IPromise<TRet> Promise {
14 public IPromise<TRet> Promise {
9 get { return m_next.Promise; }
15 get { return m_next.Promise; }
10 }
16 }
11
17
12 public PromiseFuncReaction(Func<TIn, TRet> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) : base(dispatcher) {
18 public PromiseFuncReaction(Action<TIn, Deferred<TRet>> fulfilled, Action<Exception, Deferred<TRet>> rejected, Deferred<TRet> next, IDispatcher dispatcher) {
13 m_next = new Deferred<TRet>(dispatcher);
19 m_next = next;
14 if (fulfilled != null)
20 m_fulfilled = fulfilled;
15 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
21 m_rejected = rejected;
16
22 m_dispatcher = dispatcher;
17 if (rejected != null)
18 RejectHandler = PromiseHandler.Create(rejected, m_next);
19 }
23 }
20
24
21 public PromiseFuncReaction(Func<TIn, IPromise<TRet>> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) : base(dispatcher) {
25 public void Resolve(TIn result) {
22 m_next = new Deferred<TRet>(dispatcher);
26 if (m_fulfilled != null) {
23 if (fulfilled != null)
27 if (m_dispatcher != null)
24 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
28 m_dispatcher.Enqueue(ResolveImpl, result);
29 else
30 ResolveImpl(result);
31 } else {
32 try {
33 m_next.Resolve((TRet)(object)result);
34 } catch(Exception error) {
35 // handle cast exceptions
36 m_next.Reject(error);
37 }
38 }
39 }
25
40
26 if (rejected != null)
41 void ResolveImpl (TIn result) {
27 RejectHandler = PromiseHandler.Create(rejected, m_next);
42 m_fulfilled(result, m_next);
43 }
44
45 public void Reject(Exception error) {
46 if (m_fulfilled != null) {
47 if (m_dispatcher != null)
48 m_dispatcher.Enqueue(RejectImpl, error);
49 else
50 RejectImpl(error);
51 } else {
52 m_next.Reject(error);
53 }
28 }
54 }
29
55
30 public PromiseFuncReaction(Func<TIn, TRet> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) : base(dispatcher) {
56 void RejectImpl(Exception error) {
31 m_next = new Deferred<TRet>(dispatcher);
57 m_rejected(error, m_next);
32 if (fulfilled != null)
58 }
33 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
59
34
60
35 if (rejected != null)
61 public static PromiseFuncReaction<TIn,TRet> Create(Func<TIn,TRet> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) {
36 RejectHandler = PromiseHandler.Create(rejected, m_next);
62 return new PromiseFuncReaction<TIn,TRet>(
63 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
64 rejected != null ? PromiseHandler.Create(rejected) : null,
65 new Deferred<TRet>(),
66 dispatcher
67 );
37 }
68 }
38
69
39 public PromiseFuncReaction(Func<TIn, IPromise<TRet>> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) : base(dispatcher) {
70 public static PromiseFuncReaction<TIn,TRet> Create(Func<TIn,IPromise<TRet>> fulfilled, Func<Exception, TRet> rejected, IDispatcher dispatcher) {
40 m_next = new Deferred<TRet>(dispatcher);
71 return new PromiseFuncReaction<TIn,TRet>(
41 if (fulfilled != null)
72 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
42 FulfilHandler = PromiseHandler.Create(fulfilled, m_next);
73 rejected != null ? PromiseHandler.Create(rejected) : null,
43
74 new Deferred<TRet>(),
44 if (rejected != null)
75 dispatcher
45 RejectHandler = PromiseHandler.Create(rejected, m_next);
76 );
46 }
77 }
47
78
48 protected override void DefaultReject(Exception reason) {
79 public static PromiseFuncReaction<TIn,TRet> Create(Func<TIn,TRet> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) {
49 m_next.Reject(reason);
80 return new PromiseFuncReaction<TIn,TRet>(
81 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
82 rejected != null ? PromiseHandler.Create(rejected) : null,
83 new Deferred<TRet>(),
84 dispatcher
85 );
50 }
86 }
51
87
52 protected override void DefaultResolve(TIn result) {
88 public static PromiseFuncReaction<TIn,TRet> Create(Func<TIn,IPromise<TRet>> fulfilled, Func<Exception, IPromise<TRet>> rejected, IDispatcher dispatcher) {
53 m_next.Resolve((TRet)(object)result);
89 return new PromiseFuncReaction<TIn,TRet>(
90 fulfilled != null ? PromiseHandler.Create(fulfilled) : null,
91 rejected != null ? PromiseHandler.Create(rejected) : null,
92 new Deferred<TRet>(),
93 dispatcher
94 );
54 }
95 }
55 }
96 }
56 } No newline at end of file
97 }
@@ -1,102 +1,102
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3
3
4 namespace Implab {
4 namespace Implab {
5 class PromiseHandler {
5 class PromiseHandler {
6 public static Action<T> Create<T>(Action<T> handler, Deferred next) {
6 public static Action<T, Deferred> Create<T>(Action<T> handler) {
7 Debug.Assert(handler != null);
7 Debug.Assert(handler != null);
8
8
9 return (v) => {
9 return (v, next) => {
10 try {
10 try {
11 handler(v);
11 handler(v);
12 next.Resolve();
12 next.Resolve();
13 } catch (Exception err) {
13 } catch (Exception err) {
14 next.Reject(err);
14 next.Reject(err);
15 }
15 }
16 };
16 };
17 }
17 }
18
18
19 public static Action<T> Create<T>(Func<T, IPromise> handler, Deferred next) {
19 public static Action<T, Deferred> Create<T>(Func<T, IPromise> handler) {
20 Debug.Assert(handler != null);
20 Debug.Assert(handler != null);
21
21
22 return (v) => {
22 return (v, next) => {
23 try {
23 try {
24 next.Resolve(handler(v));
24 next.Resolve(handler(v));
25 } catch (Exception err) {
25 } catch (Exception err) {
26 next.Reject(err);
26 next.Reject(err);
27 }
27 }
28 };
28 };
29 }
29 }
30
30
31 public static Action<T> Create<T, T2>(Func<T, T2> handler, Deferred<T2> next) {
31 public static Action<T, Deferred<T2>> Create<T, T2>(Func<T, T2> handler) {
32 Debug.Assert(handler != null);
32 Debug.Assert(handler != null);
33
33
34 return (v) => {
34 return (v, next) => {
35 try {
35 try {
36 next.Resolve(handler(v));
36 next.Resolve(handler(v));
37 } catch (Exception err) {
37 } catch (Exception err) {
38 next.Reject(err);
38 next.Reject(err);
39 }
39 }
40 };
40 };
41 }
41 }
42
42
43 public static Action<T> Create<T, T2>(Func<T, IPromise<T2>> handler, Deferred<T2> next) {
43 public static Action<T, Deferred<T2>> Create<T, T2>(Func<T, IPromise<T2>> handler) {
44 Debug.Assert(handler != null);
44 Debug.Assert(handler != null);
45 return (v) => {
45 return (v, next) => {
46 try {
46 try {
47 next.Resolve(handler(v));
47 next.Resolve(handler(v));
48 } catch (Exception err) {
48 } catch (Exception err) {
49 next.Reject(err);
49 next.Reject(err);
50 }
50 }
51 };
51 };
52 }
52 }
53
53
54 public static Action Create(Action handler, Deferred next) {
54 public static Action<Deferred> Create(Action handler) {
55 Debug.Assert(handler != null);
55 Debug.Assert(handler != null);
56
56
57 return () => {
57 return (next) => {
58 try {
58 try {
59 handler();
59 handler();
60 next.Resolve();
60 next.Resolve();
61 } catch (Exception err) {
61 } catch (Exception err) {
62 next.Reject(err);
62 next.Reject(err);
63 }
63 }
64 };
64 };
65 }
65 }
66
66
67 public static Action Create(Func<IPromise> handler, Deferred next) {
67 public static Action<Deferred> Create(Func<IPromise> handler) {
68 Debug.Assert(handler != null);
68 Debug.Assert(handler != null);
69
69
70 return () => {
70 return (next) => {
71 try {
71 try {
72 next.Resolve(handler());
72 next.Resolve(handler());
73 } catch (Exception err) {
73 } catch (Exception err) {
74 next.Reject(err);
74 next.Reject(err);
75 }
75 }
76 };
76 };
77 }
77 }
78
78
79 public static Action Create<T2>(Func<T2> handler, Deferred<T2> next) {
79 public static Action<Deferred<T2>> Create<T2>(Func<T2> handler) {
80 Debug.Assert(handler != null);
80 Debug.Assert(handler != null);
81
81
82 return () => {
82 return (next) => {
83 try {
83 try {
84 next.Resolve(handler());
84 next.Resolve(handler());
85 } catch (Exception err) {
85 } catch (Exception err) {
86 next.Reject(err);
86 next.Reject(err);
87 }
87 }
88 };
88 };
89 }
89 }
90
90
91 public static Action Create<T2>(Func<IPromise<T2>> handler, Deferred<T2> next) {
91 public static Action<Deferred<T2>> Create<T2>(Func<IPromise<T2>> handler) {
92 Debug.Assert(handler != null);
92 Debug.Assert(handler != null);
93 return () => {
93 return (next) => {
94 try {
94 try {
95 next.Resolve(handler());
95 next.Resolve(handler());
96 } catch (Exception err) {
96 } catch (Exception err) {
97 next.Reject(err);
97 next.Reject(err);
98 }
98 }
99 };
99 };
100 }
100 }
101 }
101 }
102 } No newline at end of file
102 }
@@ -1,38 +1,38
1 using System;
1 using System;
2
2
3 namespace Implab
3 namespace Implab
4 {
4 {
5 public struct RejectedPromise : IPromise {
5 public struct RejectedPromise : IPromise {
6 readonly Exception m_reason;
6 readonly Exception m_reason;
7
7
8 public Type ResultType => typeof(void);
8 public Type ResultType => typeof(void);
9
9
10 public bool IsResolved => true;
10 public bool IsResolved => true;
11
11
12 public bool IsRejected => true;
12 public bool IsRejected => true;
13
13
14 public bool IsFulfilled => false;
14 public bool IsFulfilled => false;
15
15
16 public Exception RejectReason => m_reason;
16 public Exception RejectReason => m_reason;
17
17
18 public RejectedPromise(Exception reason) {
18 public RejectedPromise(Exception reason) {
19 m_reason = reason;
19 m_reason = reason;
20 }
20 }
21
21
22 public IPromise<T> Cast<T>() {
22 public IPromise<T> Cast<T>() {
23 throw new InvalidCastException();
23 throw new InvalidCastException();
24 }
24 }
25
25
26 public void Join() {
26 public void Join() {
27 m_reason.ThrowInvocationException();
27 throw m_reason.Wrap();
28 }
28 }
29
29
30 public void Join(int timeout) {
30 public void Join(int timeout) {
31 m_reason.ThrowInvocationException();
31 throw m_reason.Wrap();
32 }
32 }
33
33
34 public void Then(IResolvable next) {
34 public void Then(IResolvable next) {
35 next.Reject(m_reason);
35 next.Reject(m_reason);
36 }
36 }
37 }
37 }
38 } No newline at end of file
38 }
@@ -1,52 +1,50
1 using System;
1 using System;
2
2
3 namespace Implab
3 namespace Implab
4 {
4 {
5 public struct RejectedPromise<T> : IPromise<T> {
5 public struct RejectedPromise<T> : IPromise<T> {
6 readonly Exception m_reason;
6 readonly Exception m_reason;
7
7
8 public Type ResultType => typeof(void);
8 public Type ResultType => typeof(void);
9
9
10 public bool IsResolved => true;
10 public bool IsResolved => true;
11
11
12 public bool IsRejected => true;
12 public bool IsRejected => true;
13
13
14 public bool IsFulfilled => false;
14 public bool IsFulfilled => false;
15
15
16 public Exception RejectReason => m_reason;
16 public Exception RejectReason => m_reason;
17
17
18 public RejectedPromise(Exception reason) {
18 public RejectedPromise(Exception reason) {
19 m_reason = reason;
19 m_reason = reason;
20 }
20 }
21
21
22 public IPromise<T2> Cast<T2>() {
22 public IPromise<T2> Cast<T2>() {
23 return (IPromise<T2>)(IPromise<T>)this;
23 return (IPromise<T2>)(IPromise<T>)this;
24 }
24 }
25
25
26 void IPromise.Join() {
26 void IPromise.Join() {
27 m_reason.ThrowInvocationException();
27 throw m_reason.Wrap();
28 }
28 }
29
29
30 void IPromise.Join(int timeout) {
30 void IPromise.Join(int timeout) {
31 m_reason.ThrowInvocationException();
31 throw m_reason.Wrap();
32 }
32 }
33
33
34 public T Join() {
34 public T Join() {
35 m_reason.ThrowInvocationException();
35 throw m_reason.Wrap();
36 throw new Exception(); // unreachable code
37 }
36 }
38
37
39 public T Join(int timeout) {
38 public T Join(int timeout) {
40 m_reason.ThrowInvocationException();
39 throw m_reason.Wrap();
41 throw new Exception(); // unreachable code
42 }
40 }
43
41
44 public void Then(IResolvable next) {
42 public void Then(IResolvable next) {
45 next.Reject(m_reason);
43 next.Reject(m_reason);
46 }
44 }
47
45
48 public void Then(IResolvable<T> next) {
46 public void Then(IResolvable<T> next) {
49 next.Reject(m_reason);
47 next.Reject(m_reason);
50 }
48 }
51 }
49 }
52 } No newline at end of file
50 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
This diff has been collapsed as it changes many lines, (878 lines changed) Show them Hide them
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
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