1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.arch.core.executor;
18 
19 import androidx.annotation.RestrictTo;
20 
21 import org.jspecify.annotations.NonNull;
22 import org.jspecify.annotations.Nullable;
23 
24 import java.util.concurrent.Executor;
25 
26 /**
27  * A static class that serves as a central point to execute common tasks.
28  * <p>
29  *
30  */
31 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
32 public class ArchTaskExecutor extends TaskExecutor {
33     private static volatile ArchTaskExecutor sInstance;
34 
35     private @NonNull TaskExecutor mDelegate;
36 
37     private final @NonNull TaskExecutor mDefaultTaskExecutor;
38 
39     private static final @NonNull Executor sMainThreadExecutor =
40             command -> getInstance().postToMainThread(command);
41 
42     private static final @NonNull Executor sIOThreadExecutor =
43             command -> getInstance().executeOnDiskIO(command);
44 
ArchTaskExecutor()45     private ArchTaskExecutor() {
46         mDefaultTaskExecutor = new DefaultTaskExecutor();
47         mDelegate = mDefaultTaskExecutor;
48     }
49 
50     /**
51      * Returns an instance of the task executor.
52      *
53      * @return The singleton ArchTaskExecutor.
54      */
getInstance()55     public static @NonNull ArchTaskExecutor getInstance() {
56         if (sInstance != null) {
57             return sInstance;
58         }
59         synchronized (ArchTaskExecutor.class) {
60             if (sInstance == null) {
61                 sInstance = new ArchTaskExecutor();
62             }
63         }
64         return sInstance;
65     }
66 
67     /**
68      * Sets a delegate to handle task execution requests.
69      * <p>
70      * If you have a common executor, you can set it as the delegate and App Toolkit components will
71      * use your executors. You may also want to use this for your tests.
72      * <p>
73      * Calling this method with {@code null} sets it to the default TaskExecutor.
74      *
75      * @param taskExecutor The task executor to handle task requests.
76      */
setDelegate(@ullable TaskExecutor taskExecutor)77     public void setDelegate(@Nullable TaskExecutor taskExecutor) {
78         mDelegate = taskExecutor == null ? mDefaultTaskExecutor : taskExecutor;
79     }
80 
81     @Override
executeOnDiskIO(@onNull Runnable runnable)82     public void executeOnDiskIO(@NonNull Runnable runnable) {
83         mDelegate.executeOnDiskIO(runnable);
84     }
85 
86     @Override
postToMainThread(@onNull Runnable runnable)87     public void postToMainThread(@NonNull Runnable runnable) {
88         mDelegate.postToMainThread(runnable);
89     }
90 
getMainThreadExecutor()91     public static @NonNull Executor getMainThreadExecutor() {
92         return sMainThreadExecutor;
93     }
94 
getIOThreadExecutor()95     public static @NonNull Executor getIOThreadExecutor() {
96         return sIOThreadExecutor;
97     }
98 
99     @Override
isMainThread()100     public boolean isMainThread() {
101         return mDelegate.isMainThread();
102     }
103 }
104