# HG changeset patch # User cin # Date 2016-02-03 23:43:05 # Node ID ec91a6dfa5b3f458072b9373a36c2e5ddb231c68 # Parent 3258399cba83ea4cd9b8565ef802cd0a9c29f98c Added support for 'await' operator to promises diff --git a/Implab.Fx/Implab.Fx.csproj b/Implab.Fx/Implab.Fx.csproj --- a/Implab.Fx/Implab.Fx.csproj +++ b/Implab.Fx/Implab.Fx.csproj @@ -12,6 +12,7 @@ Implab.Fx v4.0 512 + 0.2 true diff --git a/Implab.Test/AsyncTests.cs b/Implab.Test/AsyncTests.cs --- a/Implab.Test/AsyncTests.cs +++ b/Implab.Test/AsyncTests.cs @@ -845,6 +845,19 @@ namespace Implab.Test { Console.WriteLine(m); } } + + #if NET_4_5 + + [TestMethod] + public async void TaskInteropTest() { + var promise = new Promise(); + promise.Resolve(10); + var res = await promise; + + Assert.AreEqual(10, res); + } + + #endif } } diff --git a/Implab.Test/Implab.Test.mono.csproj b/Implab.Test/Implab.Test.mono.csproj --- a/Implab.Test/Implab.Test.mono.csproj +++ b/Implab.Test/Implab.Test.mono.csproj @@ -10,6 +10,7 @@ Implab.Test Implab.Test v4.5 + 0.2 true diff --git a/Implab.mono.sln b/Implab.mono.sln --- a/Implab.mono.sln +++ b/Implab.mono.sln @@ -79,7 +79,6 @@ Global {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 @@ Global $34.NamingStyle = PascalCase $34.IncludeInstanceMembers = True $34.IncludeStaticEntities = True + version = 0.2 + StartupItem = MonoPlay\MonoPlay.csproj EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = Implab.vsmdi diff --git a/Implab/IPromise.cs b/Implab/IPromise.cs --- a/Implab/IPromise.cs +++ b/Implab/IPromise.cs @@ -27,46 +27,6 @@ namespace Implab { Exception Error { get; } /// - /// Creates a new promise dependend on the current one and resolved on - /// executing the specified handlers. - /// - /// The handler called on the successful promise completion. - /// The handler is called if an error while completing the promise occurred. - /// The handler is called in case of promise cancellation. - /// The newly created dependant promise. - /// - /// - /// 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. - /// - /// - /// 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 . The handler may raise - /// to cancel the dependant promise, the innner exception specifies the reason why the promise - /// is canceled. - /// - /// - /// 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. - /// - /// - /* IPromise Then(Action success, Action error, Action cancel); - IPromise Then(Action success, Action error); - IPromise Then(Action success); - - IPromise Chain(Func chained, Func error, Func cancel); - IPromise Chain(Func chained, Func error); - IPromise Chain(Func chained);*/ - - /// /// Adds specified listeners to the current promise. /// /// The handler called on the successful promise completion. diff --git a/Implab/Implab.csproj b/Implab/Implab.csproj --- a/Implab/Implab.csproj +++ b/Implab/Implab.csproj @@ -7,6 +7,10 @@ Library Implab Implab + 8.0.30703 + 2.0 + 0.2 + v4.5 true @@ -68,6 +72,7 @@ + @@ -173,6 +178,8 @@ + + diff --git a/Implab/PromiseAwaiter.cs b/Implab/PromiseAwaiter.cs new file mode 100644 --- /dev/null +++ b/Implab/PromiseAwaiter.cs @@ -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; + } + } + } +} + diff --git a/Implab/PromiseAwaiterT.cs b/Implab/PromiseAwaiterT.cs new file mode 100644 --- /dev/null +++ b/Implab/PromiseAwaiterT.cs @@ -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 T GetResult() { + return m_promise.Join(); + } + + public bool IsCompleted { + get { + return m_promise.IsResolved; + } + } + } +} + diff --git a/Implab/PromiseExtensions.cs b/Implab/PromiseExtensions.cs --- a/Implab/PromiseExtensions.cs +++ b/Implab/PromiseExtensions.cs @@ -287,13 +287,10 @@ namespace Implab { #if NET_4_5 - public static Task GetTask(this IPromise that) { + public static PromiseAwaiter GetAwaiter(this IPromise that) { Safe.ArgumentNotNull(that, "that"); - var tcs = new TaskCompletionSource(); - that.On(tcs.SetResult, tcs.SetException, r => tcs.SetCanceled()); - - return tcs.Task; + return new PromiseAwaiter(that); } #endif diff --git a/MonoPlay/MonoPlay.csproj b/MonoPlay/MonoPlay.csproj --- a/MonoPlay/MonoPlay.csproj +++ b/MonoPlay/MonoPlay.csproj @@ -10,6 +10,7 @@ MonoPlay MonoPlay v4.5 + 0.2 true diff --git a/MonoPlay/Program.cs b/MonoPlay/Program.cs --- a/MonoPlay/Program.cs +++ b/MonoPlay/Program.cs @@ -7,6 +7,7 @@ using System.Collections.Concurrent; using System.Threading; using Implab.JSON; using System.IO; +using System.Threading.Tasks; namespace MonoPlay { class MainClass { @@ -18,26 +19,22 @@ namespace MonoPlay { 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 DoItem(int x) { + return Promise.FromResult(x + 1); + } - - + static async Task DoWork() { + var c = 0; + for (int i = 0; i < 10000000; i++) + c = await DoItem(c); + return c; } }