77package cn .brainpoint .febs ;
88
99import java .util .ArrayList ;
10+ import java .util .Arrays ;
11+ import java .util .List ;
1012import java .util .concurrent .CompletableFuture ;
1113import java .util .concurrent .ConcurrentSkipListSet ;
14+ import java .util .concurrent .atomic .AtomicInteger ;
15+ import java .util .concurrent .atomic .AtomicReference ;
1216
1317import cn .brainpoint .febs .libs .promise .IExecute ;
1418import cn .brainpoint .febs .libs .promise .IFinish ;
3539 * <b>date</b> 2020/1/30 5:12 下午
3640 */
3741public class Promise <TP > implements java .lang .Comparable , IPromise {
42+
43+ static {
44+ Febs .init ();
45+ }
46+
3847 static public final String STATUS_PENDING = "pending" ;
3948 static public final String STATUS_FULFILLED = "fulfilled" ;
4049 static public final String STATUS_REJECTED = "rejected" ;
@@ -54,7 +63,7 @@ public class Promise<TP> implements java.lang.Comparable, IPromise {
5463 private Object tag ;
5564 private Promise <?> ancestor ;
5665 private boolean _inExecute = false ;
57- private Object _inTag ;
66+ private Object _inTag ; // internal use.
5867 private CompletableFuture _cf ;
5968
6069 private static class PromiseExecutor <TP > implements IPromise {
@@ -64,6 +73,9 @@ public PromiseExecutor(Promise<TP> p) {
6473 this .p = p ;
6574 }
6675
76+ @ Override
77+ public boolean isExecutor () { return true ; }
78+
6779 @ Override
6880 public IPromise execute () {
6981 this .p .execute ();
@@ -107,46 +119,63 @@ public static void setUncaughtExceptionHandler(IReject listener) {
107119 * Promise.all({})
108120 * .then(...)
109121 *
122+ * !Warning: All promise object cannot call execute() function.
123+ *
110124 * @param list Promise object set.
111125 * @return Promise
112126 */
113- public static Promise all (Promise ... list ) {
127+ public static Promise all (List < IPromise > list ) {
114128
115- if (list == null || list . length <= 0 ) {
129+ if (list == null ) {
116130 throw new RuntimeException ("Promise list should not be empty!" );
117131 }
118132
119- if (list != null && list .length > 0 ) {
120- Promise p = new Promise <Void >((resolve , reject )->{
121- resolve .execute (null );
122- }).then (new Runnable () {
123- int completedCount = 0 ;
124- Object [] result = new Object [list .length ];
125- Exception ex ;
126-
127- @ Override
128- public void run () {
129- for (int i = 0 ; i < list .length ; i ++) {
130- Promise promise = list [i ];
131- promise ._inTag = i ;
132- promise .then (res -> {
133- result [(int ) promise ._inTag ] = res ;
134- completed (null );
135- return res ;
136- }).fail (this ::completed );
133+ if (list .size () > 0 ) {
134+ Promise p = new Promise ((resolve , reject )->{
135+
136+ AtomicReference <Exception > ex = new AtomicReference <>(null );
137+ AtomicInteger completedCount = new AtomicInteger (0 );
138+ Object [] result = new Object [list .size ()];
139+
140+ for (int i = 0 ; i < list .size (); i ++) {
141+ if (ex .get () != null ) {
142+ reject .execute (ex .get ());
143+ return ;
137144 }
138- Promise .join (5 , list );
139- if (ex != null ) {
140- throw new RuntimeException (ex );
145+
146+ Promise promise ;
147+ if (list .get (i ).isExecutor ()) {
148+ promise = ((PromiseExecutor )list .get (i )).p ;
149+ }
150+ else {
151+ promise = (Promise )list .get (i );
141152 }
142- }
143153
144- private Object completed (Exception err ) throws Exception {
145- completedCount ++;
146- if (err != null ) {
147- ex = err ;
154+ // can call execute
155+ Promise ancestor = promise .ancestor == null ? promise : promise .ancestor ;
156+ if (!ancestor .status .equals (STATUS_PENDING ) || ancestor ._inExecute == true ) {
157+ reject .execute (new RuntimeException ("Promise is not in pending status" ));
158+ return ;
148159 }
149- return null ;
160+
161+ promise ._inTag = i ;
162+ promise .then (res -> {
163+ result [(int ) promise ._inTag ] = res ;
164+ completedCount .getAndIncrement ();
165+ }).fail (e ->{
166+ ex .set (e );
167+ }).execute ();
168+
169+ join (promise );
170+ }
171+
172+ if (ex .get () != null ) {
173+ reject .execute (ex .get ());
174+ return ;
175+ }
176+ if (completedCount .get () == result .length ) {
177+ resolve .execute (result );
178+ return ;
150179 }
151180 });
152181 return p ;
@@ -161,6 +190,24 @@ private Object completed(Exception err) throws Exception {
161190 }
162191 }
163192
193+ /**
194+ * Promise.all({})
195+ * .then(...)
196+ *
197+ * !Warning: All promise object cannot call execute() function.
198+ *
199+ * @param list Promise object set.
200+ * @return Promise
201+ */
202+ public static Promise all (IPromise ... list ) {
203+
204+ if (list == null || list .length <= 0 ) {
205+ throw new RuntimeException ("Promise list should not be empty!" );
206+ }
207+
208+ return all (Arrays .asList (list ));
209+ }
210+
164211 /**
165212 * Wait all promise done. will broke thread.
166213 *
@@ -170,35 +217,63 @@ public static void join(IPromise... list) {
170217 join (10 , list );
171218 }
172219
220+ /**
221+ * Wait all promise done. will broke thread.
222+ *
223+ * @param list Promise object set.
224+ */
225+ public static void join (List <IPromise > list ) {
226+ join (10 , list );
227+ }
228+
173229 /**
174230 * Wait all promise done. will broke thread.
175231 *
176232 * @param list Promise object set.
177233 * @param peekInMillisecond peek interval.
178234 */
179235 public static void join (int peekInMillisecond , IPromise ... list ) {
236+ if (list .length == 0 ) {
237+ return ;
238+ }
239+
240+ join (peekInMillisecond , Arrays .asList (list ));
241+ }
242+
243+ /**
244+ * Wait all promise done. will broke thread.
245+ *
246+ * @param list Promise object set.
247+ * @param peekInMillisecond peek interval.
248+ */
249+ public static void join (int peekInMillisecond , List <IPromise > list ) {
250+ if (list == null || list .isEmpty ()) {
251+ return ;
252+ }
253+
180254 while (true ) {
181255 int doneCount = 0 ;
182- for (int i = 0 ; i < list .length ; i ++) {
183- if (list [i ].getStatus () != STATUS_PENDING ) {
256+ for (int i = 0 ; i < list .size (); i ++) {
257+ IPromise p1 = list .get (i );
258+ if (p1 .getStatus () != STATUS_PENDING ) {
184259 doneCount ++;
185260 }
186- else if (list [ i ] instanceof PromiseExecutor ) {
187- PromiseExecutor pe = (PromiseExecutor )list [ i ] ;
261+ else if (p1 instanceof PromiseExecutor ) {
262+ PromiseExecutor pe = (PromiseExecutor )p1 ;
188263 Promise p = pe .p ;
189264 p = p .ancestor == null ? p : p .ancestor ;
190265 if (!p ._inExecute ) {
191266 p .execute ();
192267 }
193268 } else {
194- Promise p = (Promise )list [ i ] ;
269+ Promise p = (Promise )p1 ;
195270 p = p .ancestor == null ? p : p .ancestor ;
196271 if (!p ._inExecute ) {
197272 p .execute ();
198273 }
199274 }
200275 }
201- if (doneCount == list .length ) {
276+ if (doneCount == list .size () ) {
202277 return ;
203278 }
204279 try {
@@ -209,6 +284,9 @@ else if (list[i] instanceof PromiseExecutor) {
209284 }
210285 }
211286
287+ @ Override
288+ public boolean isExecutor () { return false ; }
289+
212290 /**
213291 * Get the current status of promise.
214292 *
0 commit comments