| @@ -0,0 +1,144 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | using Implab.Parallels; | |||
| 
             | 
        3 | ||||
| 
             | 
        4 | #if MONO | |||
| 
             | 
        5 | ||||
| 
             | 
        6 | using NUnit.Framework; | |||
| 
             | 
        7 | using TestClassAttribute = NUnit.Framework.TestFixtureAttribute; | |||
| 
             | 
        8 | using TestMethodAttribute = NUnit.Framework.TestAttribute; | |||
| 
             | 
        9 | ||||
| 
             | 
        10 | #else | |||
| 
             | 
        11 | ||||
| 
             | 
        12 | using Microsoft.VisualStudio.TestTools.UnitTesting; | |||
| 
             | 
        13 | ||||
| 
             | 
        14 | #endif | |||
| 
             | 
        15 | ||||
| 
             | 
        16 | namespace Implab.Test { | |||
| 
             | 
        17 | [TestClass] | |||
| 
             | 
        18 | public class CancelationTests { | |||
| 
             | 
        19 | ||||
| 
             | 
        20 | [TestMethod] | |||
| 
             | 
        21 | public void PromiseCancelTest() { | |||
| 
             | 
        22 | var p = new Promise(); | |||
| 
             | 
        23 | bool requested = false; | |||
| 
             | 
        24 | var reason = new Exception("Test"); | |||
| 
             | 
        25 | ||||
| 
             | 
        26 | // request cancelation | |||
| 
             | 
        27 | p.Cancel(reason); | |||
| 
             | 
        28 | ||||
| 
             | 
        29 | Assert.IsTrue(p.IsCancellationRequested); | |||
| 
             | 
        30 | Assert.AreSame(reason, p.CancellationReason); | |||
| 
             | 
        31 | Assert.IsFalse(p.IsCancelled); | |||
| 
             | 
        32 | ||||
| 
             | 
        33 | p.CancellationRequested(r => { | |||
| 
             | 
        34 | Assert.AreSame(reason, r); | |||
| 
             | 
        35 | requested = true; | |||
| 
             | 
        36 | }); | |||
| 
             | 
        37 | ||||
| 
             | 
        38 | Assert.IsTrue(requested); | |||
| 
             | 
        39 | ||||
| 
             | 
        40 | // cancel the promise | |||
| 
             | 
        41 | Assert.IsTrue(p.CancelOperationIfRequested()); | |||
| 
             | 
        42 | Assert.IsTrue(p.IsCancelled); | |||
| 
             | 
        43 | Assert.AreSame(reason, p.Error); | |||
| 
             | 
        44 | } | |||
| 
             | 
        45 | ||||
| 
             | 
        46 | [TestMethod] | |||
| 
             | 
        47 | public void CancelActionBeforeStartTask() { | |||
| 
             | 
        48 | bool run = false; | |||
| 
             | 
        49 | var task = new ActionTask(() => { | |||
| 
             | 
        50 | run = true; | |||
| 
             | 
        51 | }, null, null); | |||
| 
             | 
        52 | ||||
| 
             | 
        53 | // request cancelation | |||
| 
             | 
        54 | task.Cancel(); | |||
| 
             | 
        55 | Assert.IsTrue(task.IsCancelled); | |||
| 
             | 
        56 | task.Resolve(); | |||
| 
             | 
        57 | Assert.IsFalse(run); | |||
| 
             | 
        58 | } | |||
| 
             | 
        59 | ||||
| 
             | 
        60 | [TestMethod] | |||
| 
             | 
        61 | public void CancelActionAfterTaskStarted() { | |||
| 
             | 
        62 | var finish = new Signal(); | |||
| 
             | 
        63 | var started = new Signal(); | |||
| 
             | 
        64 | ||||
| 
             | 
        65 | var task = new ActionTask(() => { | |||
| 
             | 
        66 | started.Set(); | |||
| 
             | 
        67 | finish.Wait(); | |||
| 
             | 
        68 | }, null, null); | |||
| 
             | 
        69 | ||||
| 
             | 
        70 | AsyncPool.RunThread(() => { | |||
| 
             | 
        71 | task.Resolve(); | |||
| 
             | 
        72 | }); | |||
| 
             | 
        73 | ||||
| 
             | 
        74 | started.Wait(1000); | |||
| 
             | 
        75 | ||||
| 
             | 
        76 | task.Cancel(); | |||
| 
             | 
        77 | Assert.IsTrue(task.IsCancellationRequested); | |||
| 
             | 
        78 | Assert.IsFalse(task.IsCancelled); | |||
| 
             | 
        79 | Assert.IsFalse(task.IsResolved); | |||
| 
             | 
        80 | ||||
| 
             | 
        81 | finish.Set(); | |||
| 
             | 
        82 | task.Join(1000); | |||
| 
             | 
        83 | ||||
| 
             | 
        84 | } | |||
| 
             | 
        85 | ||||
| 
             | 
        86 | [TestMethod] | |||
| 
             | 
        87 | public void CancelTaskChainFromBottom() { | |||
| 
             | 
        88 | var check1 = new Signal(); | |||
| 
             | 
        89 | var requested = false; | |||
| 
             | 
        90 | var p1 = AsyncPool.RunThread(token => { | |||
| 
             | 
        91 | token.CancellationRequested(reason => requested = true); | |||
| 
             | 
        92 | check1.Wait(); | |||
| 
             | 
        93 | token.CancelOperationIfRequested(); | |||
| 
             | 
        94 | }); | |||
| 
             | 
        95 | ||||
| 
             | 
        96 | var p2 = p1.Then(() => { | |||
| 
             | 
        97 | }); | |||
| 
             | 
        98 | ||||
| 
             | 
        99 | Assert.IsFalse(p1.IsResolved); | |||
| 
             | 
        100 | Assert.IsFalse(p2.IsResolved); | |||
| 
             | 
        101 | ||||
| 
             | 
        102 | p2.Cancel(); | |||
| 
             | 
        103 | ||||
| 
             | 
        104 | Assert.IsFalse(p2.IsCancelled); | |||
| 
             | 
        105 | Assert.IsFalse(p1.IsCancelled); | |||
| 
             | 
        106 | Assert.IsTrue(requested); | |||
| 
             | 
        107 | ||||
| 
             | 
        108 | check1.Set(); | |||
| 
             | 
        109 | ||||
| 
             | 
        110 | try { | |||
| 
             | 
        111 | p2.Join(1000); | |||
| 
             | 
        112 | Assert.Fail("The chain isn't cancelled"); | |||
| 
             | 
        113 | } catch(OperationCanceledException){ | |||
| 
             | 
        114 | } | |||
| 
             | 
        115 | ||||
| 
             | 
        116 | Assert.IsTrue(p1.IsCancelled); | |||
| 
             | 
        117 | Assert.IsTrue(p2.IsCancelled); | |||
| 
             | 
        118 | } | |||
| 
             | 
        119 | ||||
| 
             | 
        120 | ||||
| 
             | 
        121 | ||||
| 
             | 
        122 | [TestMethod] | |||
| 
             | 
        123 | public void CancellableAsyncTask() { | |||
| 
             | 
        124 | var finish = new Signal(); | |||
| 
             | 
        125 | var started = new Signal(); | |||
| 
             | 
        126 | ||||
| 
             | 
        127 | var p = AsyncPool.RunThread(token => { | |||
| 
             | 
        128 | token.CancellationRequested(r => finish.Set()); | |||
| 
             | 
        129 | started.Set(); | |||
| 
             | 
        130 | finish.Wait(); | |||
| 
             | 
        131 | Assert.IsTrue(token.CancelOperationIfRequested()); | |||
| 
             | 
        132 | }); | |||
| 
             | 
        133 | ||||
| 
             | 
        134 | started.Wait(1000); | |||
| 
             | 
        135 | Assert.IsFalse(p.IsResolved); | |||
| 
             | 
        136 | p.Cancel(); | |||
| 
             | 
        137 | try { | |||
| 
             | 
        138 | p.Join(1000); | |||
| 
             | 
        139 | } catch (OperationCanceledException) { | |||
| 
             | 
        140 | } | |||
| 
             | 
        141 | } | |||
| 
             | 
        142 | } | |||
| 
             | 
        143 | } | |||
| 
             | 
        144 | ||||
| @@ -0,0 +1,23 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | ||||
| 
             | 
        3 | namespace Implab { | |||
| 
             | 
        4 | public class ActionChainTask : ActionChainTaskBase, IDeferred { | |||
| 
             | 
        5 | readonly Func<IPromise> m_task; | |||
| 
             | 
        6 | ||||
| 
             | 
        7 | public ActionChainTask(Func<IPromise> task, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) : base(error,cancel) { | |||
| 
             | 
        8 | m_task = task; | |||
| 
             | 
        9 | } | |||
| 
             | 
        10 | ||||
| 
             | 
        11 | public void Resolve() { | |||
| 
             | 
        12 | if (m_task != null && LockCancelation()) { | |||
| 
             | 
        13 | try { | |||
| 
             | 
        14 | Observe(m_task()); | |||
| 
             | 
        15 | } catch(Exception err) { | |||
| 
             | 
        16 | HandleErrorInternal(err); | |||
| 
             | 
        17 | } | |||
| 
             | 
        18 | } | |||
| 
             | 
        19 | } | |||
| 
             | 
        20 | ||||
| 
             | 
        21 | } | |||
| 
             | 
        22 | } | |||
| 
             | 
        23 | ||||
| @@ -0,0 +1,62 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | using System.Threading; | |||
| 
             | 
        3 | ||||
| 
             | 
        4 | namespace Implab { | |||
| 
             | 
        5 | public class ActionChainTaskBase : AbstractPromise { | |||
| 
             | 
        6 | readonly Func<Exception, IPromise> m_error; | |||
| 
             | 
        7 | readonly Func<Exception, IPromise> m_cancel; | |||
| 
             | 
        8 | ||||
| 
             | 
        9 | int m_cancelationLock; | |||
| 
             | 
        10 | ||||
| 
             | 
        11 | protected ActionChainTaskBase( Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) { | |||
| 
             | 
        12 | m_error = error; | |||
| 
             | 
        13 | m_cancel = cancel; | |||
| 
             | 
        14 | } | |||
| 
             | 
        15 | ||||
| 
             | 
        16 | public void Reject(Exception error) { | |||
| 
             | 
        17 | if (LockCancelation()) | |||
| 
             | 
        18 | HandleErrorInternal(error); | |||
| 
             | 
        19 | } | |||
| 
             | 
        20 | ||||
| 
             | 
        21 | ||||
| 
             | 
        22 | ||||
| 
             | 
        23 | public override void CancelOperation(Exception reason) { | |||
| 
             | 
        24 | if (m_cancel != null && LockCancelation()) { | |||
| 
             | 
        25 | try { | |||
| 
             | 
        26 | Observe(m_cancel(reason)); | |||
| 
             | 
        27 | } catch(Exception err) { | |||
| 
             | 
        28 | HandleErrorInternal(err); | |||
| 
             | 
        29 | } | |||
| 
             | 
        30 | } | |||
| 
             | 
        31 | ||||
| 
             | 
        32 | } | |||
| 
             | 
        33 | ||||
| 
             | 
        34 | protected void HandleErrorInternal(Exception error) { | |||
| 
             | 
        35 | if (m_error != null) { | |||
| 
             | 
        36 | try { | |||
| 
             | 
        37 | Observe(m_error(error)); | |||
| 
             | 
        38 | } catch(Exception err) { | |||
| 
             | 
        39 | SetError(err); | |||
| 
             | 
        40 | } | |||
| 
             | 
        41 | } else { | |||
| 
             | 
        42 | SetError(error); | |||
| 
             | 
        43 | } | |||
| 
             | 
        44 | } | |||
| 
             | 
        45 | ||||
| 
             | 
        46 | protected void Observe(IPromise operation) { | |||
| 
             | 
        47 | if (operation == null) | |||
| 
             | 
        48 | throw new NullReferenceException("The task returned null promise"); | |||
| 
             | 
        49 | ||||
| 
             | 
        50 | // pass operation results to the current promise | |||
| 
             | 
        51 | operation.On(SetResult, SetError, SetCancelled); | |||
| 
             | 
        52 | ||||
| 
             | 
        53 | // pass the cancelation request | |||
| 
             | 
        54 | CancellationRequested(operation.Cancel); | |||
| 
             | 
        55 | } | |||
| 
             | 
        56 | ||||
| 
             | 
        57 | protected bool LockCancelation() { | |||
| 
             | 
        58 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | |||
| 
             | 
        59 | } | |||
| 
             | 
        60 | } | |||
| 
             | 
        61 | } | |||
