1 /* 2 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.jfr.consumer; 27 28 import java.util.ArrayList; 29 import java.util.List; 30 31 /** 32 * Holds mapping between a set of keys and their corresponding object. 33 * 34 * If the type is a known type, i.e. {@link RecordedThread}, an 35 * {@link ObjectFactory} can be supplied which will instantiate a typed object. 36 */ 37 final class ConstantMap { 38 private final static class Reference { 39 private final long key; 40 private final ConstantMap pool; 41 42 Reference(ConstantMap pool, long key) { 43 this.pool = pool; 44 this.key = key; 45 } 46 47 Object resolve() { 48 return pool.get(key); 49 } 50 } 51 52 private final ObjectFactory<?> factory; 53 private final LongMap<Object> objects; 54 55 private LongMap<Boolean> isResolving; 56 private boolean allResolved; 57 private String name; 58 59 ConstantMap(ObjectFactory<?> factory, String name) { 60 this.name = name; 61 this.objects = new LongMap<>(); 62 this.factory = factory; 63 } 64 65 Object get(long id) { 66 // fast path, all objects in pool resolved 67 if (allResolved) { 68 return objects.get(id); 69 } 70 // referenced from a pool, deal with this later 71 if (isResolving == null) { 72 return new Reference(this, id); 73 } 74 75 Boolean beingResolved = isResolving.get(id); 76 77 // we are resolved (but not the whole pool) 78 if (Boolean.FALSE.equals(beingResolved)) { 79 return objects.get(id); 80 } 81 82 // resolving ourself, abort to avoid infinite recursion 83 if (Boolean.TRUE.equals(beingResolved)) { 84 return null; 85 } 86 87 // resolve me! 88 isResolving.put(id, Boolean.TRUE); 89 Object resolved = resolve(objects.get(id)); 90 isResolving.put(id, Boolean.FALSE); 91 if (factory != null) { 92 Object factorized = factory.createObject(id, resolved); 93 objects.put(id, factorized); 94 return factorized; 95 } else { 96 objects.put(id, resolved); 97 return resolved; 98 } 99 } 100 101 private static Object resolve(Object o) { 102 if (o instanceof Reference) { 103 return resolve(((Reference) o).resolve()); 104 } 105 if (o != null && o.getClass().isArray()) { 106 final Object[] array = (Object[]) o; 107 for (int i = 0; i < array.length; i++) { 108 array[i] = resolve(array[i]); 109 } 110 return array; 111 } 112 return o; 113 } 114 115 public void resolve() { 116 List<Long> keyList = new ArrayList<>(); 117 objects.keys().forEachRemaining(keyList::add); 118 for (Long l : keyList) { 119 get(l); 120 } 121 } 122 123 public void put(long key, Object value) { 124 objects.put(key, value); 125 } 126 127 public void setIsResolving() { 128 isResolving = new LongMap<>(); 129 } 130 131 public void setResolved() { 132 allResolved = true; 133 isResolving = null; // pool finished, release memory 134 } 135 136 public String getName() { 137 return name; 138 } 139 }