1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | package org.chromium.base; |
6 | |
7 | import android.os.Handler; |
8 | import android.os.Looper; |
9 | import android.os.Process; |
10 | |
11 | import java.util.concurrent.Callable; |
12 | import java.util.concurrent.ExecutionException; |
13 | import java.util.concurrent.FutureTask; |
14 | |
15 | /** |
16 | * Helper methods to deal with threading related tasks. |
17 | */ |
18 | public class ThreadUtils { |
19 | |
20 | /** |
21 | * Run the supplied Runnable on the main thread. The method will block until the Runnable |
22 | * completes. |
23 | * |
24 | * @param r The Runnable to run. |
25 | */ |
26 | public static void runOnUiThreadBlocking(final Runnable r) { |
27 | if (runningOnUiThread()) { |
28 | r.run(); |
29 | } else { |
30 | FutureTask<Void> task = new FutureTask<Void>(r, null); |
31 | postOnUiThread(task); |
32 | try { |
33 | task.get(); |
34 | } catch (Exception e) { |
35 | throw new RuntimeException("Exception occured while waiting for runnable", e); |
36 | } |
37 | } |
38 | } |
39 | |
40 | /** |
41 | * Run the supplied Callable on the main thread, wrapping any exceptions in a RuntimeException. |
42 | * The method will block until the Callable completes. |
43 | * |
44 | * @param c The Callable to run |
45 | * @return The result of the callable |
46 | */ |
47 | public static <T> T runOnUiThreadBlockingNoException(Callable<T> c) { |
48 | try { |
49 | return runOnUiThreadBlocking(c); |
50 | } catch (ExecutionException e) { |
51 | throw new RuntimeException("Error occured waiting for callable", e); |
52 | } |
53 | } |
54 | |
55 | /** |
56 | * Run the supplied Callable on the main thread, The method will block until the Callable |
57 | * completes. |
58 | * |
59 | * @param c The Callable to run |
60 | * @return The result of the callable |
61 | * @throws ExecutionException c's exception |
62 | */ |
63 | public static <T> T runOnUiThreadBlocking(Callable<T> c) throws ExecutionException { |
64 | FutureTask<T> task = new FutureTask<T>(c); |
65 | runOnUiThread(task); |
66 | try { |
67 | return task.get(); |
68 | } catch (InterruptedException e) { |
69 | throw new RuntimeException("Interrupted waiting for callable", e); |
70 | } |
71 | } |
72 | |
73 | /** |
74 | * Run the supplied FutureTask on the main thread. The method will block only if the current |
75 | * thread is the main thread. |
76 | * |
77 | * @param task The FutureTask to run |
78 | * @return The queried task (to aid inline construction) |
79 | */ |
80 | public static <T> FutureTask<T> runOnUiThread(FutureTask<T> task) { |
81 | if (runningOnUiThread()) { |
82 | task.run(); |
83 | } else { |
84 | postOnUiThread(task); |
85 | } |
86 | return task; |
87 | } |
88 | |
89 | /** |
90 | * Run the supplied Callable on the main thread. The method will block only if the current |
91 | * thread is the main thread. |
92 | * |
93 | * @param c The Callable to run |
94 | * @return A FutureTask wrapping the callable to retrieve results |
95 | */ |
96 | public static <T> FutureTask<T> runOnUiThread(Callable<T> c) { |
97 | return runOnUiThread(new FutureTask<T>(c)); |
98 | } |
99 | |
100 | /** |
101 | * Run the supplied Runnable on the main thread. The method will block only if the current |
102 | * thread is the main thread. |
103 | * |
104 | * @param r The Runnable to run |
105 | */ |
106 | public static void runOnUiThread(Runnable r) { |
107 | if (runningOnUiThread()) { |
108 | r.run(); |
109 | } else { |
110 | LazyHolder.sUiThreadHandler.post(r); |
111 | } |
112 | } |
113 | |
114 | /** |
115 | * Post the supplied FutureTask to run on the main thread. The method will not block, even if |
116 | * called on the UI thread. |
117 | * |
118 | * @param task The FutureTask to run |
119 | * @return The queried task (to aid inline construction) |
120 | */ |
121 | public static <T> FutureTask<T> postOnUiThread(FutureTask<T> task) { |
122 | LazyHolder.sUiThreadHandler.post(task); |
123 | return task; |
124 | } |
125 | |
126 | /** |
127 | * Post the supplied Runnable to run on the main thread. The method will not block, even if |
128 | * called on the UI thread. |
129 | * |
130 | * @param task The Runnable to run |
131 | */ |
132 | public static void postOnUiThread(Runnable r) { |
133 | LazyHolder.sUiThreadHandler.post(r); |
134 | } |
135 | |
136 | /** |
137 | * Post the supplied Runnable to run on the main thread after the given amount of time. The |
138 | * method will not block, even if called on the UI thread. |
139 | * |
140 | * @param task The Runnable to run |
141 | * @param delayMillis The delay in milliseconds until the Runnable will be run |
142 | */ |
143 | public static void postOnUiThreadDelayed(Runnable r, long delayMillis) { |
144 | LazyHolder.sUiThreadHandler.postDelayed(r, delayMillis); |
145 | } |
146 | |
147 | /** |
148 | * Asserts that the current thread is running on the main thread. |
149 | */ |
150 | public static void assertOnUiThread() { |
151 | assert runningOnUiThread(); |
152 | } |
153 | |
154 | /** |
155 | * @return true iff the current thread is the main (UI) thread. |
156 | */ |
157 | public static boolean runningOnUiThread() { |
158 | return Looper.getMainLooper() == Looper.myLooper(); |
159 | } |
160 | |
161 | /** |
162 | * Set thread priority to audio. |
163 | */ |
164 | @CalledByNative |
165 | public static void setThreadPriorityAudio(int tid) { |
166 | Process.setThreadPriority(tid, Process.THREAD_PRIORITY_AUDIO); |
167 | } |
168 | |
169 | private static class LazyHolder { |
170 | private static Handler sUiThreadHandler = new Handler(Looper.getMainLooper()); |
171 | } |
172 | } |