Mercurial > pub > ImplabNet
changeset 75:4439140706d0 v2
major refactoring, added tasks support
author | cin |
---|---|
date | Wed, 10 Sep 2014 11:17:37 +0400 |
parents | c4140283575c |
children | c761fc982e1d |
files | Implab.Fx.Test/Implab.Fx.Test.csproj Implab.Fx/Implab.Fx.csproj Implab.Test/Implab.Test.csproj Implab.sln Implab/IPromise.cs Implab/IPromiseT.cs Implab/Implab.csproj Implab/Parallels/ArrayTraits.cs Implab/Promise.cs Implab/PromiseExtensions.cs |
diffstat | 10 files changed, 221 insertions(+), 53 deletions(-) [+] |
line wrap: on
line diff
--- a/Implab.Fx.Test/Implab.Fx.Test.csproj Mon Sep 08 17:40:46 2014 +0400 +++ b/Implab.Fx.Test/Implab.Fx.Test.csproj Wed Sep 10 11:17:37 2014 +0400 @@ -31,6 +31,23 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> <ItemGroup> <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> <Reference Include="System" />
--- a/Implab.Fx/Implab.Fx.csproj Mon Sep 08 17:40:46 2014 +0400 +++ b/Implab.Fx/Implab.Fx.csproj Wed Sep 10 11:17:37 2014 +0400 @@ -30,6 +30,23 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Core" />
--- a/Implab.Test/Implab.Test.csproj Mon Sep 08 17:40:46 2014 +0400 +++ b/Implab.Test/Implab.Test.csproj Wed Sep 10 11:17:37 2014 +0400 @@ -31,6 +31,23 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> <ItemGroup> <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> <Reference Include="System" />
--- a/Implab.sln Mon Sep 08 17:40:46 2014 +0400 +++ b/Implab.sln Wed Sep 10 11:17:37 2014 +0400 @@ -20,22 +20,40 @@ GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU + Debug 4.5|Any CPU = Debug 4.5|Any CPU + Release 4.5|Any CPU = Release 4.5|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU + {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU + {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.Build.0 = Release|Any CPU + {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU + {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU + {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.ActiveCfg = Release|Any CPU {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.Build.0 = Release|Any CPU + {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU + {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU + {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.ActiveCfg = Release|Any CPU {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.Build.0 = Release|Any CPU + {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU + {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU + {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.ActiveCfg = Release|Any CPU {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection
--- a/Implab/IPromise.cs Mon Sep 08 17:40:46 2014 +0400 +++ b/Implab/IPromise.cs Wed Sep 10 11:17:37 2014 +0400 @@ -27,16 +27,26 @@ /// </summary> bool IsCancelled { get; } - IPromise Then(Action success,ErrorHandler error); + IPromise Then(Action success, ErrorHandler error, Action cancel); + IPromise Then(Action success, ErrorHandler error); IPromise Then(Action success); + + /// <summary> + /// Добавляет последнй обработчик в цепочку обещаний, не создает промежуточных обещаний. + /// </summary> + /// <param name="success">Success.</param> + /// <param name="error">Error.</param> + /// <param name="cancel">Cancel.</param> + void Last(Action success, ErrorHandler error, Action cancel); + void Last(Action success, ErrorHandler error); + void Last(Action success); + IPromise Error(ErrorHandler error); /// <summary> /// Обрабатывает либо ошибку, либо результат. Событие отмены не обрабатывается. /// </summary> /// <param name="handler">Обработчик.</param> /// <remarks>После обработке ошибки, она передается дальше.</remarks> - IPromise Anyway(Action handler); - /// <summary> /// Обрабатывает либо ошибку, либо результат, либо отмену обещания. /// </summary>
--- a/Implab/IPromiseT.cs Mon Sep 08 17:40:46 2014 +0400 +++ b/Implab/IPromiseT.cs Wed Sep 10 11:17:37 2014 +0400 @@ -3,27 +3,35 @@ using System.Linq; using System.Text; -namespace Implab -{ - public interface IPromise<T>: IPromise - { +namespace Implab { + public interface IPromise<T>: IPromise { new T Join(); + new T Join(int timeout); + IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error, Action cancel); + IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error); + IPromise<T> Then(ResultHandler<T> success); + + void Last(ResultHandler<T> success, ErrorHandler error, Action cancel); + void Last(ResultHandler<T> success, ErrorHandler error); + void Last(ResultHandler<T> success); + IPromise<T> Error(ErrorHandler<T> error); - IPromise<T2> Map<T2>(ResultMapper<T,T2> mapper, ErrorHandler<T> error); - IPromise<T2> Map<T2>(ResultMapper<T, T2> mapper); + IPromise<T2> Then<T2>(ResultMapper<T,T2> mapper, ErrorHandler<T> error); + + IPromise<T2> Then<T2>(ResultMapper<T,T2> mapper); - IPromise<T2> Chain<T2>(ChainedOperation<T, T2> chained, ErrorHandler<T> error); - IPromise<T2> Chain<T2>(ChainedOperation<T, T2> chained); + IPromise<T2> Then<T2>(ChainedOperation<T, T2> chained, ErrorHandler<T> error); + + IPromise<T2> Then<T2>(ChainedOperation<T, T2> chained); new IPromise<T> Cancelled(Action handler); + new IPromise<T> Finally(Action handler); - new IPromise<T> Anyway(Action handler); - } }
--- a/Implab/Implab.csproj Mon Sep 08 17:40:46 2014 +0400 +++ b/Implab/Implab.csproj Wed Sep 10 11:17:37 2014 +0400 @@ -29,6 +29,25 @@ <WarningLevel>4</WarningLevel> <ConsolePause>false</ConsolePause> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug</OutputPath> + <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <RunCodeAnalysis>true</RunCodeAnalysis> + <ConsolePause>false</ConsolePause> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' "> + <Optimize>true</Optimize> + <OutputPath>bin\Release</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <ConsolePause>false</ConsolePause> + <DefineConstants>NET_4_5</DefineConstants> + </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Xml" />
--- a/Implab/Parallels/ArrayTraits.cs Mon Sep 08 17:40:46 2014 +0400 +++ b/Implab/Parallels/ArrayTraits.cs Wed Sep 10 11:17:37 2014 +0400 @@ -29,8 +29,7 @@ m_pending = source.Length; m_action = action; - m_promise.Anyway(() => Dispose()); - m_promise.Cancelled(() => Dispose()); + m_promise.Finally(Dispose); InitPool(); } @@ -48,7 +47,7 @@ protected override bool TryDequeue(out int unit) { unit = Interlocked.Increment(ref m_next) - 1; - return unit >= m_source.Length ? false : true; + return unit < m_source.Length; } protected override void InvokeUnit(int unit) { @@ -86,8 +85,7 @@ m_transform = transform; m_traceContext = TraceContext.Snapshot(); - m_promise.Anyway(() => Dispose()); - m_promise.Cancelled(() => Dispose()); + m_promise.Finally(Dispose); InitPool(); } @@ -157,16 +155,17 @@ var semaphore = new Semaphore(threads, threads); + // Analysis disable AccessToDisposedClosure AsyncPool.InvokeNewThread(() => { for (int i = 0; i < source.Length; i++) { if(promise.IsResolved) break; // stop processing in case of error or cancellation var idx = i; + semaphore.WaitOne(); try { var p1 = transform(source[i]); - p1.Anyway(() => semaphore.Release()); - p1.Cancelled(() => semaphore.Release()); + p1.Finally(() => semaphore.Release()); p1.Then( x => { res[idx] = x; @@ -187,7 +186,7 @@ return 0; }); - return promise.Anyway(() => semaphore.Dispose()); + return promise.Finally(semaphore.Dispose); } }
--- a/Implab/Promise.cs Mon Sep 08 17:40:46 2014 +0400 +++ b/Implab/Promise.cs Wed Sep 10 11:17:37 2014 +0400 @@ -225,6 +225,18 @@ Cancel(); } + + public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error, Action cancel) { + if (success == null && error == null && cancel == null) + return this; + + var medium = new Promise<T>(this, true); + + AddHandler(success, error, cancel, medium); + + return medium; + } + /// <summary> /// Adds new handlers to this promise. /// </summary> @@ -243,6 +255,17 @@ return medium; } + public IPromise Then(Action success, ErrorHandler error, Action cancel) { + return Then( + x => success(), + e => { + error(e); + return default(T); + }, + cancel + ); + } + public IPromise Then(Action success, ErrorHandler error) { return Then( x => success(), @@ -269,6 +292,39 @@ return medium; } + public void Last(ResultHandler<T> success, ErrorHandler error, Action cancel) { + if (success == null && error == null && cancel == null) + return; + + ErrorHandler<T> errorHandler = null; + if (error != null) + errorHandler = err => { + error(err); + return default(T); + }; + AddHandler(success, errorHandler, cancel, null); + } + + public void Last(ResultHandler<T> success, ErrorHandler error) { + Last(success, error, null); + } + + public void Last(ResultHandler<T> success) { + Last(success, null, null); + } + + public void Last(Action success,ErrorHandler error, Action cancel) { + Last(x => success(), error, cancel); + } + + public void Last(Action success,ErrorHandler error) { + Last(x => success(), error, null); + } + + public void Last(Action success) { + Last(x => success(), null, null); + } + public IPromise Error(ErrorHandler error) { if (error == null) return this; @@ -307,25 +363,6 @@ return medium; } - public IPromise<T> Anyway(Action handler) { - if (handler == null) - return this; - - var medium = new Promise<T>(this, true); - - AddHandler( - x => handler(), - e => { - handler(); - throw new TransientPromiseException(e); - }, - null, - medium - ); - - return medium; - } - /// <summary> /// Позволяет преобразовать результат выполения операции к новому типу. /// </summary> @@ -334,7 +371,7 @@ /// <param name="error">Обработчик ошибки. Данный обработчик получит /// исключение возникшее при выполнении операции.</param> /// <returns>Новое обещание, которое будет выполнено при выполнении исходного обещания.</returns> - public IPromise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<T> error) { + public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<T> error) { if (mapper == null) throw new ArgumentNullException("mapper"); @@ -370,8 +407,8 @@ return chained; } - public IPromise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper) { - return Map(mapper, null); + public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper) { + return Then(mapper, null); } /// <summary> @@ -384,7 +421,7 @@ /// <param name="error">Обработчик ошибки. Данный обработчик получит /// исключение возникшее при выполнении текуещй операции.</param> /// <returns>Новое обещание, которое будет выполнено по окончанию указанной аснхронной операции.</returns> - public IPromise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler<T> error) { + public IPromise<TNew> Then<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler<T> error) { // проблема в том, что на момент связывания еще не начата асинхронная операция, поэтому нужно // создать посредника, к которому будут подвызяваться следующие обработчики. @@ -442,8 +479,8 @@ return medium; } - public IPromise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained) { - return Chain(chained, null); + public IPromise<TNew> Then<TNew>(ChainedOperation<T, TNew> chained) { + return Then(chained, null); } public IPromise<T> Cancelled(Action handler) { @@ -478,7 +515,7 @@ /// <typeparam name="T2"></typeparam> /// <returns></returns> public IPromise<T2> Cast<T2>() { - return Map(x => (T2)(object)x, null); + return Then(x => (T2)(object)x, null); } /// <summary> @@ -504,8 +541,7 @@ /// <returns>Результат выполнения обещания</returns> public T Join(int timeout) { var evt = new ManualResetEvent(false); - Anyway(() => evt.Set()); - Cancelled(() => evt.Set()); + Finally(() => evt.Set()); if (!evt.WaitOne(timeout, true)) throw new TimeoutException(); @@ -704,10 +740,6 @@ return Error(error); } - IPromise IPromise.Anyway(Action handler) { - return Anyway(handler); - } - IPromise IPromise.Finally(Action handler) { return Finally(handler); }
--- a/Implab/PromiseExtensions.cs Mon Sep 08 17:40:46 2014 +0400 +++ b/Implab/PromiseExtensions.cs Wed Sep 10 11:17:37 2014 +0400 @@ -1,8 +1,13 @@ using System.Threading; +using System; +#if NET_4_5 +using System.Threading.Tasks; +#endif namespace Implab { public static class PromiseExtensions { public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) { + Safe.ArgumentNotNull(that, "that"); var context = SynchronizationContext.Current; if (context == null) return that; @@ -20,6 +25,7 @@ } public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) { + Safe.ArgumentNotNull(that, "that"); Safe.ArgumentNotNull(context, "context"); var p = new SyncContextPromise<T>(context, that, true); @@ -33,6 +39,31 @@ ); return p; } + + public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult,T> callback) { + Safe.ArgumentNotNull(that, "that"); + Safe.ArgumentNotNull(callback, "callback"); + return ar => { + try { + that.Resolve(callback(ar)); + } catch (Exception err) { + that.Reject(err); + } + }; + } + + #if NET_4_5 + + public static Task<T> GetTask<T>(this IPromise<T> that) { + Safe.ArgumentNotNull(that, "that"); + var tcs = new TaskCompletionSource<T>(); + + that.Last(tcs.SetResult, tcs.SetException, tcs.SetCanceled); + + return tcs.Task; + } + + #endif } }