Mercurial > pub > ImplabNet
comparison Implab/Promise.cs @ 248:5cb4826c2c2a v3
Added awaiters to promises
Added static methods to Promise Resolve, Reject, All.
Updated promise helpers
| author | cin |
|---|---|
| date | Tue, 30 Jan 2018 01:37:17 +0300 |
| parents | |
| children | d82909310094 |
comparison
equal
deleted
inserted
replaced
| 247:fb70574741a1 | 248:5cb4826c2c2a |
|---|---|
| 1 using System; | |
| 2 using System.Collections.Generic; | |
| 3 using System.Diagnostics; | |
| 4 using System.Reflection; | |
| 5 using System.Threading.Tasks; | |
| 6 using Implab.Parallels; | |
| 7 | |
| 8 namespace Implab { | |
| 9 public class Promise : AbstractEvent<IResolvable>, IPromise { | |
| 10 public static IDispatcher DefaultDispatcher { | |
| 11 get { | |
| 12 return ThreadPoolDispatcher.Instance; | |
| 13 } | |
| 14 } | |
| 15 | |
| 16 class ResolvableSignal : IResolvable { | |
| 17 public Signal Signal { get; private set; } | |
| 18 public ResolvableSignal() { | |
| 19 Signal = new Signal(); | |
| 20 } | |
| 21 | |
| 22 | |
| 23 public void Reject(Exception error) { | |
| 24 Signal.Set(); | |
| 25 } | |
| 26 | |
| 27 public void Resolve() { | |
| 28 Signal.Set(); | |
| 29 } | |
| 30 } | |
| 31 | |
| 32 PromiseState m_state; | |
| 33 | |
| 34 Exception m_error; | |
| 35 | |
| 36 public bool IsRejected { | |
| 37 get { | |
| 38 return m_state == PromiseState.Rejected; | |
| 39 } | |
| 40 } | |
| 41 | |
| 42 public bool IsFulfilled { | |
| 43 get { | |
| 44 return m_state == PromiseState.Fulfilled; | |
| 45 } | |
| 46 } | |
| 47 | |
| 48 public Exception RejectReason { | |
| 49 get { | |
| 50 return m_error; | |
| 51 } | |
| 52 } | |
| 53 | |
| 54 internal Promise() { | |
| 55 | |
| 56 } | |
| 57 | |
| 58 internal void ResolvePromise() { | |
| 59 if (BeginTransit()) { | |
| 60 m_state = PromiseState.Fulfilled; | |
| 61 CompleteTransit(); | |
| 62 } | |
| 63 } | |
| 64 | |
| 65 internal void RejectPromise(Exception reason) { | |
| 66 if (BeginTransit()) { | |
| 67 m_error = reason; | |
| 68 m_state = PromiseState.Rejected; | |
| 69 CompleteTransit(); | |
| 70 } | |
| 71 } | |
| 72 | |
| 73 | |
| 74 #region implemented abstract members of AbstractPromise | |
| 75 | |
| 76 protected override void SignalHandler(IResolvable handler) { | |
| 77 switch (m_state) { | |
| 78 case PromiseState.Fulfilled: | |
| 79 handler.Resolve(); | |
| 80 break; | |
| 81 case PromiseState.Rejected: | |
| 82 handler.Reject(RejectReason); | |
| 83 break; | |
| 84 default: | |
| 85 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state)); | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 protected void WaitResult(int timeout) { | |
| 90 if (!(IsResolved || GetFulfillSignal().Wait(timeout))) | |
| 91 throw new TimeoutException(); | |
| 92 } | |
| 93 | |
| 94 protected Signal GetFulfillSignal() { | |
| 95 var next = new ResolvableSignal(); | |
| 96 Then(next); | |
| 97 return next.Signal; | |
| 98 } | |
| 99 | |
| 100 #endregion | |
| 101 | |
| 102 | |
| 103 public Type ResultType { | |
| 104 get { | |
| 105 return typeof(void); | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 | |
| 110 protected void Rethrow() { | |
| 111 Debug.Assert(m_error != null); | |
| 112 if (m_error is OperationCanceledException) | |
| 113 throw new OperationCanceledException("Operation cancelled", m_error); | |
| 114 else | |
| 115 throw new TargetInvocationException(m_error); | |
| 116 } | |
| 117 | |
| 118 public void Then(IResolvable next) { | |
| 119 AddHandler(next); | |
| 120 } | |
| 121 | |
| 122 public IPromise<T> Cast<T>() { | |
| 123 throw new InvalidCastException(); | |
| 124 } | |
| 125 | |
| 126 public void Join() { | |
| 127 WaitResult(-1); | |
| 128 if (IsRejected) | |
| 129 Rethrow(); | |
| 130 } | |
| 131 | |
| 132 public void Join(int timeout) { | |
| 133 WaitResult(timeout); | |
| 134 if (IsRejected) | |
| 135 Rethrow(); | |
| 136 } | |
| 137 | |
| 138 public static ResolvedPromise Resolve() { | |
| 139 return new ResolvedPromise(); | |
| 140 } | |
| 141 | |
| 142 public static ResolvedPromise<T> Resolve<T>(T result) { | |
| 143 return new ResolvedPromise<T>(result); | |
| 144 } | |
| 145 | |
| 146 public static RejectedPromise Reject(Exception reason) { | |
| 147 return new RejectedPromise(reason); | |
| 148 } | |
| 149 | |
| 150 public static RejectedPromise<T> Reject<T>(Exception reason) { | |
| 151 return new RejectedPromise<T>(reason); | |
| 152 } | |
| 153 | |
| 154 public static IPromise Create(PromiseExecutor executor) { | |
| 155 Safe.ArgumentNotNull(executor, nameof(executor)); | |
| 156 | |
| 157 var p = new Promise(); | |
| 158 var d = new Deferred(p, DefaultDispatcher); | |
| 159 | |
| 160 try { | |
| 161 executor(d); | |
| 162 } catch (Exception e) { | |
| 163 d.Reject(e); | |
| 164 } | |
| 165 | |
| 166 return d.Promise; | |
| 167 } | |
| 168 | |
| 169 public static IPromise<T> Create<T>(PromiseExecutor<T> executor) { | |
| 170 Safe.ArgumentNotNull(executor, nameof(executor)); | |
| 171 | |
| 172 var p = new Promise<T>(); | |
| 173 var d = new Deferred<T>(p, DefaultDispatcher); | |
| 174 | |
| 175 try { | |
| 176 executor(d); | |
| 177 } catch (Exception e) { | |
| 178 d.Reject(e); | |
| 179 } | |
| 180 | |
| 181 return d.Promise; | |
| 182 } | |
| 183 | |
| 184 public static IPromise All(IEnumerable<IPromise> promises) { | |
| 185 var d = new Deferred(DefaultDispatcher); | |
| 186 var all = new PromiseAll(d); | |
| 187 foreach (var promise in promises) { | |
| 188 all.AddPromise(promise); | |
| 189 if (all.Done) | |
| 190 break; | |
| 191 } | |
| 192 all.Complete(); | |
| 193 return all.ResultPromise; | |
| 194 } | |
| 195 | |
| 196 public static IPromise<T[]> All<T>(IEnumerable<IPromise<T>> promises, Func<T, IPromise> cleanup, Action cancel) { | |
| 197 var d = new Deferred<T[]>(DefaultDispatcher); | |
| 198 var all = new PromiseAll<T>(d, cleanup, cancel); | |
| 199 foreach (var promise in promises) { | |
| 200 all.AddPromise(promise); | |
| 201 if (all.Done) | |
| 202 break; | |
| 203 } | |
| 204 all.Complete(); | |
| 205 return all.ResultPromise; | |
| 206 } | |
| 207 } | |
| 208 } | |
| 209 |