| 
             | 
        62 | ||||
| @@ -0,0 +1,23 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | ||||
| 
             | 
        3 | namespace Implab { | |||
| 
             | 
        4 | public class ActionChainTask<T> : ActionChainTaskBase, IDeferred<T> { | |||
| 
             | 
        5 | readonly Func<T, IPromise> m_task; | |||
| 
             | 
        6 | ||||
| 
             | 
        7 | public ActionChainTask(Func<T, IPromise> task, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) : base(error,cancel) { | |||
| 
             | 
        8 | m_task = task; | |||
| 
             | 
        9 | } | |||
| 
             | 
        10 | ||||
| 
             | 
        11 | public void Resolve(T value) { | |||
| 
             | 
        12 | if (m_task != null && LockCancelation()) { | |||
| 
             | 
        13 | try { | |||
| 
             | 
        14 | Observe(m_task(value)); | |||
| 
             | 
        15 | } catch(Exception err) { | |||
| 
             | 
        16 | HandleErrorInternal(err); | |||
| 
             | 
        17 | } | |||
| 
             | 
        18 | } | |||
| 
             | 
        19 | } | |||
| 
             | 
        20 | ||||
| 
             | 
        21 | } | |||
| 
             | 
        22 | } | |||
| 
             | 
        23 | ||||
| @@ -0,0 +1,22 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | ||||
| 
             | 
        3 | namespace Implab { | |||
| 
             | 
        4 | public class ActionTask : ActionTaskBase, IDeferred { | |||
| 
             | 
        5 | readonly Action m_task; | |||
| 
             | 
        6 | public ActionTask(Action task, Action<Exception> error, Action<Exception> cancel) : base(error,cancel) { | |||
| 
             | 
        7 | m_task = task; | |||
| 
             | 
        8 | } | |||
| 
             | 
        9 | ||||
| 
             | 
        10 | public void Resolve() { | |||
| 
             | 
        11 | if (m_task != null && LockCancelation()) { | |||
| 
             | 
        12 | try { | |||
| 
             | 
        13 | m_task(); | |||
| 
             | 
        14 | SetResult(); | |||
| 
             | 
        15 | } catch(Exception err) { | |||
| 
             | 
        16 | HandleErrorInternal(err); | |||
| 
             | 
        17 | } | |||
| 
             | 
        18 | } | |||
| 
             | 
        19 | } | |||
| 
             | 
        20 | } | |||
| 
             | 
        21 | } | |||
| 
             | 
        22 | ||||
| @@ -0,0 +1,55 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | using System.Threading; | |||
| 
             | 
        3 | ||||
| 
             | 
        4 | namespace Implab { | |||
| 
             | 
        5 | public class ActionTaskBase : AbstractPromise { | |||
| 
             | 
        6 | readonly Action<Exception> m_cancel; | |||
| 
             | 
        7 | readonly Action<Exception> m_error; | |||
| 
             | 
        8 | ||||
| 
             | 
        9 | int m_cancelationLock; | |||
| 
             | 
        10 | ||||
| 
             | 
        11 | protected ActionTaskBase( Action<Exception> error, Action<Exception> cancel) { | |||
| 
             | 
        12 | m_error = error; | |||
| 
             | 
        13 | m_cancel = cancel; | |||
| 
             | 
        14 | } | |||
| 
             | 
        15 | ||||
| 
             | 
        16 | public void Reject(Exception error) { | |||
| 
             | 
        17 | Safe.ArgumentNotNull(error, "error"); | |||
| 
             | 
        18 | if (LockCancelation()) | |||
| 
             | 
        19 | HandleErrorInternal(error); | |||
| 
             | 
        20 | } | |||
| 
             | 
        21 | ||||
| 
             | 
        22 | protected void HandleErrorInternal(Exception error) { | |||
| 
             | 
        23 | if (m_error != null) { | |||
| 
             | 
        24 | try { | |||
| 
             | 
        25 | m_error(error); | |||
| 
             | 
        26 | SetResult(); | |||
| 
             | 
        27 | } catch(Exception err) { | |||
| 
             | 
        28 | SetError(err); | |||
| 
             | 
        29 | } | |||
| 
             | 
        30 | } else { | |||
| 
             | 
        31 | SetError(error); | |||
| 
             | 
        32 | } | |||
| 
             | 
        33 | } | |||
| 
             | 
        34 | ||||
| 
             | 
        35 | public override void CancelOperation(Exception reason) { | |||
| 
             | 
        36 | if (LockCancelation()) { | |||
| 
             | 
        37 | if (m_cancel != null) { | |||
| 
             | 
        38 | try { | |||
| 
             | 
        39 | m_cancel(reason); | |||
| 
             | 
        40 | SetResult(); | |||
| 
             | 
        41 | } catch (Exception err) { | |||
| 
             | 
        42 | HandleErrorInternal(err); | |||
| 
             | 
        43 | } | |||
| 
             | 
        44 | } else { | |||
| 
             | 
        45 | SetCancelled(reason); | |||
| 
             | 
        46 | } | |||
| 
             | 
        47 | } | |||
| 
             | 
        48 | } | |||
| 
             | 
        49 | ||||
| 
             | 
        50 | protected bool LockCancelation() { | |||
| 
             | 
        51 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | |||
| 
             | 
        52 | } | |||
| 
             | 
        53 | } | |||
| 
             | 
        54 | } | |||
| 
             | 
        55 | ||||
| @@ -0,0 +1,22 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | ||||
| 
             | 
        3 | namespace Implab { | |||
| 
             | 
        4 | public class ActionTask<T> : ActionTaskBase, IDeferred<T> { | |||
| 
             | 
        5 | readonly Action<T> m_task; | |||
| 
             | 
        6 | public ActionTask(Action<T> task, Action<Exception> error, Action<Exception> cancel) : base(error,cancel) { | |||
| 
             | 
        7 | m_task = task; | |||
| 
             | 
        8 | } | |||
| 
             | 
        9 | ||||
| 
             | 
        10 | public void Resolve(T value) { | |||
| 
             | 
        11 | if (m_task != null && LockCancelation()) { | |||
| 
             | 
        12 | try { | |||
| 
             | 
        13 | m_task(value); | |||
| 
             | 
        14 | SetResult(); | |||
| 
             | 
        15 | } catch(Exception err) { | |||
| 
             | 
        16 | HandleErrorInternal(err); | |||
| 
             | 
        17 | } | |||
| 
             | 
        18 | } | |||
| 
             | 
        19 | } | |||
| 
             | 
        20 | } | |||
| 
             | 
        21 | } | |||
| 
             | 
        22 | ||||
| @@ -0,0 +1,21 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | ||||
| 
             | 
        3 | namespace Implab { | |||
| 
             | 
        4 | public class FuncChainTask<TResult> : FuncChainTaskBase<TResult>, IDeferred { | |||
| 
             | 
        5 | readonly Func<IPromise<TResult>> m_task; | |||
| 
             | 
        6 | ||||
| 
             | 
        7 | public FuncChainTask(Func<IPromise<TResult>> task, Func<Exception, IPromise<TResult>> error, Func<Exception, IPromise<TResult>> cancel) : base(error, cancel){ | |||
| 
             | 
        8 | m_task = task; | |||
| 
             | 
        9 | } | |||
| 
             | 
        10 | ||||
| 
             | 
        11 | public void Resolve() { | |||
| 
             | 
        12 | if (m_task != null && LockCancelation()) { | |||
| 
             | 
        13 | try { | |||
| 
             | 
        14 | Observe(m_task()); | |||
| 
             | 
        15 | } catch (Exception err) { | |||
| 
             | 
        16 | HandleErrorInternal(err); | |||
| 
             | 
        17 | } | |||
| 
             | 
        18 | } | |||
| 
             | 
        19 | } | |||
| 
             | 
        20 | } | |||
| 
             | 
        21 | } No newline at end of file | |||
| @@ -0,0 +1,60 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | using System.Threading; | |||
| 
             | 
        3 | ||||
| 
             | 
        4 | namespace Implab { | |||
| 
             | 
        5 | public class FuncChainTaskBase<TResult> : AbstractPromise<TResult> { | |||
| 
             | 
        6 | readonly Func<Exception, IPromise<TResult>> m_error; | |||
| 
             | 
        7 | readonly Func<Exception, IPromise<TResult>> m_cancel; | |||
| 
             | 
        8 | ||||
| 
             | 
        9 | int m_cancelationLock; | |||
| 
             | 
        10 | ||||
| 
             | 
        11 | protected FuncChainTaskBase( Func<Exception, IPromise<TResult>> error, Func<Exception, IPromise<TResult>> cancel) { | |||
| 
             | 
        12 | m_error = error; | |||
| 
             | 
        13 | m_cancel = cancel; | |||
| 
             | 
        14 | } | |||
| 
             | 
        15 | ||||
| 
             | 
        16 | public void Reject(Exception error) { | |||
| 
             | 
        17 | if (LockCancelation()) | |||
| 
             | 
        18 | HandleErrorInternal(error); | |||
| 
             | 
        19 | } | |||
| 
             | 
        20 | ||||
| 
             | 
        21 | public override void CancelOperation(Exception reason) { | |||
| 
             | 
        22 | if (m_cancel != null && LockCancelation()) { | |||
| 
             | 
        23 | try { | |||
| 
             | 
        24 | Observe(m_cancel(reason)); | |||
| 
             | 
        25 | } catch(Exception err) { | |||
| 
             | 
        26 | HandleErrorInternal(err); | |||
| 
             | 
        27 | } | |||
| 
             | 
        28 | } | |||
| 
             | 
        29 | ||||
| 
             | 
        30 | } | |||
| 
             | 
        31 | ||||
| 
             | 
        32 | protected void HandleErrorInternal(Exception error) { | |||
| 
             | 
        33 | if (m_error != null) { | |||
| 
             | 
        34 | try { | |||
| 
             | 
        35 | Observe(m_error(error)); | |||
| 
             | 
        36 | } catch(Exception err) { | |||
| 
             | 
        37 | SetError(err); | |||
| 
             | 
        38 | } | |||
| 
             | 
        39 | } else { | |||
| 
             | 
        40 | SetError(error); | |||
| 
             | 
        41 | } | |||
| 
             | 
        42 | } | |||
| 
             | 
        43 | ||||
| 
             | 
        44 | protected void Observe(IPromise<TResult> operation) { | |||
| 
             | 
        45 | if (operation == null) | |||
| 
             | 
        46 | throw new NullReferenceException("The task returned null promise"); | |||
| 
             | 
        47 | ||||
| 
             | 
        48 | // pass operation results to the current promise | |||
| 
             | 
        49 | operation.On(SetResult, SetError, SetCancelled); | |||
| 
             | 
        50 | ||||
| 
             | 
        51 | // pass the cancelation request | |||
| 
             | 
        52 | CancellationRequested(operation.Cancel); | |||
| 
             | 
        53 | } | |||
| 
             | 
        54 | ||||
| 
             | 
        55 | protected bool LockCancelation() { | |||
| 
             | 
        56 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | |||
| 
             | 
        57 | } | |||
| 
             | 
        58 | } | |||
| 
             | 
        59 | } | |||
