Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package org.chromium.chromoting; | |
| 6 | |
| 7 import java.util.HashSet; | |
| 8 import java.util.Set; | |
| 9 | |
| 10 /** | |
| 11 * A thread-safe event queue which provides both {@link #add} and {@link #remove } functions with | |
| 12 * O(log(n)) time complex, and a {@link raise} function in Executor inheritance to execute all | |
| 13 * queued object. | |
| 14 * | |
| 15 * @param <ParamType> The parameter used in {@link ParameterRunnable} callback. | |
| 16 */ | |
| 17 public class Event<ParamType> { | |
| 18 /** | |
| 19 * A runnable with parameter. | |
| 20 */ | |
| 21 public static interface ParameterRunnable<ParamType> { | |
| 22 void run(ParamType p); | |
| 23 } | |
| 24 | |
| 25 /** | |
| 26 * A callback with parameter. | |
| 27 */ | |
| 28 public static interface ParameterCallback<ReturnType, ParamType> { | |
| 29 ReturnType run(ParamType p); | |
| 30 } | |
| 31 | |
| 32 /** | |
| 33 * An event provider version of {@link Event} implementation, provides {@lin k raise} function to | |
|
Lambros
2016/05/27 00:38:51
Why subclass, instead of adding raise() to Event?
Hzj_jie
2016/05/27 02:55:20
This pattern can avoid any potential misusage of a
| |
| 34 * execute appended {@link ParameterRunnable}. | |
| 35 */ | |
| 36 public static final class Executor<ParamType> extends Event<ParamType> { | |
| 37 public void clear() { | |
| 38 synchronized (mLock) { | |
| 39 mSet.clear(); | |
| 40 } | |
| 41 } | |
| 42 | |
| 43 /** | |
| 44 * Executes all queued {@link ParameterRunnable} with |parameter|, retur ns an integer of | |
| 45 * total callbacks executed. Note, if an 'add' function call is executin g concurrently | |
| 46 * with the 'raise' function call, the newly added object may not be exe cuted. | |
| 47 */ | |
| 48 public int raise(ParamType parameter) { | |
| 49 Set<ParameterRunnable<ParamType>> set = eventSet(); | |
| 50 Preconditions.notNull(set); | |
|
Lambros
2016/05/27 00:38:52
Don't need this Preconditions. It's obvious that e
Hzj_jie
2016/05/27 02:55:20
Done.
| |
| 51 int r = 0; | |
|
Lambros
2016/05/27 00:38:51
Avoid single-letter names (for-loop variables and
Hzj_jie
2016/05/27 02:55:19
Done.
| |
| 52 for (ParameterRunnable<ParamType> e : set) { | |
| 53 e.run(parameter); | |
| 54 r++; | |
| 55 } | |
| 56 return r; | |
| 57 } | |
| 58 | |
| 59 /** | |
| 60 * Returns a shadow copy of {@link mSet} as a {@link Set}. | |
| 61 */ | |
| 62 @SuppressWarnings("unchecked") | |
| 63 private Set<ParameterRunnable<ParamType>> eventSet() { | |
|
Lambros
2016/05/27 00:38:52
If you use toArray() instead of clone(), you don't
Hzj_jie
2016/05/27 02:55:19
Done.
| |
| 64 synchronized (mLock) { | |
| 65 return (Set<ParameterRunnable<ParamType>>) mSet.clone(); | |
| 66 } | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 /** | |
| 71 * A self removable {@link ParameterRunner}, uses a boolean {@link Parameter Callback} to decide | |
| 72 * whether removes self from {@link Event} or not. | |
| 73 */ | |
| 74 private static class SelfRemovableParameterRunnable<ParamType> | |
| 75 implements ParameterRunnable<ParamType> { | |
| 76 private final ParameterCallback<Boolean, ParamType> mRef; | |
|
Lambros
2016/05/27 00:38:52
Don't abbreviate names (in general; sometimes it's
Hzj_jie
2016/05/27 02:55:19
Done.
| |
| 77 private final Event<ParamType> mOwner; | |
| 78 // This lock is used to make sure mId is correctly set before remove in run function. i.e. | |
|
Lambros
2016/05/27 00:38:51
Blank line before comment.
Also, mId doesn't exist
Hzj_jie
2016/05/27 02:55:20
If the logic runs in following order, it will fail
| |
| 79 // mOwner.add and assigment of mId need to be atomic. | |
| 80 private final Object mLock; | |
| 81 private final Object mEvent; | |
| 82 | |
| 83 private SelfRemovableParameterRunnable(Event<ParamType> owner, | |
| 84 ParameterCallback<Boolean, ParamT ype> callback) { | |
| 85 Preconditions.notNull(owner); | |
|
Lambros
2016/05/27 00:38:51
This is OK for now, but I'd generally avoid over-u
Hzj_jie
2016/05/27 02:55:19
Yes, updated.
| |
| 86 Preconditions.notNull(callback); | |
| 87 mRef = callback; | |
| 88 mOwner = owner; | |
| 89 mLock = new Object(); | |
| 90 synchronized (mLock) { | |
| 91 mEvent = mOwner.add(this); | |
|
Lambros
2016/05/27 00:38:51
I'm not sure, but this might be too much work to d
Hzj_jie
2016/05/27 02:55:20
If we move some logic in to a new function, we wil
| |
| 92 } | |
| 93 Preconditions.notNull(mEvent); | |
| 94 } | |
| 95 | |
| 96 public final void run(ParamType p) { | |
| 97 if (!mRef.run(p)) { | |
| 98 synchronized (mLock) { | |
| 99 Preconditions.isTrue(mOwner.remove(mEvent)); | |
|
Lambros
2016/05/27 00:38:52
I don't think this is safe if two threads call Eve
Hzj_jie
2016/05/27 02:55:19
Done, but this class is designed to be single read
Lambros
2016/05/27 22:26:06
Even if Event.Executor.raise() is always called fr
Hzj_jie
2016/05/28 00:32:06
Oh, yes, I forgot Event.Executor.clear. I will rem
| |
| 100 } | |
| 101 } | |
| 102 } | |
| 103 | |
| 104 // This class is self-contained, i.e. consumers do not need to have a re ference of this | |
| 105 // instance, but all the logic is in new function. | |
|
Lambros
2016/05/27 00:38:51
I don't think this should be called create() - it
Hzj_jie
2016/05/27 02:55:20
Done.
| |
| 106 public static final <ParamType> void create( | |
| 107 Event<ParamType> owner, | |
| 108 ParameterCallback<Boolean, ParamType> callback) { | |
| 109 new SelfRemovableParameterRunnable<ParamType>(owner, callback); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 protected final HashSet<ParameterRunnable<ParamType>> mSet; | |
| 114 protected final Object mLock; | |
|
Lambros
2016/05/27 00:38:51
Since mSet is final, you don't need a separate mLo
Hzj_jie
2016/05/27 02:55:19
Done.
| |
| 115 | |
| 116 public Event() { | |
| 117 mLock = new Object(); | |
| 118 mSet = new HashSet<>(); | |
| 119 } | |
| 120 | |
| 121 /** | |
| 122 * Adds a {@link ParameterRunnable} object into current instance, returns an object which can | |
| 123 * be used to {@link remove} the runnable from this instance. If |runnable| is null or it has | |
| 124 * been added to this instance already, this function returns null. | |
| 125 */ | |
| 126 public Object add(ParameterRunnable<ParamType> runnable) { | |
| 127 if (runnable == null) { | |
| 128 return null; | |
| 129 } | |
| 130 synchronized (mLock) { | |
| 131 if (mSet.add(runnable)) { | |
| 132 return runnable; | |
| 133 } | |
| 134 } | |
| 135 return null; | |
| 136 } | |
| 137 | |
| 138 /** | |
| 139 * Adds a self removable {@link ParameterRunnable} object into current insta nce, since | |
| 140 * {@link SelfRemovableParameterRunnable} will remove itself from {@link Eve nt} instance, this | |
|
Lambros
2016/05/27 00:38:51
SelfRemovableParameterRunnable is a private implem
Hzj_jie
2016/05/27 02:55:19
Done.
| |
| 141 * function returns a boolean value to indicate the success or not of the op eration. | |
|
Lambros
2016/05/27 00:38:51
The boolean return is not needed (it's always true
Hzj_jie
2016/05/27 02:55:19
Done.
| |
| 142 */ | |
| 143 public boolean addSelfRemovable(ParameterCallback<Boolean, ParamType> callba ck) { | |
| 144 if (callback == null) { | |
| 145 return false; | |
| 146 } | |
| 147 SelfRemovableParameterRunnable.<ParamType>create(this, callback); | |
| 148 return true; | |
| 149 } | |
| 150 | |
| 151 /** | |
| 152 * Removes an object represents an event and returned by {@link add} functio n from this | |
|
Lambros
2016/05/27 00:38:52
s/represents/representing
Or maybe rephrase:
Remo
Hzj_jie
2016/05/27 02:55:20
Done.
| |
| 153 * instance. Returns false if the object is not in the event queue, or not r eturned by | |
| 154 * {@link add} function. | |
| 155 */ | |
| 156 public boolean remove(Object obj) { | |
| 157 if (obj == null) { | |
| 158 return false; | |
| 159 } | |
| 160 synchronized (mLock) { | |
| 161 return mSet.remove(obj); | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 /** | |
| 166 * Returns the total count of runnables attached to current instance. | |
| 167 */ | |
| 168 public int size() { | |
| 169 synchronized (mLock) { | |
| 170 return mSet.size(); | |
| 171 } | |
| 172 } | |
| 173 | |
| 174 /** | |
| 175 * Returns true if there are at least one runnable attached to current insta nce. | |
|
Lambros
2016/05/27 00:38:51
s/are/is
Hzj_jie
2016/05/27 02:55:20
Done.
| |
| 176 */ | |
|
Lambros
2016/05/27 00:38:52
'attached' is maybe a little bit strange. Maybe ha
Hzj_jie
2016/05/27 02:55:20
Done.
| |
| 177 public boolean attached() { | |
| 178 synchronized (mLock) { | |
| 179 return !mSet.isEmpty(); | |
| 180 } | |
| 181 } | |
| 182 } | |
| OLD | NEW |