Chromium Code Reviews| Index: remoting/android/java/src/org/chromium/chromoting/Event.java |
| diff --git a/remoting/android/java/src/org/chromium/chromoting/Event.java b/remoting/android/java/src/org/chromium/chromoting/Event.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..43e86ecd8b23892a1412a5ec423be55be4f3055b |
| --- /dev/null |
| +++ b/remoting/android/java/src/org/chromium/chromoting/Event.java |
| @@ -0,0 +1,184 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.chromoting; |
| + |
| +import java.util.HashSet; |
| + |
| +/** |
| + * A thread-safe event queue which provides both {@link #add} and {@link #remove} functions with |
| + * O(log(n)) time complex, and a {@link raise} function in Executor inheritance to execute all |
|
Lambros
2016/05/27 22:26:06
s/complex/complexity/
s/Executor inheritance/the d
Hzj_jie
2016/05/28 00:32:06
Done.
|
| + * queued object. |
|
Lambros
2016/05/27 22:26:06
s/object/objects/
Hzj_jie
2016/05/28 00:32:07
Done.
|
| + * |
| + * @param <ParamType> The parameter used in {@link ParameterRunnable} callback. |
|
Lambros
2016/05/27 22:26:06
We should probably comply with the Google style gu
Hzj_jie
2016/05/28 00:32:06
Done.
|
| + */ |
| +public class Event<ParamType> { |
| + /** |
| + * A runnable with parameter. |
|
Lambros
2016/05/27 22:26:06
Elsewhere, we've formatted single-line JavaDoc as
Hzj_jie
2016/05/28 00:32:07
I did not see a coding style for this, but yes, we
|
| + */ |
| + public static interface ParameterRunnable<ParamType> { |
| + void run(ParamType p); |
| + } |
| + |
| + /** |
| + * A callback with parameter. |
| + */ |
| + public static interface ParameterCallback<ReturnType, ParamType> { |
| + ReturnType run(ParamType p); |
| + } |
| + |
| + /** |
| + * An event provider version of {@link Event} implementation, provides {@link raise} function to |
| + * execute appended {@link ParameterRunnable}. |
| + */ |
| + public static final class Executor<ParamType> extends Event<ParamType> { |
| + public void clear() { |
|
Lambros
2016/05/27 22:26:06
Need JavaDoc for public methods (linter will compl
Hzj_jie
2016/05/28 00:32:07
Done.
|
| + synchronized (mSet) { |
| + mSet.clear(); |
| + } |
| + } |
| + |
| + /** |
| + * Executes all queued {@link ParameterRunnable} with |parameter|, returns an integer of |
| + * total callbacks executed. Note, if an 'add' function call is executing concurrently |
| + * with the 'raise' function call, the newly added object may not be executed. |
| + */ |
| + public int raise(ParamType parameter) { |
| + Object[] array; |
| + synchronized (mSet) { |
| + array = mSet.toArray(); |
| + } |
| + int count = 0; |
| + for (Object obj : array) { |
| + execute(obj, parameter); |
| + count++; |
| + } |
| + return count; |
| + } |
| + |
| + /** |
| + * Executes |obj| as ParameterRunnable<ParamType> with |parameter| as ParamType. |
| + */ |
| + @SuppressWarnings("unchecked") |
|
Lambros
2016/05/27 22:26:06
I'm not sure about this. Android style guide:
http
Hzj_jie
2016/05/28 00:32:06
Oops, I have tried several ways, but looks like we
|
| + private void execute(Object obj, ParamType parameter) { |
| + ParameterRunnable<ParamType> runnable = (ParameterRunnable<ParamType>) obj; |
| + runnable.run(parameter); |
| + } |
| + } |
| + |
| + /** |
| + * A self removable {@link ParameterRunner}, uses a boolean {@link ParameterCallback} to decide |
| + * whether removes self from {@link Event} or not. |
| + */ |
| + private static class SelfRemovableParameterRunnable<ParamType> |
| + implements ParameterRunnable<ParamType> { |
| + private final ParameterCallback<Boolean, ParamType> mCallback; |
| + private final Event<ParamType> mOwner; |
| + |
| + // This lock is used to make sure mEvent is correctly set before remove in run function. |
| + // i.e. mOwner.add and assigment of mEvent need to be atomic. |
| + private final Object mLock; |
| + private final Object mEvent; |
| + |
| + private SelfRemovableParameterRunnable(Event<ParamType> owner, |
| + ParameterCallback<Boolean, ParamType> callback) { |
| + Preconditions.notNull(callback); |
| + mCallback = callback; |
| + mOwner = owner; |
| + mLock = new Object(); |
| + synchronized (mLock) { |
| + mEvent = mOwner.add(this); |
|
Lambros
2016/05/27 22:26:06
Please verify that FindBugs is happy with leaking
Hzj_jie
2016/05/28 00:32:06
No, findbugs does not raise any issue. And synchro
|
| + } |
| + Preconditions.notNull(mEvent); |
| + } |
| + |
| + public final void run(ParamType p) { |
| + synchronized (mLock) { |
| + if (mOwner.contains(mEvent)) { |
| + if (!mCallback.run(p)) { |
|
Lambros
2016/05/31 17:50:35
I know the CL has landed now, but I see a couple o
|
| + Preconditions.isTrue(mOwner.remove(mEvent)); |
| + } |
| + } |
| + } |
| + } |
| + } |
| + |
| + protected final HashSet<ParameterRunnable<ParamType>> mSet; |
| + |
| + public Event() { |
| + mSet = new HashSet<>(); |
| + } |
| + |
| + /** |
| + * Adds a {@link ParameterRunnable} object into current instance, returns an object which can |
| + * be used to {@link remove} the runnable from this instance. If |runnable| is null or it has |
| + * been added to this instance already, this function returns null. |
| + */ |
| + public Object add(ParameterRunnable<ParamType> runnable) { |
| + if (runnable == null) { |
| + return null; |
| + } |
| + synchronized (mSet) { |
| + if (mSet.add(runnable)) { |
| + return runnable; |
| + } |
| + } |
| + return null; |
| + } |
| + |
| + /** |
| + * Adds a self removable {@link ParameterRunnable} object into current instance, the runnable |
|
Lambros
2016/05/27 22:26:06
Grammar nit:
This is 2 sentences, so:
Either s/,/;
Hzj_jie
2016/05/28 00:32:06
Done.
|
| + * will remove itself from {@link Event} instance when callback returns false. |
| + */ |
| + public void addSelfRemovable(ParameterCallback<Boolean, ParamType> callback) { |
| + Preconditions.notNull(callback); |
| + // SelfRemovableParameterRunner is self-contained, i.e. consumers do not need to have a |
|
Lambros
2016/05/27 22:26:07
Blank line before comment.
Hzj_jie
2016/05/28 00:32:06
Done.
|
| + // reference of this instance, but all the logic is in new function. |
| + new SelfRemovableParameterRunnable<ParamType>(this, callback); |
| + } |
| + |
| + /** |
| + * Removes an object that was previously returned by {@link add}. Returns false if the object |
| + * is not in the event queue, or not returned by {@link add} function. |
| + */ |
| + public boolean remove(Object obj) { |
| + if (obj == null) { |
|
Lambros
2016/05/27 22:26:06
Maybe remove this test?
Hzj_jie
2016/05/28 00:32:07
Done.
|
| + return false; |
| + } |
| + synchronized (mSet) { |
| + return mSet.remove(obj); |
| + } |
| + } |
| + |
| + /** |
| + * Returns whether current instance contains the object that was previously returned by |
| + * {@link add}. |
| + */ |
| + public boolean contains(Object obj) { |
| + if (obj == null) { |
|
Lambros
2016/05/27 22:26:06
Maybe remove this test?
Hzj_jie
2016/05/28 00:32:06
Done.
|
| + return false; |
| + } |
| + synchronized (mSet) { |
| + return mSet.contains(obj); |
| + } |
| + } |
| + |
| + /** |
| + * Returns the total count of runnables attached to current instance. |
| + */ |
| + public int size() { |
| + synchronized (mSet) { |
| + return mSet.size(); |
| + } |
| + } |
| + |
| + /** |
| + * Returns true if there is no runnable attached to current instance. |
| + */ |
| + public boolean isEmpty() { |
| + synchronized (mSet) { |
| + return mSet.isEmpty(); |
| + } |
| + } |
| +} |