1 | /* |
2 | |
3 | Derby - Class org.apache.derby.impl.store.access.sort.NodeAllocator |
4 | |
5 | Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.impl.store.access.sort; |
22 | |
23 | /** |
24 | |
25 | NodeAllocator manages an array of nodes which can be reused. |
26 | |
27 | **/ |
28 | |
29 | final class NodeAllocator |
30 | { |
31 | private static final int DEFAULT_INIT_SIZE = 128; |
32 | private static final int GROWTH_MULTIPLIER = 2; |
33 | private static final int DEFAULT_MAX_SIZE = 1024; |
34 | |
35 | private Node array[]; |
36 | private int maxSize; |
37 | private int nAllocated; |
38 | private Node freeList = null; |
39 | |
40 | /** |
41 | Construct an empty allocator. The caller must call |
42 | init() before using it. |
43 | **/ |
44 | public NodeAllocator() |
45 | { |
46 | array = null; |
47 | nAllocated = 0; |
48 | maxSize = 0; |
49 | } |
50 | |
51 | public Node newNode() |
52 | { |
53 | // Caller forgot to init? |
54 | if (array == null) |
55 | { |
56 | if (init() == false) |
57 | return null; |
58 | } |
59 | |
60 | if (freeList != null) |
61 | { |
62 | Node n = freeList; |
63 | freeList = n.rightLink; |
64 | n.rightLink = null; |
65 | return n; |
66 | } |
67 | |
68 | // Do we need to try reallocating the array? |
69 | if (nAllocated == array.length) |
70 | { |
71 | // If the array is already the maximum size, then |
72 | // tell the caller that there are no more nodes |
73 | // available. |
74 | if (array.length >= maxSize) |
75 | return null; |
76 | |
77 | // Attempt to allocate a new array. If the allocation |
78 | // fails, tell the caller that there are no more |
79 | // nodes available. |
80 | Node[] newArray = new Node[array.length * GROWTH_MULTIPLIER]; |
81 | if (newArray == null) |
82 | return null; |
83 | |
84 | // The new array was successfully allocated. Copy the |
85 | // nodes from the original array into it, and make the |
86 | // new array the allocator's array. |
87 | System.arraycopy(array, 0, newArray, 0, array.length); |
88 | array = newArray; |
89 | } |
90 | |
91 | // If this slot in the array hasn't had a node |
92 | // allocated for it yet, do so now. |
93 | if (array[nAllocated] == null) |
94 | array[nAllocated] = new Node(nAllocated); |
95 | |
96 | // Return the node and increase the allocated count. |
97 | return array[nAllocated++]; |
98 | } |
99 | |
100 | /** |
101 | Return a node to the allocator. |
102 | **/ |
103 | public void freeNode(Node n) |
104 | { |
105 | n.reset(); |
106 | n.rightLink = freeList; |
107 | freeList = n; |
108 | } |
109 | |
110 | /** |
111 | Initialize the allocator with default values for |
112 | initial and maximum size. Returns false if sufficient |
113 | memory could not be allocated. |
114 | **/ |
115 | public boolean init() |
116 | { |
117 | return init(DEFAULT_INIT_SIZE, DEFAULT_MAX_SIZE); |
118 | } |
119 | |
120 | /** |
121 | Initialize the allocator with default values for |
122 | initial size and the provided maximum size. |
123 | Returns false if sufficient memory could not be allocated. |
124 | **/ |
125 | public boolean init(int maxSize) |
126 | { |
127 | return init(DEFAULT_INIT_SIZE, maxSize); |
128 | } |
129 | |
130 | /** |
131 | Initialize the allocator with the given initial and |
132 | maximum sizes. This method does not check, but assumes |
133 | that the value of initSize is less than the value of |
134 | maxSize, and that they are both powers of two. Returns |
135 | false if sufficient memory could not be allocated. |
136 | **/ |
137 | public boolean init(int initSize, int maxSize) |
138 | { |
139 | this.maxSize = maxSize; |
140 | if (maxSize < initSize) |
141 | initSize = maxSize; |
142 | array = new Node[initSize]; |
143 | if (array == null) |
144 | return false; |
145 | nAllocated = 0; |
146 | return true; |
147 | } |
148 | |
149 | /** |
150 | Expand the node allocator's capacity by certain percent. |
151 | **/ |
152 | public void grow(int percent) |
153 | { |
154 | if (percent > 0) // cannot shrink |
155 | maxSize = maxSize * (100+percent)/100; |
156 | } |
157 | |
158 | /** |
159 | Clear all nodes that this allocator has allocated. |
160 | The allocator must already have been initialized. |
161 | **/ |
162 | public void reset() |
163 | { |
164 | if (array == null) |
165 | return; |
166 | for (int i = 0; i < nAllocated; i++) |
167 | array[i].reset(); |
168 | nAllocated = 0; |
169 | freeList = null; |
170 | } |
171 | |
172 | public void close() |
173 | { |
174 | array = null; |
175 | nAllocated = 0; |
176 | maxSize = 0; |
177 | freeList = null; |
178 | } |
179 | |
180 | public int capacity() |
181 | { |
182 | return maxSize; |
183 | } |
184 | } |