| 
             | 
        60 | ||||
| @@ -0,0 +1,21 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | ||||
| 
             | 
        3 | namespace Implab { | |||
| 
             | 
        4 | public class FuncChainTask<TArg,TResult> : FuncChainTaskBase<TResult>, IDeferred<TArg> { | |||
| 
             | 
        5 | readonly Func<TArg, IPromise<TResult>> m_task; | |||
| 
             | 
        6 | ||||
| 
             | 
        7 | public FuncChainTask(Func<TArg, IPromise<TResult>> task, Func<Exception, IPromise<TResult>> error, Func<Exception, IPromise<TResult>> cancel) : base(error, cancel){ | |||
| 
             | 
        8 | m_task = task; | |||
| 
             | 
        9 | } | |||
| 
             | 
        10 | ||||
| 
             | 
        11 | public void Resolve(TArg value) { | |||
| 
             | 
        12 | if (m_task != null && LockCancelation()) { | |||
| 
             | 
        13 | try { | |||
| 
             | 
        14 | Observe(m_task(value)); | |||
| 
             | 
        15 | } catch (Exception err) { | |||
| 
             | 
        16 | HandleErrorInternal(err); | |||
| 
             | 
        17 | } | |||
| 
             | 
        18 | } | |||
| 
             | 
        19 | } | |||
| 
             | 
        20 | } | |||
| 
             | 
        21 | } No newline at end of file | |||
| @@ -0,0 +1,36 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | ||||
| 
             | 
        3 | namespace Implab { | |||
| 
             | 
        4 | public interface ICancellationToken { | |||
| 
             | 
        5 | /// <summary> | |||
| 
             | 
        6 | /// Indicates wherther the cancellation was requested. | |||
| 
             | 
        7 | /// </summary> | |||
| 
             | 
        8 | bool IsCancellationRequested { get ; } | |||
| 
             | 
        9 | ||||
| 
             | 
        10 | /// <summary> | |||
| 
             | 
        11 | /// The reason why the operation should be cancelled. | |||
| 
             | 
        12 | /// </summary> | |||
| 
             | 
        13 | Exception CancellationReason { get ; } | |||
| 
             | 
        14 | ||||
| 
             | 
        15 | /// <summary> | |||
| 
             | 
        16 | /// Accepts if requested. | |||
| 
             | 
        17 | /// </summary> | |||
| 
             | 
        18 | /// <returns><c>true</c>, if if requested was accepted, <c>false</c> otherwise.</returns> | |||
| 
             | 
        19 | bool CancelOperationIfRequested(); | |||
| 
             | 
        20 | ||||
| 
             | 
        21 | /// <summary> | |||
| 
             | 
        22 | /// Sets the token to cancelled state. | |||
| 
             | 
        23 | /// </summary> | |||
| 
             | 
        24 | /// <param name="reason">The reason why the operation was cancelled.</param> | |||
| 
             | 
        25 | void CancelOperation(Exception reason); | |||
| 
             | 
        26 | ||||
| 
             | 
        27 | /// <summary> | |||
| 
             | 
        28 | /// Adds the listener for the cancellation request, is the cancellation was requested the <paramref name="handler"/> | |||
| 
             | 
        29 | /// is executed immediatelly. | |||
| 
             | 
        30 | /// </summary> | |||
| 
             | 
        31 | /// <param name="handler">The handler which will be executed if the cancel occurs.</param> | |||
| 
             | 
        32 | void CancellationRequested(Action<Exception> handler); | |||
| 
             | 
        33 | ||||
| 
             | 
        34 | } | |||
| 
             | 
        35 | } | |||
| 
             | 
        36 | ||||
| @@ -0,0 +1,111 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | ||||
| 
             | 
        3 | namespace Implab { | |||
| 
             | 
        4 | public class SuccessPromise : IPromise { | |||
| 
             | 
        5 | #region IPromise implementation | |||
| 
             | 
        6 | ||||
| 
             | 
        7 | public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) { | |||
| 
             | 
        8 | if (success != null) { | |||
| 
             | 
        9 | try { | |||
| 
             | 
        10 | success(); | |||
| 
             | 
        11 | } catch(Exception err) { | |||
| 
             | 
        12 | if (error != null) { | |||
| 
             | 
        13 | try { | |||
| 
             | 
        14 | error(err); | |||
| 
             | 
        15 | // Analysis disable once EmptyGeneralCatchClause | |||
| 
             | 
        16 | } catch { | |||
| 
             | 
        17 | } | |||
| 
             | 
        18 | } | |||
| 
             | 
        19 | } | |||
| 
             | 
        20 | } | |||
| 
             | 
        21 | return this; | |||
| 
             | 
        22 | } | |||
| 
             | 
        23 | ||||
| 
             | 
        24 | public IPromise On(Action success, Action<Exception> error) { | |||
| 
             | 
        25 | if (success != null) { | |||
| 
             | 
        26 | try { | |||
| 
             | 
        27 | success(); | |||
| 
             | 
        28 | } catch(Exception err) { | |||
| 
             | 
        29 | if (error != null) { | |||
| 
             | 
        30 | try { | |||
| 
             | 
        31 | error(err); | |||
| 
             | 
        32 | // Analysis disable once EmptyGeneralCatchClause | |||
| 
             | 
        33 | } catch { | |||
| 
             | 
        34 | } | |||
| 
             | 
        35 | } | |||
| 
             | 
        36 | } | |||
| 
             | 
        37 | } | |||
| 
             | 
        38 | return this; | |||
| 
             | 
        39 | } | |||
| 
             | 
        40 | ||||
| 
             | 
        41 | public IPromise On(Action success) { | |||
| 
             | 
        42 | if (success != null) { | |||
| 
             | 
        43 | try { | |||
| 
             | 
        44 | success(); | |||
| 
             | 
        45 | // Analysis disable once EmptyGeneralCatchClause | |||
| 
             | 
        46 | } catch { | |||
| 
             | 
        47 | } | |||
| 
             | 
        48 | } | |||
| 
             | 
        49 | return this; | |||
| 
             | 
        50 | } | |||
| 
             | 
        51 | ||||
| 
             | 
        52 | public IPromise On(Action handler, PromiseEventType events) { | |||
| 
             | 
        53 | if (handler != null && events.HasFlag(PromiseEventType.Success)) { | |||
| 
             | 
        54 | try { | |||
| 
             | 
        55 | handler(); | |||
| 
             | 
        56 | // Analysis disable once EmptyGeneralCatchClause | |||
| 
             | 
        57 | } catch { | |||
| 
             | 
        58 | } | |||
| 
             | 
        59 | } | |||
| 
             | 
        60 | return this; | |||
| 
             | 
        61 | } | |||
| 
             | 
        62 | ||||
| 
             | 
        63 | public IPromise<T> Cast<T>() { | |||
| 
             | 
        64 | throw new InvalidCastException(); | |||
| 
             | 
        65 | } | |||
| 
             | 
        66 | ||||
| 
             | 
        67 | public void Join() { | |||
| 
             | 
        68 | } | |||
| 
             | 
        69 | ||||
| 
             | 
        70 | public void Join(int timeout) { | |||
| 
             | 
        71 | } | |||
| 
             | 
        72 | ||||
| 
             | 
        73 | public Type PromiseType { | |||
| 
             | 
        74 | get { | |||
| 
             | 
        75 | return typeof(void); | |||
| 
             | 
        76 | } | |||
| 
             | 
        77 | } | |||
| 
             | 
        78 | ||||
| 
             | 
        79 | public bool IsResolved { | |||
| 
             | 
        80 | get { | |||
| 
             | 
        81 | return true; | |||
| 
             | 
        82 | } | |||
| 
             | 
        83 | } | |||
| 
             | 
        84 | ||||
| 
             | 
        85 | public bool IsCancelled { | |||
| 
             | 
        86 | get { | |||
| 
             | 
        87 | return false; | |||
| 
             | 
        88 | } | |||
| 
             | 
        89 | } | |||
| 
             | 
        90 | ||||
| 
             | 
        91 | public Exception Error { | |||
| 
             | 
        92 | get { | |||
| 
             | 
        93 | return null; | |||
| 
             | 
        94 | } | |||
| 
             | 
        95 | } | |||
| 
             | 
        96 | ||||
| 
             | 
        97 | #endregion | |||
| 
             | 
        98 | ||||
| 
             | 
        99 | #region ICancellable implementation | |||
| 
             | 
        100 | ||||
| 
             | 
        101 | public void Cancel() { | |||
| 
             | 
        102 | } | |||
| 
             | 
        103 | ||||
| 
             | 
        104 | public void Cancel(Exception reason) { | |||
| 
             | 
        105 | } | |||
| 
             | 
        106 | ||||
| 
             | 
        107 | #endregion | |||
| 
             | 
        108 | ||||
| 
             | 
        109 | } | |||
| 
             | 
        110 | } | |||
| 
             | 
        111 | ||||
| @@ -0,0 +1,177 | |||||
| 
             | 
        1 | using System; | |||
| 
             | 
        2 | ||||
