changeset 151:ec91a6dfa5b3 v2

Added support for 'await' operator to promises
author cin
date Thu, 04 Feb 2016 02:43:05 +0300
parents 3258399cba83
children 240aa6994018
files Implab.Fx/Implab.Fx.csproj Implab.Test/AsyncTests.cs Implab.Test/Implab.Test.mono.csproj Implab.mono.sln Implab/IPromise.cs Implab/Implab.csproj Implab/PromiseAwaiter.cs Implab/PromiseAwaiterT.cs Implab/PromiseExtensions.cs MonoPlay/MonoPlay.csproj MonoPlay/Program.cs
diffstat 11 files changed, 93 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/Implab.Fx/Implab.Fx.csproj	Sat Dec 12 22:12:44 2015 +0300
+++ b/Implab.Fx/Implab.Fx.csproj	Thu Feb 04 02:43:05 2016 +0300
@@ -12,6 +12,7 @@
     <AssemblyName>Implab.Fx</AssemblyName>
     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
+    <ReleaseVersion>0.2</ReleaseVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
--- a/Implab.Test/AsyncTests.cs	Sat Dec 12 22:12:44 2015 +0300
+++ b/Implab.Test/AsyncTests.cs	Thu Feb 04 02:43:05 2016 +0300
@@ -845,6 +845,19 @@
                     Console.WriteLine(m);
             }
         }
+
+        #if NET_4_5
+
+        [TestMethod]
+        public async void TaskInteropTest() {
+            var promise = new Promise<int>();
+            promise.Resolve(10);
+            var res = await promise;
+
+            Assert.AreEqual(10, res);
+        }
+
+        #endif
     }
 }
 
--- a/Implab.Test/Implab.Test.mono.csproj	Sat Dec 12 22:12:44 2015 +0300
+++ b/Implab.Test/Implab.Test.mono.csproj	Thu Feb 04 02:43:05 2016 +0300
@@ -10,6 +10,7 @@
     <RootNamespace>Implab.Test</RootNamespace>
     <AssemblyName>Implab.Test</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <ReleaseVersion>0.2</ReleaseVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
--- a/Implab.mono.sln	Sat Dec 12 22:12:44 2015 +0300
+++ b/Implab.mono.sln	Thu Feb 04 02:43:05 2016 +0300
@@ -79,7 +79,6 @@
 		{2BD05F84-E067-4B87-9477-FDC2676A21C6} = {BCA337C3-BFDC-4825-BBDB-E6D467E4E452}
 	EndGlobalSection
 	GlobalSection(MonoDevelopProperties) = preSolution
-		StartupItem = MonoPlay\MonoPlay.csproj
 		Policies = $0
 		$0.CSharpFormattingPolicy = $1
 		$1.IndentSwitchBody = True
@@ -279,6 +278,8 @@
 		$34.NamingStyle = PascalCase
 		$34.IncludeInstanceMembers = True
 		$34.IncludeStaticEntities = True
+		version = 0.2
+		StartupItem = MonoPlay\MonoPlay.csproj
 	EndGlobalSection
 	GlobalSection(TestCaseManagementSettings) = postSolution
 		CategoryFile = Implab.vsmdi
--- a/Implab/IPromise.cs	Sat Dec 12 22:12:44 2015 +0300
+++ b/Implab/IPromise.cs	Thu Feb 04 02:43:05 2016 +0300
@@ -27,46 +27,6 @@
         Exception Error { get; }
 
         /// <summary>
-        /// Creates a new promise dependend on the current one and resolved on
-        /// executing the specified handlers.
-        /// </summary>
-        /// <param name="success">The handler called on the successful promise completion.</param>
-        /// <param name="error">The handler is called if an error while completing the promise occurred.</param>
-        /// <param name="cancel">The handler is called in case of promise cancellation.</param>
-        /// <returns>The newly created dependant promise.</returns>
-        /// <remarks>
-        /// <para>
-        /// If the success handler is specified the dependend promise will be resolved after the handler is
-        /// executed and the dependent promise will be linked to the current one, i.e. the cancellation
-        /// of the dependent property will lead to the cancellation of the current promise. If the
-        /// success handler isn't specified the dependent promise will not be linked to and
-        /// will not be resolved after the successfull resolution of the current one.
-        /// </para>
-        /// <para>
-        /// When the error handler is specified, the exception raised during the current promise completion
-        /// will be passed to it as the parameter. If the error handler returns without raising an
-        /// exception then the dependant promise will be resolved successfully, otherwise the exception
-        /// raised by the handler will be transmitted to the dependent promise. If the handler wants
-        /// to passthrough the original exception it needs to wrap the exception with
-        /// the <see cref="PromiseTransientException"/>. The handler may raise <see cref="OperationCanceledException"/>
-        /// to cancel the dependant promise, the innner exception specifies the reason why the promise
-        /// is canceled.
-        /// </para>
-        /// <para>
-        /// If the cancelation handler is specified and the current promise is cancelled then the dependent
-        /// promise will be resolved after the handler is executed. If the cancelation handler raises the
-        /// exception it will be passed to the dependent promise.
-        /// </para>
-        /// </remarks>
-        /* IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel);
-        IPromise Then(Action success, Action<Exception> error);
-        IPromise Then(Action success);
-
-        IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel);
-        IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error);
-        IPromise Chain(Func<IPromise> chained);*/
-
-        /// <summary>
         /// Adds specified listeners to the current promise.
         /// </summary>
         /// <param name="success">The handler called on the successful promise completion.</param>
