/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.prism.impl;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.PhantomReference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Hashtable;
import java.util.LinkedList;
This class is used for registering and disposing the native
data associated with Java objects.
The object can register itself by calling one of the addRecord
methods and providing either the pointer to the native disposal
method or a descendant of the Disposer.Record interface with overridden
dispose() method.
When the object becomes unreachable, the dispose() method
of the associated Disposer.Record object will be called.
/**
* This class is used for registering and disposing the native
* data associated with Java objects.
*
* The object can register itself by calling one of the addRecord
* methods and providing either the pointer to the native disposal
* method or a descendant of the Disposer.Record interface with overridden
* dispose() method.
*
* When the object becomes unreachable, the dispose() method
* of the associated Disposer.Record object will be called.
*/
public class Disposer {
private static Disposer disposerInstance;
private static final int WEAK = 0;
private static final int PHANTOM = 1;
private static final int SOFT = 2;
private static int refType = PHANTOM;
static {
String type = PrismSettings.refType;
if (type != null) {
if (type.equals("weak")) {
refType = WEAK;
if (PrismSettings.verbose) System.err.println("Using WEAK refs");
} else if (type.equals("soft")) {
refType = SOFT;
if (PrismSettings.verbose) System.err.println("Using SOFT refs");
} else {
refType = PHANTOM;
if (PrismSettings.verbose) System.err.println("Using PHANTOM refs");
}
}
disposerInstance = new Disposer();
}
private final ReferenceQueue queue = new ReferenceQueue();
private final Hashtable records = new Hashtable();
private final LinkedList<Record> disposalQueue = new LinkedList<Record>();
Private constructor to prevent outside instantiation.
/**
* Private constructor to prevent outside instantiation.
*/
private Disposer() {
}
// /**
// * Registers the object and the native data for later disposal.
// * @param target Object to be registered
// * @param disposeMethod pointer to the native disposal method
// * @param pData pointer to the data to be passed to the
// * native disposal method
// */
// public static void addRecord(Object target,
// long disposeMethod, long pData)
// {
// disposerInstance.add(target,
// new DefaultDisposerRecord(disposeMethod, pData));
// }
Registers the target object and the native data for later disposal when
the target is unreachable.
.
Params: - target – Object to be registered
- rec – the associated DisposerRecord object
See Also: - DisposerRecord
/**
* Registers the target object and the native data for later disposal when
* the target is unreachable.
* .
* @param target Object to be registered
* @param rec the associated DisposerRecord object
* @see DisposerRecord
*/
public static void addRecord(Object target, Disposer.Record rec) {
disposerInstance.add(target, rec);
}
Add the object to the disposal queue. The object will be disposed
the next time cleanup is called.
Params: - rec – the DisposerRecord object to be disposed
/**
* Add the object to the disposal queue. The object will be disposed
* the next time cleanup is called.
*
* @param rec the DisposerRecord object to be disposed
*/
public static void disposeRecord(Disposer.Record rec) {
disposerInstance.addToDisposalQueue(rec);
}
Disposes all unreachable objects and all objects in the disposal queue.
It first polls the reference queue, calling the dispose method of each
unreachable object. It then iterates the list of objects in the
disposal queue, calling the dispose method of each object.
NOTE: This method must only be called from the Render Thread (the
thread on which the resources were created).
/**
* Disposes all unreachable objects and all objects in the disposal queue.
* It first polls the reference queue, calling the dispose method of each
* unreachable object. It then iterates the list of objects in the
* disposal queue, calling the dispose method of each object.
*
* NOTE: This method must only be called from the Render Thread (the
* thread on which the resources were created).
*/
public static void cleanUp() {
disposerInstance.disposeUnreachables();
disposerInstance.processDisposalQueue();
}
Performs the actual registration of the target object to be disposed.
Params: - target – Object to be registered, or if target is an instance
of DisposerTarget, its associated disposer referent
will be the Object that is registered
- rec – the associated DisposerRecord object
See Also: - DisposerRecord
/**
* Performs the actual registration of the target object to be disposed.
* @param target Object to be registered, or if target is an instance
* of DisposerTarget, its associated disposer referent
* will be the Object that is registered
* @param rec the associated DisposerRecord object
* @see DisposerRecord
*/
synchronized private void add(Object target, Disposer.Record rec) {
if (target instanceof Disposer.Target) {
target = ((Disposer.Target)target).getDisposerReferent();
}
Reference ref;
if (refType == PHANTOM) {
ref = new PhantomReference(target, queue);
} else if (refType == SOFT) {
ref = new SoftReference(target, queue);
} else {
ref = new WeakReference(target, queue);
}
records.put(ref, rec);
}
synchronized private void addToDisposalQueue(Disposer.Record rec) {
disposalQueue.add(rec);
}
Polls the reference queue to see if there are any unreachable objects
to be disposed. If there is work to be done, this method disposes all
unreachable objects in the queue, otherwise it returns immediately.
/**
* Polls the reference queue to see if there are any unreachable objects
* to be disposed. If there is work to be done, this method disposes all
* unreachable objects in the queue, otherwise it returns immediately.
*/
synchronized private void disposeUnreachables() {
Object obj;
while ((obj = queue.poll()) != null) {
try {
((Reference)obj).clear();
Disposer.Record rec = (Disposer.Record)records.remove(obj);
rec.dispose();
obj = null;
rec = null;
} catch (Exception e) {
System.out.println("Exception while removing reference: " + e);
e.printStackTrace();
}
}
}
synchronized private void processDisposalQueue() {
// disposalQueue is always empty in the case of Windows using the d3d pipe.
while (!disposalQueue.isEmpty()) {
disposalQueue.remove().dispose();
}
}
This interface is used to hold the resource to be disposed.
/**
* This interface is used to hold the resource to be disposed.
*/
public static interface Record {
public void dispose();
}
This is an interface which should be implemented by
the classes which use Disposer.
/**
* This is an interface which should be implemented by
* the classes which use Disposer.
*/
public static interface Target {
Returns an object which will be
used as the referent in the ReferenceQueue.
/**
* Returns an object which will be
* used as the referent in the ReferenceQueue.
*/
public Object getDisposerReferent();
}
}