Skip to content

Commit a25ec9d

Browse files
committed
[bugfix] promise all
1 parent b05a567 commit a25ec9d

9 files changed

Lines changed: 172 additions & 82 deletions

File tree

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>cn.brainpoint</groupId>
88
<artifactId>febs</artifactId>
9-
<version>0.0.1</version>
9+
<version>0.0.2</version>
1010
<packaging>jar</packaging>
1111

1212
<name>febs</name>

readme.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ Febs.init(new Febs.ThreadPoolCfg(
5454
2,
5555
4,
5656
20000,
57-
new ArrayBlockingQueue<>(20),
57+
new LinkedBlockingQueue<>(),
5858
new ThreadPoolExecutor.AbortPolicy())
5959
);
6060
```
@@ -138,6 +138,7 @@ promise.then(res->{
138138
```js
139139
/**
140140
* Promise object array.
141+
* !Warning: All promise object cannot call execute() funciton.
141142
*/
142143
Promise[] promiseArr = {...};
143144

@@ -159,6 +160,7 @@ Promise promise = Promise.all(promiseArr)
159160
It will store promise object in global until promise finish, after promise object is created. We can call Promise.join to wait promise finish.
160161

161162
```js
163+
IPromise promiseObj = new Promise((resolve, reject)->{ resolve.execute(); });
162164
Promise.join(promiseObj);
163165
```
164166

src/main/java/cn/brainpoint/febs/Febs.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,7 @@
66

77
package cn.brainpoint.febs;
88

9-
import java.util.concurrent.ArrayBlockingQueue;
10-
import java.util.concurrent.BlockingQueue;
11-
import java.util.concurrent.ExecutorService;
12-
import java.util.concurrent.RejectedExecutionHandler;
13-
import java.util.concurrent.ThreadPoolExecutor;
14-
import java.util.concurrent.TimeUnit;
9+
import java.util.concurrent.*;
1510

1611
/**
1712
* @author pengxiang.li
@@ -36,7 +31,7 @@ public static class ThreadPoolCfg {
3631
* in millisecond.
3732
*/
3833
public int keepAliveTime = 20000;
39-
public BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(20);
34+
public BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
4035
public RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
4136

4237
public ThreadPoolCfg() {

src/main/java/cn/brainpoint/febs/Net.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
*/
2121
public class Net {
2222

23+
static {
24+
Febs.init();
25+
}
26+
2327
/***
2428
* The network transfer in fetch style.
2529
*

src/main/java/cn/brainpoint/febs/Promise.java

Lines changed: 114 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77
package cn.brainpoint.febs;
88

99
import java.util.ArrayList;
10+
import java.util.Arrays;
11+
import java.util.List;
1012
import java.util.concurrent.CompletableFuture;
1113
import java.util.concurrent.ConcurrentSkipListSet;
14+
import java.util.concurrent.atomic.AtomicInteger;
15+
import java.util.concurrent.atomic.AtomicReference;
1216

1317
import cn.brainpoint.febs.libs.promise.IExecute;
1418
import cn.brainpoint.febs.libs.promise.IFinish;
@@ -35,6 +39,11 @@
3539
* <b>date</b> 2020/1/30 5:12 下午
3640
*/
3741
public 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
*

src/main/java/cn/brainpoint/febs/Utils.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
*/
1313
public class Utils {
1414

15+
static {
16+
Febs.init();
17+
}
18+
1519
/**
1620
* Sleep in promise way.
1721
* <i>e.g.</i>

src/main/java/cn/brainpoint/febs/libs/promise/IPromise.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@ public interface IPromise {
2727

2828
Object getTag();
2929
void setTag(Object tag);
30+
31+
boolean isExecutor();
3032
}

0 commit comments

Comments
 (0)