Chromium Code Reviews| 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 |