OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chromoting; | 5 package org.chromium.chromoting; |
6 | 6 |
7 import android.os.Handler; | |
8 import android.os.Looper; | |
9 | |
7 import java.util.HashSet; | 10 import java.util.HashSet; |
8 | 11 |
9 /** | 12 /** |
10 * A thread-safe event queue which provides both {@link #add} and {@link #remove } functions with | 13 * A thread-safe event queue which provides both {@link #add} and {@link #remove } functions with |
11 * O(log(n)) time complexity, and a {@link raise} function in the derived class | 14 * O(log(n)) time complexity, and a {@link #raise} function in the derived class |
12 * {@link Event.Raisable} to execute all queued callbacks. | 15 * {@link Event.Raisable} to execute all queued callbacks. |
13 * | 16 * |
14 * @param <ParamT> The parameter used in {@link ParameterRunnable} callback. | 17 * @param <ParamT> The parameter used in {@link ParameterRunnable} callback. |
15 */ | 18 */ |
16 public class Event<ParamT> { | 19 public class Event<ParamT> { |
17 /** A runnable with parameter. */ | 20 /** A runnable with parameter. */ |
18 public static interface ParameterRunnable<ParamT> { | 21 public static interface ParameterRunnable<ParamT> { |
19 void run(ParamT p); | 22 void run(ParamT p); |
20 } | 23 } |
21 | 24 |
22 /** A callback with parameter. */ | 25 /** A callback with parameter. */ |
23 public static interface ParameterCallback<ReturnT, ParamT> { | 26 public static interface ParameterCallback<ReturnT, ParamT> { |
24 ReturnT run(ParamT p); | 27 ReturnT run(ParamT p); |
25 } | 28 } |
26 | 29 |
27 /** | 30 /** |
28 * An event provider version of {@link Event} implementation, provides {@lin k raise} function to | 31 * An event provider version of {@link Event} implementation, provides {@lin k #raise} function |
29 * execute appended {@link ParameterRunnable}, and {@link clear} function to clear all appended | 32 * to execute appended {@link ParameterRunnable}, and {@link #clear} functio n to clear all |
30 * callbacks. | 33 * appended callbacks. |
31 */ | 34 */ |
32 public static final class Raisable<ParamT> extends Event<ParamT> { | 35 public static class Raisable<ParamT> extends Event<ParamT> { |
33 /** Clears all appended callbacks */ | 36 /** Clears all appended callbacks */ |
34 public void clear() { | 37 public void clear() { |
35 synchronized (mSet) { | 38 synchronized (mSet) { |
36 mSet.clear(); | 39 mSet.clear(); |
37 } | 40 } |
38 } | 41 } |
39 | 42 |
40 /** | 43 /** |
41 * Executes all queued {@link ParameterRunnable} with |parameter|, retur ns an integer of | 44 * Executes all queued {@link ParameterRunnable} with |parameter|, retur ns an integer of |
42 * total callbacks executed. Note, if an 'add' function call is executin g concurrently | 45 * total callbacks executed. Note, if an 'add' function call is executin g concurrently |
43 * with the 'raise' function call, the newly added object may not be exe cuted. | 46 * with the 'raise' function call, the newly added object may not be exe cuted. |
44 */ | 47 */ |
45 public int raise(ParamT parameter) { | 48 public int raise(ParamT parameter) { |
46 Object[] array; | 49 Object[] array; |
47 synchronized (mSet) { | 50 synchronized (mSet) { |
48 array = mSet.toArray(); | 51 array = mSet.toArray(); |
49 } | 52 } |
50 int count = 0; | 53 int count = 0; |
51 for (Object obj : array) { | 54 for (Object obj : array) { |
52 execute(obj, parameter); | 55 execute(obj, parameter); |
Yuwei
2016/10/06 01:32:24
Will you also make Raisable.raise() async?
Hzj_jie
2016/10/07 00:07:21
That seems not necessary. raise function is not co
| |
53 count++; | 56 count++; |
54 } | 57 } |
55 return count; | 58 return count; |
56 } | 59 } |
57 | 60 |
58 /** Executes |obj| as ParameterRunnable<ParamT> with |parameter| as Para mT. */ | 61 /** Executes |obj| as ParameterRunnable<ParamT> with |parameter| as Para mT. */ |
59 @SuppressWarnings("unchecked") | 62 @SuppressWarnings("unchecked") |
60 private void execute(Object obj, ParamT parameter) { | 63 private void execute(Object obj, ParamT parameter) { |
61 ParameterRunnable<ParamT> runnable = (ParameterRunnable<ParamT>) obj ; | 64 ParameterRunnable<ParamT> runnable = (ParameterRunnable<ParamT>) obj ; |
62 runnable.run(parameter); | 65 runnable.run(parameter); |
63 } | 66 } |
64 } | 67 } |
65 | 68 |
66 /** | 69 /** |
70 * A {@link Raisable} which always executes the newly added {@link Parameter Runnable} with the | |
71 * parameter sent to the last {@link #raise} function call. If the event has not been raised, | |
72 * this class has consistent behavior as {@link Raisable}. <br> | |
73 * This class is useful for some one-time events, such as RenderStub.onClien tSizeChanged(). A | |
74 * later attached runnable will never be able to get the event. <br> | |
75 * The {@link ParameterRunnable} will be executed in the thread in which {@l ink #add} | |
76 * function is called if the event has been raised before. If there is not a {@link Looper} on | |
77 * current thread, the runnable will be executed immediately. Otherwise, a t ask will be posted | |
78 * to current looper. Note that it may be executed twice on different thread s with the exactly | |
79 * same parameter. | |
80 */ | |
81 public static final class PromisedRaisable<ParamT> extends Raisable<ParamT> { | |
82 private boolean mRaised; | |
83 private ParamT mLastParameter; | |
84 | |
85 @Override | |
86 public Object add(final ParameterRunnable<ParamT> runnable) { | |
87 Object result = super.add(runnable); | |
88 if (result != null) { | |
89 synchronized (mSet) { | |
90 if (mRaised) { | |
91 if (Looper.myLooper() == null) { | |
92 runnable.run(mLastParameter); | |
93 } else { | |
94 // We should always use the latest parameter, otherw ise the order of | |
95 // parameters current runnable gets may not be corre ct. | |
96 final PromisedRaisable<ParamT> me = this; | |
97 Handler h = new Handler(Looper.myLooper()); | |
98 h.post(new Runnable() { | |
99 @Override | |
100 public void run() { | |
101 runnable.run(me.mLastParameter); | |
102 } | |
103 }); | |
104 } | |
105 } | |
106 } | |
107 } | |
108 return result; | |
109 } | |
110 | |
111 @Override | |
112 public int raise(ParamT parameter) { | |
113 synchronized (mSet) { | |
114 mRaised = true; | |
115 mLastParameter = parameter; | |
116 } | |
117 return super.raise(parameter); | |
118 } | |
119 } | |
120 | |
121 /** | |
67 * A self removable {@link ParameterRunner}, uses a boolean {@link Parameter Callback} to decide | 122 * A self removable {@link ParameterRunner}, uses a boolean {@link Parameter Callback} to decide |
68 * whether removes self from {@link Event} or not. | 123 * whether removes self from {@link Event} or not. |
69 */ | 124 */ |
70 private static final class SelfRemovableParameterRunnable<ParamT> | 125 private static final class SelfRemovableParameterRunnable<ParamT> |
71 implements ParameterRunnable<ParamT> { | 126 implements ParameterRunnable<ParamT> { |
72 private final ParameterCallback<Boolean, ParamT> mCallback; | 127 private final ParameterCallback<Boolean, ParamT> mCallback; |
73 private final Event<ParamT> mOwner; | 128 private final Event<ParamT> mOwner; |
74 | 129 |
75 // This lock is used to make sure mEvent is correctly set before remove in run function. | 130 // This lock is used to make sure mEvent is correctly set before remove in run function. |
76 // i.e. mOwner.add and assigment of mEvent need to be atomic. | 131 // i.e. mOwner.add and assigment of mEvent need to be atomic. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
167 | 222 |
168 /** | 223 /** |
169 * Returns true if there is no runnable attached to current instance. | 224 * Returns true if there is no runnable attached to current instance. |
170 */ | 225 */ |
171 public boolean isEmpty() { | 226 public boolean isEmpty() { |
172 synchronized (mSet) { | 227 synchronized (mSet) { |
173 return mSet.isEmpty(); | 228 return mSet.isEmpty(); |
174 } | 229 } |
175 } | 230 } |
176 } | 231 } |
OLD | NEW |