Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: remoting/android/java/src/org/chromium/chromoting/Event.java

Issue 1999583002: Add Event and EventTest (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use only a Set instead of a Set and a List Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698