##// END OF EJS Templates
fixed Promise.Error handler
cin -
r112:38d6a4db35d7 v2
parent child
Show More
@@ -1,954 +1,954
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Reflection;
3 using System.Reflection;
4 using System.Threading;
4 using System.Threading;
5 using Implab.Parallels;
5 using Implab.Parallels;
6
6
7 namespace Implab {
7 namespace Implab {
8
8
9 /// <summary>
9 /// <summary>
10 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
10 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
11 /// </summary>
11 /// </summary>
12 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
12 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
13 /// <remarks>
13 /// <remarks>
14 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
14 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
15 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
15 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
16 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
16 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
17 /// <para>
17 /// <para>
18 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
18 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
19 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
19 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
20 /// </para>
20 /// </para>
21 /// <para>
21 /// <para>
22 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
22 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
23 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
23 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
24 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
24 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
25 /// </para>
25 /// </para>
26 /// <para>
26 /// <para>
27 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
27 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
28 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
28 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
29 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
29 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
30 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
30 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
31 /// обСщания.
31 /// обСщания.
32 /// </para>
32 /// </para>
33 /// <para>
33 /// <para>
34 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
34 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
35 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
35 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
36 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
36 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
37 /// </para>
37 /// </para>
38 /// <para>
38 /// <para>
39 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
39 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
40 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
40 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
41 /// </para>
41 /// </para>
42 /// </remarks>
42 /// </remarks>
43 public class Promise<T> : IPromise<T> {
43 public class Promise<T> : IPromise<T> {
44
44
45 protected abstract class AbstractHandler : MTCustomQueueNode<AbstractHandler> {
45 protected abstract class AbstractHandler : MTCustomQueueNode<AbstractHandler> {
46 public abstract void Resolve(T result);
46 public abstract void Resolve(T result);
47 public abstract void Reject(Exception error);
47 public abstract void Reject(Exception error);
48 public abstract void Cancel();
48 public abstract void Cancel();
49 }
49 }
50
50
51 protected class RemapDescriptor<T2> : AbstractHandler {
51 protected class RemapDescriptor<T2> : AbstractHandler {
52
52
53 readonly Func<T,T2> m_resultHandler;
53 readonly Func<T,T2> m_resultHandler;
54 readonly Func<Exception,T2> m_errorHandler;
54 readonly Func<Exception,T2> m_errorHandler;
55 readonly Action m_cancellHandler;
55 readonly Action m_cancellHandler;
56 readonly Promise<T2> m_medium;
56 readonly Promise<T2> m_medium;
57
57
58 public RemapDescriptor(Func<T,T2> resultHandler, Func<Exception,T2> errorHandler, Action cancelHandler, Promise<T2> medium) {
58 public RemapDescriptor(Func<T,T2> resultHandler, Func<Exception,T2> errorHandler, Action cancelHandler, Promise<T2> medium) {
59 m_resultHandler = resultHandler;
59 m_resultHandler = resultHandler;
60 m_errorHandler = errorHandler;
60 m_errorHandler = errorHandler;
61 m_cancellHandler = cancelHandler;
61 m_cancellHandler = cancelHandler;
62 m_medium = medium;
62 m_medium = medium;
63 }
63 }
64
64
65 public override void Resolve(T result) {
65 public override void Resolve(T result) {
66 if (m_resultHandler != null) {
66 if (m_resultHandler != null) {
67 try {
67 try {
68 if (m_medium != null)
68 if (m_medium != null)
69 m_medium.Resolve(m_resultHandler(result));
69 m_medium.Resolve(m_resultHandler(result));
70 else
70 else
71 m_resultHandler(result);
71 m_resultHandler(result);
72 } catch (Exception e) {
72 } catch (Exception e) {
73 Reject(e);
73 Reject(e);
74 }
74 }
75 } else if(m_medium != null)
75 } else if(m_medium != null)
76 m_medium.Resolve(default(T2));
76 m_medium.Resolve(default(T2));
77 }
77 }
78
78
79 public override void Reject(Exception error) {
79 public override void Reject(Exception error) {
80 if (m_errorHandler != null) {
80 if (m_errorHandler != null) {
81 try {
81 try {
82 var res = m_errorHandler(error);
82 var res = m_errorHandler(error);
83 if (m_medium != null)
83 if (m_medium != null)
84 m_medium.Resolve(res);
84 m_medium.Resolve(res);
85 } catch (Exception err2) {
85 } catch (Exception err2) {
86 if (m_medium != null)
86 if (m_medium != null)
87 m_medium.Reject(err2);
87 m_medium.Reject(err2);
88 }
88 }
89 } else if (m_medium != null)
89 } else if (m_medium != null)
90 m_medium.Reject(error);
90 m_medium.Reject(error);
91 }
91 }
92
92
93 public override void Cancel() {
93 public override void Cancel() {
94 if (m_cancellHandler != null) {
94 if (m_cancellHandler != null) {
95 try {
95 try {
96 m_cancellHandler();
96 m_cancellHandler();
97 } catch (Exception err) {
97 } catch (Exception err) {
98 Reject(err);
98 Reject(err);
99 return;
99 return;
100 }
100 }
101 }
101 }
102 if (m_medium != null)
102 if (m_medium != null)
103 m_medium.Cancel();
103 m_medium.Cancel();
104 }
104 }
105 }
105 }
106
106
107 protected class HandlerDescriptor : AbstractHandler {
107 protected class HandlerDescriptor : AbstractHandler {
108
108
109 readonly Action<T> m_resultHandler;
109 readonly Action<T> m_resultHandler;
110 readonly Action<Exception> m_errorHandler;
110 readonly Action<Exception> m_errorHandler;
111 readonly Action m_cancellHandler;
111 readonly Action m_cancellHandler;
112 readonly Promise<T> m_medium;
112 readonly Promise<T> m_medium;
113
113
114 public HandlerDescriptor(Action<T> resultHandler, Action<Exception> errorHandler, Action cancelHandler, Promise<T> medium) {
114 public HandlerDescriptor(Action<T> resultHandler, Action<Exception> errorHandler, Action cancelHandler, Promise<T> medium) {
115 m_resultHandler = resultHandler;
115 m_resultHandler = resultHandler;
116 m_errorHandler = errorHandler;
116 m_errorHandler = errorHandler;
117 m_cancellHandler = cancelHandler;
117 m_cancellHandler = cancelHandler;
118 m_medium = medium;
118 m_medium = medium;
119 }
119 }
120
120
121 public override void Resolve(T result) {
121 public override void Resolve(T result) {
122 if (m_resultHandler != null) {
122 if (m_resultHandler != null) {
123 try {
123 try {
124 m_resultHandler(result);
124 m_resultHandler(result);
125 } catch (Exception e) {
125 } catch (Exception e) {
126 Reject(e);
126 Reject(e);
127 return;
127 return;
128 }
128 }
129 }
129 }
130 if(m_medium != null)
130 if(m_medium != null)
131 m_medium.Resolve(result);
131 m_medium.Resolve(result);
132 }
132 }
133
133
134 public override void Reject(Exception error) {
134 public override void Reject(Exception error) {
135 if (m_errorHandler != null) {
135 if (m_errorHandler != null) {
136 try {
136 try {
137 m_errorHandler(error);
137 m_errorHandler(error);
138 if (m_medium != null)
138 if (m_medium != null)
139 m_medium.Resolve(default(T));
139 m_medium.Resolve(default(T));
140 } catch (Exception err2) {
140 } catch (Exception err2) {
141 if (m_medium != null)
141 if (m_medium != null)
142 m_medium.Reject(err2);
142 m_medium.Reject(err2);
143 }
143 }
144 } else if (m_medium != null)
144 } else if (m_medium != null)
145 m_medium.Reject(error);
145 m_medium.Reject(error);
146 }
146 }
147
147
148 public override void Cancel() {
148 public override void Cancel() {
149 if (m_cancellHandler != null) {
149 if (m_cancellHandler != null) {
150 try {
150 try {
151 m_cancellHandler();
151 m_cancellHandler();
152 } catch (Exception err) {
152 } catch (Exception err) {
153 Reject(err);
153 Reject(err);
154 return;
154 return;
155 }
155 }
156 }
156 }
157 if (m_medium != null)
157 if (m_medium != null)
158 m_medium.Cancel();
158 m_medium.Cancel();
159 }
159 }
160 }
160 }
161
161
162 const int UNRESOLVED_SATE = 0;
162 const int UNRESOLVED_SATE = 0;
163 const int TRANSITIONAL_STATE = 1;
163 const int TRANSITIONAL_STATE = 1;
164 const int SUCCEEDED_STATE = 2;
164 const int SUCCEEDED_STATE = 2;
165 const int REJECTED_STATE = 3;
165 const int REJECTED_STATE = 3;
166 const int CANCELLED_STATE = 4;
166 const int CANCELLED_STATE = 4;
167
167
168 int m_childrenCount;
168 int m_childrenCount;
169 int m_state;
169 int m_state;
170 T m_result;
170 T m_result;
171 Exception m_error;
171 Exception m_error;
172
172
173 readonly MTCustomQueue<AbstractHandler> m_handlers = new MTCustomQueue<AbstractHandler>();
173 readonly MTCustomQueue<AbstractHandler> m_handlers = new MTCustomQueue<AbstractHandler>();
174 //readonly MTQueue<AbstractHandler> m_handlers = new MTQueue<AbstractHandler>();
174 //readonly MTQueue<AbstractHandler> m_handlers = new MTQueue<AbstractHandler>();
175
175
176 public Promise() {
176 public Promise() {
177 }
177 }
178
178
179 public Promise(IPromise parent) {
179 public Promise(IPromise parent) {
180 if (parent != null)
180 if (parent != null)
181 AddMappers<T>(
181 AddHandler(
182 null,
182 null,
183 null,
183 null,
184 () => {
184 () => {
185 if (parent.IsExclusive)
185 if (parent.IsExclusive)
186 parent.Cancel();
186 parent.Cancel();
187 },
187 },
188 null,
188 null,
189 false
189 false
190 );
190 );
191 }
191 }
192
192
193 bool BeginTransit() {
193 bool BeginTransit() {
194 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
194 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
195 }
195 }
196
196
197 void CompleteTransit(int state) {
197 void CompleteTransit(int state) {
198 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
198 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
199 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
199 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
200 }
200 }
201
201
202 void WaitTransition() {
202 void WaitTransition() {
203 while (m_state == TRANSITIONAL_STATE) {
203 while (m_state == TRANSITIONAL_STATE) {
204 Thread.MemoryBarrier();
204 Thread.MemoryBarrier();
205 }
205 }
206 }
206 }
207
207
208 public bool IsResolved {
208 public bool IsResolved {
209 get {
209 get {
210 Thread.MemoryBarrier();
210 Thread.MemoryBarrier();
211 return m_state > 1;
211 return m_state > 1;
212 }
212 }
213 }
213 }
214
214
215 public bool IsCancelled {
215 public bool IsCancelled {
216 get {
216 get {
217 Thread.MemoryBarrier();
217 Thread.MemoryBarrier();
218 return m_state == CANCELLED_STATE;
218 return m_state == CANCELLED_STATE;
219 }
219 }
220 }
220 }
221
221
222 public Type PromiseType {
222 public Type PromiseType {
223 get { return typeof(T); }
223 get { return typeof(T); }
224 }
224 }
225
225
226 /// <summary>
226 /// <summary>
227 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
227 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
228 /// </summary>
228 /// </summary>
229 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
229 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
230 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
230 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
231 public void Resolve(T result) {
231 public void Resolve(T result) {
232 if (BeginTransit()) {
232 if (BeginTransit()) {
233 m_result = result;
233 m_result = result;
234 CompleteTransit(SUCCEEDED_STATE);
234 CompleteTransit(SUCCEEDED_STATE);
235 OnStateChanged();
235 OnStateChanged();
236 } else {
236 } else {
237 WaitTransition();
237 WaitTransition();
238 if (m_state != CANCELLED_STATE)
238 if (m_state != CANCELLED_STATE)
239 throw new InvalidOperationException("The promise is already resolved");
239 throw new InvalidOperationException("The promise is already resolved");
240 }
240 }
241 }
241 }
242
242
243 /// <summary>
243 /// <summary>
244 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ выполнСния Π±ΡƒΠ΄Π΅Ρ‚ пустоС значСния.
244 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ выполнСния Π±ΡƒΠ΄Π΅Ρ‚ пустоС значСния.
245 /// </summary>
245 /// </summary>
246 /// <remarks>
246 /// <remarks>
247 /// Π”Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π² случаях, ΠΊΠΎΠ³Π΄Π° интСрСсСн Ρ„Π°ΠΊΡ‚ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π΅ΠΆΠ΅Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
247 /// Π”Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π² случаях, ΠΊΠΎΠ³Π΄Π° интСрСсСн Ρ„Π°ΠΊΡ‚ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π΅ΠΆΠ΅Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
248 /// </remarks>
248 /// </remarks>
249 public void Resolve() {
249 public void Resolve() {
250 Resolve(default(T));
250 Resolve(default(T));
251 }
251 }
252
252
253 /// <summary>
253 /// <summary>
254 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
254 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
255 /// </summary>
255 /// </summary>
256 /// <remarks>
256 /// <remarks>
257 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
257 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
258 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
258 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
259 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
259 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
260 /// </remarks>
260 /// </remarks>
261 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
261 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
262 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
262 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
263 public void Reject(Exception error) {
263 public void Reject(Exception error) {
264 if (BeginTransit()) {
264 if (BeginTransit()) {
265 m_error = error is TransientPromiseException ? error.InnerException : error;
265 m_error = error is TransientPromiseException ? error.InnerException : error;
266 CompleteTransit(REJECTED_STATE);
266 CompleteTransit(REJECTED_STATE);
267 OnStateChanged();
267 OnStateChanged();
268 } else {
268 } else {
269 WaitTransition();
269 WaitTransition();
270 if (m_state == SUCCEEDED_STATE)
270 if (m_state == SUCCEEDED_STATE)
271 throw new InvalidOperationException("The promise is already resolved");
271 throw new InvalidOperationException("The promise is already resolved");
272 }
272 }
273 }
273 }
274
274
275 /// <summary>
275 /// <summary>
276 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
276 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
277 /// </summary>
277 /// </summary>
278 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
278 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
279 public void Cancel() {
279 public void Cancel() {
280 if (BeginTransit()) {
280 if (BeginTransit()) {
281 CompleteTransit(CANCELLED_STATE);
281 CompleteTransit(CANCELLED_STATE);
282 OnStateChanged();
282 OnStateChanged();
283 }
283 }
284 }
284 }
285
285
286 /// <summary>
286 /// <summary>
287 /// ПослСдний ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
287 /// ПослСдний ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
288 /// </summary>
288 /// </summary>
289 /// <param name="success"></param>
289 /// <param name="success"></param>
290 /// <param name="error"></param>
290 /// <param name="error"></param>
291 /// <param name="cancel"></param>
291 /// <param name="cancel"></param>
292 /// <remarks>
292 /// <remarks>
293 /// <para>
293 /// <para>
294 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π½Π΅ создаСт связанного с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ обСщания ΠΈ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ для окончания
294 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π½Π΅ создаСт связанного с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ обСщания ΠΈ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ для окончания
295 /// фсинхронной Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ.
295 /// фсинхронной Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ.
296 /// </para>
296 /// </para>
297 /// <para>
297 /// <para>
298 /// Если Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ нСсколько Ρ€Π°Π·, Π»ΠΈΠ±ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, Ρ‚ΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ°
298 /// Если Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ нСсколько Ρ€Π°Π·, Π»ΠΈΠ±ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, Ρ‚ΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ°
299 /// Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ΠΎΡ‡Π½ΠΎΠΉ <see cref="IsExclusive"/> ΠΈ, ΠΊΠ°ΠΊ слСдствиС, Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ΠΎΡ‚ΠΌΠ΅Π½Π°
299 /// Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ΠΎΡ‡Π½ΠΎΠΉ <see cref="IsExclusive"/> ΠΈ, ΠΊΠ°ΠΊ слСдствиС, Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ΠΎΡ‚ΠΌΠ΅Π½Π°
300 /// всСй Ρ†Π΅ΠΏΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ снизу (с самого послСднСго обСщания).
300 /// всСй Ρ†Π΅ΠΏΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ снизу (с самого послСднСго обСщания).
301 /// </para>
301 /// </para>
302 /// </remarks>
302 /// </remarks>
303 public void On(Action<T> success, Action<Exception> error, Action cancel) {
303 public void On(Action<T> success, Action<Exception> error, Action cancel) {
304 if (success == null && error == null && cancel == null)
304 if (success == null && error == null && cancel == null)
305 return;
305 return;
306
306
307 AddHandler(success, error, cancel, null, false);
307 AddHandler(success, error, cancel, null, false);
308 }
308 }
309
309
310 public void On(Action<T> success, Action<Exception> error) {
310 public void On(Action<T> success, Action<Exception> error) {
311 AddHandler(success, error, null, null, false);
311 AddHandler(success, error, null, null, false);
312 }
312 }
313
313
314 public void On(Action<T> success) {
314 public void On(Action<T> success) {
315 AddHandler(success, null, null, null, false);
315 AddHandler(success, null, null, null, false);
316 }
316 }
317
317
318 public void On(Action handler, PromiseEventType events) {
318 public void On(Action handler, PromiseEventType events) {
319 Safe.ArgumentNotNull(handler, "handler");
319 Safe.ArgumentNotNull(handler, "handler");
320
320
321
321
322 AddHandler(
322 AddHandler(
323 events.HasFlag(PromiseEventType.Success) ? new Action<T>(x => handler()) : null,
323 events.HasFlag(PromiseEventType.Success) ? new Action<T>(x => handler()) : null,
324 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>( x => handler()) : null,
324 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>( x => handler()) : null,
325 events.HasFlag(PromiseEventType.Cancelled) ? handler : null,
325 events.HasFlag(PromiseEventType.Cancelled) ? handler : null,
326 null,
326 null,
327 false
327 false
328 );
328 );
329 }
329 }
330
330
331 public IPromise Error(Action<Exception> error) {
331 public IPromise Error(Action<Exception> error) {
332 if (error == null)
332 if (error == null)
333 return this;
333 return this;
334
334
335 var medium = new Promise<T>(this);
335 var medium = new Promise<T>(this);
336
336
337 AddMappers(
337 AddMappers(
338 null,
338 x => x,
339 e => {
339 e => {
340 error(e);
340 error(e);
341 return default(T);
341 return default(T);
342 },
342 },
343 null,
343 null,
344 medium,
344 medium,
345 true
345 true
346 );
346 );
347
347
348 return medium;
348 return medium;
349 }
349 }
350
350
351 /// <summary>
351 /// <summary>
352 /// Handles error and allows to keep the promise.
352 /// Handles error and allows to keep the promise.
353 /// </summary>
353 /// </summary>
354 /// <remarks>
354 /// <remarks>
355 /// If the specified handler throws an exception, this exception will be used to reject the promise.
355 /// If the specified handler throws an exception, this exception will be used to reject the promise.
356 /// </remarks>
356 /// </remarks>
357 /// <param name="handler">The error handler which returns the result of the promise.</param>
357 /// <param name="handler">The error handler which returns the result of the promise.</param>
358 /// <returns>New promise.</returns>
358 /// <returns>New promise.</returns>
359 public IPromise<T> Error(Func<Exception,T> handler) {
359 public IPromise<T> Error(Func<Exception,T> handler) {
360 if (handler == null)
360 if (handler == null)
361 return this;
361 return this;
362
362
363 var medium = new Promise<T>(this);
363 var medium = new Promise<T>(this);
364
364
365 AddMappers(null, handler, null, medium, true);
365 AddMappers(x => x, handler, null, medium, true);
366
366
367 return medium;
367 return medium;
368 }
368 }
369
369
370 /// <summary>
370 /// <summary>
371 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
371 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
372 /// </summary>
372 /// </summary>
373 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
373 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
374 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
374 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
375 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
375 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
376 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
376 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
377 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
377 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
378 /// <param name = "cancel"></param>
378 /// <param name = "cancel"></param>
379 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error, Action cancel) {
379 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error, Action cancel) {
380 Safe.ArgumentNotNull(mapper, "mapper");
380 Safe.ArgumentNotNull(mapper, "mapper");
381
381
382 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
382 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
383 var medium = new Promise<TNew>(this);
383 var medium = new Promise<TNew>(this);
384
384
385 AddMappers(
385 AddMappers(
386 mapper,
386 mapper,
387 error,
387 error,
388 cancel,
388 cancel,
389 medium,
389 medium,
390 true
390 true
391 );
391 );
392
392
393 return medium;
393 return medium;
394 }
394 }
395
395
396 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error) {
396 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error) {
397 return Then(mapper, error, null);
397 return Then(mapper, error, null);
398 }
398 }
399
399
400 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper) {
400 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper) {
401 return Then(mapper, null, null);
401 return Then(mapper, null, null);
402 }
402 }
403
403
404 /// <summary>
404 /// <summary>
405 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
405 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
406 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
406 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
407 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
407 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
408 /// </summary>
408 /// </summary>
409 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
409 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
410 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
410 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
411 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
411 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
412 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
412 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
413 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
413 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
414 /// <param name = "cancel"></param>
414 /// <param name = "cancel"></param>
415 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error, Action cancel) {
415 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error, Action cancel) {
416
416
417 Safe.ArgumentNotNull(chained, "chained");
417 Safe.ArgumentNotNull(chained, "chained");
418
418
419 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
419 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
420 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
420 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
421 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
421 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
422 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
422 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
423 var medium = new Promise<TNew>(this);
423 var medium = new Promise<TNew>(this);
424
424
425 Func<T,T> resultHandler = delegate(T result) {
425 Func<T,T> resultHandler = delegate(T result) {
426 if (medium.IsCancelled)
426 if (medium.IsCancelled)
427 return default(T);
427 return default(T);
428
428
429 var promise = chained(result);
429 var promise = chained(result);
430
430
431 promise.On(
431 promise.On(
432 medium.Resolve,
432 medium.Resolve,
433 medium.Reject,
433 medium.Reject,
434 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
434 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
435 );
435 );
436
436
437 // notify chained operation that it's not needed anymore
437 // notify chained operation that it's not needed anymore
438 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
438 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
439 // зависит IsExclusive
439 // зависит IsExclusive
440 medium.On(
440 medium.On(
441 null,
441 null,
442 null,
442 null,
443 () => {
443 () => {
444 if (promise.IsExclusive)
444 if (promise.IsExclusive)
445 promise.Cancel();
445 promise.Cancel();
446 }
446 }
447 );
447 );
448
448
449 return default(T);
449 return default(T);
450 };
450 };
451
451
452 Func<Exception,T> errorHandler;
452 Func<Exception,T> errorHandler;
453
453
454 if (error != null)
454 if (error != null)
455 errorHandler = delegate(Exception e) {
455 errorHandler = delegate(Exception e) {
456 try {
456 try {
457 var promise = error(e);
457 var promise = error(e);
458
458
459 promise.On(
459 promise.On(
460 medium.Resolve,
460 medium.Resolve,
461 medium.Reject,
461 medium.Reject,
462 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
462 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
463 );
463 );
464
464
465 // notify chained operation that it's not needed anymore
465 // notify chained operation that it's not needed anymore
466 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
466 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
467 // зависит IsExclusive
467 // зависит IsExclusive
468 medium.Cancelled(() => {
468 medium.Cancelled(() => {
469 if (promise.IsExclusive)
469 if (promise.IsExclusive)
470 promise.Cancel();
470 promise.Cancel();
471 });
471 });
472 } catch (Exception e2) {
472 } catch (Exception e2) {
473 medium.Reject(e2);
473 medium.Reject(e2);
474 }
474 }
475 return default(T);
475 return default(T);
476 };
476 };
477 else
477 else
478 errorHandler = err => {
478 errorHandler = err => {
479 medium.Reject(err);
479 medium.Reject(err);
480 return default(T);
480 return default(T);
481 };
481 };
482
482
483
483
484 Action cancelHandler;
484 Action cancelHandler;
485 if (cancel != null)
485 if (cancel != null)
486 cancelHandler = () => {
486 cancelHandler = () => {
487 if (cancel != null)
487 if (cancel != null)
488 cancel();
488 cancel();
489 medium.Cancel();
489 medium.Cancel();
490 };
490 };
491 else
491 else
492 cancelHandler = medium.Cancel;
492 cancelHandler = medium.Cancel;
493
493
494 AddMappers(
494 AddMappers(
495 resultHandler,
495 resultHandler,
496 errorHandler,
496 errorHandler,
497 cancelHandler,
497 cancelHandler,
498 null,
498 null,
499 true
499 true
500 );
500 );
501
501
502 return medium;
502 return medium;
503 }
503 }
504
504
505 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error) {
505 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error) {
506 return Chain(chained, error, null);
506 return Chain(chained, error, null);
507 }
507 }
508
508
509 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained) {
509 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained) {
510 return Chain(chained, null, null);
510 return Chain(chained, null, null);
511 }
511 }
512
512
513 public IPromise<T> Cancelled(Action handler) {
513 public IPromise<T> Cancelled(Action handler) {
514 var medium = new Promise<T>(this);
514 var medium = new Promise<T>(this);
515 AddHandler(null, null, handler, medium, false);
515 AddHandler(null, null, handler, medium, false);
516 return medium;
516 return medium;
517 }
517 }
518
518
519 /// <summary>
519 /// <summary>
520 /// Adds the specified handler for all cases (success, error, cancel)
520 /// Adds the specified handler for all cases (success, error, cancel)
521 /// </summary>
521 /// </summary>
522 /// <param name="handler">The handler that will be called anyway</param>
522 /// <param name="handler">The handler that will be called anyway</param>
523 /// <returns>self</returns>
523 /// <returns>self</returns>
524 public IPromise<T> Anyway(Action handler) {
524 public IPromise<T> Anyway(Action handler) {
525 Safe.ArgumentNotNull(handler, "handler");
525 Safe.ArgumentNotNull(handler, "handler");
526
526
527 var medium = new Promise<T>(this);
527 var medium = new Promise<T>(this);
528
528
529 AddHandler(
529 AddHandler(
530 x => handler(),
530 x => handler(),
531 e => {
531 e => {
532 handler();
532 handler();
533 throw new TransientPromiseException(e);
533 throw new TransientPromiseException(e);
534 },
534 },
535 handler,
535 handler,
536 medium,
536 medium,
537 true
537 true
538 );
538 );
539
539
540 return medium;
540 return medium;
541 }
541 }
542
542
543 /// <summary>
543 /// <summary>
544 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ
544 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ
545 /// </summary>
545 /// </summary>
546 /// <typeparam name="T2"></typeparam>
546 /// <typeparam name="T2"></typeparam>
547 /// <returns></returns>
547 /// <returns></returns>
548 public IPromise<T2> Cast<T2>() {
548 public IPromise<T2> Cast<T2>() {
549 return Then(x => (T2)(object)x, null);
549 return Then(x => (T2)(object)x, null);
550 }
550 }
551
551
552 /// <summary>
552 /// <summary>
553 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
553 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
554 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
554 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
555 /// </summary>
555 /// </summary>
556 /// <remarks>
556 /// <remarks>
557 /// <para>
557 /// <para>
558 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
558 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
559 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
559 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
560 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
560 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
561 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
561 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
562 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
562 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
563 /// </para>
563 /// </para>
564 /// <para>
564 /// <para>
565 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
565 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
566 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
566 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
567 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
567 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
568 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
568 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
569 /// </para>
569 /// </para>
570 /// </remarks>
570 /// </remarks>
571 /// <param name="timeout">ВрСмя оТидания</param>
571 /// <param name="timeout">ВрСмя оТидания</param>
572 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
572 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
573 public T Join(int timeout) {
573 public T Join(int timeout) {
574 var evt = new ManualResetEvent(false);
574 var evt = new ManualResetEvent(false);
575 Anyway(() => evt.Set());
575 Anyway(() => evt.Set());
576
576
577 if (!evt.WaitOne(timeout, true))
577 if (!evt.WaitOne(timeout, true))
578 throw new TimeoutException();
578 throw new TimeoutException();
579
579
580 switch (m_state) {
580 switch (m_state) {
581 case SUCCEEDED_STATE:
581 case SUCCEEDED_STATE:
582 return m_result;
582 return m_result;
583 case CANCELLED_STATE:
583 case CANCELLED_STATE:
584 throw new OperationCanceledException();
584 throw new OperationCanceledException();
585 case REJECTED_STATE:
585 case REJECTED_STATE:
586 throw new TargetInvocationException(m_error);
586 throw new TargetInvocationException(m_error);
587 default:
587 default:
588 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
588 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
589 }
589 }
590 }
590 }
591
591
592 public T Join() {
592 public T Join() {
593 return Join(Timeout.Infinite);
593 return Join(Timeout.Infinite);
594 }
594 }
595
595
596 void AddMappers<T2>(Func<T,T2> success, Func<Exception,T2> error, Action cancel, Promise<T2> medium, bool inc) {
596 void AddMappers<T2>(Func<T,T2> success, Func<Exception,T2> error, Action cancel, Promise<T2> medium, bool inc) {
597 if (inc)
597 if (inc)
598 Interlocked.Increment(ref m_childrenCount);
598 Interlocked.Increment(ref m_childrenCount);
599
599
600 AbstractHandler handler = new RemapDescriptor<T2>(success, error, cancel, medium);
600 AbstractHandler handler = new RemapDescriptor<T2>(success, error, cancel, medium);
601
601
602 bool queued;
602 bool queued;
603
603
604 if (!IsResolved) {
604 if (!IsResolved) {
605 m_handlers.Enqueue(handler);
605 m_handlers.Enqueue(handler);
606 queued = true;
606 queued = true;
607 } else {
607 } else {
608 // the promise is in resolved state, just invoke the handled with minimum overhead
608 // the promise is in resolved state, just invoke the handled with minimum overhead
609 queued = false;
609 queued = false;
610 InvokeHandler(handler);
610 InvokeHandler(handler);
611 }
611 }
612
612
613 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
613 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
614 // if the promise have been resolved while we was adding handler to the queue
614 // if the promise have been resolved while we was adding handler to the queue
615 // we can't guarantee that someone is still processing it
615 // we can't guarantee that someone is still processing it
616 // therefore we will fetch a handler from the queue and execute it
616 // therefore we will fetch a handler from the queue and execute it
617 // note that fetched handler may be not the one that we have added
617 // note that fetched handler may be not the one that we have added
618 // even we can fetch no handlers at all :)
618 // even we can fetch no handlers at all :)
619 InvokeHandler(handler);
619 InvokeHandler(handler);
620 }
620 }
621
621
622 void AddHandler(Action<T> success, Action<Exception> error, Action cancel, Promise<T> medium, bool inc) {
622 void AddHandler(Action<T> success, Action<Exception> error, Action cancel, Promise<T> medium, bool inc) {
623 if (inc)
623 if (inc)
624 Interlocked.Increment(ref m_childrenCount);
624 Interlocked.Increment(ref m_childrenCount);
625
625
626 AbstractHandler handler = new HandlerDescriptor(success, error, cancel, medium);
626 AbstractHandler handler = new HandlerDescriptor(success, error, cancel, medium);
627
627
628 bool queued;
628 bool queued;
629
629
630 if (!IsResolved) {
630 if (!IsResolved) {
631 m_handlers.Enqueue(handler);
631 m_handlers.Enqueue(handler);
632 queued = true;
632 queued = true;
633 } else {
633 } else {
634 // the promise is in resolved state, just invoke the handled with minimum overhead
634 // the promise is in resolved state, just invoke the handled with minimum overhead
635 queued = false;
635 queued = false;
636 InvokeHandler(handler);
636 InvokeHandler(handler);
637 }
637 }
638
638
639 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
639 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
640 // if the promise have been resolved while we was adding handler to the queue
640 // if the promise have been resolved while we was adding handler to the queue
641 // we can't guarantee that someone is still processing it
641 // we can't guarantee that someone is still processing it
642 // therefore we will fetch a handler from the queue and execute it
642 // therefore we will fetch a handler from the queue and execute it
643 // note that fetched handler may be not the one that we have added
643 // note that fetched handler may be not the one that we have added
644 // even we can fetch no handlers at all :)
644 // even we can fetch no handlers at all :)
645 InvokeHandler(handler);
645 InvokeHandler(handler);
646 }
646 }
647
647
648 protected virtual void InvokeHandler(AbstractHandler handler) {
648 protected virtual void InvokeHandler(AbstractHandler handler) {
649 switch (m_state) {
649 switch (m_state) {
650 case SUCCEEDED_STATE:
650 case SUCCEEDED_STATE:
651 handler.Resolve(m_result);
651 handler.Resolve(m_result);
652 break;
652 break;
653 case REJECTED_STATE:
653 case REJECTED_STATE:
654 handler.Reject(m_error);
654 handler.Reject(m_error);
655 break;
655 break;
656 case CANCELLED_STATE:
656 case CANCELLED_STATE:
657 handler.Cancel();
657 handler.Cancel();
658 break;
658 break;
659 default:
659 default:
660 // do nothing
660 // do nothing
661 return;
661 return;
662 }
662 }
663 }
663 }
664
664
665 void OnStateChanged() {
665 void OnStateChanged() {
666 AbstractHandler handler;
666 AbstractHandler handler;
667 while (m_handlers.TryDequeue(out handler))
667 while (m_handlers.TryDequeue(out handler))
668 InvokeHandler(handler);
668 InvokeHandler(handler);
669 }
669 }
670
670
671 public bool IsExclusive {
671 public bool IsExclusive {
672 get {
672 get {
673 return m_childrenCount <= 1;
673 return m_childrenCount <= 1;
674 }
674 }
675 }
675 }
676
676
677 /// <summary>
677 /// <summary>
678 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся массив Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
678 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся массив Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
679 /// Если хотябы ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚ΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
679 /// Если хотябы ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚ΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
680 /// ΠŸΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ обСщания, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ обСщания Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹, Ссли Π½ΠΈΠΊΡ‚ΠΎ большС Π½Π° Π½ΠΈΡ… Π½Π΅ подписан.
680 /// ΠŸΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ обСщания, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ обСщания Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹, Ссли Π½ΠΈΠΊΡ‚ΠΎ большС Π½Π° Π½ΠΈΡ… Π½Π΅ подписан.
681 /// </summary>
681 /// </summary>
682 /// <param name="promises">Бписок ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. Если список пустой, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ возвращаСтся ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌ.</param>
682 /// <param name="promises">Бписок ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. Если список пустой, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ возвращаСтся ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌ.</param>
683 /// <returns>ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.</returns>
683 /// <returns>ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.</returns>
684 /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ null</exception>
684 /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ null</exception>
685 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
685 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
686 if (promises == null)
686 if (promises == null)
687 throw new ArgumentNullException();
687 throw new ArgumentNullException();
688
688
689 // создаСм аккумулятор для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
689 // создаСм аккумулятор для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
690 var result = new T[promises.Count];
690 var result = new T[promises.Count];
691 var promise = new Promise<T[]>();
691 var promise = new Promise<T[]>();
692
692
693 // special case
693 // special case
694 if (promises.Count == 0) {
694 if (promises.Count == 0) {
695 promise.Resolve(result);
695 promise.Resolve(result);
696 return promise;
696 return promise;
697 }
697 }
698
698
699 int pending = promises.Count;
699 int pending = promises.Count;
700
700
701 for (int i = 0; i < promises.Count; i++) {
701 for (int i = 0; i < promises.Count; i++) {
702 var dest = i;
702 var dest = i;
703
703
704 if (promises[i] != null) {
704 if (promises[i] != null) {
705 promises[i].On(
705 promises[i].On(
706 x => {
706 x => {
707 result[dest] = x;
707 result[dest] = x;
708 if (Interlocked.Decrement(ref pending) == 0)
708 if (Interlocked.Decrement(ref pending) == 0)
709 promise.Resolve(result);
709 promise.Resolve(result);
710 },
710 },
711 promise.Reject
711 promise.Reject
712 );
712 );
713 } else {
713 } else {
714 if (Interlocked.Decrement(ref pending) == 0)
714 if (Interlocked.Decrement(ref pending) == 0)
715 promise.Resolve(result);
715 promise.Resolve(result);
716 }
716 }
717 }
717 }
718
718
719 promise.Cancelled(
719 promise.Cancelled(
720 () => {
720 () => {
721 foreach (var d in promises)
721 foreach (var d in promises)
722 if (d != null && d.IsExclusive)
722 if (d != null && d.IsExclusive)
723 d.Cancel();
723 d.Cancel();
724 }
724 }
725 );
725 );
726
726
727 return promise;
727 return promise;
728 }
728 }
729
729
730 /// <summary>
730 /// <summary>
731 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ
731 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ
732 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ всСх ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. ΠŸΡ€ΠΈ этом Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
732 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ всСх ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. ΠŸΡ€ΠΈ этом Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
733 /// ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ.
733 /// ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ.
734 /// </summary>
734 /// </summary>
735 /// <param name="promises">ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±ΡŠΠ΅Π΄Π΅Π½Π΅Π½Ρ‹ Π² ΠΎΠ΄Π½ΠΎ.</param>
735 /// <param name="promises">ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±ΡŠΠ΅Π΄Π΅Π½Π΅Π½Ρ‹ Π² ΠΎΠ΄Π½ΠΎ.</param>
736 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅.</returns>
736 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅.</returns>
737 /// <remarks>
737 /// <remarks>
738 /// Если Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡŒΡΡ <c>null</c>, Ρ‚ΠΎ ΠΎΠ½ΠΈ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ обСщания.
738 /// Если Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡŒΡΡ <c>null</c>, Ρ‚ΠΎ ΠΎΠ½ΠΈ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ обСщания.
739 /// </remarks>
739 /// </remarks>
740 public static IPromise CreateComposite(ICollection<IPromise> promises) {
740 public static IPromise CreateComposite(ICollection<IPromise> promises) {
741 if (promises == null)
741 if (promises == null)
742 throw new ArgumentNullException();
742 throw new ArgumentNullException();
743 if (promises.Count == 0)
743 if (promises.Count == 0)
744 return Promise<object>.ResultToPromise(null);
744 return Promise<object>.ResultToPromise(null);
745
745
746 int countdown = promises.Count;
746 int countdown = promises.Count;
747
747
748 var result = new Promise<object>();
748 var result = new Promise<object>();
749
749
750 foreach (var d in promises) {
750 foreach (var d in promises) {
751 if (d == null) {
751 if (d == null) {
752 if (Interlocked.Decrement(ref countdown) == 0)
752 if (Interlocked.Decrement(ref countdown) == 0)
753 result.Resolve(null);
753 result.Resolve(null);
754 } else {
754 } else {
755 d.Then(() => {
755 d.Then(() => {
756 if (Interlocked.Decrement(ref countdown) == 0)
756 if (Interlocked.Decrement(ref countdown) == 0)
757 result.Resolve(null);
757 result.Resolve(null);
758 });
758 });
759 }
759 }
760 }
760 }
761
761
762 result.Cancelled(() => {
762 result.Cancelled(() => {
763 foreach (var d in promises)
763 foreach (var d in promises)
764 if (d != null && d.IsExclusive)
764 if (d != null && d.IsExclusive)
765 d.Cancel();
765 d.Cancel();
766 });
766 });
767
767
768 return result;
768 return result;
769 }
769 }
770
770
771 public static Promise<T> ResultToPromise(T result) {
771 public static Promise<T> ResultToPromise(T result) {
772 var p = new Promise<T>();
772 var p = new Promise<T>();
773 p.Resolve(result);
773 p.Resolve(result);
774 return p;
774 return p;
775 }
775 }
776
776
777 public static Promise<T> ExceptionToPromise(Exception error) {
777 public static Promise<T> ExceptionToPromise(Exception error) {
778 if (error == null)
778 if (error == null)
779 throw new ArgumentNullException();
779 throw new ArgumentNullException();
780
780
781 var p = new Promise<T>();
781 var p = new Promise<T>();
782 p.Reject(error);
782 p.Reject(error);
783 return p;
783 return p;
784 }
784 }
785
785
786 #region IPromiseBase explicit implementation
786 #region IPromiseBase explicit implementation
787
787
788 IPromise IPromise.Then(Action success, Action<Exception> error, Action cancel) {
788 IPromise IPromise.Then(Action success, Action<Exception> error, Action cancel) {
789 return Then(
789 return Then(
790 success != null ? new Func<T,T>(x => {
790 success != null ? new Func<T,T>(x => {
791 success();
791 success();
792 return x;
792 return x;
793 }) : null,
793 }) : null,
794 error != null ? new Func<Exception,T>(e => {
794 error != null ? new Func<Exception,T>(e => {
795 error(e);
795 error(e);
796 return default(T);
796 return default(T);
797 }) : null,
797 }) : null,
798 cancel
798 cancel
799 );
799 );
800 }
800 }
801
801
802 IPromise IPromise.Then(Action success, Action<Exception> error) {
802 IPromise IPromise.Then(Action success, Action<Exception> error) {
803 return Then(
803 return Then(
804 success != null ? new Func<T,T>(x => {
804 success != null ? new Func<T,T>(x => {
805 success();
805 success();
806 return x;
806 return x;
807 }) : null,
807 }) : null,
808 error != null ? new Func<Exception,T>(e => {
808 error != null ? new Func<Exception,T>(e => {
809 error(e);
809 error(e);
810 return default(T);
810 return default(T);
811 }) : null
811 }) : null
812 );
812 );
813 }
813 }
814
814
815 IPromise IPromise.Then(Action success) {
815 IPromise IPromise.Then(Action success) {
816 Safe.ArgumentNotNull(success, "success");
816 Safe.ArgumentNotNull(success, "success");
817 return Then(x => {
817 return Then(x => {
818 success();
818 success();
819 return x;
819 return x;
820 });
820 });
821 }
821 }
822
822
823 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
823 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
824 return ChainNoResult(chained, error, cancel);
824 return ChainNoResult(chained, error, cancel);
825 }
825 }
826
826
827 IPromise ChainNoResult(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
827 IPromise ChainNoResult(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
828 Safe.ArgumentNotNull(chained, "chained");
828 Safe.ArgumentNotNull(chained, "chained");
829
829
830 var medium = new Promise<object>(this);
830 var medium = new Promise<object>(this);
831
831
832 Func<T,T> resultHandler = delegate {
832 Func<T,T> resultHandler = delegate {
833 if (medium.IsCancelled)
833 if (medium.IsCancelled)
834 return default(T);
834 return default(T);
835
835
836 var promise = chained();
836 var promise = chained();
837
837
838 promise.On(
838 promise.On(
839 medium.Resolve,
839 medium.Resolve,
840 medium.Reject,
840 medium.Reject,
841 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
841 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
842 );
842 );
843
843
844 // notify chained operation that it's not needed anymore
844 // notify chained operation that it's not needed anymore
845 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
845 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
846 // зависит IsExclusive
846 // зависит IsExclusive
847 medium.Cancelled(() => {
847 medium.Cancelled(() => {
848 if (promise.IsExclusive)
848 if (promise.IsExclusive)
849 promise.Cancel();
849 promise.Cancel();
850 });
850 });
851
851
852 return default(T);
852 return default(T);
853 };
853 };
854
854
855 Func<Exception,T> errorHandler;
855 Func<Exception,T> errorHandler;
856
856
857 if (error != null)
857 if (error != null)
858 errorHandler = delegate(Exception e) {
858 errorHandler = delegate(Exception e) {
859 try {
859 try {
860 var promise = error(e);
860 var promise = error(e);
861
861
862 promise.On(
862 promise.On(
863 medium.Resolve,
863 medium.Resolve,
864 medium.Reject,
864 medium.Reject,
865 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
865 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
866 );
866 );
867
867
868 // notify chained operation that it's not needed anymore
868 // notify chained operation that it's not needed anymore
869 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
869 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
870 // зависит IsExclusive
870 // зависит IsExclusive
871 medium.Cancelled(() => {
871 medium.Cancelled(() => {
872 if (promise.IsExclusive)
872 if (promise.IsExclusive)
873 promise.Cancel();
873 promise.Cancel();
874 });
874 });
875 } catch (Exception e2) {
875 } catch (Exception e2) {
876 medium.Reject(e2);
876 medium.Reject(e2);
877 }
877 }
878 return default(T);
878 return default(T);
879 };
879 };
880 else
880 else
881 errorHandler = err => {
881 errorHandler = err => {
882 medium.Reject(err);
882 medium.Reject(err);
883 return default(T);
883 return default(T);
884 };
884 };
885
885
886
886
887 Action cancelHandler;
887 Action cancelHandler;
888 if (cancel != null)
888 if (cancel != null)
889 cancelHandler = () => {
889 cancelHandler = () => {
890 if (cancel != null)
890 if (cancel != null)
891 cancel();
891 cancel();
892 medium.Cancel();
892 medium.Cancel();
893 };
893 };
894 else
894 else
895 cancelHandler = medium.Cancel;
895 cancelHandler = medium.Cancel;
896
896
897 AddMappers(
897 AddMappers(
898 resultHandler,
898 resultHandler,
899 errorHandler,
899 errorHandler,
900 cancelHandler,
900 cancelHandler,
901 null,
901 null,
902 true
902 true
903 );
903 );
904
904
905 return medium;
905 return medium;
906 }
906 }
907
907
908 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error) {
908 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error) {
909 return ChainNoResult(chained, error, null);
909 return ChainNoResult(chained, error, null);
910 }
910 }
911
911
912 IPromise IPromise.Chain(Func<IPromise> chained) {
912 IPromise IPromise.Chain(Func<IPromise> chained) {
913 return ChainNoResult(chained, null, null);
913 return ChainNoResult(chained, null, null);
914 }
914 }
915
915
916
916
917 void IPromise.On(Action success, Action<Exception> error, Action cancel) {
917 void IPromise.On(Action success, Action<Exception> error, Action cancel) {
918 On(success != null ? new Action<T>(x => success()) : null, error, cancel);
918 On(success != null ? new Action<T>(x => success()) : null, error, cancel);
919 }
919 }
920
920
921 void IPromise.On(Action success, Action<Exception> error) {
921 void IPromise.On(Action success, Action<Exception> error) {
922 On(x => success(), error, null);
922 On(x => success(), error, null);
923 }
923 }
924
924
925 void IPromise.On(Action success) {
925 void IPromise.On(Action success) {
926 On(x => success(), null, null);
926 On(x => success(), null, null);
927 }
927 }
928
928
929 IPromise IPromise.Error(Action<Exception> error) {
929 IPromise IPromise.Error(Action<Exception> error) {
930 return Error(error);
930 return Error(error);
931 }
931 }
932
932
933 IPromise IPromise.Anyway(Action handler) {
933 IPromise IPromise.Anyway(Action handler) {
934 return Anyway(handler);
934 return Anyway(handler);
935 }
935 }
936
936
937 IPromise IPromise.Cancelled(Action handler) {
937 IPromise IPromise.Cancelled(Action handler) {
938 return Cancelled(handler);
938 return Cancelled(handler);
939 }
939 }
940
940
941 void IPromise.Join() {
941 void IPromise.Join() {
942 Join();
942 Join();
943 }
943 }
944
944
945 void IPromise.Join(int timeout) {
945 void IPromise.Join(int timeout) {
946 Join(timeout);
946 Join(timeout);
947 }
947 }
948
948
949 #endregion
949 #endregion
950
950
951
951
952
952
953 }
953 }
954 }
954 }
General Comments 0
You need to be logged in to leave comments. Login now