| 
             | 
        3 | namespace Implab { | |||
| 
             | 
        4 | public class SuccessPromise<T> : IPromise<T> { | |||
| 
             | 
        5 | readonly T m_value; | |||
| 
             | 
        6 | ||||
| 
             | 
        7 | public SuccessPromise(T value){ | |||
| 
             | 
        8 | m_value = value; | |||
| 
             | 
        9 | } | |||
| 
             | 
        10 | ||||
| 
             | 
        11 | public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) { | |||
| 
             | 
        12 | if (success != null) { | |||
| 
             | 
        13 | try { | |||
| 
             | 
        14 | success(m_value); | |||
| 
             | 
        15 | } catch(Exception err) { | |||
| 
             | 
        16 | if (error != null) { | |||
| 
             | 
        17 | try { | |||
| 
             | 
        18 | error(err); | |||
| 
             | 
        19 | // Analysis disable once EmptyGeneralCatchClause | |||
| 
             | 
        20 | } catch { | |||
| 
             | 
        21 | } | |||
| 
             | 
        22 | } | |||
| 
             | 
        23 | } | |||
| 
             | 
        24 | } | |||
| 
             | 
        25 | return this; | |||
| 
             | 
        26 | } | |||
| 
             | 
        27 | ||||
| 
             | 
        28 | public IPromise<T> On(Action<T> success, Action<Exception> error) { | |||
| 
             | 
        29 | if (success != null) { | |||
| 
             | 
        30 | try { | |||
| 
             | 
        31 | success(m_value); | |||
| 
             | 
        32 | } catch(Exception err) { | |||
| 
             | 
        33 | if (error != null) { | |||
| 
             | 
        34 | try { | |||
| 
             | 
        35 | error(err); | |||
| 
             | 
        36 | // Analysis disable once EmptyGeneralCatchClause | |||
| 
             | 
        37 | } catch { | |||
| 
             | 
        38 | } | |||
| 
             | 
        39 | } | |||
| 
             | 
        40 | } | |||
| 
             | 
        41 | } | |||
| 
             | 
        42 | return this; | |||
| 
             | 
        43 | } | |||
| 
             | 
        44 | ||||
| 
             | 
        45 | public IPromise<T> On(Action<T> success) { | |||
| 
             | 
        46 | if (success != null) { | |||
| 
             | 
        47 | try { | |||
| 
             | 
        48 | success(m_value); | |||
| 
             | 
        49 | // Analysis disable once EmptyGeneralCatchClause | |||
| 
             | 
        50 | } catch { | |||
| 
             | 
        51 | } | |||
| 
             | 
        52 | } | |||
| 
             | 
        53 | return this; | |||
| 
             | 
        54 | } | |||
| 
             | 
        55 | ||||
| 
             | 
        56 | public T Join() { | |||
| 
             | 
        57 | return m_value; | |||
| 
             | 
        58 | } | |||
| 
             | 
        59 | ||||
| 
             | 
        60 | public T Join(int timeout) { | |||
| 
             | 
        61 | return m_value; | |||
| 
             | 
        62 | } | |||
| 
             | 
        63 | ||||
| 
             | 
        64 | public IPromise<T> On(Action success, Action<Exception> error, Action<Exception> cancel) { | |||
| 
             | 
        65 | if (success != null) { | |||
| 
             | 
        66 | try { | |||
| 
             | 
        67 | success(); | |||
| 
             | 
        68 | } catch(Exception err) { | |||
| 
             | 
        69 | if (error != null) { | |||
| 
             | 
        70 | try { | |||
| 
             | 
        71 | error(err); | |||
| 
             | 
        72 | // Analysis disable once EmptyGeneralCatchClause | |||
| 
             | 
        73 | } catch { | |||
| 
             | 
        74 | } | |||
| 
             | 
        75 | } | |||
| 
             | 
        76 | } | |||
| 
             | 
        77 | } | |||
| 
             | 
        78 | return this; | |||
| 
             | 
        79 | } | |||
| 
             | 
        80 | ||||
| 
             | 
        81 | public IPromise<T> On(Action success, Action<Exception> error) { | |||
| 
             | 
        82 | if (success != null) { | |||
| 
             | 
        83 | try { | |||
| 
             | 
        84 | success(); | |||
| 
             | 
        85 | } catch(Exception err) { | |||
| 
             | 
        86 | if (error != null) { | |||
| 
             | 
        87 | try { | |||
| 
             | 
        88 | error(err); | |||
| 
             | 
        89 | // Analysis disable once EmptyGeneralCatchClause | |||
| 
             | 
        90 | } catch { | |||
| 
             | 
        91 | } | |||
| 
             | 
        92 | } | |||
| 
             | 
        93 | } | |||
| 
             | 
        94 | } | |||
| 
             | 
        95 | return this; | |||
| 
             | 
        96 | } | |||
| 
             | 
        97 | ||||
| 
             | 
        98 | public IPromise<T> On(Action success) { | |||
| 
             | 
        99 | if (success != null) { | |||
| 
             | 
        100 | try { | |||
| 
             | 
        101 | success(); | |||
| 
             | 
        102 | // Analysis disable once EmptyGeneralCatchClause | |||
| 
             | 
        103 | } catch { | |||
| 
             | 
        104 | } | |||
| 
             | 
        105 | } | |||
| 
             | 
        106 | return this; | |||
| 
             | 
        107 | } | |||
| 
             | 
        108 | ||||
| 
             | 
        109 | public IPromise<T> On(Action handler, PromiseEventType events) { | |||
| 
             | 
        110 | if (handler != null && events.HasFlag(PromiseEventType.Success)) { | |||
| 
             | 
        111 | try { | |||
| 
             | 
        112 | handler(); | |||
| 
             | 
        113 | // Analysis disable once EmptyGeneralCatchClause | |||
| 
             | 
        114 | } catch { | |||
| 
             | 
        115 | } | |||
| 
             | 
        116 | } | |||
| 
             | 
        117 | return this; | |||
| 
             | 
        118 | } | |||
| 
             | 
        119 | ||||
| 
             | 
        120 | IPromise IPromise.On(Action success, Action<Exception> error, Action<Exception> cancel) { | |||
| 
             | 
        121 | return On(success, error, cancel); | |||
| 
             | 
        122 | } | |||
| 
             | 
        123 | ||||
| 
             | 
        124 | IPromise IPromise.On(Action success, Action<Exception> error) { | |||
| 
             | 
        125 | return On(success, error); | |||
| 
             | 
        126 | } | |||
| 
             | 
        127 | ||||
| 
             | 
        128 | IPromise IPromise.On(Action success) { | |||
| 
             | 
        129 | return On(success); | |||
| 
             | 
        130 | } | |||
| 
             | 
        131 | ||||
| 
             | 
        132 | IPromise IPromise.On(Action handler, PromiseEventType events) { | |||
| 
             | 
        133 | return On(handler, events); | |||
| 
             | 
        134 | } | |||
| 
             | 
        135 | ||||
| 
             | 
        136 | public IPromise<T2> Cast<T2>() { | |||
| 
             | 
        137 | return new SuccessPromise<T2>((T2)(object)m_value); | |||
| 
             | 
        138 | } | |||
| 
             | 
        139 | ||||
| 
             | 
        140 | void IPromise.Join() { | |||
| 
             | 
        141 | } | |||
| 
             | 
        142 | ||||
| 
             | 
        143 | void IPromise.Join(int timeout) { | |||
| 
             | 
        144 | } | |||
| 
             | 
        145 | ||||
| 
             | 
        146 | public Type PromiseType { | |||
| 
             | 
        147 | get { | |||
| 
             | 
        148 | return typeof(T); | |||
| 
             | 
        149 | } | |||
| 
             | 
        150 | } | |||
| 
             | 
        151 | ||||
| 
             | 
        152 | public bool IsResolved { | |||
| 
             | 
        153 | get { | |||
| 
             | 
        154 | return true; | |||
| 
             | 
        155 | } | |||
| 
             | 
        156 | } | |||
| 
             | 
        157 | ||||
| 
             | 
        158 | public bool IsCancelled { | |||
| 
             | 
        159 | get { | |||
| 
             | 
        160 | return false; | |||
| 
             | 
        161 | } | |||
| 
             | 
        162 | } | |||
| 
             | 
        163 | ||||
| 
             | 
        164 | public Exception Error { | |||
| 
             | 
        165 | get { | |||
| 
             | 
        166 | return null; | |||
| 
             | 
        167 | } | |||
| 
             | 
        168 | } | |||
| 
             | 
        169 | ||||
| 
             | 
        170 | public void Cancel() { | |||
| 
             | 
        171 | } | |||
| 
             | 
        172 | ||||
| 
             | 
        173 | public void Cancel(Exception reason) { | |||
| 
             | 
        174 | } | |||
| 
             | 
        175 | } | |||
| 
             | 
        176 | } | |||
| 
             | 
        177 | ||||
| @@ -12,23 +12,23 namespace Implab.Fx { | |||||
| 12 | m_target = target; | 
             | 
        12 | m_target = target; | |
| 13 | } | 
             | 
        13 | } | |
| 14 | 
             | 
        14 | |||