--- a/Implab/Implab.csproj	Sat Dec 12 22:12:44 2015 +0300
+++ b/Implab/Implab.csproj	Thu Feb 04 02:43:05 2016 +0300
@@ -7,6 +7,10 @@
     <OutputType>Library</OutputType>
     <RootNamespace>Implab</RootNamespace>
     <AssemblyName>Implab</AssemblyName>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ReleaseVersion>0.2</ReleaseVersion>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -68,6 +72,7 @@
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Xml" />
+    <Reference Include="mscorlib" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Component.cs" />
@@ -173,6 +178,8 @@
     <Compile Include="ICancellationToken.cs" />
     <Compile Include="SuccessPromise.cs" />
     <Compile Include="SuccessPromiseT.cs" />
+    <Compile Include="PromiseAwaiterT.cs" />
+    <Compile Include="PromiseAwaiter.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/PromiseAwaiter.cs	Thu Feb 04 02:43:05 2016 +0300
@@ -0,0 +1,28 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Implab {
+    public struct PromiseAwaiter : INotifyCompletion {
+        readonly IPromise m_promise;
+
+        public PromiseAwaiter(IPromise promise) {
+            m_promise = promise;
+        }
+
+        public void OnCompleted (Action continuation) {
+            if (m_promise != null)
+                m_promise.On(continuation, PromiseEventType.All);
+        }
+
+        public void GetResult() {
+            m_promise.Join();
+        }
+
+        public bool IsCompleted {
+            get {
+                return m_promise.IsResolved;
+            }
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/PromiseAwaiterT.cs	Thu Feb 04 02:43:05 2016 +0300
@@ -0,0 +1,28 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Implab {
+    public struct PromiseAwaiter<T> : INotifyCompletion {
+        readonly IPromise<T> m_promise;
+
+        public PromiseAwaiter(IPromise<T> promise) {
+            m_promise = promise;
+        }
+
+        public void OnCompleted (Action continuation) {
+            if (m_promise != null)
+                m_promise.On(continuation, PromiseEventType.All);
+        }
+
+        public T GetResult() {
+            return m_promise.Join();
+        }
+
+        public bool IsCompleted {
+            get {
+                return m_promise.IsResolved;
+            }
+        }
+    }
+}
+
--- a/Implab/PromiseExtensions.cs	Sat Dec 12 22:12:44 2015 +0300
+++ b/Implab/PromiseExtensions.cs	Thu Feb 04 02:43:05 2016 +0300
@@ -287,13 +287,10 @@
             
         #if NET_4_5
 
-        public static Task<T> GetTask<T>(this IPromise<T> that) {
+        public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) {
             Safe.ArgumentNotNull(that, "that");
-            var tcs = new TaskCompletionSource<T>();
 
-            that.On(tcs.SetResult, tcs.SetException, r => tcs.SetCanceled());
-
-            return tcs.Task;
+            return new PromiseAwaiter<T>(that);
         }
 
         #endif
--- a/MonoPlay/MonoPlay.csproj	Sat Dec 12 22:12:44 2015 +0300
+++ b/MonoPlay/MonoPlay.csproj	Thu Feb 04 02:43:05 2016 +0300
@@ -10,6 +10,7 @@
     <RootNamespace>MonoPlay</RootNamespace>
     <AssemblyName>MonoPlay</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <ReleaseVersion>0.2</ReleaseVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
--- a/MonoPlay/Program.cs	Sat Dec 12 22:12:44 2015 +0300
+++ b/MonoPlay/Program.cs	Thu Feb 04 02:43:05 2016 +0300
@@ -7,6 +7,7 @@
 using System.Threading;
 using Implab.JSON;
 using System.IO;
+using System.Threading.Tasks;
 
 namespace MonoPlay {
     class MainClass {
@@ -18,26 +19,22 @@
 
             var t1 = Environment.TickCount;
 
-            for(int i =0; i < 1000000; i++)
-            using (var tw = new StringWriter()) {
-                var jw = new JSONWriter(tw);
-
-                jw.WriteValue("\r\nhere\tvalue\u0002\u0003");
-
-                //Console.WriteLine(tw);
-            }
-
-
+            DoWork().GetAwaiter().GetResult();
 
             var t2 = Environment.TickCount;
             Console.WriteLine("done: {0} ms, {1:.00} Mb, {2} GC", t2 - t1, GC.GetTotalMemory(false) / (1024*1024), GC.CollectionCount(0) );
 
         }
 
-        static void DoTest() {
+        static IPromise<int> DoItem(int x) {
+            return Promise<int>.FromResult(x + 1);
+        }
 
-
-
+        static async Task<int> DoWork() {
+            var c = 0;
+            for (int i = 0; i < 10000000; i++)
+                c = await DoItem(c);
+            return c;
         }
 
     }