| @@ -38,14 +38,14 namespace Implab.Fx | |||||
| 38 | return anim; |
|
38 | return anim; | |
| 39 | } |
|
39 | } | |
| 40 |
|
40 | |||
| 41 | public static Promise<T> CloseFadeOut<T>(this T ctl) where T : Form |
|
41 | public static IPromise<T> CloseFadeOut<T>(this T ctl) where T : Form | |
| 42 | { |
|
42 | { | |
| 43 | var anim = ctl.AnimateTransparency(0); |
|
43 | var anim = ctl.AnimateTransparency(0); | |
| 44 |
|
44 | |||
| 45 | return anim.Play().DispatchToControl(ctl).Then(frm => frm.Close()); |
|
45 | return anim.Play().DispatchToControl(ctl).Then(frm => frm.Close()); | |
| 46 | } |
|
46 | } | |
| 47 |
|
47 | |||
| 48 | public static Promise<T> OverlayFadeIn<T>(this Form that, T overlay) where T : Form |
|
48 | public static IPromise<T> OverlayFadeIn<T>(this Form that, T overlay) where T : Form | |
| 49 | { |
|
49 | { | |
| 50 | if (that == null) |
|
50 | if (that == null) | |
| 51 | throw new ArgumentNullException("that"); |
|
51 | throw new ArgumentNullException("that"); | |
| @@ -255,7 +255,7 namespace Implab.Test { | |||||
| 255 |
|
255 | |||
| 256 | var t = Environment.TickCount; |
|
256 | var t = Environment.TickCount; | |
| 257 | var res = args |
|
257 | var res = args | |
| 258 |
.ChainedMap |
|
258 | .ChainedMap( | |
| 259 | x => pool.Invoke( |
|
259 | x => pool.Invoke( | |
| 260 | () => Math.Sin(x * x) |
|
260 | () => Math.Sin(x * x) | |
| 261 | ), |
|
261 | ), | |
| @@ -105,7 +105,7 namespace Implab.Parallels { | |||||
| 105 | } |
|
105 | } | |
| 106 | } |
|
106 | } | |
| 107 |
|
107 | |||
| 108 | public static Promise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) { |
|
108 | public static IPromise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) { | |
| 109 | if (source == null) |
|
109 | if (source == null) | |
| 110 | throw new ArgumentNullException("source"); |
|
110 | throw new ArgumentNullException("source"); | |
| 111 | if (transform == null) |
|
111 | if (transform == null) | |
| @@ -115,7 +115,7 namespace Implab.Parallels { | |||||
| 115 | return mapper.Promise; |
|
115 | return mapper.Promise; | |
| 116 | } |
|
116 | } | |
| 117 |
|
117 | |||
| 118 | public static Promise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) { |
|
118 | public static IPromise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) { | |
| 119 | if (source == null) |
|
119 | if (source == null) | |
| 120 | throw new ArgumentNullException("source"); |
|
120 | throw new ArgumentNullException("source"); | |
| 121 | if (action == null) |
|
121 | if (action == null) | |
| @@ -136,6 +136,7 namespace Implab.Parallels { | |||||
| 136 | var promise = new Promise<TDst[]>(); |
|
136 | var promise = new Promise<TDst[]>(); | |
| 137 | var res = new TDst[source.Length]; |
|
137 | var res = new TDst[source.Length]; | |
| 138 | var pending = source.Length; |
|
138 | var pending = source.Length; | |
|
|
139 | ||||
| 139 | var semaphore = new Semaphore(threads, threads); |
|
140 | var semaphore = new Semaphore(threads, threads); | |
| 140 |
|
141 | |||
| 141 | AsyncPool.InvokeNewThread(() => { |
|
142 | AsyncPool.InvokeNewThread(() => { | |
| @@ -143,18 +143,24 namespace Implab.Parallels { | |||||
| 143 | // anyway it may take some time for the thread to start |
|
143 | // anyway it may take some time for the thread to start | |
| 144 | // we will ensure that at least one thread is running |
|
144 | // we will ensure that at least one thread is running | |
| 145 |
|
145 | |||
| 146 | if (AllocateThreadSlot(1)) { |
|
146 | EnsurePoolIsAlive(); | |
| 147 | // if there were no threads in the pool |
|
|||
| 148 | var worker = new Thread(this.Worker); |
|
|||
| 149 | worker.IsBackground = true; |
|
|||
| 150 | worker.Start(); |
|
|||
| 151 | } |
|
|||
| 152 | } else { |
|
147 | } else { | |
| 153 | // if there is no sleeping threads in the pool |
|
148 | // if there is no sleeping threads in the pool | |
| 154 | if (!StartWorker()) |
|
149 | if (!StartWorker()) { | |
| 155 | // we haven't started a new thread, but the current can be on the way and it can't process the queue |
|
150 | // we haven't started a new thread, but the current can be on the way to terminate and it can't process the queue | |
| 156 | // send it a signal to spin again |
|
151 | // send it a signal to spin again | |
| 157 |
SignalThread(); |
|
152 | SignalThread(); | |
|
|
153 | EnsurePoolIsAlive(); | |||
|
|
154 | } | |||
|
|
155 | } | |||
|
|
156 | } | |||
|
|
157 | ||||
|
|
158 | private void EnsurePoolIsAlive() { | |||
|
|
159 | if (AllocateThreadSlot(1)) { | |||
|
|
160 | // if there were no threads in the pool | |||
|
|
161 | var worker = new Thread(this.Worker); | |||
|
|
162 | worker.IsBackground = true; | |||
|
|
163 | worker.Start(); | |||
| 158 | } |
|
164 | } | |
| 159 | } |
|
165 | } | |
| 160 |
|
166 | |||
| @@ -177,12 +183,9 namespace Implab.Parallels { | |||||
| 177 | // in case at the moment the last thread was being released |
|
183 | // in case at the moment the last thread was being released | |
| 178 | // a new task was added to the queue, we need to try |
|
184 | // a new task was added to the queue, we need to try | |
| 179 | // to revoke the thread to avoid the situation when the task is left unprocessed |
|
185 | // to revoke the thread to avoid the situation when the task is left unprocessed | |
| 180 |
if (last && |
|
186 | if (last && FetchSignalOrWait(0)) { // FetchSignalOrWait(0) will fetch pending task or will return false | |
| 181 | if (AllocateThreadSlot(1)) |
|
187 | SignalThread(); // since FetchSignalOrWait(0) has fetched the signal we need to reschedule it | |
| 182 | return true; // spin again... |
|
188 | return AllocateThreadSlot(1); // ensure that at least one thread is alive | |
| 183 | else |
|
|||
| 184 | SignalThread(); // since Sleep(0) has fetched the signal we neet to reschedule it |
|
|||
| 185 |
|
||||
| 186 | } |
|
189 | } | |
| 187 |
|
190 | |||
| 188 | return false; |
|
191 | return false; | |
| @@ -11,7 +11,7 namespace Implab { | |||||
| 11 | public delegate T ErrorHandler<out T>(Exception e); |
|
11 | public delegate T ErrorHandler<out T>(Exception e); | |
| 12 | public delegate void ResultHandler<in T>(T result); |
|
12 | public delegate void ResultHandler<in T>(T result); | |
| 13 | public delegate TNew ResultMapper<in TSrc, out TNew>(TSrc result); |
|
13 | public delegate TNew ResultMapper<in TSrc, out TNew>(TSrc result); | |
| 14 | public delegate Promise<TNew> ChainedOperation<in TSrc,TNew>(TSrc result); |
|
14 | public delegate IPromise<TNew> ChainedOperation<in TSrc,TNew>(TSrc result); | |
| 15 |
|
15 | |||
| 16 | /// <summary> |
|
16 | /// <summary> | |
| 17 | /// Класс для асинхронного получения результатов. Так называемое "обещание". |
|
17 | /// Класс для асинхронного получения результатов. Так называемое "обещание". | |
| @@ -610,7 +610,7 namespace Implab { | |||||
| 610 | /// <param name="promises">Список обещаний. Если список пустой, то результирующее обещание возвращается уже выполненным.</param> |
|
610 | /// <param name="promises">Список обещаний. Если список пустой, то результирующее обещание возвращается уже выполненным.</param> | |
| 611 | /// <returns>Обещание объединяющее в себе результат переданных обещаний.</returns> |
|
611 | /// <returns>Обещание объединяющее в себе результат переданных обещаний.</returns> | |
| 612 | /// <exception cref="ArgumentNullException"><paramref name="promises"/> не может быть null</exception> |
|
612 | /// <exception cref="ArgumentNullException"><paramref name="promises"/> не может быть null</exception> | |
| 613 | public static Promise<T[]> CreateComposite(IList<Promise<T>> promises) { |
|
613 | public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) { | |
| 614 | if (promises == null) |
|
614 | if (promises == null) | |
| 615 | throw new ArgumentNullException(); |
|
615 | throw new ArgumentNullException(); | |
| 616 |
|
616 | |||
General Comments 0
You need to be logged in to leave comments.
Login now