| 15 | 
            
                    protected override void SignalSuccess( | 
        
             | 
        15 | protected override void SignalSuccess(Promise<T>.HandlerDescriptor handler) { | |
| 16 | if (m_target.InvokeRequired) | 
             | 
        16 | if (m_target.InvokeRequired) | |
| 17 | 
            
                            m_target.BeginInvoke(new Action< | 
        
             | 
        17 | m_target.BeginInvoke(new Action<Promise<T>.HandlerDescriptor>(base.SignalSuccess), handler); | |
| 18 | else | 
             | 
        18 | else | |
| 19 | base.SignalSuccess(handler); | 
             | 
        19 | base.SignalSuccess(handler); | |
| 20 | } | 
             | 
        20 | } | |
| 21 | 
             | 
        21 | |||
| 22 | 
            
                    protected override void SignalCancelled( | 
        
             | 
        22 | protected override void SignalCancelled(Promise<T>.HandlerDescriptor handler, Exception reason) { | |
| 23 | if (m_target.InvokeRequired) | 
             | 
        23 | if (m_target.InvokeRequired) | |
| 24 | 
            
                            m_target.BeginInvoke(new Action< | 
        
             | 
        24 | m_target.BeginInvoke(new Action<Promise<T>.HandlerDescriptor,Exception>(base.SignalCancelled), handler, reason); | |
| 25 | else | 
             | 
        25 | else | |
| 26 | base.SignalCancelled(handler, reason); | 
             | 
        26 | base.SignalCancelled(handler, reason); | |
| 27 | } | 
             | 
        27 | } | |
| 28 | 
             | 
        28 | |||
| 29 | 
            
                    protected override void SignalError( | 
        
             | 
        29 | protected override void SignalError(Promise<T>.HandlerDescriptor handler, Exception error) { | |
| 30 | if (m_target.InvokeRequired) | 
             | 
        30 | if (m_target.InvokeRequired) | |
| 31 | 
            
                            m_target.BeginInvoke(new Action< | 
        
             | 
        31 | m_target.BeginInvoke(new Action<Promise<T>.HandlerDescriptor,Exception>(base.SignalError), handler, error); | |
| 32 | else | 
             | 
        32 | else | |
| 33 | base.SignalError(handler, error); | 
             | 
        33 | base.SignalError(handler, error); | |
| 34 | } | 
             | 
        34 | } | |
| @@ -7,7 +7,7 using Implab.Parallels; | |||||
| 7 | 
             | 
        7 | |||
| 8 | using NUnit.Framework; | 
             | 
        8 | using NUnit.Framework; | |
| 9 | using TestClassAttribute = NUnit.Framework.TestFixtureAttribute; | 
             | 
        9 | using TestClassAttribute = NUnit.Framework.TestFixtureAttribute; | |
| 10 | using TestMethod = NUnit.Framework.TestAttribute; | 
             | 
        10 | using TestMethodAttribute = NUnit.Framework.TestAttribute; | |
| 11 | 
             | 
        11 | |||
| 12 | #else | 
             | 
        12 | #else | |
| 13 | 
             | 
        13 | |||
| @@ -51,7 +51,7 namespace Implab.Test { | |||||
| 51 | [TestMethod] | 
             | 
        51 | [TestMethod] | |
| 52 | public void CancelExceptionTest() { | 
             | 
        52 | public void CancelExceptionTest() { | |
| 53 | var p = new Promise<bool>(); | 
             | 
        53 | var p = new Promise<bool>(); | |
| 54 | p.Cancel(); | 
             | 
        54 | p.CancelOperation(null); | |
| 55 | 
             | 
        55 | |||
| 56 | var p2 = p.Then(x => x, null, reason => { | 
             | 
        56 | var p2 = p.Then(x => x, null, reason => { | |
| 57 | throw new ApplicationException("CANCELLED"); | 
             | 
        57 | throw new ApplicationException("CANCELLED"); | |
| @@ -69,10 +69,10 namespace Implab.Test { | |||||
| 69 | [TestMethod] | 
             | 
        69 | [TestMethod] | |
| 70 | public void ContinueOnCancelTest() { | 
             | 
        70 | public void ContinueOnCancelTest() { | |
| 71 | var p = new Promise<bool>(); | 
             | 
        71 | var p = new Promise<bool>(); | |
| 72 | p.Cancel(); | 
             | 
        72 | p.CancelOperation(null); | |
| 73 | 
             | 
        73 | |||
| 74 | var p2 = p | 
             | 
        74 | var p2 = p | |
| 75 | 
            
                            .Then | 
        
             | 
        75 | .Then(x => x, null, reason => { | |
| 76 | throw new ApplicationException("CANCELLED"); | 
             | 
        76 | throw new ApplicationException("CANCELLED"); | |
| 77 | }) | 
             | 
        77 | }) | |
| 78 | .Then(x => x, e => true); | 
             | 
        78 | .Then(x => x, e => true); | |
| @@ -56,6 +56,7 | |||||
| 56 | <Compile Include="AsyncTests.cs" /> | 
             | 
        56 | <Compile Include="AsyncTests.cs" /> | |
| 57 | <Compile Include="PromiseHelper.cs" /> | 
             | 
        57 | <Compile Include="PromiseHelper.cs" /> | |
| 58 | <Compile Include="Properties\AssemblyInfo.cs" /> | 
             | 
        58 | <Compile Include="Properties\AssemblyInfo.cs" /> | |
| 
             | 
        59 | <Compile Include="CancelationTests.cs" /> | |||
| 59 | </ItemGroup> | 
             | 
        60 | </ItemGroup> | |
| 60 | <ItemGroup> | 
             | 
        61 | <ItemGroup> | |
| 61 | <ProjectReference Include="..\Implab\Implab.csproj"> | 
             | 
        62 | <ProjectReference Include="..\Implab\Implab.csproj"> | |
| @@ -4,7 +4,7 using System.Threading; | |||||
| 4 | using System.Reflection; | 
             | 
        4 | using System.Reflection; | |
| 5 | 
             | 
        5 | |||
| 6 | namespace Implab { | 
             | 
        6 | namespace Implab { | |
| 7 | public abstract class AbstractEvent<THandler> : ICancelationToken, ICancellable { | 
             | 
        7 | public abstract class AbstractEvent<THandler> : ICancellationToken, ICancellable { | |
| 8 | 
             | 
        8 | |||
| 9 | const int UNRESOLVED_SATE = 0; | 
             | 
        9 | const int UNRESOLVED_SATE = 0; | |
| 10 | const int TRANSITIONAL_STATE = 1; | 
             | 
        10 | const int TRANSITIONAL_STATE = 1; | |
| @@ -280,31 +280,34 namespace Implab { | |||||
| 280 | } | 
             | 
        280 | } | |
| 281 | } | 
             | 
        281 | } | |
| 282 | 
             | 
        282 | |||
| 283 | 
            
                    public bool  | 
        
             | 
        283 | public bool CancelOperationIfRequested() { | |
| 284 | if (IsCancelRequested) | 
             | 
        284 | if (IsCancellationRequested) { | |
| 285 | CancelOperation(CancelReason); | 
             | 
        285 | CancelOperation(CancellationReason); | |
| 
             | 
        286 | return true; | |||
| 
             | 
        287 | } | |||
| 
             | 
        288 | return false; | |||
| 286 | } | 
             | 
        289 | } | |
| 287 | 
             | 
        290 | |||
| 288 | public virtual void CancelOperation(Exception reason) { | 
             | 
        291 | public virtual void CancelOperation(Exception reason) { | |
| 289 | SetCancelled(reason); | 
             | 
        292 | SetCancelled(reason); | |
| 290 | } | 
             | 
        293 | } | |
| 291 | 
             | 
        294 | |||
| 292 | public void CancelationRequested(Action<Exception> handler) { | 
             | 
        295 | public void CancellationRequested(Action<Exception> handler) { | |
| 293 | Safe.ArgumentNotNull(handler, "handler"); | 
             | 
        296 | Safe.ArgumentNotNull(handler, "handler"); | |
| 294 | if (IsCancelRequested) | 
             | 
        297 | if (IsCancellationRequested) | |
| 295 | handler(CancelReason); | 
             | 
        298 | handler(CancellationReason); | |
| 296 | 
             | 
        299 | |||
| 297 | if (m_cancelationHandlers == null) | 
             | 
        300 | if (m_cancelationHandlers == null) | |
| 298 | Interlocked.CompareExchange(ref m_cancelationHandlers, new MTQueue<Action<Exception>>(), null); | 
             | 
        301 | Interlocked.CompareExchange(ref m_cancelationHandlers, new MTQueue<Action<Exception>>(), null); | |
| 299 | 
             | 
        302 | |||
| 300 | m_cancelationHandlers.Enqueue(handler); | 
             | 
        303 | m_cancelationHandlers.Enqueue(handler); | |
| 301 | 
             | 
        304 | |||
| 302 | if (IsCancelRequested && m_cancelationHandlers.TryDequeue(out handler)) | 
             | 
        305 | if (IsCancellationRequested && m_cancelationHandlers.TryDequeue(out handler)) | |
| 303 | // TryDeque implies MemoryBarrier() | 
             | 
        306 | // TryDeque implies MemoryBarrier() | |
| 304 | handler(m_cancelationReason); | 
             | 
        307 | handler(m_cancelationReason); | |
| 305 | } | 
             | 
        308 | } | |
| 306 | 
             | 
        309 | |||
| 307 | public bool IsCancelRequested { | 
             | 
        310 | public bool IsCancellationRequested { | |
| 308 | get { | 
             | 
        311 | get { | |
| 309 | do { | 
             | 
        312 | do { | |
| 310 | if (m_cancelRequest == CANCEL_NOT_REQUESTED) | 
             | 
        313 | if (m_cancelRequest == CANCEL_NOT_REQUESTED) | |
| @@ -316,7 +319,7 namespace Implab { | |||||
| 316 | } | 
             | 
        319 | } | |
| 317 | } | 
             | 
        320 | } | |
| 318 | 
             | 
        321 | |||
| 319 | public Exception CancelReason { | 
             | 
        322 | public Exception CancellationReason { | |
| 320 | get { | 
             | 
        323 | get { | |
| 321 | do { | 
             | 
        324 | do { | |
| 322 | Thread.MemoryBarrier(); | 
             | 
        325 | Thread.MemoryBarrier(); | |
| @@ -333,7 +336,7 namespace Implab { | |||||
| 333 | } | 
             | 
        336 | } | |
| 334 | 
             | 
        337 | |||
| 335 | public void Cancel(Exception reason) { | 
             | 
        338 | public void Cancel(Exception reason) { | |
| 336 | if (CANCEL_NOT_REQUESTED == Interlocked.CompareExchange(ref m_cancelRequest, CANCEL_REQUESTING)) { | 
             | 
        339 | if (CANCEL_NOT_REQUESTED == Interlocked.CompareExchange(ref m_cancelRequest, CANCEL_REQUESTING, CANCEL_NOT_REQUESTED)) { | |
| 337 | m_cancelationReason = reason; | 
             | 
        340 | m_cancelationReason = reason; | |
| 338 | m_cancelRequest = CANCEL_REQUESTED; | 
             | 
        341 | m_cancelRequest = CANCEL_REQUESTED; | |
| 339 | if (m_cancelationHandlers != null) { | 
             | 
        342 | if (m_cancelationHandlers != null) { | |
| @@ -18,11 +18,13 namespace Implab { | |||||
| 18 | 
             | 
        18 | |||
| 19 | public HandlerDescriptor(Action handler, PromiseEventType mask) { | 
             | 
        19 | public HandlerDescriptor(Action handler, PromiseEventType mask) { | |
| 20 | m_handler = handler; | 
             | 
        20 | m_handler = handler; | |
| 
             | 
        21 | m_error = null; | |||
| 
             | 
        22 | m_cancel = null; | |||
| 21 | m_mask = mask; | 
             | 
        23 | m_mask = mask; | |
| 22 | } | 
             | 
        24 | } | |
| 23 | 
             | 
        25 | |||
| 24 | public void SignalSuccess() { | 
             | 
        26 | public void SignalSuccess() { | |
| 25 | if (m_mask & PromiseEventType.Success && m_handler != null) { | 
             | 
        27 | if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) { | |
| 26 | try { | 
             | 
        28 | try { | |
| 27 | m_handler(); | 
             | 
        29 | m_handler(); | |
| 28 | } catch (Exception err) { | 
             | 
        30 | } catch (Exception err) { | |
| @@ -40,7 +42,7 namespace Implab { | |||||
| 40 | // Analysis disable once EmptyGeneralCatchClause | 
             | 
        42 | // Analysis disable once EmptyGeneralCatchClause | |
| 41 | } catch { | 
             | 
        43 | } catch { | |
| 42 | } | 
             | 
        44 | } | |
| 43 | } else if (m_mask & PromiseEventType.Error && m_handler != null) { | 
             | 
        45 | } else if ((m_mask & PromiseEventType.Error ) != 0 && m_handler != null) { | |
| 44 | try { | 
             | 
        46 | try { | |
| 45 | m_handler(); | 
             | 
        47 | m_handler(); | |
| 46 | // Analysis disable once EmptyGeneralCatchClause | 
             | 
        48 | // Analysis disable once EmptyGeneralCatchClause | |
| @@ -56,7 +58,7 namespace Implab { | |||||
| 56 | } catch (Exception err) { | 
             | 
        58 | } catch (Exception err) { | |
| 57 | SignalError(err); | 
             | 
        59 | SignalError(err); | |
| 58 | } | 
             | 
        60 | } | |
| 59 | } else if (m_mask & PromiseEventType.Cancelled && m_handler != null) { | 
             | 
        61 | } else if ( (m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) { | |
| 60 | try { | 
             | 
        62 | try { | |
| 61 | m_handler(); | 
             | 
        63 | m_handler(); | |
| 62 | // Analysis disable once EmptyGeneralCatchClause | 
             | 
        64 | // Analysis disable once EmptyGeneralCatchClause | |
| @@ -84,11 +86,11 namespace Implab { | |||||
| 84 | protected override Signal GetResolveSignal() { | 
             | 
        86 | protected override Signal GetResolveSignal() { | |
| 85 | var signal = new Signal(); | 
             | 
        87 | var signal = new Signal(); | |
| 86 | On(signal.Set, PromiseEventType.All); | 
             | 
        88 | On(signal.Set, PromiseEventType.All); | |
| 
             | 
        89 | return signal; | |||
| 87 | } | 
             | 
        90 | } | |
| 88 | 
             | 
        91 | |||
| 89 | #endregion | 
             | 
        92 | #endregion | |
| 90 | 
             | 
        93 | |||
| 91 | 
             | 
        ||||
| 92 | public Type PromiseType { | 
             | 
        94 | public Type PromiseType { | |
| 93 | get { | 
             | 
        95 | get { | |
| 94 | return typeof(void); | 
             | 
        96 | return typeof(void); | |
| @@ -14,10 +14,14 namespace Implab { | |||||
| 14 | m_success = success; | 
             | 
        14 | m_success = success; | |
| 15 | m_error = error; | 
             | 
        15 | m_error = error; | |
| 16 | m_cancel = cancel; | 
             | 
        16 | m_cancel = cancel; | |
| 
             | 
        17 | ||||
| 
             | 
        18 | m_handler = null; | |||
| 
             | 
        19 | m_mask = 0; | |||
| 17 | } | 
             | 
        20 | } | |
| 18 | 
             | 
        21 | |||
| 19 | public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) { | 
             | 
        22 | public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) { | |
| 20 | m_handler = success; | 
             | 
        23 | m_handler = success; | |
| 
             | 
        24 | m_success = null; | |||
| 21 | m_error = error; | 
             | 
        25 | m_error = error; | |
| 22 | m_cancel = cancel; | 
             | 
        26 | m_cancel = cancel; | |
| 23 | m_mask = PromiseEventType.Success; | 
             | 
        27 | m_mask = PromiseEventType.Success; | |
| @@ -26,6 +30,9 namespace Implab { | |||||
| 26 | public HandlerDescriptor(Action handler, PromiseEventType mask) { | 
             | 
        30 | public HandlerDescriptor(Action handler, PromiseEventType mask) { | |
| 27 | m_handler = handler; | 
             | 
        31 | m_handler = handler; | |
| 28 | m_mask = mask; | 
             | 
        32 | m_mask = mask; | |
| 
             | 
        33 | m_success = null; | |||
| 
             | 
        34 | m_error = null; | |||
| 
             | 
        35 | m_cancel = null; | |||
| 29 | } | 
             | 
        36 | } | |
| 30 | 
             | 
        37 | |||
| 31 | public void SignalSuccess(T result) { | 
             | 
        38 | public void SignalSuccess(T result) { | |
| @@ -35,7 +42,7 namespace Implab { | |||||
| 35 | } catch(Exception err) { | 
             | 
        42 | } catch(Exception err) { | |
| 36 | SignalError(err); | 
             | 
        43 | SignalError(err); | |
| 37 | } | 
             | 
        44 | } | |
| 38 | } else if (m_mask & PromiseEventType.Success && m_handler != null) { | 
             | 
        45 | } else if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) { | |
| 39 | try { | 
             | 
        46 | try { | |
| 40 | m_handler(); | 
             | 
        47 | m_handler(); | |
| 41 | } catch(Exception err) { | 
             | 
        48 | } catch(Exception err) { | |
| @@ -53,7 +60,7 namespace Implab { | |||||
| 53 | // Analysis disable once EmptyGeneralCatchClause | 
             | 
        60 | // Analysis disable once EmptyGeneralCatchClause | |
| 54 | } catch { | 
             | 
        61 | } catch { | |
| 55 | } | 
             | 
        62 | } | |
| 56 | } else if (m_mask & PromiseEventType.Error && m_handler != null) { | 
             | 
        63 | } else if ((m_mask & PromiseEventType.Error) != 0 && m_handler != null) { | |
| 57 | try { | 
             | 
        64 | try { | |
| 58 | m_handler(); | 
             | 
        65 | m_handler(); | |
| 59 | // Analysis disable once EmptyGeneralCatchClause | 
             | 
        66 | // Analysis disable once EmptyGeneralCatchClause | |
| @@ -69,7 +76,7 namespace Implab { | |||||
| 69 | } catch (Exception err) { | 
             | 
        76 | } catch (Exception err) { | |
| 70 | SignalError(err); | 
             | 
        77 | SignalError(err); | |
| 71 | } | 
             | 
        78 | } | |
| 72 | } else if (m_mask & PromiseEventType.Cancelled && m_handler != null) { | 
             | 
        79 | } else if ((m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) { | |
| 73 | try { | 
             | 
        80 | try { | |
| 74 | m_handler(); | 
             | 
        81 | m_handler(); | |
| 75 | // Analysis disable once EmptyGeneralCatchClause | 
             | 
        82 | // Analysis disable once EmptyGeneralCatchClause | |
| @@ -79,23 +86,28 namespace Implab { | |||||
| 79 | } | 
             | 
        86 | } | |
| 80 | } | 
             | 
        87 | } | |
| 81 | 
             | 
        88 | |||
| 82 | 
             | 
        ||||
| 83 | 
             | 
        ||||
| 84 | public Type PromiseType { | 
             | 
        89 | public Type PromiseType { | |
| 85 | get { | 
             | 
        90 | get { | |
| 86 | return typeof(T); | 
             | 
        91 | return typeof(T); | |
| 87 | } | 
             | 
        92 | } | |
| 88 | } | 
             | 
        93 | } | |
| 89 | 
             | 
        94 | |||
| 90 | 
            
                    public | 
        
             | 
        95 | public T Join() { | |
| 91 | WaitResult(-1); | 
             | 
        96 | WaitResult(-1); | |
| 92 | return m_result; | 
             | 
        97 | return m_result; | |
| 93 | } | 
             | 
        98 | } | |
| 94 | 
            
                    public | 
        
             | 
        99 | public T Join(int timeout) { | |
| 95 | WaitResult(timeout); | 
             | 
        100 | WaitResult(timeout); | |
| 96 | return m_result; | 
             | 
        101 | return m_result; | |
| 97 | } | 
             | 
        102 | } | |
| 98 | 
             | 
        103 | |||
| 
             | 
        104 | void IPromise.Join() { | |||
| 
             | 
        105 | WaitResult(-1); | |||
| 
             | 
        106 | } | |||
| 
             | 
        107 | void IPromise.Join(int timeout) { | |||
| 
             | 
        108 | WaitResult(timeout); | |||
| 
             | 
        109 | } | |||
| 
             | 
        110 | ||||
| 99 | public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) { | 
             | 
        111 | public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) { | |
| 100 | AddHandler(new HandlerDescriptor(success, error, cancel)); | 
             | 
        112 | AddHandler(new HandlerDescriptor(success, error, cancel)); | |
| 101 | return this; | 
             | 
        113 | return this; | |
| @@ -146,6 +158,11 namespace Implab { | |||||
| 146 | return this; | 
             | 
        158 | return this; | |
| 147 | } | 
             | 
        159 | } | |
| 148 | 
             | 
        160 | |||
| 
             | 
        161 | IPromise IPromise.On(Action handler, PromiseEventType events) { | |||
| 
             | 
        162 | AddHandler(new HandlerDescriptor(handler, events)); | |||
| 
             | 
        163 | return this; | |||
| 
             | 
        164 | } | |||
| 
             | 
        165 | ||||
| 149 | public IPromise<T2> Cast<T2>() { | 
             | 
        166 | public IPromise<T2> Cast<T2>() { | |
| 150 | return (IPromise<T2>)this; | 
             | 
        167 | return (IPromise<T2>)this; | |
| 151 | } | 
             | 
        168 | } | |
| @@ -4,7 +4,7 namespace Implab { | |||||
| 4 | /// <summary> | 
             | 
        4 | /// <summary> | |
| 5 | /// Deferred result, usually used by asynchronous services as the service part of the promise. | 
             | 
        5 | /// Deferred result, usually used by asynchronous services as the service part of the promise. | |
| 6 | /// </summary> | 
             | 
        6 | /// </summary> | |
| 7 | public interface IDeferred : ICancelationToken { | 
             | 
        7 | public interface IDeferred : ICancellationToken { | |
| 8 | 
             | 
        8 | |||
| 9 | void Resolve(); | 
             | 
        9 | void Resolve(); | |
| 10 | 
             | 
        10 | |||
| @@ -1,7 +1,7 | |||||
| 1 | using System; | 
             | 
        1 | using System; | |
| 2 | 
             | 
        2 | |||
| 3 | namespace Implab { | 
             | 
        3 | namespace Implab { | |
| 4 | public interface IDeferred<T> : ICancelationToken { | 
             | 
        4 | public interface IDeferred<in T> : ICancellationToken { | |
| 5 | void Resolve(T value); | 
             | 
        5 | void Resolve(T value); | |
| 6 | 
             | 
        6 | |||
| 7 | void Reject(Exception error); | 
             | 
        7 | void Reject(Exception error); | |
| @@ -1,7 +1,4 | |||||
| 1 | using System; | 
             | 
        1 | using System; | |
| 2 | using System.Collections.Generic; | 
             | 
        |||
| 3 | using System.Linq; | 
             | 
        |||
| 4 | using System.Text; | 
             | 
        |||
| 5 | 
             | 
        2 | |||
| 6 | namespace Implab { | 
             | 
        3 | namespace Implab { | |
| 7 | public interface ITaskController: IProgressHandler, ICancellable { | 
             | 
        4 | public interface ITaskController: IProgressHandler, ICancellable { | |
| @@ -157,14 +157,24 | |||||
| 157 | <Compile Include="Diagnostics\ILogWriter.cs" /> | 
             | 
        157 | <Compile Include="Diagnostics\ILogWriter.cs" /> | |
| 158 | <Compile Include="Diagnostics\ListenerBase.cs" /> | 
             | 
        158 | <Compile Include="Diagnostics\ListenerBase.cs" /> | |
| 159 | <Compile Include="Parallels\BlockingQueue.cs" /> | 
             | 
        159 | <Compile Include="Parallels\BlockingQueue.cs" /> | |
| 160 | <Compile Include="ICancelationToken.cs" /> | 
             | 
        |||
| 161 | <Compile Include="AbstractEvent.cs" /> | 
             | 
        160 | <Compile Include="AbstractEvent.cs" /> | |
| 162 | <Compile Include="AbstractPromise.cs" /> | 
             | 
        161 | <Compile Include="AbstractPromise.cs" /> | |
| 163 | <Compile Include="AbstractPromiseT.cs" /> | 
             | 
        162 | <Compile Include="AbstractPromiseT.cs" /> | |
| 164 | <Compile Include="FuncTask.cs" /> | 
             | 
        163 | <Compile Include="FuncTask.cs" /> | |
| 165 | <Compile Include="FuncTaskBase.cs" /> | 
             | 
        164 | <Compile Include="FuncTaskBase.cs" /> | |
| 166 | <Compile Include="FuncTaskT.cs" /> | 
             | 
        165 | <Compile Include="FuncTaskT.cs" /> | |
| 167 | <Compile Include="ChainTask.cs" /> | 
             | 
        166 | <Compile Include="ActionChainTaskBase.cs" /> | |
| 
             | 
        167 | <Compile Include="ActionChainTask.cs" /> | |||
| 
             | 
        168 | <Compile Include="ActionChainTaskT.cs" /> | |||
| 
             | 
        169 | <Compile Include="FuncChainTaskBase.cs" /> | |||
| 
             | 
        170 | <Compile Include="FuncChainTask.cs" /> | |||
| 
             | 
        171 | <Compile Include="FuncChainTaskT.cs" /> | |||
| 
             | 
        172 | <Compile Include="ActionTaskBase.cs" /> | |||
| 
             | 
        173 | <Compile Include="ActionTask.cs" /> | |||
| 
             | 
        174 | <Compile Include="ActionTaskT.cs" /> | |||
| 
             | 
        175 | <Compile Include="ICancellationToken.cs" /> | |||
| 
             | 
        176 | <Compile Include="SuccessPromise.cs" /> | |||
| 
             | 
        177 | <Compile Include="SuccessPromiseT.cs" /> | |||
| 168 | </ItemGroup> | 
             | 
        178 | </ItemGroup> | |
| 169 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> | 
             | 
        179 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> | |
| 170 | <ItemGroup /> | 
             | 
        180 | <ItemGroup /> | |
| @@ -152,7 +152,7 namespace Implab.Parallels { | |||||
| 152 | throw new ArgumentOutOfRangeException("threads","Threads number must be greater then zero"); | 
             | 
        152 | throw new ArgumentOutOfRangeException("threads","Threads number must be greater then zero"); | |
| 153 | 
             | 
        153 | |||
| 154 | if (source.Length == 0) | 
             | 
        154 | if (source.Length == 0) | |
| 155 | 
            
                            return Promise<TDst[]>.Result | 
        
             | 
        155 | return Promise<TDst[]>.FromResult(new TDst[0]); | |
| 156 | 
             | 
        156 | |||
| 157 | var promise = new Promise<TDst[]>(); | 
             | 
        157 | var promise = new Promise<TDst[]>(); | |
| 158 | var res = new TDst[source.Length]; | 
             | 
        158 | var res = new TDst[source.Length]; | |
| @@ -31,6 +31,24 namespace Implab.Parallels { | |||||
| 31 | return p; | 
             | 
        31 | return p; | |
| 32 | } | 
             | 
        32 | } | |
| 33 | 
             | 
        33 | |||
| 
             | 
        34 | public static IPromise<T> Invoke<T>(Func<ICancellationToken, T> func) { | |||
| 
             | 
        35 | var p = new Promise<T>(); | |||
| 
             | 
        36 | var caller = TraceContext.Instance.CurrentOperation; | |||
| 
             | 
        37 | ||||
| 
             | 
        38 | ThreadPool.QueueUserWorkItem(param => { | |||
| 
             | 
        39 | TraceContext.Instance.EnterLogicalOperation(caller,false); | |||
| 
             | 
        40 | try { | |||
| 
             | 
        41 | p.Resolve(func(p)); | |||
| 
             | 
        42 | } catch(Exception e) { | |||
| 
             | 
        43 | p.Reject(e); | |||
| 
             | 
        44 | } finally { | |||
| 
             | 
        45 | TraceContext.Instance.Leave(); | |||
| 
             | 
        46 | } | |||
| 
             | 
        47 | }); | |||
| 
             | 
        48 | ||||
| 
             | 
        49 | return p; | |||
| 
             | 
        50 | } | |||
| 
             | 
        51 | ||||
| 34 | public static IPromise<T> RunThread<T>(Func<T> func) { | 
             | 
        52 | public static IPromise<T> RunThread<T>(Func<T> func) { | |
| 35 | var p = new Promise<T>(); | 
             | 
        53 | var p = new Promise<T>(); | |
| 36 | 
             | 
        54 | |||
| @@ -52,6 +70,27 namespace Implab.Parallels { | |||||
| 52 | return p; | 
             | 
        70 | return p; | |
| 53 | } | 
             | 
        71 | } | |
| 54 | 
             | 
        72 | |||
| 
             | 
        73 | public static IPromise<T> RunThread<T>(Func<ICancellationToken, T> func) { | |||
| 
             | 
        74 | var p = new Promise<T>(); | |||
| 
             | 
        75 | ||||
| 
             | 
        76 | var caller = TraceContext.Instance.CurrentOperation; | |||
| 
             | 
        77 | ||||
| 
             | 
        78 | var worker = new Thread(() => { | |||
| 
             | 
        79 | TraceContext.Instance.EnterLogicalOperation(caller,false); | |||
| 
             | 
        80 | try { | |||
| 
             | 
        81 | p.Resolve(func(p)); | |||
| 
             | 
        82 | } catch (Exception e) { | |||
| 
             | 
        83 | p.Reject(e); | |||
| 
             | 
        84 | } finally { | |||
| 
             | 
        85 | TraceContext.Instance.Leave(); | |||
| 
             | 
        86 | } | |||
| 
             | 
        87 | }); | |||
| 
             | 
        88 | worker.IsBackground = true; | |||
| 
             | 
        89 | worker.Start(); | |||
| 
             | 
        90 | ||||
| 
             | 
        91 | return p; | |||
| 
             | 
        92 | } | |||
| 
             | 
        93 | ||||
| 55 | 
             | 
        94 | |||
| 56 | public static IPromise RunThread(Action func) { | 
             | 
        95 | public static IPromise RunThread(Action func) { | |
| 57 | var p = new Promise(); | 
             | 
        96 | var p = new Promise(); | |
| @@ -75,12 +114,42 namespace Implab.Parallels { | |||||
| 75 | return p; | 
             | 
        114 | return p; | |
| 76 | } | 
             | 
        115 | } | |
| 77 | 
             | 
        116 | |||
| 
             | 
        117 | public static IPromise RunThread(Action<ICancellationToken> func) { | |||
| 
             | 
        118 | var p = new Promise(); | |||
| 
             | 
        119 | ||||
| 
             | 
        120 | var caller = TraceContext.Instance.CurrentOperation; | |||
| 
             | 
        121 | ||||
| 
             | 
        122 | var worker = new Thread(() => { | |||
| 
             | 
        123 | TraceContext.Instance.EnterLogicalOperation(caller,false); | |||
| 
             | 
        124 | try { | |||
| 
             | 
        125 | func(p); | |||
| 
             | 
        126 | p.Resolve(); | |||
| 
             | 
        127 | } catch (Exception e) { | |||
| 
             | 
        128 | p.Reject(e); | |||
| 
             | 
        129 | } finally { | |||
| 
             | 
        130 | TraceContext.Instance.Leave(); | |||
| 
             | 
        131 | } | |||
| 
             | 
        132 | }); | |||
| 
             | 
        133 | worker.IsBackground = true; | |||
| 
             | 
        134 | worker.Start(); | |||
| 
             | 
        135 | ||||
| 
             | 
        136 | return p; | |||
| 
             | 
        137 | } | |||
| 
             | 
        138 | ||||
| 78 | public static IPromise[] RunThread(params Action[] func) { | 
             | 
        139 | public static IPromise[] RunThread(params Action[] func) { | |
| 79 | return func.Select(f => RunThread(f)).ToArray(); | 
             | 
        140 | return func.Select(f => RunThread(f)).ToArray(); | |
| 80 | } | 
             | 
        141 | } | |
| 81 | 
             | 
        142 | |||
| 
             | 
        143 | public static IPromise[] RunThread(params Action<ICancellationToken>[] func) { | |||
| 
             | 
        144 | return func.Select(f => RunThread(f)).ToArray(); | |||
| 
             | 
        145 | } | |||
| 
             | 
        146 | ||||
| 82 | public static IPromise<T>[] RunThread<T>(params Func<T>[] func) { | 
             | 
        147 | public static IPromise<T>[] RunThread<T>(params Func<T>[] func) { | |
| 83 | return func.Select(f => RunThread(f)).ToArray(); | 
             | 
        148 | return func.Select(f => RunThread(f)).ToArray(); | |
| 84 | } | 
             | 
        149 | } | |
| 
             | 
        150 | ||||
| 
             | 
        151 | public static IPromise<T>[] RunThread<T>(params Func<ICancellationToken, T>[] func) { | |||
| 
             | 
        152 | return func.Select(f => RunThread(f)).ToArray(); | |||
| 
             | 
        153 | } | |||
| 85 | } | 
             | 
        154 | } | |
| 86 | } | 
             | 
        155 | } | |
| @@ -174,6 +174,116 namespace Implab { | |||||
| 174 | 
             | 
        174 | |||
| 175 | return medium; | 
             | 
        175 | return medium; | |
| 176 | } | 
             | 
        176 | } | |
| 
             | 
        177 | ||||
| 
             | 
        178 | public static IPromise Then(this IPromise that, Action success, Action<Exception> error, Action<Exception> cancel) { | |||
| 
             | 
        179 | Safe.ArgumentNotNull(that, "that"); | |||
| 
             | 
        180 | ||||
| 
             | 
        181 | var d = new ActionTask(success, error, cancel); | |||
| 
             | 
        182 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |||
| 
             | 
        183 | if (success != null) | |||
| 
             | 
        184 | d.CancellationRequested(that.Cancel); | |||
| 
             | 
        185 | return d; | |||
| 
             | 
        186 | } | |||
| 
             | 
        187 | ||||
| 
             | 
        188 | public static IPromise Then(this IPromise that, Action success, Action<Exception> error) { | |||
| 
             | 
        189 | return Then(that, success, error, null); | |||
| 
             | 
        190 | } | |||
| 
             | 
        191 | ||||
| 
             | 
        192 | public static IPromise Then(this IPromise that, Action success) { | |||
| 
             | 
        193 | return Then(that, success, null, null); | |||
| 
             | 
        194 | } | |||
| 
             | 
        195 | ||||
| 
             | 
        196 | public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error, Func<Exception, T> cancel) { | |||
| 
             | 
        197 | Safe.ArgumentNotNull(that, "that"); | |||
| 
             | 
        198 | ||||
| 
             | 
        199 | var d = new FuncTask<T>(success, error, cancel); | |||
| 
             | 
        200 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |||
| 
             | 
        201 | if (success != null) | |||
| 
             | 
        202 | d.CancellationRequested(that.Cancel); | |||
| 
             | 
        203 | return d; | |||
| 
             | 
        204 | } | |||
| 
             | 
        205 | ||||
| 
             | 
        206 | public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error) { | |||
| 
             | 
        207 | return Then(that, success, error, null); | |||
| 
             | 
        208 | } | |||
| 
             | 
        209 | ||||
| 
             | 
        210 | public static IPromise<T> Then<T>(this IPromise that, Func<T> success) { | |||
| 
             | 
        211 | return Then(that, success, null, null); | |||
| 
             | 
        212 | } | |||
| 
             | 
        213 | ||||
| 
             | 
        214 | public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error, Func<Exception, T2> cancel) { | |||
| 
             | 
        215 | Safe.ArgumentNotNull(that, "that"); | |||
| 
             | 
        216 | var d = new FuncTask<T,T2>(success, error, cancel); | |||
| 
             | 
        217 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |||
| 
             | 
        218 | if (success != null) | |||
| 
             | 
        219 | d.CancellationRequested(that.Cancel); | |||
| 
             | 
        220 | return d; | |||
| 
             | 
        221 | } | |||
| 
             | 
        222 | ||||
| 
             | 
        223 | public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error) { | |||
| 
             | 
        224 | return Then(that, success, error, null); | |||
| 
             | 
        225 | } | |||
| 
             | 
        226 | ||||
| 
             | 
        227 | public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success) { | |||
| 
             | 
        228 | return Then(that, success, null, null); | |||
| 
             | 
        229 | } | |||
| 
             | 
        230 | ||||
| 
             | 
        231 | #region chain traits | |||
| 
             | 
        232 | public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception,IPromise> error, Func<Exception,IPromise> cancel) { | |||
| 
             | 
        233 | Safe.ArgumentNotNull(that, "that"); | |||
| 
             | 
        234 | ||||
| 
             | 
        235 | var d = new ActionChainTask(success, error, cancel); | |||
| 
             | 
        236 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |||
| 
             | 
        237 | if (success != null) | |||
| 
             | 
        238 | d.CancellationRequested(that.Cancel); | |||
| 
             | 
        239 | return d; | |||
| 
             | 
        240 | } | |||
| 
             | 
        241 | ||||
| 
             | 
        242 | public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception,IPromise> error) { | |||
| 
             | 
        243 | return Chain(that, success, error, null); | |||
| 
             | 
        244 | } | |||
| 
             | 
        245 | ||||
| 
             | 
        246 | public static IPromise Chain(this IPromise that, Func<IPromise> success) { | |||
| 
             | 
        247 | return Chain(that, success, null, null); | |||
| 
             | 
        248 | } | |||
| 
             | 
        249 | ||||
| 
             | 
        250 | public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error, Func<Exception, IPromise<T>> cancel) { | |||
| 
             | 
        251 | Safe.ArgumentNotNull(that, "that"); | |||
| 
             | 
        252 | ||||
| 
             | 
        253 | var d = new FuncChainTask<T>(success, error, cancel); | |||
| 
             | 
        254 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |||
| 
             | 
        255 | if (success != null) | |||
| 
             | 
        256 | d.CancellationRequested(that.Cancel); | |||
| 
             | 
        257 | return d; | |||
| 
             | 
        258 | } | |||
| 
             | 
        259 | ||||
| 
             | 
        260 | public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error) { | |||
| 
             | 
        261 | return Chain(that, success, error, null); | |||
| 
             | 
        262 | } | |||
| 
             | 
        263 | ||||
| 
             | 
        264 | public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success) { | |||
| 
             | 
        265 | return Chain(that, success, null, null); | |||
| 
             | 
        266 | } | |||
| 
             | 
        267 | ||||
| 
             | 
        268 | public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) { | |||
| 
             | 
        269 | Safe.ArgumentNotNull(that, "that"); | |||
| 
             | 
        270 | var d = new FuncChainTask<T,T2>(success, error, cancel); | |||
| 
             | 
        271 | that.On(d.Resolve, d.Reject, d.CancelOperation); | |||
| 
             | 
        272 | if (success != null) | |||
| 
             | 
        273 | d.CancellationRequested(that.Cancel); | |||
| 
             | 
        274 | return d; | |||
| 
             | 
        275 | } | |||
| 
             | 
        276 | ||||
| 
             | 
        277 | public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error) { | |||
| 
             | 
        278 | return Chain(that, success, error, null); | |||
| 
             | 
        279 | } | |||
| 
             | 
        280 | ||||
| 
             | 
        281 | public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success) { | |||
| 
             | 
        282 | return Chain(that, success, null, null); | |||
| 
             | 
        283 | } | |||
| 
             | 
        284 | ||||
| 
             | 
        285 | #endregion | |||
| 
             | 
        286 | ||||
| 177 | 
             | 
        287 | |||
| 178 | #if NET_4_5 | 
             | 
        288 | #if NET_4_5 | |
| 179 | 
             | 
        289 | |||
| @@ -109,9 +109,9 namespace Implab | |||||
| 109 | ArgumentNotNull(action, "action"); | 
             | 
        109 | ArgumentNotNull(action, "action"); | |
| 110 | 
             | 
        110 | |||
| 111 | try { | 
             | 
        111 | try { | |
| 112 | 
            
                            return action() ?? Promise<T>.Exception | 
        
             | 
        112 | return action() ?? Promise<T>.FromException(new Exception("The action returned null")); | |
| 113 | } catch (Exception err) { | 
             | 
        113 | } catch (Exception err) { | |
| 114 | 
            
                            return Promise<T>.Exception | 
        
             | 
        114 | return Promise<T>.FromException(err); | |
| 115 | } | 
             | 
        115 | } | |
| 116 | } | 
             | 
        116 | } | |
| 117 | } | 
             | 
        117 | } | |
| @@ -10,15 +10,15 namespace Implab { | |||||
| 10 | m_context = context; | 
             | 
        10 | m_context = context; | |
| 11 | } | 
             | 
        11 | } | |
| 12 | 
             | 
        12 | |||
| 13 | 
            
                    protected override void SignalSuccess( | 
        
             | 
        13 | protected override void SignalSuccess(Promise<T>.HandlerDescriptor handler) { | |
| 14 | m_context.Post(x => base.SignalSuccess(handler), null); | 
             | 
        14 | m_context.Post(x => base.SignalSuccess(handler), null); | |
| 15 | } | 
             | 
        15 | } | |
| 16 | 
             | 
        16 | |||
| 17 | 
            
                    protected override void SignalError( | 
        
             | 
        17 | protected override void SignalError(Promise<T>.HandlerDescriptor handler, Exception error) { | |
| 18 | m_context.Post(x => base.SignalError(handler, error), null); | 
             | 
        18 | m_context.Post(x => base.SignalError(handler, error), null); | |
| 19 | } | 
             | 
        19 | } | |
| 20 | 
             | 
        20 | |||
| 21 | 
            
                    protected override void SignalCancelled( | 
        
             | 
        21 | protected override void SignalCancelled(Promise<T>.HandlerDescriptor handler, Exception reason) { | |
| 22 | m_context.Post(x => base.SignalCancelled(handler, reason), null); | 
             | 
        22 | m_context.Post(x => base.SignalCancelled(handler, reason), null); | |
| 23 | } | 
             | 
        23 | } | |
| 24 | } | 
             | 
        24 | } | |
| @@ -8,86 +8,33 using System.Threading; | |||||
| 8 | 
             | 
        8 | |||
| 9 | namespace MonoPlay { | 
             | 
        9 | namespace MonoPlay { | |
| 10 | class MainClass { | 
             | 
        10 | class MainClass { | |
| 
             | 
        11 | ||||
| 
             | 
        12 | ||||
| 11 | public static void Main(string[] args) { | 
             | 
        13 | public static void Main(string[] args) { | |
| 12 | if (args == null) | 
             | 
        14 | if (args == null) | |
| 13 | throw new ArgumentNullException("args"); | 
             | 
        15 | throw new ArgumentNullException("args"); | |
| 14 | 
             | 
        16 | |||
| 15 | var t1 = Environment.TickCount; | 
             | 
        17 | var t1 = Environment.TickCount; | |
| 16 | 
             | 
        18 | |||
| 17 | 
            
                         | 
        
             | 
        19 | for (int i = 0; i < 10000000; i++) { | |
| 18 | const int writes = 1000; | 
             | 
        20 | ||
| 19 | const int readThreads = 8; | 
             | 
        21 | var p = new Promise<int>(); | |
| 20 | const int writeThreads = 0; | 
             | 
        22 | p.On(HandleResult); | |
| 21 | 
             | 
        23 | p.Resolve(i); | ||
| 22 | var l = new SharedLock(); | 
             | 
        24 | } | |
| 23 | var st = new HashSet<int>(); | 
             | 
        |||
| 24 | 
             | 
        ||||
| 25 | Action reader1 = () => { | 
             | 
        |||
| 26 | for (int i =0; i < reads; i++) { | 
             | 
        |||
| 27 | try { | 
             | 
        |||
| 28 | l.LockShared(); | 
             | 
        |||
| 29 | st.Contains(i % 1000); | 
             | 
        |||
| 30 | Thread.Sleep(0); | 
             | 
        |||
| 31 | } finally { | 
             | 
        |||
| 32 | l.Release(); | 
             | 
        |||
| 33 | } | 
             | 
        |||
| 34 | } | 
             | 
        |||
| 35 | }; | 
             | 
        |||
| 36 | 
             | 
        ||||
| 37 | Action reader2 = () => { | 
             | 
        |||
| 38 | for(var i = 0; i < reads; i++) | 
             | 
        |||
| 39 | lock(st) { | 
             | 
        |||
| 40 | st.Contains(i % 1000); | 
             | 
        |||
| 41 | Thread.Sleep(0); | 
             | 
        |||
| 42 | } | 
             | 
        |||
| 43 | }; | 
             | 
        |||
| 44 | 
             | 
        ||||
| 45 | Action writer1 = () => { | 
             | 
        |||
| 46 | var rnd = new Random(Environment.TickCount); | 
             | 
        |||
| 47 | for (int i = 0; i < writes; i++) { | 
             | 
        |||
| 48 | try { | 
             | 
        |||
| 49 | l.LockExclusive(); | 
             | 
        |||
| 50 | st.Add(rnd.Next(1000)); | 
             | 
        |||
| 51 | //Thread.Sleep(1); | 
             | 
        |||
| 52 | } finally { | 
             | 
        |||
| 53 | l.Release(); | 
             | 
        |||
| 54 | } | 
             | 
        |||
| 55 | } | 
             | 
        |||
| 56 | }; | 
             | 
        |||
| 57 | 
             | 
        ||||
| 58 | Action writer2 = () => { | 
             | 
        |||
| 59 | var rnd = new Random(Environment.TickCount); | 
             | 
        |||
| 60 | for (int i = 0; i < writes; i++) { | 
             | 
        |||
| 61 | lock (st) { | 
             | 
        |||
| 62 | st.Add(rnd.Next(1000)); | 
             | 
        |||
| 63 | //Thread.Sleep(1); | 
             | 
        |||
| 64 | } | 
             | 
        |||
| 65 | } | 
             | 
        |||
| 66 | }; | 
             | 
        |||
| 67 | 
             | 
        ||||
| 68 | 
             | 
        ||||
| 69 | 
             | 
        ||||
| 70 | var readers = new IPromise[readThreads]; | 
             | 
        |||
| 71 | for (int i = 0; i < readThreads; i++) | 
             | 
        |||
| 72 | readers[i] = AsyncPool.RunThread(reader2); | 
             | 
        |||
| 73 | 
             | 
        ||||
| 74 | var writers = new IPromise[writeThreads]; | 
             | 
        |||
| 75 | for (int i = 0; i < writeThreads; i++) | 
             | 
        |||
| 76 | writers[i] = AsyncPool.RunThread(writer1); | 
             | 
        |||
| 77 | 
             | 
        ||||
| 78 | 
             | 
        ||||
| 79 | new [] { | 
             | 
        |||
| 80 | readers.Bundle().On(() => Console.WriteLine("readers complete in {0} ms", Environment.TickCount - t1)), | 
             | 
        |||
| 81 | writers.Bundle().On(() => Console.WriteLine("writers complete in {0} ms", Environment.TickCount - t1)) | 
             | 
        |||
| 82 | }.Bundle().Join(); | 
             | 
        |||
| 83 | 
             | 
        ||||
| 84 | 
             | 
        ||||
| 85 | 
             | 
        25 | |||
| 86 | var t2 = Environment.TickCount; | 
             | 
        26 | var t2 = Environment.TickCount; | |
| 87 | Console.WriteLine("done: {0} ms, {1:.00} Mb, {2} GC", t2 - t1, GC.GetTotalMemory(false) / (1024*1024), GC.CollectionCount(0) ); | 
             | 
        27 | Console.WriteLine("done: {0} ms, {1:.00} Mb, {2} GC", t2 - t1, GC.GetTotalMemory(false) / (1024*1024), GC.CollectionCount(0) ); | |
| 88 | 
             | 
        28 | |||
| 89 | } | 
             | 
        29 | } | |
| 90 | 
             | 
        30 | |||
| 
             | 
        31 | static void HandleAction () | |||
| 
             | 
        32 | { | |||
| 
             | 
        33 | ||||
| 
             | 
        34 | } | |||
| 91 | 
             | 
        35 | |||
| 
             | 
        36 | static void HandleResult(int x) { | |||
| 
             | 
        37 | ||||
| 
             | 
        38 | } | |||
| 92 | } | 
             | 
        39 | } | |
| 93 | } | 
             | 
        40 | } | |
| 1 | NO CONTENT: file was removed | 
             | 
        NO CONTENT: file was removed | 
| 1 | NO CONTENT: file was removed | 
             | 
        NO CONTENT: file was removed | 
        
        General Comments 0
    
    
  
  
                      You need to be logged in to leave comments.
                      Login now
                    
                