001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.lang.reflect.repository;
018:
019: import java.lang.reflect.TypeVariable;
020: import java.lang.reflect.GenericDeclaration;
021:
022: /**
023: * @author Serguei S. Zapreyev
024: * @version $Revision: 1.1.2.1 $
025: */
026:
027: /**
028: * (This all should be considered as an experimental approach which could be changed on
029: * java.lang.ref using)
030: *
031: * TypeVariableRepository keeps iformation about type variables.
032: *
033: * For now the following approach for keeping is realized.
034: * A concreet TV instance is included into repository if somebody do the *first* request for
035: * the reflect's method like Method.getGenericReturnType()->Class.MethodData.initGenericReturnType()
036: * (Field.getGenericType()->Field.FieldData.initGenericType()
037: * Method.getGenericExceptionTypes()->Class.MethodData.initGenericExceptionTypes()
038: * ...
039: * Constructor.getGenericParameterTypes()->Class.ConstructorData.initGenericParameterTypes()
040: * ...
041: * ). If the identical TV is accessed anyhow then the pointer from repository is used. However,
042: * further it can be removed from the repository if the cache is full under the new instance including.
043: * Then if reflect's request for such TV using the earlier used interface methods then the pointers
044: * to such instance kept within the Method/Constructor/Field/Class instances are returned just if it is
045: * absent within repository. But if we use other Method/Constructor/Field/Class instances to access
046: * to some instance of the same TV type which has been removed from repository then the new
047: * exemplar of instance is included into repository and the pointer to it is replicated if it needs
048: * into the new Method/Constructor/Field/Class instances.
049: * Another way to recreate some TV entry within repository is the AuxiliaryFinder.findTypeVariable() method
050: * which can recreate the removed instance getting it within Method/Constructor/Field/Class instances
051: * which were used to acces to the mentioned TV earlier.
052: *
053: * Maybe, it would be more convinient to realize another repository implementation
054: * where the accumulative approach will be used.
055: *
056: */
057: public final class TypeVariableRepository {
058:
059: static final class TypeVariableCache {
060:
061: /**
062: * This class realizes the TypeVariable repository which
063: * is just a cache. When the cache is exceeded at that time this experimental original cache algorithm (which, if
064: * it will justify hopes, should be combined in one for all type repositories here) rewrites the worst entity
065: * which can't be copied any more only recreated (as equal, of course). If the cache has an entity which
066: * the reflect supporting algorithm supposes to include there than the cache's algorithm copies the existing entity.
067: * If the cache is not full and an entity does not exist than there the cache's algorithm
068: * creates preliminary an entity and inserts it there.
069: * So, an earlier created type variable exists while the cache's algorithm has pointer[s] of it
070: * within the cache (entity has not removed yet during cleanings)
071: * or user's java code keeps pointer[s] of this type variable.
072: */
073:
074: private static class TVSSynchro {
075: };
076:
077: private static int cacheLenght = 2048;
078: private static TypeVariable cache[] = new TypeVariable[cacheLenght];
079: private static int counter = 0;
080: private static int worth[] = new int[cacheLenght];
081:
082: /**
083: * To delete the worst entry.
084: */
085: static int deleteTypeVariable() {
086: int min = -1;
087: int min2 = -1;
088:
089: synchronized (TVSSynchro.class) {
090: float minWorth = ((worth[0] >> 16) > 0 ? (worth[0] & 0xFFFF)
091: / worth[0] >> 16
092: : worth[0]);
093: int minWorth2 = worth[0];
094: float tmp;
095: int i = 0;
096: for (; i < cacheLenght; i++) {
097: try {
098: if ((tmp = (worth[i] & 0xFFFF) / worth[i] >> 16) <= minWorth) {
099: min = i;
100: minWorth = tmp;
101: }
102: } catch (ArithmeticException _) {
103: if ((tmp = worth[i]) <= minWorth2) {
104: min2 = i;
105: minWorth2 = (int) tmp;
106: }
107: }
108: }
109: if (i == cacheLenght && min == -1) {
110: min = min2;
111: }
112: cache[min] = null;
113: worth[min] = 0;
114: }
115: return min;
116: }
117:
118: /**
119: * To create new cache entry
120: */
121: static int insertTypeVariable(TypeVariable typeVariable, int ip) {
122: synchronized (TVSSynchro.class) {
123: if (ip < 0) {
124: for (int ind = 0; ind < cacheLenght; ind++) {
125: if (null == cache[ind]) {
126: cache[ind] = typeVariable;
127: worth[ind] = 1;
128: return ind;
129: }
130: }
131: return insertTypeVariable(typeVariable,
132: deleteTypeVariable());
133: } else {
134: cache[ip] = typeVariable;
135:
136: boolean flg = false;
137: short sv = (short) (worth[ip] & 0xFFFF);
138: if (sv == Short.MAX_VALUE - 1) {
139: flg = true; // to reduce
140: }
141: worth[ip] = (sv + 1) | (worth[ip] & 0xFFFF0000);
142: if (flg) {
143: try {
144: for (int ind = 0; ind < cacheLenght; ind++) { // reducing
145: short sv1 = (short) (worth[ind] >> 16);
146: short sv2 = (short) (worth[ind] & 0xFFFF);
147: worth[ind] = (sv2 == 1 ? 1 : sv2 >> 2)
148: | (((sv1 == 1 ? 1 : sv1 >> 2) + 1) << 16);
149: }
150: } catch (NullPointerException _) {
151: }
152: }
153: }
154: }
155: return ip;
156: }
157:
158: /**
159: * To return TypeVariable of cache.
160: */
161: static TypeVariable valueTypeVariable(String typeVariableName,
162: GenericDeclaration decl) {
163: synchronized (TVSSynchro.class) {
164: boolean flg = false;
165: if (counter == cacheLenght) { // Do smoke, it's time for reordering
166: try {
167: for (int ind = 0; ind < cacheLenght; ind++) {
168: short sv1 = (short) (worth[ind] >> 16);
169: if (sv1 == Short.MAX_VALUE - 1) {
170: flg = true; // to reduce
171: }
172: worth[ind] = worth[ind] & 0xFFFF
173: | ((sv1 + 1) << 16);
174: }
175: } catch (NullPointerException _) {
176: }
177: if (flg) {
178: try {
179: for (int ind = 0; ind < cacheLenght; ind++) { // reducing
180: short sv1 = (short) (worth[ind] >> 16);
181: short sv2 = (short) (worth[ind] & 0xFFFF);
182: worth[ind] = (sv2 == 1 ? 1 : sv2 >> 2)
183: | (((sv1 == 1 ? 1 : sv1 >> 2) + 1) << 16);
184: }
185: } catch (NullPointerException _) {
186: }
187: }
188: counter = 0;
189: } else {
190: counter++;
191: }
192: }
193: try {
194: for (int ind = 0; ind < cacheLenght; ind++) {
195: if (typeVariableName.equals(cache[ind].getName())
196: && decl.equals(cache[ind]
197: .getGenericDeclaration())) {
198: return cache[ind];
199: }
200: }
201: } catch (NullPointerException _) {
202: }
203: return null;
204: }
205: }
206:
207: /**
208: * This method returns a registered type variable if it exists within the repository.
209: *
210: * @param typeVariableName a name of a type variable.
211: * @param startPoint an instance of the Class, Method, Constructor or Field type to start the search
212: * of a type variable declaration place.
213: * @return the found type variable or null if it does not exist within repository.
214: */
215: public static TypeVariable findTypeVariable(
216: String typeVariableName, Object startPoint) {
217: return TypeVariableCache.valueTypeVariable(typeVariableName,
218: (GenericDeclaration) startPoint);
219: }
220:
221: /**
222: * This method registers a type variable within the repository.
223: *
224: * @param typeVariable a type variable.
225: * @param typeVariableName a name of a type variable.
226: * @param startPoint an instance of the Class, Method, Constructor or Field type to start the search
227: * of a type variable declaration place.
228: */
229: public static void registerTypeVariable(TypeVariable typeVariable,
230: String typeVariableName, Object startPoint) {
231: TypeVariableCache.insertTypeVariable(typeVariable, -1);
232: }
233: }
|