1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
/*
* Copyright (c) 2003, 2018, 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.
*
* 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 nsk.share.gc;
import java.io.*;
import java.util.*;
import nsk.share.test.ExecutionController;
/**
* <tt>NonbranchyTree</tt> defines a tree structure. Each node of the tree
* always has one son. A node may have the second son with probability
* <tt>branchiness</tt>.
*/
public class NonbranchyTree {
/** Minimal size of each node (in bytes) */
public final static int MIN_NODE_SIZE = 20;
private Node root;
private Random random;
private int numberOfNodes;
private float branchiness;
private int size;
private ExecutionController controller;
/**
* Creates a new tree with number of nodes not more than
* <tt>numberOfNodes</tt>. The implementation uses recursion to build the
* tree, so if <tt>StackOverflowError</tt> or <tt>OutOfMemoryError</tt> is
* thrown, the recursion is stopped and the method finishes building of the
* tree. Each node consists of <tt>byte[]</tt> of length <tt>size</tt>.
*
* @param numberOfNodes maximum number of nodes for the tree.
* @param branchiness probability for each node to have the second son.
* @param size number of bytes to store in a node.
*
* @throws <i>IllegalArgumentException</i> if <tt>numberOfNodes</tt> is
* less than 1; or <tt>branchiness</tt> is greater than 1, or less
* or equal than 0; or <tt>size</tt> is less than 1.
*
*/
public NonbranchyTree(int numberOfNodes, float branchiness, int size) {
this(numberOfNodes, branchiness, size, new Random(System.currentTimeMillis()), null);
initTree();
}
public NonbranchyTree(int numberOfNodes, float branchiness, int size, ExecutionController controller) {
this(numberOfNodes, branchiness, size, new Random(System.currentTimeMillis()), controller);
initTree();
}
private NonbranchyTree(int numberOfNodes, float branchiness, int size, Random random, ExecutionController controller) {
this.numberOfNodes = numberOfNodes;
this.branchiness = branchiness;
this.size = size;
this.random = random;
this.controller = controller;
}
private void initTree() {
if (numberOfNodes < 1) {
throw new IllegalArgumentException("Illegal number of nodes: "
+ numberOfNodes + ", must be at "
+ "least 1.");
}
if ( (branchiness >= 1) || (branchiness <= 0) ) {
throw new IllegalArgumentException("Illegal value of branchiness: "
+ numberOfNodes + ", must be at "
+ "greater than 0 and less than "
+ " 1.");
}
if (size < 1) {
throw new IllegalArgumentException("Illegal size of nodes: "
+ size + ", must be at least 1.");
}
root = createTree(numberOfNodes, size);
}
// Create a new tree with specified number of nodes and size of each node
private Node createTree(int numberOfNodes, int size) {
// Make sure we respect the controller and stop test after
// given time.
if (controller != null && !controller.continueExecution()) {
return null;
}
Node node = new Node(size);
try {
if (numberOfNodes == 0) {
// No more nodes need to be built
return null;
} else if (numberOfNodes == 1) {
return node;
} else if (numberOfNodes == 2) {
node.left = createTree(1, size);
return node;
} else {
// Create a few nodes
if (makeRightNode()) {
// The node will have two sons
int leftNodes = 1 + random.nextInt(numberOfNodes - 2);
int rightNodes = numberOfNodes - 1 - leftNodes;
node.left = createTree(leftNodes, size);
node.right = createTree(rightNodes, size);
} else {
// The node will have just one son
Node leftTree = createTree(numberOfNodes - 1, size);
node.left = leftTree;
}
return node;
} // if
} catch(StackOverflowError e) {
// No more memory for such long tree
return node;
} catch(OutOfMemoryError e) {
// No more memory for such long tree
return node;
} // try
} // createTree()
// Define the "branchiness" of the tree
private boolean makeRightNode() {
return (random.nextFloat() < branchiness);
}
/**
* Bends the tree. A son of a leaf of the tree is set to the root node.
*
*/
public void bend() {
bend(root);
}
// Bend the tree: make a reference from a leat of the tree to the specified
// node
private void bend(Node markedNode) {
Node node = root;
while ( (node.left != null) || (node.right != null) )
node = node.left;
node.right = markedNode;
}
/**
* Prints the whole tree from the root to the defined PrintStream.
*
* @param out PrintStream to print the tree in
*
*/
public void print(PrintStream out) {
print(out, root);
}
// Print the sub-tree from the specified node and down
private void print(PrintStream out, Node node) {
node.print(out);
if (node.left != null)
print(out, node.left);
if (node.right != null)
print(out, node.right);
}
}
// The class defines a node of a tree
class Node {
Node left;
Node right;
byte[] core;
Node(int size) {
left = null;
right = null;
core = new byte[size];
// Initizlize the core array
for (int i = 0; i < size; i++)
core[i] = (byte) i;
}
// Print the node info
void print(PrintStream out) {
out.println("node = " + this + " (" + left + ", " + right + ")");
}
}
|