/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-2010 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id$
*/
package org.exist.util.pool;
import java.util.LinkedList;
import org.exist.dom.persistent.AttrImpl;
import org.exist.dom.persistent.CDATASectionImpl;
import org.exist.dom.persistent.CommentImpl;
import org.exist.dom.persistent.ElementImpl;
import org.exist.dom.persistent.NodeImpl;
import org.exist.dom.persistent.ProcessingInstructionImpl;
import org.exist.dom.persistent.TextImpl;
import org.exist.util.hashtable.Int2ObjectHashMap;
import org.w3c.dom.Node;
/**
* A pool of node objects. Storing a resource creates many, short-lived DOM node
* objects. To reduce garbage collection, we use a pool to cache a certain number
* of objects.
*/
public class NodePool {
public final static int MAX_OBJECTS = 20;
public static NodePool getInstance() {
return pools.get();
}
private static class PoolThreadLocal extends ThreadLocal<NodePool> {
protected NodePool initialValue() {
return new NodePool(MAX_OBJECTS);
}
}
private static final ThreadLocal<NodePool> pools = new PoolThreadLocal();
private int maxActive;
private Int2ObjectHashMap<Pool> poolMap = new Int2ObjectHashMap<Pool>(17);
public NodePool(int maxObjects) {
this.maxActive = maxObjects;
}
public NodeImpl borrowNode(short key) {
Pool pool = (Pool) poolMap.get(key);
if (pool == null) {
pool = new Pool();
poolMap.put(key, pool);
}
return pool.borrowNode(key);
}
public void returnNode(NodeImpl node) {
final Pool pool = (Pool) poolMap.get(node.getNodeType());
if (pool != null)
{pool.returnNode(node);}
}
public int getSize(short key) {
final Pool pool = (Pool) poolMap.get(key);
return pool.stack.size();
}
private NodeImpl makeObject(short key) {
switch (key) {
case Node.ELEMENT_NODE:
return new ElementImpl();
case Node.TEXT_NODE:
return new TextImpl();
case Node.ATTRIBUTE_NODE:
return new AttrImpl();
case Node.CDATA_SECTION_NODE:
return new CDATASectionImpl();
case Node.PROCESSING_INSTRUCTION_NODE:
return new ProcessingInstructionImpl();
case Node.COMMENT_NODE:
return new CommentImpl();
}
throw new IllegalStateException("Unable to create object of type " + key);
}
private class Pool {
private LinkedList<NodeImpl> stack = new LinkedList<NodeImpl>();
public NodeImpl borrowNode(short key) {
if (stack.isEmpty()) {
return makeObject(key);
}
return stack.removeLast();
}
public void returnNode(NodeImpl node) {
// Only cache up to maxActive nodes
if (stack.size() < maxActive)
{stack.addLast(node);}
}
}
}