Skip to content

Commit a1db62a

Browse files
rogerhuRoger Hu
and
Roger Hu
authored
Add bolts tasks to this library (#1018)
Co-authored-by: Roger Hu <rogerh@squareup.com>
1 parent 2d92432 commit a1db62a

18 files changed

+3474
-2
lines changed

bolts-tasks/build.gradle

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright (c) Facebook, Inc. and its affiliates.
2+
//
3+
// This source code is licensed under the MIT license found in the/
4+
// LICENSE file in the root directory of this source tree.
5+
6+
apply plugin: 'java'
7+
8+
configurations {
9+
provided
10+
}
11+
12+
sourceSets {
13+
main {
14+
compileClasspath += configurations.provided
15+
}
16+
}
17+
18+
dependencies {
19+
provided 'com.google.android:android:4.1.1.4'
20+
testImplementation 'junit:junit:4.12'
21+
}
22+
23+
24+
javadoc.options.addStringOption('Xdoclint:none', '-quiet')
25+
26+
task sourcesJar(type: Jar) {
27+
classifier = 'sources'
28+
from sourceSets.main.allJava
29+
}
30+
31+
task javadocJar (type: Jar, dependsOn: javadoc) {
32+
classifier = 'javadoc'
33+
from javadoc.destinationDir
34+
}
35+
36+
artifacts {
37+
archives sourcesJar
38+
archives javadocJar
39+
}
40+
41+
//endregion
42+
43+
//region Code Coverage
44+
45+
apply plugin: 'jacoco'
46+
47+
jacoco {
48+
toolVersion = '0.7.1.201405082137'
49+
}
50+
51+
jacocoTestReport {
52+
group = "Reporting"
53+
description = "Generate Jacoco coverage reports after running tests."
54+
reports {
55+
xml.enabled true
56+
html.enabled true
57+
}
58+
}
59+
60+
//endregion
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
package bolts;
8+
9+
import java.io.PrintStream;
10+
import java.io.PrintWriter;
11+
import java.util.ArrayList;
12+
import java.util.Arrays;
13+
import java.util.Collections;
14+
import java.util.List;
15+
16+
/**
17+
* Aggregates multiple {@code Throwable}s that may be thrown in the process of a task's execution.
18+
*
19+
* @see Task#whenAll(java.util.Collection)
20+
*/
21+
public class AggregateException extends Exception {
22+
private static final long serialVersionUID = 1L;
23+
24+
private static final String DEFAULT_MESSAGE = "There were multiple errors.";
25+
26+
private List<Throwable> innerThrowables;
27+
28+
/**
29+
* Constructs a new {@code AggregateException} with the current stack trace, the specified detail
30+
* message and with references to the inner throwables that are the cause of this exception.
31+
*
32+
* @param detailMessage The detail message for this exception.
33+
* @param innerThrowables The exceptions that are the cause of the current exception.
34+
*/
35+
public AggregateException(String detailMessage, Throwable[] innerThrowables) {
36+
this(detailMessage, Arrays.asList(innerThrowables));
37+
}
38+
39+
40+
/**
41+
* Constructs a new {@code AggregateException} with the current stack trace, the specified detail
42+
* message and with references to the inner throwables that are the cause of this exception.
43+
*
44+
* @param detailMessage The detail message for this exception.
45+
* @param innerThrowables The exceptions that are the cause of the current exception.
46+
*/
47+
public AggregateException(String detailMessage, List<? extends Throwable> innerThrowables) {
48+
super(detailMessage,
49+
innerThrowables != null && innerThrowables.size() > 0 ? innerThrowables.get(0) : null);
50+
this.innerThrowables = Collections.unmodifiableList(innerThrowables);
51+
}
52+
53+
/**
54+
* Constructs a new {@code AggregateException} with the current stack trace and with references to
55+
* the inner throwables that are the cause of this exception.
56+
*
57+
* @param innerThrowables The exceptions that are the cause of the current exception.
58+
*/
59+
public AggregateException(List<? extends Throwable> innerThrowables) {
60+
this(DEFAULT_MESSAGE, innerThrowables);
61+
}
62+
63+
/**
64+
* Returns a read-only {@link List} of the {@link Throwable} instances that caused the current
65+
* exception.
66+
*/
67+
public List<Throwable> getInnerThrowables() {
68+
return innerThrowables;
69+
}
70+
71+
@Override
72+
public void printStackTrace(PrintStream err) {
73+
super.printStackTrace(err);
74+
75+
int currentIndex = -1;
76+
for (Throwable throwable : innerThrowables) {
77+
err.append("\n");
78+
err.append(" Inner throwable #");
79+
err.append(Integer.toString(++currentIndex));
80+
err.append(": ");
81+
throwable.printStackTrace(err);
82+
err.append("\n");
83+
}
84+
}
85+
86+
@Override
87+
public void printStackTrace(PrintWriter err) {
88+
super.printStackTrace(err);
89+
90+
int currentIndex = -1;
91+
for (Throwable throwable : innerThrowables) {
92+
err.append("\n");
93+
err.append(" Inner throwable #");
94+
err.append(Integer.toString(++currentIndex));
95+
err.append(": ");
96+
throwable.printStackTrace(err);
97+
err.append("\n");
98+
}
99+
}
100+
101+
/**
102+
* @deprecated Please use {@link #getInnerThrowables()} instead.
103+
*/
104+
@Deprecated
105+
public List<Exception> getErrors() {
106+
List<Exception> errors = new ArrayList<Exception>();
107+
if (innerThrowables == null) {
108+
return errors;
109+
}
110+
111+
for (Throwable cause : innerThrowables) {
112+
if (cause instanceof Exception) {
113+
errors.add((Exception) cause);
114+
} else {
115+
errors.add(new Exception(cause));
116+
}
117+
}
118+
return errors;
119+
}
120+
121+
/**
122+
* @deprecated Please use {@link #getInnerThrowables()} instead.
123+
*/
124+
@Deprecated
125+
public Throwable[] getCauses() {
126+
return innerThrowables.toArray(new Throwable[innerThrowables.size()]);
127+
}
128+
129+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
package bolts;
8+
9+
import android.annotation.SuppressLint;
10+
import android.os.Build;
11+
import android.os.Handler;
12+
import android.os.Looper;
13+
14+
import java.util.concurrent.Executor;
15+
import java.util.concurrent.ExecutorService;
16+
import java.util.concurrent.LinkedBlockingQueue;
17+
import java.util.concurrent.ThreadFactory;
18+
import java.util.concurrent.ThreadPoolExecutor;
19+
import java.util.concurrent.TimeUnit;
20+
21+
/**
22+
* This was created because the helper methods in {@link java.util.concurrent.Executors} do not work
23+
* as people would normally expect.
24+
* <p>
25+
* Normally, you would think that a cached thread pool would create new threads when necessary,
26+
* queue them when the pool is full, and kill threads when they've been inactive for a certain
27+
* period of time. This is not how {@link java.util.concurrent.Executors#newCachedThreadPool()}
28+
* works.
29+
* <p>
30+
* Instead, {@link java.util.concurrent.Executors#newCachedThreadPool()} executes all tasks on
31+
* a new or cached thread immediately because corePoolSize is 0, SynchronousQueue is a queue with
32+
* size 0 and maxPoolSize is Integer.MAX_VALUE. This is dangerous because it can create an unchecked
33+
* amount of threads.
34+
*/
35+
/* package */ final class AndroidExecutors {
36+
37+
private static final AndroidExecutors INSTANCE = new AndroidExecutors();
38+
39+
private final Executor uiThread;
40+
41+
private AndroidExecutors() {
42+
uiThread = new UIThreadExecutor();
43+
}
44+
45+
/**
46+
* Nexus 5: Quad-Core
47+
* Moto X: Dual-Core
48+
* <p>
49+
* AsyncTask:
50+
* CORE_POOL_SIZE = CPU_COUNT + 1
51+
* MAX_POOL_SIZE = CPU_COUNT * 2 + 1
52+
* <p>
53+
* https://github.com/android/platform_frameworks_base/commit/719c44e03b97e850a46136ba336d729f5fbd1f47
54+
*/
55+
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
56+
/* package */ static final int CORE_POOL_SIZE = CPU_COUNT + 1;
57+
/* package */ static final int MAX_POOL_SIZE = CPU_COUNT * 2 + 1;
58+
/* package */ static final long KEEP_ALIVE_TIME = 1L;
59+
60+
/**
61+
* Creates a proper Cached Thread Pool. Tasks will reuse cached threads if available
62+
* or create new threads until the core pool is full. tasks will then be queued. If an
63+
* task cannot be queued, a new thread will be created unless this would exceed max pool
64+
* size, then the task will be rejected. Threads will time out after 1 second.
65+
* <p>
66+
* Core thread timeout is only available on android-9+.
67+
*
68+
* @return the newly created thread pool
69+
*/
70+
public static ExecutorService newCachedThreadPool() {
71+
ThreadPoolExecutor executor = new ThreadPoolExecutor(
72+
CORE_POOL_SIZE,
73+
MAX_POOL_SIZE,
74+
KEEP_ALIVE_TIME, TimeUnit.SECONDS,
75+
new LinkedBlockingQueue<Runnable>());
76+
77+
allowCoreThreadTimeout(executor, true);
78+
79+
return executor;
80+
}
81+
82+
/**
83+
* Creates a proper Cached Thread Pool. Tasks will reuse cached threads if available
84+
* or create new threads until the core pool is full. tasks will then be queued. If an
85+
* task cannot be queued, a new thread will be created unless this would exceed max pool
86+
* size, then the task will be rejected. Threads will time out after 1 second.
87+
* <p>
88+
* Core thread timeout is only available on android-9+.
89+
*
90+
* @param threadFactory the factory to use when creating new threads
91+
* @return the newly created thread pool
92+
*/
93+
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
94+
ThreadPoolExecutor executor = new ThreadPoolExecutor(
95+
CORE_POOL_SIZE,
96+
MAX_POOL_SIZE,
97+
KEEP_ALIVE_TIME, TimeUnit.SECONDS,
98+
new LinkedBlockingQueue<Runnable>(),
99+
threadFactory);
100+
101+
allowCoreThreadTimeout(executor, true);
102+
103+
return executor;
104+
}
105+
106+
/**
107+
* Compatibility helper function for
108+
* {@link java.util.concurrent.ThreadPoolExecutor#allowCoreThreadTimeOut(boolean)}
109+
* <p>
110+
* Only available on android-9+.
111+
*
112+
* @param executor the {@link java.util.concurrent.ThreadPoolExecutor}
113+
* @param value true if should time out, else false
114+
*/
115+
@SuppressLint("NewApi")
116+
public static void allowCoreThreadTimeout(ThreadPoolExecutor executor, boolean value) {
117+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
118+
executor.allowCoreThreadTimeOut(value);
119+
}
120+
}
121+
122+
/**
123+
* An {@link java.util.concurrent.Executor} that executes tasks on the UI thread.
124+
*/
125+
public static Executor uiThread() {
126+
return INSTANCE.uiThread;
127+
}
128+
129+
/**
130+
* An {@link java.util.concurrent.Executor} that runs tasks on the UI thread.
131+
*/
132+
private static class UIThreadExecutor implements Executor {
133+
@Override
134+
public void execute(Runnable command) {
135+
new Handler(Looper.getMainLooper()).post(command);
136+
}
137+
}
138+
}

0 commit comments

Comments
 (0)