1 /* 2 * 3 * Copyright 2015 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #include <grpc/support/port_platform.h> 20 21 #include "src/core/lib/avl/avl.h" 22 23 #include <assert.h> 24 #include <stdlib.h> 25 26 #include <grpc/support/alloc.h> 27 #include <grpc/support/string_util.h> 28 29 #include "src/core/lib/gpr/useful.h" 30 31 grpc_avl grpc_avl_create(const grpc_avl_vtable* vtable) { 32 grpc_avl out; 33 out.vtable = vtable; 34 out.root = nullptr; 35 return out; 36 } 37 38 static grpc_avl_node* ref_node(grpc_avl_node* node) { 39 if (node) { 40 gpr_ref(&node->refs); 41 } 42 return node; 43 } 44 45 static void unref_node(const grpc_avl_vtable* vtable, grpc_avl_node* node, 46 void* user_data) { 47 if (node == nullptr) { 48 return; 49 } 50 if (gpr_unref(&node->refs)) { 51 vtable->destroy_key(node->key, user_data); 52 vtable->destroy_value(node->value, user_data); 53 unref_node(vtable, node->left, user_data); 54 unref_node(vtable, node->right, user_data); 55 gpr_free(node); 56 } 57 } 58 59 static long node_height(grpc_avl_node* node) { 60 return node == nullptr ? 0 : node->height; 61 } 62 63 #ifndef NDEBUG 64 static long calculate_height(grpc_avl_node* node) { 65 return node == nullptr ? 0 66 : 1 + GPR_MAX(calculate_height(node->left), 67 calculate_height(node->right)); 68 } 69 70 static grpc_avl_node* assert_invariants(grpc_avl_node* n) { 71 if (n == nullptr) return nullptr; 72 assert_invariants(n->left); 73 assert_invariants(n->right); 74 assert(calculate_height(n) == n->height); 75 assert(labs(node_height(n->left) - node_height(n->right)) <= 1); 76 return n; 77 } 78 #else 79 static grpc_avl_node* assert_invariants(grpc_avl_node* n) { return n; } 80 #endif 81 82 grpc_avl_node* new_node(void* key, void* value, grpc_avl_node* left, 83 grpc_avl_node* right) { 84 grpc_avl_node* node = static_cast<grpc_avl_node*>(gpr_malloc(sizeof(*node))); 85 gpr_ref_init(&node->refs, 1); 86 node->key = key; 87 node->value = value; 88 node->left = assert_invariants(left); 89 node->right = assert_invariants(right); 90 node->height = 1 + GPR_MAX(node_height(left), node_height(right)); 91 return node; 92 } 93 94 static grpc_avl_node* get(const grpc_avl_vtable* vtable, grpc_avl_node* node, 95 void* key, void* user_data) { 96 long cmp; 97 98 if (node == nullptr) { 99 return nullptr; 100 } 101 102 cmp = vtable->compare_keys(node->key, key, user_data); 103 if (cmp == 0) { 104 return node; 105 } else if (cmp > 0) { 106 return get(vtable, node->left, key, user_data); 107 } else { 108 return get(vtable, node->right, key, user_data); 109 } 110 } 111 112 void* grpc_avl_get(grpc_avl avl, void* key, void* user_data) { 113 grpc_avl_node* node = get(avl.vtable, avl.root, key, user_data); 114 return node ? node->value : nullptr; 115 } 116 117 int grpc_avl_maybe_get(grpc_avl avl, void* key, void** value, void* user_data) { 118 grpc_avl_node* node = get(avl.vtable, avl.root, key, user_data); 119 if (node != nullptr) { 120 *value = node->value; 121 return 1; 122 } 123 return 0; 124 } 125 126 static grpc_avl_node* rotate_left(const grpc_avl_vtable* vtable, void* key, 127 void* value, grpc_avl_node* left, 128 grpc_avl_node* right, void* user_data) { 129 grpc_avl_node* n = new_node(vtable->copy_key(right->key, user_data), 130 vtable->copy_value(right->value, user_data), 131 new_node(key, value, left, ref_node(right->left)), 132 ref_node(right->right)); 133 unref_node(vtable, right, user_data); 134 return n; 135 } 136 137 static grpc_avl_node* rotate_right(const grpc_avl_vtable* vtable, void* key, 138 void* value, grpc_avl_node* left, 139 grpc_avl_node* right, void* user_data) { 140 grpc_avl_node* n = 141 new_node(vtable->copy_key(left->key, user_data), 142 vtable->copy_value(left->value, user_data), ref_node(left->left), 143 new_node(key, value, ref_node(left->right), right)); 144 unref_node(vtable, left, user_data); 145 return n; 146 } 147 148 static grpc_avl_node* rotate_left_right(const grpc_avl_vtable* vtable, 149 void* key, void* value, 150 grpc_avl_node* left, 151 grpc_avl_node* right, void* user_data) { 152 /* rotate_right(..., rotate_left(left), right) */ 153 grpc_avl_node* n = 154 new_node(vtable->copy_key(left->right->key, user_data), 155 vtable->copy_value(left->right->value, user_data), 156 new_node(vtable->copy_key(left->key, user_data), 157 vtable->copy_value(left->value, user_data), 158 ref_node(left->left), ref_node(left->right->left)), 159 new_node(key, value, ref_node(left->right->right), right)); 160 unref_node(vtable, left, user_data); 161 return n; 162 } 163 164 static grpc_avl_node* rotate_right_left(const grpc_avl_vtable* vtable, 165 void* key, void* value, 166 grpc_avl_node* left, 167 grpc_avl_node* right, void* user_data) { 168 /* rotate_left(..., left, rotate_right(right)) */ 169 grpc_avl_node* n = 170 new_node(vtable->copy_key(right->left->key, user_data), 171 vtable->copy_value(right->left->value, user_data), 172 new_node(key, value, left, ref_node(right->left->left)), 173 new_node(vtable->copy_key(right->key, user_data), 174 vtable->copy_value(right->value, user_data), 175 ref_node(right->left->right), ref_node(right->right))); 176 unref_node(vtable, right, user_data); 177 return n; 178 } 179 180 static grpc_avl_node* rebalance(const grpc_avl_vtable* vtable, void* key, 181 void* value, grpc_avl_node* left, 182 grpc_avl_node* right, void* user_data) { 183 switch (node_height(left) - node_height(right)) { 184 case 2: 185 if (node_height(left->left) - node_height(left->right) == -1) { 186 return assert_invariants( 187 rotate_left_right(vtable, key, value, left, right, user_data)); 188 } else { 189 return assert_invariants( 190 rotate_right(vtable, key, value, left, right, user_data)); 191 } 192 case -2: 193 if (node_height(right->left) - node_height(right->right) == 1) { 194 return assert_invariants( 195 rotate_right_left(vtable, key, value, left, right, user_data)); 196 } else { 197 return assert_invariants( 198 rotate_left(vtable, key, value, left, right, user_data)); 199 } 200 default: 201 return assert_invariants(new_node(key, value, left, right)); 202 } 203 } 204 205 static grpc_avl_node* add_key(const grpc_avl_vtable* vtable, 206 grpc_avl_node* node, void* key, void* value, 207 void* user_data) { 208 long cmp; 209 if (node == nullptr) { 210 return new_node(key, value, nullptr, nullptr); 211 } 212 cmp = vtable->compare_keys(node->key, key, user_data); 213 if (cmp == 0) { 214 return new_node(key, value, ref_node(node->left), ref_node(node->right)); 215 } else if (cmp > 0) { 216 return rebalance(vtable, vtable->copy_key(node->key, user_data), 217 vtable->copy_value(node->value, user_data), 218 add_key(vtable, node->left, key, value, user_data), 219 ref_node(node->right), user_data); 220 } else { 221 return rebalance( 222 vtable, vtable->copy_key(node->key, user_data), 223 vtable->copy_value(node->value, user_data), ref_node(node->left), 224 add_key(vtable, node->right, key, value, user_data), user_data); 225 } 226 } 227 228 grpc_avl grpc_avl_add(grpc_avl avl, void* key, void* value, void* user_data) { 229 grpc_avl_node* old_root = avl.root; 230 avl.root = add_key(avl.vtable, avl.root, key, value, user_data); 231 assert_invariants(avl.root); 232 unref_node(avl.vtable, old_root, user_data); 233 return avl; 234 } 235 236 static grpc_avl_node* in_order_head(grpc_avl_node* node) { 237 while (node->left != nullptr) { 238 node = node->left; 239 } 240 return node; 241 } 242 243 static grpc_avl_node* in_order_tail(grpc_avl_node* node) { 244 while (node->right != nullptr) { 245 node = node->right; 246 } 247 return node; 248 } 249 250 static grpc_avl_node* remove_key(const grpc_avl_vtable* vtable, 251 grpc_avl_node* node, void* key, 252 void* user_data) { 253 long cmp; 254 if (node == nullptr) { 255 return nullptr; 256 } 257 cmp = vtable->compare_keys(node->key, key, user_data); 258 if (cmp == 0) { 259 if (node->left == nullptr) { 260 return ref_node(node->right); 261 } else if (node->right == nullptr) { 262 return ref_node(node->left); 263 } else if (node->left->height < node->right->height) { 264 grpc_avl_node* h = in_order_head(node->right); 265 return rebalance( 266 vtable, vtable->copy_key(h->key, user_data), 267 vtable->copy_value(h->value, user_data), ref_node(node->left), 268 remove_key(vtable, node->right, h->key, user_data), user_data); 269 } else { 270 grpc_avl_node* h = in_order_tail(node->left); 271 return rebalance(vtable, vtable->copy_key(h->key, user_data), 272 vtable->copy_value(h->value, user_data), 273 remove_key(vtable, node->left, h->key, user_data), 274 ref_node(node->right), user_data); 275 } 276 } else if (cmp > 0) { 277 return rebalance(vtable, vtable->copy_key(node->key, user_data), 278 vtable->copy_value(node->value, user_data), 279 remove_key(vtable, node->left, key, user_data), 280 ref_node(node->right), user_data); 281 } else { 282 return rebalance( 283 vtable, vtable->copy_key(node->key, user_data), 284 vtable->copy_value(node->value, user_data), ref_node(node->left), 285 remove_key(vtable, node->right, key, user_data), user_data); 286 } 287 } 288 289 grpc_avl grpc_avl_remove(grpc_avl avl, void* key, void* user_data) { 290 grpc_avl_node* old_root = avl.root; 291 avl.root = remove_key(avl.vtable, avl.root, key, user_data); 292 assert_invariants(avl.root); 293 unref_node(avl.vtable, old_root, user_data); 294 return avl; 295 } 296 297 grpc_avl grpc_avl_ref(grpc_avl avl, void* user_data) { 298 ref_node(avl.root); 299 return avl; 300 } 301 302 void grpc_avl_unref(grpc_avl avl, void* user_data) { 303 unref_node(avl.vtable, avl.root, user_data); 304 } 305 306 int grpc_avl_is_empty(grpc_avl avl) { return avl.root == nullptr; } 307