This source file includes following definitions.
- cleanupNow
- handleOnUiThread
- runCleanupTaskInternal
package org.chromium.content.common;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.base.TraceEvent;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.Set;
public class CleanupReference extends WeakReference<Object> {
private static final String TAG = "CleanupReference";
private static final boolean DEBUG = false;
private static ReferenceQueue<Object> sGcQueue = new ReferenceQueue<Object>();
private static Object sCleanupMonitor = new Object();
private static final Thread sReaperThread = new Thread(TAG) {
@Override
public void run() {
while (true) {
try {
CleanupReference ref = (CleanupReference) sGcQueue.remove();
if (DEBUG) Log.d(TAG, "removed one ref from GC queue");
synchronized (sCleanupMonitor) {
Message.obtain(LazyHolder.sHandler, REMOVE_REF, ref).sendToTarget();
sCleanupMonitor.wait(500);
}
} catch (Exception e) {
Log.e(TAG, "Queue remove exception:", e);
}
}
}
};
static {
sReaperThread.setDaemon(true);
sReaperThread.start();
}
private static final int ADD_REF = 1;
private static final int REMOVE_REF = 2;
private static class LazyHolder {
static final Handler sHandler = new Handler(ThreadUtils.getUiThreadLooper()) {
@Override
public void handleMessage(Message msg) {
TraceEvent.begin();
CleanupReference ref = (CleanupReference) msg.obj;
switch (msg.what) {
case ADD_REF:
sRefs.add(ref);
break;
case REMOVE_REF:
ref.runCleanupTaskInternal();
break;
default:
Log.e(TAG, "Bad message=" + msg.what);
break;
}
if (DEBUG) Log.d(TAG, "will try and cleanup; max = " + sRefs.size());
synchronized (sCleanupMonitor) {
while ((ref = (CleanupReference) sGcQueue.poll()) != null) {
ref.runCleanupTaskInternal();
}
sCleanupMonitor.notifyAll();
}
TraceEvent.end();
}
};
}
private static Set<CleanupReference> sRefs = new HashSet<CleanupReference>();
private Runnable mCleanupTask;
public CleanupReference(Object obj, Runnable cleanupTask) {
super(obj, sGcQueue);
if (DEBUG) Log.d(TAG, "+++ CREATED ONE REF");
mCleanupTask = cleanupTask;
handleOnUiThread(ADD_REF);
}
public void cleanupNow() {
handleOnUiThread(REMOVE_REF);
}
private void handleOnUiThread(int what) {
Message msg = Message.obtain(LazyHolder.sHandler, what, this);
if (Looper.myLooper() == msg.getTarget().getLooper()) {
msg.getTarget().handleMessage(msg);
msg.recycle();
} else {
msg.sendToTarget();
}
}
private void runCleanupTaskInternal() {
if (DEBUG) Log.d(TAG, "runCleanupTaskInternal");
sRefs.remove(this);
if (mCleanupTask != null) {
if (DEBUG) Log.i(TAG, "--- CLEANING ONE REF");
mCleanupTask.run();
mCleanupTask = null;
}
clear();
}
}