1 /* 2 * Copyright (c) 2012, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_VM_UTILITIES_RESOURCEHASH_HPP 26 #define SHARE_VM_UTILITIES_RESOURCEHASH_HPP 27 28 #include "memory/allocation.hpp" 29 30 template<typename K> struct ResourceHashtableFns { 31 typedef unsigned (*hash_fn)(K const&); 32 typedef bool (*equals_fn)(K const&, K const&); 33 }; 34 35 template< 36 typename K, typename V, 37 // xlC does not compile this: 38 // http://stackoverflow.com/questions/8532961/template-argument-of-type-that-is-defined-by-inner-typedef-from-other-template-c 39 //typename ResourceHashtableFns<K>::hash_fn HASH = primitive_hash<K>, 40 //typename ResourceHashtableFns<K>::equals_fn EQUALS = primitive_equals<K>, 41 unsigned (*HASH) (K const&) = primitive_hash<K>, 42 bool (*EQUALS)(K const&, K const&) = primitive_equals<K>, 43 unsigned SIZE = 256, 44 ResourceObj::allocation_type ALLOC_TYPE = ResourceObj::RESOURCE_AREA, 45 MEMFLAGS MEM_TYPE = mtInternal 46 > 47 class ResourceHashtable : public ResourceObj { 48 private: 49 50 class Node : public ResourceObj { 51 public: 52 unsigned _hash; 53 K _key; 54 V _value; 55 Node* _next; 56 57 Node(unsigned hash, K const& key, V const& value) : 58 _hash(hash), _key(key), _value(value), _next(NULL) {} 59 }; 60 61 Node* _table[SIZE]; 62 63 // Returns a pointer to where the node where the value would reside if 64 // it's in the table. 65 Node** lookup_node(unsigned hash, K const& key) { 66 unsigned index = hash % SIZE; 67 Node** ptr = &_table[index]; 68 while (*ptr != NULL) { 69 Node* node = *ptr; 70 if (node->_hash == hash && EQUALS(key, node->_key)) { 71 break; 72 } 73 ptr = &(node->_next); 74 } 75 return ptr; 76 } 77 78 Node const** lookup_node(unsigned hash, K const& key) const { 79 return const_cast<Node const**>( 80 const_cast<ResourceHashtable*>(this)->lookup_node(hash, key)); 81 } 82 83 public: 84 ResourceHashtable() { memset(_table, 0, SIZE * sizeof(Node*)); } 85 86 ~ResourceHashtable() { 87 if (ALLOC_TYPE == C_HEAP) { 88 Node* const* bucket = _table; 89 while (bucket < &_table[SIZE]) { 90 Node* node = *bucket; 91 while (node != NULL) { 92 Node* cur = node; 93 node = node->_next; 94 delete cur; 95 } 96 ++bucket; 97 } 98 } 99 } 100 101 bool contains(K const& key) const { 102 return get(key) != NULL; 103 } 104 105 V* get(K const& key) const { 106 unsigned hv = HASH(key); 107 Node const** ptr = lookup_node(hv, key); 108 if (*ptr != NULL) { 109 return const_cast<V*>(&(*ptr)->_value); 110 } else { 111 return NULL; 112 } 113 } 114 115 /** 116 * Inserts or replaces a value in the table. 117 * @return: true: if a new item is added 118 * false: if the item already existed and the value is updated 119 */ 120 bool put(K const& key, V const& value) { 121 unsigned hv = HASH(key); 122 Node** ptr = lookup_node(hv, key); 123 if (*ptr != NULL) { 124 (*ptr)->_value = value; 125 return false; 126 } else { 127 *ptr = new (ALLOC_TYPE, MEM_TYPE) Node(hv, key, value); 128 return true; 129 } 130 } 131 132 bool remove(K const& key) { 133 unsigned hv = HASH(key); 134 Node** ptr = lookup_node(hv, key); 135 136 Node* node = *ptr; 137 if (node != NULL) { 138 *ptr = node->_next; 139 if (ALLOC_TYPE == C_HEAP) { 140 delete node; 141 } 142 return true; 143 } 144 return false; 145 } 146 147 // ITER contains bool do_entry(K const&, V const&), which will be 148 // called for each entry in the table. If do_entry() returns false, 149 // the iteration is cancelled. 150 template<class ITER> 151 void iterate(ITER* iter) const { 152 Node* const* bucket = _table; 153 while (bucket < &_table[SIZE]) { 154 Node* node = *bucket; 155 while (node != NULL) { 156 bool cont = iter->do_entry(node->_key, node->_value); 157 if (!cont) { return; } 158 node = node->_next; 159 } 160 ++bucket; 161 } 162 } 163 164 static size_t node_size() { 165 return sizeof(Node); 166 } 167 }; 168 169 170 #endif // SHARE_VM_UTILITIES_RESOURCEHASH_HPP