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

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: Created 4 years, 7 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.lang.ref.WeakReference;
8 import java.util.ArrayList;
9 import java.util.HashSet;
10 import java.util.Iterator;
11
12 /**
13 * A thread-safe event queue which provides both {@link #add} and {@link #remove } functions with
14 * O(log(n)) time complex, and a {@link raise} function in Executor inheritance to execute all
15 * queued object.
16 *
17 * @param <ParamType> The parameter used in {@link ParameterRunnable} callback.
18 */
19 public class Event<ParamType> {
20 /**
21 * A runnable with parameter.
22 */
23 public static interface ParameterRunnable<ParamType> {
24 void run(ParamType p);
25 }
26
27 /**
28 * A callback with parameter.
29 */
30 public static interface ParameterCallback<ReturnType, ParamType> {
31 ReturnType run(ParamType p);
32 }
33
34 /**
35 * An event provider version of {@link Event} implementation, provides {@lin k raise} function to
36 * execute appended {@link ParameterRunnable}.
37 */
38 public static final class Executor<ParamType> extends Event<ParamType> {
39 public void clear() {
40 synchronized (mLock) {
41 mArray.clear();
42 mFreeSet.clear();
43 }
44 }
45
46 /**
47 * Executes all queued {@link ParameterRunnable} with |parameter|, retur ns an integer of
48 * total callbacks executed. Note, if an 'add' function call is executin g concurrently
49 * with the 'raise' function call, the newly added object may not be exe cuted.
50 */
51 public int raise(ParamType parameter) {
52 int r = 0;
53 for (int i = 0; i < mArray.size(); i++) {
Hzj_jie 2016/05/23 23:39:14 This is memory ordering safe, in Java, "After we e
Lambros 2016/05/24 17:56:41 I think that quote is misleading, and you do need
Hzj_jie 2016/05/24 18:24:38 I totally agree we would get a random value withou
54 ParameterRunnable<ParamType> e = mArray.get(i);
55 if (e != null) {
56 e.run(parameter);
57 r++;
58 }
59 }
60 return r;
61 }
62 }
63
64 /**
65 * A self removable {@link ParameterRunner}, uses a boolean {@link Parameter Callback} to decide
66 * whether removes self from {@link Event} or not.
67 */
68 private static class SelfRemovableParameterRunnable<ParamType>
69 implements ParameterRunnable<ParamType> {
70 private final ParameterCallback<Boolean, ParamType> mRef;
71 private final Event<ParamType> mOwner;
72 // This lock is used to make sure mId is correctly set before remove in run function. i.e.
73 // mOwner.add and assigment of mId need to be atomic.
74 private final Object mLock;
75 private final int mId;
76
77 private SelfRemovableParameterRunnable(Event<ParamType> owner,
78 ParameterCallback<Boolean, ParamT ype> callback) {
79 Preconditions.notNull(owner);
80 Preconditions.notNull(callback);
81 mRef = callback;
82 mOwner = owner;
83 mLock = new Object();
84 synchronized (mLock) {
85 mId = mOwner.add(this);
86 }
87 Preconditions.isTrue(mId >= 0);
88 }
89
90 public final void run(ParamType p) {
91 if (!mRef.run(p)) {
92 synchronized (mLock) {
93 Preconditions.isTrue(mOwner.remove(mId));
94 }
95 }
96 }
97
98 // This class is self-contained, i.e. consumers do not need to have a re ference of this
99 // instance, but all the logic is in new function.
100 public static final <ParamType> void create(
101 Event<ParamType> owner,
102 ParameterCallback<Boolean, ParamType> callback) {
103 new SelfRemovableParameterRunnable<ParamType>(owner, callback);
104 }
105 }
106
107 /**
108 * A weak reference based {@link ParameterRunner}, so a registered callback won't block GC to
109 * finalize the instance.
110 */
111 private static class WeakParameterRunnable<ParamType>
112 extends SelfRemovableParameterRunnable<ParamType> {
113 private WeakParameterRunnable(Event<ParamType> owner,
114 final WeakReference<ParameterRunnable<Para mType>> ref) {
115 super(owner, new ParameterCallback<Boolean, ParamType>() {
116 @Override
117 public Boolean run(ParamType param) {
118 ParameterRunnable<ParamType> runnable = ref.get();
119 if (runnable == null) {
120 return false;
121 }
122 runnable.run(param);
123 return true;
124 }
125 });
126 }
127
128 public static final <ParamType> void create(
129 Event<ParamType> owner,
130 ParameterRunnable<ParamType> runnable) {
131 new WeakParameterRunnable<ParamType>(owner, new WeakReference<>(runn able));
132 }
133 }
134
135 protected final ArrayList<ParameterRunnable<ParamType>> mArray;
136 protected final HashSet<Integer> mFreeSet;
137 protected final Object mLock;
138
139 public Event() {
140 mArray = new ArrayList<>();
141 mFreeSet = new HashSet<>();
142 mLock = new Object();
143 }
144
145 /**
146 * Adds a {@link ParameterRunnable} object into current instance, returns an integer as its
147 * position.
148 */
149 public int add(ParameterRunnable<ParamType> runnable) {
150 if (runnable == null) {
151 return -1;
152 }
153 synchronized (mLock) {
154 if (mFreeSet.isEmpty()) {
155 Preconditions.isTrue(mArray.add(runnable));
156 return mArray.size() - 1;
157 }
158 Iterator<Integer> it = mFreeSet.iterator();
159 Preconditions.isTrue(it.hasNext());
160 int id = it.next();
161 mArray.set(id, runnable);
162 Preconditions.isTrue(mFreeSet.remove(id));
163 return id;
164 }
165 }
166
167 /**
168 * Adds a self removable {@link ParameterRunnable} object into current insta nce, since
169 * {@link SelfRemovableParameterRunnable} will remove itself from {@link Eve nt} instance, this
170 * function returns a boolean value to indicate the success or not of the op eration.
171 */
172 public boolean addSelfRemovable(ParameterCallback<Boolean, ParamType> callba ck) {
173 if (callback == null) {
174 return false;
175 }
176 SelfRemovableParameterRunnable.<ParamType>create(this, callback);
177 return true;
178 }
179
180 /**
181 * Adds a weak referred {@link ParameterRunnable} object into current instan ce, since
182 * {@link WeakParameterRunnable} will remove itself from {@link Event} insta nce, this function
183 * returns a boolean value to indicate the success or not of the operation.
184 */
185 public boolean addWeakReferred(ParameterRunnable<ParamType> runnable) {
186 if (runnable == null) {
187 return false;
188 }
189 WeakParameterRunnable.<ParamType>create(this, runnable);
190 return true;
191 }
192
193 /**
194 * Removes a Runnable object at position |id|, returns false if the |id| is not in the range of
195 * {@link mArray}.
196 */
197 public boolean remove(int id) {
198 if (id < 0 || id >= mArray.size() || mArray.get(id) == null) {
199 return false;
200 }
201 synchronized (mLock) {
202 mArray.set(id, null);
203 mFreeSet.add(id);
204 }
205 return true;
206 }
207
208 /**
209 * Returns the total count of runnables attached to current instance.
210 */
211 public int size() {
212 synchronized (mLock) {
213 return mArray.size() - mFreeSet.size();
214 }
215 }
216
217 /**
218 * Returns true if there are at least one runnable attached to current insta nce.
219 */
220 public boolean attached() {
221 return size() > 0;
222 }
223 }
OLDNEW
« no previous file with comments | « remoting/android/client_java_tmpl.gni ('k') | remoting/android/java/src/org/chromium/chromoting/Preconditions.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698