14
14
15
15
package com .google .firebase .firestore .util ;
16
16
17
- import android .os .AsyncTask ;
17
+ import static kotlinx .coroutines .ExecutorsKt .asExecutor ;
18
+
18
19
import com .google .android .gms .tasks .TaskExecutors ;
19
20
import java .util .concurrent .Executor ;
21
+ import kotlinx .coroutines .Dispatchers ;
20
22
21
23
/** Helper class for executors. */
22
24
public final class Executors {
23
25
/**
24
- * The maximum number of tasks we submit to AsyncTask.THREAD_POOL_EXECUTOR.
25
- *
26
- * <p>The limit is based on the number of core threads spun by THREAD_POOL_EXECUTOR and is well
27
- * below the queue size limit of 120 pending tasks. Limiting our usage of the THREAD_POOL_EXECUTOR
28
- * allows other users to schedule their own operations on the shared THREAD_POOL_EXECUTOR .
26
+ * The number of physical CPU cores available for multithreaded execution, or 2, whichever is
27
+ * larger.
28
+ * <p>
29
+ * CPU-bound tasks should never use more than this number of concurrent threads as doing so will
30
+ * almost certainly reduce throughput due to the overhead of context switching .
29
31
*/
30
- private static final int ASYNC_THREAD_POOL_MAXIMUM_CONCURRENCY = 4 ;
32
+ public static final int HARDWARE_CONCURRENCY =
33
+ Math .max (2 , Runtime .getRuntime ().availableProcessors ());
31
34
32
35
/**
33
36
* The default executor for user visible callbacks. It is an executor scheduling callbacks on
@@ -38,10 +41,46 @@ public final class Executors {
38
41
/** An executor that executes the provided runnable immediately on the current thread. */
39
42
public static final Executor DIRECT_EXECUTOR = Runnable ::run ;
40
43
41
- /** An executor that runs tasks in parallel on Android's AsyncTask.THREAD_POOL_EXECUTOR. */
42
- public static final Executor BACKGROUND_EXECUTOR =
43
- new ThrottledForwardingExecutor (
44
- ASYNC_THREAD_POOL_MAXIMUM_CONCURRENCY , AsyncTask .THREAD_POOL_EXECUTOR );
44
+ /**
45
+ * An executor suitable for short tasks that perform little or no blocking.
46
+ */
47
+ public static final Executor SHORT_WORKLOAD_EXECUTOR =
48
+ asExecutor (
49
+ Dispatchers .getIO ()
50
+ .limitedParallelism (HARDWARE_CONCURRENCY , "firestore.SHORT_WORKLOAD_EXECUTOR" ));
51
+
52
+ /**
53
+ * An executor suitable for IO-bound workloads. New threads are usually created to satisfy demand,
54
+ * and, therefore, tasks do not usually wait in a queue for execution.
55
+ */
56
+ public static final Executor IO_WORKLOAD_EXECUTOR = asExecutor (Dispatchers .getIO ());
57
+
58
+ /**
59
+ * An executor suitable for CPU-bound workloads. No more tasks than available CPU cores will
60
+ * execute concurrently, while other tasks line up and wait for a thread to become available, and
61
+ * are scheduled in an arbitrary order.
62
+ */
63
+ public static final Executor CPU_WORKLOAD_EXECUTOR =
64
+ asExecutor (
65
+ Dispatchers .getIO ()
66
+ .limitedParallelism (HARDWARE_CONCURRENCY , "firestore.CPU_WORKLOAD_EXECUTOR" ));
67
+
68
+ /**
69
+ * Creates and returns a new {@link Executor} that executes tasks sequentially.
70
+ * <p>
71
+ * The implementation guarantees that tasks are executed sequentially and that a happens-before
72
+ * relation is established between them. This means that tasks run by this executor do _not_ need
73
+ * to synchronize access to shared resources, such as using "synchronized" blocks or "volatile"
74
+ * variables. See `kotlinx.coroutines.limitedParallelism` for full details.
75
+ * <p>
76
+ * Note that there is no guarantee that tasks will all run on the _same thread_.
77
+ *
78
+ * @param name a brief name to assign to the executor, for debugging purposes.
79
+ * @return the newly-created executor.
80
+ */
81
+ public static Executor newSequentialExecutor (String name ) {
82
+ return asExecutor (Dispatchers .getIO ().limitedParallelism (1 , "firestore.seq." + name ));
83
+ }
45
84
46
85
private Executors () {
47
86
// Private constructor to prevent initialization
0 commit comments