1*d6b92ffaSHans Petter Selasky /* 2*d6b92ffaSHans Petter Selasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. 3*d6b92ffaSHans Petter Selasky * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4*d6b92ffaSHans Petter Selasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5*d6b92ffaSHans Petter Selasky * 6*d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two 7*d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU 8*d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file 9*d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the 10*d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below: 11*d6b92ffaSHans Petter Selasky * 12*d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or 13*d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following 14*d6b92ffaSHans Petter Selasky * conditions are met: 15*d6b92ffaSHans Petter Selasky * 16*d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above 17*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 18*d6b92ffaSHans Petter Selasky * disclaimer. 19*d6b92ffaSHans Petter Selasky * 20*d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above 21*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 22*d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials 23*d6b92ffaSHans Petter Selasky * provided with the distribution. 24*d6b92ffaSHans Petter Selasky * 25*d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26*d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27*d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28*d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29*d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30*d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31*d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32*d6b92ffaSHans Petter Selasky * SOFTWARE. 33*d6b92ffaSHans Petter Selasky * 34*d6b92ffaSHans Petter Selasky */ 35*d6b92ffaSHans Petter Selasky 36*d6b92ffaSHans Petter Selasky /* 37*d6b92ffaSHans Petter Selasky * Abstract: 38*d6b92ffaSHans Petter Selasky * Implementation of quick map, a binary tree where the caller always 39*d6b92ffaSHans Petter Selasky * provides all necessary storage. 40*d6b92ffaSHans Petter Selasky * 41*d6b92ffaSHans Petter Selasky */ 42*d6b92ffaSHans Petter Selasky 43*d6b92ffaSHans Petter Selasky /***************************************************************************** 44*d6b92ffaSHans Petter Selasky * 45*d6b92ffaSHans Petter Selasky * Map 46*d6b92ffaSHans Petter Selasky * 47*d6b92ffaSHans Petter Selasky * Map is an associative array. By providing a key, the caller can retrieve 48*d6b92ffaSHans Petter Selasky * an object from the map. All objects in the map have an associated key, 49*d6b92ffaSHans Petter Selasky * as specified by the caller when the object was inserted into the map. 50*d6b92ffaSHans Petter Selasky * In addition to random access, the caller can traverse the map much like 51*d6b92ffaSHans Petter Selasky * a linked list, either forwards from the first object or backwards from 52*d6b92ffaSHans Petter Selasky * the last object. The objects in the map are always traversed in 53*d6b92ffaSHans Petter Selasky * order since the nodes are stored sorted. 54*d6b92ffaSHans Petter Selasky * 55*d6b92ffaSHans Petter Selasky * This implementation of Map uses a red black tree verified against 56*d6b92ffaSHans Petter Selasky * Cormen-Leiserson-Rivest text, McGraw-Hill Edition, fourteenth 57*d6b92ffaSHans Petter Selasky * printing, 1994. 58*d6b92ffaSHans Petter Selasky * 59*d6b92ffaSHans Petter Selasky *****************************************************************************/ 60*d6b92ffaSHans Petter Selasky 61*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H 62*d6b92ffaSHans Petter Selasky # include <config.h> 63*d6b92ffaSHans Petter Selasky #endif /* HAVE_CONFIG_H */ 64*d6b92ffaSHans Petter Selasky 65*d6b92ffaSHans Petter Selasky #include <string.h> 66*d6b92ffaSHans Petter Selasky #include <complib/cl_qmap.h> 67*d6b92ffaSHans Petter Selasky #include <complib/cl_map.h> 68*d6b92ffaSHans Petter Selasky #include <complib/cl_fleximap.h> 69*d6b92ffaSHans Petter Selasky 70*d6b92ffaSHans Petter Selasky /****************************************************************************** 71*d6b92ffaSHans Petter Selasky IMPLEMENTATION OF QUICK MAP 72*d6b92ffaSHans Petter Selasky ******************************************************************************/ 73*d6b92ffaSHans Petter Selasky 74*d6b92ffaSHans Petter Selasky /* 75*d6b92ffaSHans Petter Selasky * Get the root. 76*d6b92ffaSHans Petter Selasky */ 77*d6b92ffaSHans Petter Selasky static inline cl_map_item_t *__cl_map_root(IN const cl_qmap_t * const p_map) 78*d6b92ffaSHans Petter Selasky { 79*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 80*d6b92ffaSHans Petter Selasky return (p_map->root.p_left); 81*d6b92ffaSHans Petter Selasky } 82*d6b92ffaSHans Petter Selasky 83*d6b92ffaSHans Petter Selasky /* 84*d6b92ffaSHans Petter Selasky * Returns whether a given item is on the left of its parent. 85*d6b92ffaSHans Petter Selasky */ 86*d6b92ffaSHans Petter Selasky static boolean_t __cl_map_is_left_child(IN const cl_map_item_t * const p_item) 87*d6b92ffaSHans Petter Selasky { 88*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 89*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up); 90*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up != p_item); 91*d6b92ffaSHans Petter Selasky 92*d6b92ffaSHans Petter Selasky return (p_item->p_up->p_left == p_item); 93*d6b92ffaSHans Petter Selasky } 94*d6b92ffaSHans Petter Selasky 95*d6b92ffaSHans Petter Selasky /* 96*d6b92ffaSHans Petter Selasky * Retrieve the pointer to the parent's pointer to an item. 97*d6b92ffaSHans Petter Selasky */ 98*d6b92ffaSHans Petter Selasky static cl_map_item_t **__cl_map_get_parent_ptr_to_item(IN cl_map_item_t * 99*d6b92ffaSHans Petter Selasky const p_item) 100*d6b92ffaSHans Petter Selasky { 101*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 102*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up); 103*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up != p_item); 104*d6b92ffaSHans Petter Selasky 105*d6b92ffaSHans Petter Selasky if (__cl_map_is_left_child(p_item)) 106*d6b92ffaSHans Petter Selasky return (&p_item->p_up->p_left); 107*d6b92ffaSHans Petter Selasky 108*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up->p_right == p_item); 109*d6b92ffaSHans Petter Selasky return (&p_item->p_up->p_right); 110*d6b92ffaSHans Petter Selasky } 111*d6b92ffaSHans Petter Selasky 112*d6b92ffaSHans Petter Selasky /* 113*d6b92ffaSHans Petter Selasky * Rotate a node to the left. This rotation affects the least number of links 114*d6b92ffaSHans Petter Selasky * between nodes and brings the level of C up by one while increasing the depth 115*d6b92ffaSHans Petter Selasky * of A one. Note that the links to/from W, X, Y, and Z are not affected. 116*d6b92ffaSHans Petter Selasky * 117*d6b92ffaSHans Petter Selasky * R R 118*d6b92ffaSHans Petter Selasky * | | 119*d6b92ffaSHans Petter Selasky * A C 120*d6b92ffaSHans Petter Selasky * / \ / \ 121*d6b92ffaSHans Petter Selasky * W C A Z 122*d6b92ffaSHans Petter Selasky * / \ / \ 123*d6b92ffaSHans Petter Selasky * B Z W B 124*d6b92ffaSHans Petter Selasky * / \ / \ 125*d6b92ffaSHans Petter Selasky * X Y X Y 126*d6b92ffaSHans Petter Selasky */ 127*d6b92ffaSHans Petter Selasky static void __cl_map_rot_left(IN cl_qmap_t * const p_map, 128*d6b92ffaSHans Petter Selasky IN cl_map_item_t * const p_item) 129*d6b92ffaSHans Petter Selasky { 130*d6b92ffaSHans Petter Selasky cl_map_item_t **pp_root; 131*d6b92ffaSHans Petter Selasky 132*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 133*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 134*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_right != &p_map->nil); 135*d6b92ffaSHans Petter Selasky 136*d6b92ffaSHans Petter Selasky pp_root = __cl_map_get_parent_ptr_to_item(p_item); 137*d6b92ffaSHans Petter Selasky 138*d6b92ffaSHans Petter Selasky /* Point R to C instead of A. */ 139*d6b92ffaSHans Petter Selasky *pp_root = p_item->p_right; 140*d6b92ffaSHans Petter Selasky /* Set C's parent to R. */ 141*d6b92ffaSHans Petter Selasky (*pp_root)->p_up = p_item->p_up; 142*d6b92ffaSHans Petter Selasky 143*d6b92ffaSHans Petter Selasky /* Set A's right to B */ 144*d6b92ffaSHans Petter Selasky p_item->p_right = (*pp_root)->p_left; 145*d6b92ffaSHans Petter Selasky /* 146*d6b92ffaSHans Petter Selasky * Set B's parent to A. We trap for B being NIL since the 147*d6b92ffaSHans Petter Selasky * caller may depend on NIL not changing. 148*d6b92ffaSHans Petter Selasky */ 149*d6b92ffaSHans Petter Selasky if ((*pp_root)->p_left != &p_map->nil) 150*d6b92ffaSHans Petter Selasky (*pp_root)->p_left->p_up = p_item; 151*d6b92ffaSHans Petter Selasky 152*d6b92ffaSHans Petter Selasky /* Set C's left to A. */ 153*d6b92ffaSHans Petter Selasky (*pp_root)->p_left = p_item; 154*d6b92ffaSHans Petter Selasky /* Set A's parent to C. */ 155*d6b92ffaSHans Petter Selasky p_item->p_up = *pp_root; 156*d6b92ffaSHans Petter Selasky } 157*d6b92ffaSHans Petter Selasky 158*d6b92ffaSHans Petter Selasky /* 159*d6b92ffaSHans Petter Selasky * Rotate a node to the right. This rotation affects the least number of links 160*d6b92ffaSHans Petter Selasky * between nodes and brings the level of A up by one while increasing the depth 161*d6b92ffaSHans Petter Selasky * of C one. Note that the links to/from W, X, Y, and Z are not affected. 162*d6b92ffaSHans Petter Selasky * 163*d6b92ffaSHans Petter Selasky * R R 164*d6b92ffaSHans Petter Selasky * | | 165*d6b92ffaSHans Petter Selasky * C A 166*d6b92ffaSHans Petter Selasky * / \ / \ 167*d6b92ffaSHans Petter Selasky * A Z W C 168*d6b92ffaSHans Petter Selasky * / \ / \ 169*d6b92ffaSHans Petter Selasky * W B B Z 170*d6b92ffaSHans Petter Selasky * / \ / \ 171*d6b92ffaSHans Petter Selasky * X Y X Y 172*d6b92ffaSHans Petter Selasky */ 173*d6b92ffaSHans Petter Selasky static void __cl_map_rot_right(IN cl_qmap_t * const p_map, 174*d6b92ffaSHans Petter Selasky IN cl_map_item_t * const p_item) 175*d6b92ffaSHans Petter Selasky { 176*d6b92ffaSHans Petter Selasky cl_map_item_t **pp_root; 177*d6b92ffaSHans Petter Selasky 178*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 179*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 180*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_left != &p_map->nil); 181*d6b92ffaSHans Petter Selasky 182*d6b92ffaSHans Petter Selasky /* Point R to A instead of C. */ 183*d6b92ffaSHans Petter Selasky pp_root = __cl_map_get_parent_ptr_to_item(p_item); 184*d6b92ffaSHans Petter Selasky (*pp_root) = p_item->p_left; 185*d6b92ffaSHans Petter Selasky /* Set A's parent to R. */ 186*d6b92ffaSHans Petter Selasky (*pp_root)->p_up = p_item->p_up; 187*d6b92ffaSHans Petter Selasky 188*d6b92ffaSHans Petter Selasky /* Set C's left to B */ 189*d6b92ffaSHans Petter Selasky p_item->p_left = (*pp_root)->p_right; 190*d6b92ffaSHans Petter Selasky /* 191*d6b92ffaSHans Petter Selasky * Set B's parent to C. We trap for B being NIL since the 192*d6b92ffaSHans Petter Selasky * caller may depend on NIL not changing. 193*d6b92ffaSHans Petter Selasky */ 194*d6b92ffaSHans Petter Selasky if ((*pp_root)->p_right != &p_map->nil) 195*d6b92ffaSHans Petter Selasky (*pp_root)->p_right->p_up = p_item; 196*d6b92ffaSHans Petter Selasky 197*d6b92ffaSHans Petter Selasky /* Set A's right to C. */ 198*d6b92ffaSHans Petter Selasky (*pp_root)->p_right = p_item; 199*d6b92ffaSHans Petter Selasky /* Set C's parent to A. */ 200*d6b92ffaSHans Petter Selasky p_item->p_up = *pp_root; 201*d6b92ffaSHans Petter Selasky } 202*d6b92ffaSHans Petter Selasky 203*d6b92ffaSHans Petter Selasky void cl_qmap_init(IN cl_qmap_t * const p_map) 204*d6b92ffaSHans Petter Selasky { 205*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 206*d6b92ffaSHans Petter Selasky 207*d6b92ffaSHans Petter Selasky memset(p_map, 0, sizeof(cl_qmap_t)); 208*d6b92ffaSHans Petter Selasky 209*d6b92ffaSHans Petter Selasky /* special setup for the root node */ 210*d6b92ffaSHans Petter Selasky p_map->root.p_up = &p_map->root; 211*d6b92ffaSHans Petter Selasky p_map->root.p_left = &p_map->nil; 212*d6b92ffaSHans Petter Selasky p_map->root.p_right = &p_map->nil; 213*d6b92ffaSHans Petter Selasky p_map->root.color = CL_MAP_BLACK; 214*d6b92ffaSHans Petter Selasky 215*d6b92ffaSHans Petter Selasky /* Setup the node used as terminator for all leaves. */ 216*d6b92ffaSHans Petter Selasky p_map->nil.p_up = &p_map->nil; 217*d6b92ffaSHans Petter Selasky p_map->nil.p_left = &p_map->nil; 218*d6b92ffaSHans Petter Selasky p_map->nil.p_right = &p_map->nil; 219*d6b92ffaSHans Petter Selasky p_map->nil.color = CL_MAP_BLACK; 220*d6b92ffaSHans Petter Selasky 221*d6b92ffaSHans Petter Selasky p_map->state = CL_INITIALIZED; 222*d6b92ffaSHans Petter Selasky 223*d6b92ffaSHans Petter Selasky cl_qmap_remove_all(p_map); 224*d6b92ffaSHans Petter Selasky } 225*d6b92ffaSHans Petter Selasky 226*d6b92ffaSHans Petter Selasky cl_map_item_t *cl_qmap_get(IN const cl_qmap_t * const p_map, 227*d6b92ffaSHans Petter Selasky IN const uint64_t key) 228*d6b92ffaSHans Petter Selasky { 229*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item; 230*d6b92ffaSHans Petter Selasky 231*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 232*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 233*d6b92ffaSHans Petter Selasky 234*d6b92ffaSHans Petter Selasky p_item = __cl_map_root(p_map); 235*d6b92ffaSHans Petter Selasky 236*d6b92ffaSHans Petter Selasky while (p_item != &p_map->nil) { 237*d6b92ffaSHans Petter Selasky if (key == p_item->key) 238*d6b92ffaSHans Petter Selasky break; /* just right */ 239*d6b92ffaSHans Petter Selasky 240*d6b92ffaSHans Petter Selasky if (key < p_item->key) 241*d6b92ffaSHans Petter Selasky p_item = p_item->p_left; /* too small */ 242*d6b92ffaSHans Petter Selasky else 243*d6b92ffaSHans Petter Selasky p_item = p_item->p_right; /* too big */ 244*d6b92ffaSHans Petter Selasky } 245*d6b92ffaSHans Petter Selasky 246*d6b92ffaSHans Petter Selasky return (p_item); 247*d6b92ffaSHans Petter Selasky } 248*d6b92ffaSHans Petter Selasky 249*d6b92ffaSHans Petter Selasky cl_map_item_t *cl_qmap_get_next(IN const cl_qmap_t * const p_map, 250*d6b92ffaSHans Petter Selasky IN const uint64_t key) 251*d6b92ffaSHans Petter Selasky { 252*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item; 253*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item_found; 254*d6b92ffaSHans Petter Selasky 255*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 256*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 257*d6b92ffaSHans Petter Selasky 258*d6b92ffaSHans Petter Selasky p_item = __cl_map_root(p_map); 259*d6b92ffaSHans Petter Selasky p_item_found = (cl_map_item_t *) & p_map->nil; 260*d6b92ffaSHans Petter Selasky 261*d6b92ffaSHans Petter Selasky while (p_item != &p_map->nil) { 262*d6b92ffaSHans Petter Selasky if (key < p_item->key) { 263*d6b92ffaSHans Petter Selasky p_item_found = p_item; 264*d6b92ffaSHans Petter Selasky p_item = p_item->p_left; 265*d6b92ffaSHans Petter Selasky } else { 266*d6b92ffaSHans Petter Selasky p_item = p_item->p_right; 267*d6b92ffaSHans Petter Selasky } 268*d6b92ffaSHans Petter Selasky } 269*d6b92ffaSHans Petter Selasky 270*d6b92ffaSHans Petter Selasky return (p_item_found); 271*d6b92ffaSHans Petter Selasky } 272*d6b92ffaSHans Petter Selasky 273*d6b92ffaSHans Petter Selasky void cl_qmap_apply_func(IN const cl_qmap_t * const p_map, 274*d6b92ffaSHans Petter Selasky IN cl_pfn_qmap_apply_t pfn_func, 275*d6b92ffaSHans Petter Selasky IN const void *const context) 276*d6b92ffaSHans Petter Selasky { 277*d6b92ffaSHans Petter Selasky cl_map_item_t *p_map_item; 278*d6b92ffaSHans Petter Selasky 279*d6b92ffaSHans Petter Selasky /* Note that context can have any arbitrary value. */ 280*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 281*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 282*d6b92ffaSHans Petter Selasky CL_ASSERT(pfn_func); 283*d6b92ffaSHans Petter Selasky 284*d6b92ffaSHans Petter Selasky p_map_item = cl_qmap_head(p_map); 285*d6b92ffaSHans Petter Selasky while (p_map_item != cl_qmap_end(p_map)) { 286*d6b92ffaSHans Petter Selasky pfn_func(p_map_item, (void *)context); 287*d6b92ffaSHans Petter Selasky p_map_item = cl_qmap_next(p_map_item); 288*d6b92ffaSHans Petter Selasky } 289*d6b92ffaSHans Petter Selasky } 290*d6b92ffaSHans Petter Selasky 291*d6b92ffaSHans Petter Selasky /* 292*d6b92ffaSHans Petter Selasky * Balance a tree starting at a given item back to the root. 293*d6b92ffaSHans Petter Selasky */ 294*d6b92ffaSHans Petter Selasky static void __cl_map_ins_bal(IN cl_qmap_t * const p_map, 295*d6b92ffaSHans Petter Selasky IN cl_map_item_t * p_item) 296*d6b92ffaSHans Petter Selasky { 297*d6b92ffaSHans Petter Selasky cl_map_item_t *p_grand_uncle; 298*d6b92ffaSHans Petter Selasky 299*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 300*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 301*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item != &p_map->root); 302*d6b92ffaSHans Petter Selasky 303*d6b92ffaSHans Petter Selasky while (p_item->p_up->color == CL_MAP_RED) { 304*d6b92ffaSHans Petter Selasky if (__cl_map_is_left_child(p_item->p_up)) { 305*d6b92ffaSHans Petter Selasky p_grand_uncle = p_item->p_up->p_up->p_right; 306*d6b92ffaSHans Petter Selasky CL_ASSERT(p_grand_uncle); 307*d6b92ffaSHans Petter Selasky if (p_grand_uncle->color == CL_MAP_RED) { 308*d6b92ffaSHans Petter Selasky p_grand_uncle->color = CL_MAP_BLACK; 309*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 310*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED; 311*d6b92ffaSHans Petter Selasky p_item = p_item->p_up->p_up; 312*d6b92ffaSHans Petter Selasky continue; 313*d6b92ffaSHans Petter Selasky } 314*d6b92ffaSHans Petter Selasky 315*d6b92ffaSHans Petter Selasky if (!__cl_map_is_left_child(p_item)) { 316*d6b92ffaSHans Petter Selasky p_item = p_item->p_up; 317*d6b92ffaSHans Petter Selasky __cl_map_rot_left(p_map, p_item); 318*d6b92ffaSHans Petter Selasky } 319*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 320*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED; 321*d6b92ffaSHans Petter Selasky __cl_map_rot_right(p_map, p_item->p_up->p_up); 322*d6b92ffaSHans Petter Selasky } else { 323*d6b92ffaSHans Petter Selasky p_grand_uncle = p_item->p_up->p_up->p_left; 324*d6b92ffaSHans Petter Selasky CL_ASSERT(p_grand_uncle); 325*d6b92ffaSHans Petter Selasky if (p_grand_uncle->color == CL_MAP_RED) { 326*d6b92ffaSHans Petter Selasky p_grand_uncle->color = CL_MAP_BLACK; 327*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 328*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED; 329*d6b92ffaSHans Petter Selasky p_item = p_item->p_up->p_up; 330*d6b92ffaSHans Petter Selasky continue; 331*d6b92ffaSHans Petter Selasky } 332*d6b92ffaSHans Petter Selasky 333*d6b92ffaSHans Petter Selasky if (__cl_map_is_left_child(p_item)) { 334*d6b92ffaSHans Petter Selasky p_item = p_item->p_up; 335*d6b92ffaSHans Petter Selasky __cl_map_rot_right(p_map, p_item); 336*d6b92ffaSHans Petter Selasky } 337*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 338*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED; 339*d6b92ffaSHans Petter Selasky __cl_map_rot_left(p_map, p_item->p_up->p_up); 340*d6b92ffaSHans Petter Selasky } 341*d6b92ffaSHans Petter Selasky } 342*d6b92ffaSHans Petter Selasky } 343*d6b92ffaSHans Petter Selasky 344*d6b92ffaSHans Petter Selasky cl_map_item_t *cl_qmap_insert(IN cl_qmap_t * const p_map, 345*d6b92ffaSHans Petter Selasky IN const uint64_t key, 346*d6b92ffaSHans Petter Selasky IN cl_map_item_t * const p_item) 347*d6b92ffaSHans Petter Selasky { 348*d6b92ffaSHans Petter Selasky cl_map_item_t *p_insert_at, *p_comp_item; 349*d6b92ffaSHans Petter Selasky 350*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 351*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 352*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 353*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->root.p_up == &p_map->root); 354*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->root.color != CL_MAP_RED); 355*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->nil.color != CL_MAP_RED); 356*d6b92ffaSHans Petter Selasky 357*d6b92ffaSHans Petter Selasky p_item->p_left = &p_map->nil; 358*d6b92ffaSHans Petter Selasky p_item->p_right = &p_map->nil; 359*d6b92ffaSHans Petter Selasky p_item->key = key; 360*d6b92ffaSHans Petter Selasky p_item->color = CL_MAP_RED; 361*d6b92ffaSHans Petter Selasky 362*d6b92ffaSHans Petter Selasky /* Find the insertion location. */ 363*d6b92ffaSHans Petter Selasky p_insert_at = &p_map->root; 364*d6b92ffaSHans Petter Selasky p_comp_item = __cl_map_root(p_map); 365*d6b92ffaSHans Petter Selasky 366*d6b92ffaSHans Petter Selasky while (p_comp_item != &p_map->nil) { 367*d6b92ffaSHans Petter Selasky p_insert_at = p_comp_item; 368*d6b92ffaSHans Petter Selasky 369*d6b92ffaSHans Petter Selasky if (key == p_insert_at->key) 370*d6b92ffaSHans Petter Selasky return (p_insert_at); 371*d6b92ffaSHans Petter Selasky 372*d6b92ffaSHans Petter Selasky /* Traverse the tree until the correct insertion point is found. */ 373*d6b92ffaSHans Petter Selasky if (key < p_insert_at->key) 374*d6b92ffaSHans Petter Selasky p_comp_item = p_insert_at->p_left; 375*d6b92ffaSHans Petter Selasky else 376*d6b92ffaSHans Petter Selasky p_comp_item = p_insert_at->p_right; 377*d6b92ffaSHans Petter Selasky } 378*d6b92ffaSHans Petter Selasky 379*d6b92ffaSHans Petter Selasky CL_ASSERT(p_insert_at != &p_map->nil); 380*d6b92ffaSHans Petter Selasky CL_ASSERT(p_comp_item == &p_map->nil); 381*d6b92ffaSHans Petter Selasky /* Insert the item. */ 382*d6b92ffaSHans Petter Selasky if (p_insert_at == &p_map->root) { 383*d6b92ffaSHans Petter Selasky p_insert_at->p_left = p_item; 384*d6b92ffaSHans Petter Selasky /* 385*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of 386*d6b92ffaSHans Petter Selasky * the existing item. 387*d6b92ffaSHans Petter Selasky */ 388*d6b92ffaSHans Petter Selasky __cl_primitive_insert(&p_map->nil.pool_item.list_item, 389*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item); 390*d6b92ffaSHans Petter Selasky } else if (key < p_insert_at->key) { 391*d6b92ffaSHans Petter Selasky p_insert_at->p_left = p_item; 392*d6b92ffaSHans Petter Selasky /* 393*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of 394*d6b92ffaSHans Petter Selasky * the existing item. 395*d6b92ffaSHans Petter Selasky */ 396*d6b92ffaSHans Petter Selasky __cl_primitive_insert(&p_insert_at->pool_item.list_item, 397*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item); 398*d6b92ffaSHans Petter Selasky } else { 399*d6b92ffaSHans Petter Selasky p_insert_at->p_right = p_item; 400*d6b92ffaSHans Petter Selasky /* 401*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of 402*d6b92ffaSHans Petter Selasky * the existing item. 403*d6b92ffaSHans Petter Selasky */ 404*d6b92ffaSHans Petter Selasky __cl_primitive_insert(p_insert_at->pool_item.list_item.p_next, 405*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item); 406*d6b92ffaSHans Petter Selasky } 407*d6b92ffaSHans Petter Selasky /* Increase the count. */ 408*d6b92ffaSHans Petter Selasky p_map->count++; 409*d6b92ffaSHans Petter Selasky 410*d6b92ffaSHans Petter Selasky p_item->p_up = p_insert_at; 411*d6b92ffaSHans Petter Selasky 412*d6b92ffaSHans Petter Selasky /* 413*d6b92ffaSHans Petter Selasky * We have added depth to this section of the tree. 414*d6b92ffaSHans Petter Selasky * Rebalance as necessary as we retrace our path through the tree 415*d6b92ffaSHans Petter Selasky * and update colors. 416*d6b92ffaSHans Petter Selasky */ 417*d6b92ffaSHans Petter Selasky __cl_map_ins_bal(p_map, p_item); 418*d6b92ffaSHans Petter Selasky 419*d6b92ffaSHans Petter Selasky __cl_map_root(p_map)->color = CL_MAP_BLACK; 420*d6b92ffaSHans Petter Selasky 421*d6b92ffaSHans Petter Selasky /* 422*d6b92ffaSHans Petter Selasky * Note that it is not necessary to re-color the nil node black because all 423*d6b92ffaSHans Petter Selasky * red color assignments are made via the p_up pointer, and nil is never 424*d6b92ffaSHans Petter Selasky * set as the value of a p_up pointer. 425*d6b92ffaSHans Petter Selasky */ 426*d6b92ffaSHans Petter Selasky 427*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_ 428*d6b92ffaSHans Petter Selasky /* Set the pointer to the map in the map item for consistency checking. */ 429*d6b92ffaSHans Petter Selasky p_item->p_map = p_map; 430*d6b92ffaSHans Petter Selasky #endif 431*d6b92ffaSHans Petter Selasky 432*d6b92ffaSHans Petter Selasky return (p_item); 433*d6b92ffaSHans Petter Selasky } 434*d6b92ffaSHans Petter Selasky 435*d6b92ffaSHans Petter Selasky static void __cl_map_del_bal(IN cl_qmap_t * const p_map, 436*d6b92ffaSHans Petter Selasky IN cl_map_item_t * p_item) 437*d6b92ffaSHans Petter Selasky { 438*d6b92ffaSHans Petter Selasky cl_map_item_t *p_uncle; 439*d6b92ffaSHans Petter Selasky 440*d6b92ffaSHans Petter Selasky while ((p_item->color != CL_MAP_RED) && (p_item->p_up != &p_map->root)) { 441*d6b92ffaSHans Petter Selasky if (__cl_map_is_left_child(p_item)) { 442*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right; 443*d6b92ffaSHans Petter Selasky 444*d6b92ffaSHans Petter Selasky if (p_uncle->color == CL_MAP_RED) { 445*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_BLACK; 446*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_RED; 447*d6b92ffaSHans Petter Selasky __cl_map_rot_left(p_map, p_item->p_up); 448*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right; 449*d6b92ffaSHans Petter Selasky } 450*d6b92ffaSHans Petter Selasky 451*d6b92ffaSHans Petter Selasky if (p_uncle->p_right->color != CL_MAP_RED) { 452*d6b92ffaSHans Petter Selasky if (p_uncle->p_left->color != CL_MAP_RED) { 453*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED; 454*d6b92ffaSHans Petter Selasky p_item = p_item->p_up; 455*d6b92ffaSHans Petter Selasky continue; 456*d6b92ffaSHans Petter Selasky } 457*d6b92ffaSHans Petter Selasky 458*d6b92ffaSHans Petter Selasky p_uncle->p_left->color = CL_MAP_BLACK; 459*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED; 460*d6b92ffaSHans Petter Selasky __cl_map_rot_right(p_map, p_uncle); 461*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right; 462*d6b92ffaSHans Petter Selasky } 463*d6b92ffaSHans Petter Selasky p_uncle->color = p_item->p_up->color; 464*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 465*d6b92ffaSHans Petter Selasky p_uncle->p_right->color = CL_MAP_BLACK; 466*d6b92ffaSHans Petter Selasky __cl_map_rot_left(p_map, p_item->p_up); 467*d6b92ffaSHans Petter Selasky break; 468*d6b92ffaSHans Petter Selasky } else { 469*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left; 470*d6b92ffaSHans Petter Selasky 471*d6b92ffaSHans Petter Selasky if (p_uncle->color == CL_MAP_RED) { 472*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_BLACK; 473*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_RED; 474*d6b92ffaSHans Petter Selasky __cl_map_rot_right(p_map, p_item->p_up); 475*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left; 476*d6b92ffaSHans Petter Selasky } 477*d6b92ffaSHans Petter Selasky 478*d6b92ffaSHans Petter Selasky if (p_uncle->p_left->color != CL_MAP_RED) { 479*d6b92ffaSHans Petter Selasky if (p_uncle->p_right->color != CL_MAP_RED) { 480*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED; 481*d6b92ffaSHans Petter Selasky p_item = p_item->p_up; 482*d6b92ffaSHans Petter Selasky continue; 483*d6b92ffaSHans Petter Selasky } 484*d6b92ffaSHans Petter Selasky 485*d6b92ffaSHans Petter Selasky p_uncle->p_right->color = CL_MAP_BLACK; 486*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED; 487*d6b92ffaSHans Petter Selasky __cl_map_rot_left(p_map, p_uncle); 488*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left; 489*d6b92ffaSHans Petter Selasky } 490*d6b92ffaSHans Petter Selasky p_uncle->color = p_item->p_up->color; 491*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 492*d6b92ffaSHans Petter Selasky p_uncle->p_left->color = CL_MAP_BLACK; 493*d6b92ffaSHans Petter Selasky __cl_map_rot_right(p_map, p_item->p_up); 494*d6b92ffaSHans Petter Selasky break; 495*d6b92ffaSHans Petter Selasky } 496*d6b92ffaSHans Petter Selasky } 497*d6b92ffaSHans Petter Selasky p_item->color = CL_MAP_BLACK; 498*d6b92ffaSHans Petter Selasky } 499*d6b92ffaSHans Petter Selasky 500*d6b92ffaSHans Petter Selasky void cl_qmap_remove_item(IN cl_qmap_t * const p_map, 501*d6b92ffaSHans Petter Selasky IN cl_map_item_t * const p_item) 502*d6b92ffaSHans Petter Selasky { 503*d6b92ffaSHans Petter Selasky cl_map_item_t *p_child, *p_del_item; 504*d6b92ffaSHans Petter Selasky 505*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 506*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 507*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 508*d6b92ffaSHans Petter Selasky 509*d6b92ffaSHans Petter Selasky if (p_item == cl_qmap_end(p_map)) 510*d6b92ffaSHans Petter Selasky return; 511*d6b92ffaSHans Petter Selasky 512*d6b92ffaSHans Petter Selasky /* must be checked after comparing to cl_qmap_end, since 513*d6b92ffaSHans Petter Selasky the end is not a valid item. */ 514*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_map == p_map); 515*d6b92ffaSHans Petter Selasky 516*d6b92ffaSHans Petter Selasky if ((p_item->p_right == &p_map->nil) || (p_item->p_left == &p_map->nil)) { 517*d6b92ffaSHans Petter Selasky /* The item being removed has children on at most on side. */ 518*d6b92ffaSHans Petter Selasky p_del_item = p_item; 519*d6b92ffaSHans Petter Selasky } else { 520*d6b92ffaSHans Petter Selasky /* 521*d6b92ffaSHans Petter Selasky * The item being removed has children on both side. 522*d6b92ffaSHans Petter Selasky * We select the item that will replace it. After removing 523*d6b92ffaSHans Petter Selasky * the substitute item and rebalancing, the tree will have the 524*d6b92ffaSHans Petter Selasky * correct topology. Exchanging the substitute for the item 525*d6b92ffaSHans Petter Selasky * will finalize the removal. 526*d6b92ffaSHans Petter Selasky */ 527*d6b92ffaSHans Petter Selasky p_del_item = cl_qmap_next(p_item); 528*d6b92ffaSHans Petter Selasky CL_ASSERT(p_del_item != &p_map->nil); 529*d6b92ffaSHans Petter Selasky } 530*d6b92ffaSHans Petter Selasky 531*d6b92ffaSHans Petter Selasky /* Remove the item from the list. */ 532*d6b92ffaSHans Petter Selasky __cl_primitive_remove(&p_item->pool_item.list_item); 533*d6b92ffaSHans Petter Selasky /* Decrement the item count. */ 534*d6b92ffaSHans Petter Selasky p_map->count--; 535*d6b92ffaSHans Petter Selasky 536*d6b92ffaSHans Petter Selasky /* Get the pointer to the new root's child, if any. */ 537*d6b92ffaSHans Petter Selasky if (p_del_item->p_left != &p_map->nil) 538*d6b92ffaSHans Petter Selasky p_child = p_del_item->p_left; 539*d6b92ffaSHans Petter Selasky else 540*d6b92ffaSHans Petter Selasky p_child = p_del_item->p_right; 541*d6b92ffaSHans Petter Selasky 542*d6b92ffaSHans Petter Selasky /* 543*d6b92ffaSHans Petter Selasky * This assignment may modify the parent pointer of the nil node. 544*d6b92ffaSHans Petter Selasky * This is inconsequential. 545*d6b92ffaSHans Petter Selasky */ 546*d6b92ffaSHans Petter Selasky p_child->p_up = p_del_item->p_up; 547*d6b92ffaSHans Petter Selasky (*__cl_map_get_parent_ptr_to_item(p_del_item)) = p_child; 548*d6b92ffaSHans Petter Selasky 549*d6b92ffaSHans Petter Selasky if (p_del_item->color != CL_MAP_RED) 550*d6b92ffaSHans Petter Selasky __cl_map_del_bal(p_map, p_child); 551*d6b92ffaSHans Petter Selasky 552*d6b92ffaSHans Petter Selasky /* 553*d6b92ffaSHans Petter Selasky * Note that the splicing done below does not need to occur before 554*d6b92ffaSHans Petter Selasky * the tree is balanced, since the actual topology changes are made by the 555*d6b92ffaSHans Petter Selasky * preceding code. The topology is preserved by the color assignment made 556*d6b92ffaSHans Petter Selasky * below (reader should be reminded that p_del_item == p_item in some cases). 557*d6b92ffaSHans Petter Selasky */ 558*d6b92ffaSHans Petter Selasky if (p_del_item != p_item) { 559*d6b92ffaSHans Petter Selasky /* 560*d6b92ffaSHans Petter Selasky * Finalize the removal of the specified item by exchanging it with 561*d6b92ffaSHans Petter Selasky * the substitute which we removed above. 562*d6b92ffaSHans Petter Selasky */ 563*d6b92ffaSHans Petter Selasky p_del_item->p_up = p_item->p_up; 564*d6b92ffaSHans Petter Selasky p_del_item->p_left = p_item->p_left; 565*d6b92ffaSHans Petter Selasky p_del_item->p_right = p_item->p_right; 566*d6b92ffaSHans Petter Selasky (*__cl_map_get_parent_ptr_to_item(p_item)) = p_del_item; 567*d6b92ffaSHans Petter Selasky p_item->p_right->p_up = p_del_item; 568*d6b92ffaSHans Petter Selasky p_item->p_left->p_up = p_del_item; 569*d6b92ffaSHans Petter Selasky p_del_item->color = p_item->color; 570*d6b92ffaSHans Petter Selasky } 571*d6b92ffaSHans Petter Selasky 572*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->nil.color != CL_MAP_RED); 573*d6b92ffaSHans Petter Selasky 574*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_ 575*d6b92ffaSHans Petter Selasky /* Clear the pointer to the map since the item has been removed. */ 576*d6b92ffaSHans Petter Selasky p_item->p_map = NULL; 577*d6b92ffaSHans Petter Selasky #endif 578*d6b92ffaSHans Petter Selasky } 579*d6b92ffaSHans Petter Selasky 580*d6b92ffaSHans Petter Selasky cl_map_item_t *cl_qmap_remove(IN cl_qmap_t * const p_map, IN const uint64_t key) 581*d6b92ffaSHans Petter Selasky { 582*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item; 583*d6b92ffaSHans Petter Selasky 584*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 585*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 586*d6b92ffaSHans Petter Selasky 587*d6b92ffaSHans Petter Selasky /* Seek the node with the specified key */ 588*d6b92ffaSHans Petter Selasky p_item = cl_qmap_get(p_map, key); 589*d6b92ffaSHans Petter Selasky 590*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(p_map, p_item); 591*d6b92ffaSHans Petter Selasky 592*d6b92ffaSHans Petter Selasky return (p_item); 593*d6b92ffaSHans Petter Selasky } 594*d6b92ffaSHans Petter Selasky 595*d6b92ffaSHans Petter Selasky void cl_qmap_merge(OUT cl_qmap_t * const p_dest_map, 596*d6b92ffaSHans Petter Selasky IN OUT cl_qmap_t * const p_src_map) 597*d6b92ffaSHans Petter Selasky { 598*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item, *p_item2, *p_next; 599*d6b92ffaSHans Petter Selasky 600*d6b92ffaSHans Petter Selasky CL_ASSERT(p_dest_map); 601*d6b92ffaSHans Petter Selasky CL_ASSERT(p_src_map); 602*d6b92ffaSHans Petter Selasky 603*d6b92ffaSHans Petter Selasky p_item = cl_qmap_head(p_src_map); 604*d6b92ffaSHans Petter Selasky 605*d6b92ffaSHans Petter Selasky while (p_item != cl_qmap_end(p_src_map)) { 606*d6b92ffaSHans Petter Selasky p_next = cl_qmap_next(p_item); 607*d6b92ffaSHans Petter Selasky 608*d6b92ffaSHans Petter Selasky /* Remove the item from its current map. */ 609*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(p_src_map, p_item); 610*d6b92ffaSHans Petter Selasky /* Insert the item into the destination map. */ 611*d6b92ffaSHans Petter Selasky p_item2 = 612*d6b92ffaSHans Petter Selasky cl_qmap_insert(p_dest_map, cl_qmap_key(p_item), p_item); 613*d6b92ffaSHans Petter Selasky /* Check that the item was successfully inserted. */ 614*d6b92ffaSHans Petter Selasky if (p_item2 != p_item) { 615*d6b92ffaSHans Petter Selasky /* Put the item in back in the source map. */ 616*d6b92ffaSHans Petter Selasky p_item2 = 617*d6b92ffaSHans Petter Selasky cl_qmap_insert(p_src_map, cl_qmap_key(p_item), 618*d6b92ffaSHans Petter Selasky p_item); 619*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item2 == p_item); 620*d6b92ffaSHans Petter Selasky } 621*d6b92ffaSHans Petter Selasky p_item = p_next; 622*d6b92ffaSHans Petter Selasky } 623*d6b92ffaSHans Petter Selasky } 624*d6b92ffaSHans Petter Selasky 625*d6b92ffaSHans Petter Selasky static void __cl_qmap_delta_move(IN OUT cl_qmap_t * const p_dest, 626*d6b92ffaSHans Petter Selasky IN OUT cl_qmap_t * const p_src, 627*d6b92ffaSHans Petter Selasky IN OUT cl_map_item_t ** const pp_item) 628*d6b92ffaSHans Petter Selasky { 629*d6b92ffaSHans Petter Selasky cl_map_item_t __attribute__((__unused__)) *p_temp; 630*d6b92ffaSHans Petter Selasky cl_map_item_t *p_next; 631*d6b92ffaSHans Petter Selasky 632*d6b92ffaSHans Petter Selasky /* 633*d6b92ffaSHans Petter Selasky * Get the next item so that we can ensure that pp_item points to 634*d6b92ffaSHans Petter Selasky * a valid item upon return from the function. 635*d6b92ffaSHans Petter Selasky */ 636*d6b92ffaSHans Petter Selasky p_next = cl_qmap_next(*pp_item); 637*d6b92ffaSHans Petter Selasky /* Move the old item from its current map the the old map. */ 638*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(p_src, *pp_item); 639*d6b92ffaSHans Petter Selasky p_temp = cl_qmap_insert(p_dest, cl_qmap_key(*pp_item), *pp_item); 640*d6b92ffaSHans Petter Selasky /* We should never have duplicates. */ 641*d6b92ffaSHans Petter Selasky CL_ASSERT(p_temp == *pp_item); 642*d6b92ffaSHans Petter Selasky /* Point pp_item to a valid item in the source map. */ 643*d6b92ffaSHans Petter Selasky (*pp_item) = p_next; 644*d6b92ffaSHans Petter Selasky } 645*d6b92ffaSHans Petter Selasky 646*d6b92ffaSHans Petter Selasky void cl_qmap_delta(IN OUT cl_qmap_t * const p_map1, 647*d6b92ffaSHans Petter Selasky IN OUT cl_qmap_t * const p_map2, 648*d6b92ffaSHans Petter Selasky OUT cl_qmap_t * const p_new, OUT cl_qmap_t * const p_old) 649*d6b92ffaSHans Petter Selasky { 650*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item1, *p_item2; 651*d6b92ffaSHans Petter Selasky uint64_t key1, key2; 652*d6b92ffaSHans Petter Selasky 653*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map1); 654*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map2); 655*d6b92ffaSHans Petter Selasky CL_ASSERT(p_new); 656*d6b92ffaSHans Petter Selasky CL_ASSERT(p_old); 657*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_qmap_empty(p_new)); 658*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_qmap_empty(p_old)); 659*d6b92ffaSHans Petter Selasky 660*d6b92ffaSHans Petter Selasky p_item1 = cl_qmap_head(p_map1); 661*d6b92ffaSHans Petter Selasky p_item2 = cl_qmap_head(p_map2); 662*d6b92ffaSHans Petter Selasky 663*d6b92ffaSHans Petter Selasky while (p_item1 != cl_qmap_end(p_map1) && p_item2 != cl_qmap_end(p_map2)) { 664*d6b92ffaSHans Petter Selasky key1 = cl_qmap_key(p_item1); 665*d6b92ffaSHans Petter Selasky key2 = cl_qmap_key(p_item2); 666*d6b92ffaSHans Petter Selasky if (key1 < key2) { 667*d6b92ffaSHans Petter Selasky /* We found an old item. */ 668*d6b92ffaSHans Petter Selasky __cl_qmap_delta_move(p_old, p_map1, &p_item1); 669*d6b92ffaSHans Petter Selasky } else if (key1 > key2) { 670*d6b92ffaSHans Petter Selasky /* We found a new item. */ 671*d6b92ffaSHans Petter Selasky __cl_qmap_delta_move(p_new, p_map2, &p_item2); 672*d6b92ffaSHans Petter Selasky } else { 673*d6b92ffaSHans Petter Selasky /* Move both forward since they have the same key. */ 674*d6b92ffaSHans Petter Selasky p_item1 = cl_qmap_next(p_item1); 675*d6b92ffaSHans Petter Selasky p_item2 = cl_qmap_next(p_item2); 676*d6b92ffaSHans Petter Selasky } 677*d6b92ffaSHans Petter Selasky } 678*d6b92ffaSHans Petter Selasky 679*d6b92ffaSHans Petter Selasky /* Process the remainder if the end of either source map was reached. */ 680*d6b92ffaSHans Petter Selasky while (p_item2 != cl_qmap_end(p_map2)) 681*d6b92ffaSHans Petter Selasky __cl_qmap_delta_move(p_new, p_map2, &p_item2); 682*d6b92ffaSHans Petter Selasky 683*d6b92ffaSHans Petter Selasky while (p_item1 != cl_qmap_end(p_map1)) 684*d6b92ffaSHans Petter Selasky __cl_qmap_delta_move(p_old, p_map1, &p_item1); 685*d6b92ffaSHans Petter Selasky } 686*d6b92ffaSHans Petter Selasky 687*d6b92ffaSHans Petter Selasky /****************************************************************************** 688*d6b92ffaSHans Petter Selasky IMPLEMENTATION OF MAP 689*d6b92ffaSHans Petter Selasky ******************************************************************************/ 690*d6b92ffaSHans Petter Selasky 691*d6b92ffaSHans Petter Selasky #define MAP_GROW_SIZE 32 692*d6b92ffaSHans Petter Selasky 693*d6b92ffaSHans Petter Selasky void cl_map_construct(IN cl_map_t * const p_map) 694*d6b92ffaSHans Petter Selasky { 695*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 696*d6b92ffaSHans Petter Selasky 697*d6b92ffaSHans Petter Selasky cl_qpool_construct(&p_map->pool); 698*d6b92ffaSHans Petter Selasky } 699*d6b92ffaSHans Petter Selasky 700*d6b92ffaSHans Petter Selasky cl_status_t cl_map_init(IN cl_map_t * const p_map, IN const uint32_t min_items) 701*d6b92ffaSHans Petter Selasky { 702*d6b92ffaSHans Petter Selasky uint32_t grow_size; 703*d6b92ffaSHans Petter Selasky 704*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 705*d6b92ffaSHans Petter Selasky 706*d6b92ffaSHans Petter Selasky cl_qmap_init(&p_map->qmap); 707*d6b92ffaSHans Petter Selasky 708*d6b92ffaSHans Petter Selasky /* 709*d6b92ffaSHans Petter Selasky * We will grow by min_items/8 items at a time, with a minimum of 710*d6b92ffaSHans Petter Selasky * MAP_GROW_SIZE. 711*d6b92ffaSHans Petter Selasky */ 712*d6b92ffaSHans Petter Selasky grow_size = min_items >> 3; 713*d6b92ffaSHans Petter Selasky if (grow_size < MAP_GROW_SIZE) 714*d6b92ffaSHans Petter Selasky grow_size = MAP_GROW_SIZE; 715*d6b92ffaSHans Petter Selasky 716*d6b92ffaSHans Petter Selasky return (cl_qpool_init(&p_map->pool, min_items, 0, grow_size, 717*d6b92ffaSHans Petter Selasky sizeof(cl_map_obj_t), NULL, NULL, NULL)); 718*d6b92ffaSHans Petter Selasky } 719*d6b92ffaSHans Petter Selasky 720*d6b92ffaSHans Petter Selasky void cl_map_destroy(IN cl_map_t * const p_map) 721*d6b92ffaSHans Petter Selasky { 722*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 723*d6b92ffaSHans Petter Selasky 724*d6b92ffaSHans Petter Selasky cl_qpool_destroy(&p_map->pool); 725*d6b92ffaSHans Petter Selasky } 726*d6b92ffaSHans Petter Selasky 727*d6b92ffaSHans Petter Selasky void *cl_map_insert(IN cl_map_t * const p_map, 728*d6b92ffaSHans Petter Selasky IN const uint64_t key, IN const void *const p_object) 729*d6b92ffaSHans Petter Selasky { 730*d6b92ffaSHans Petter Selasky cl_map_obj_t *p_map_obj, *p_obj_at_key; 731*d6b92ffaSHans Petter Selasky 732*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 733*d6b92ffaSHans Petter Selasky 734*d6b92ffaSHans Petter Selasky p_map_obj = (cl_map_obj_t *) cl_qpool_get(&p_map->pool); 735*d6b92ffaSHans Petter Selasky 736*d6b92ffaSHans Petter Selasky if (!p_map_obj) 737*d6b92ffaSHans Petter Selasky return (NULL); 738*d6b92ffaSHans Petter Selasky 739*d6b92ffaSHans Petter Selasky cl_qmap_set_obj(p_map_obj, p_object); 740*d6b92ffaSHans Petter Selasky 741*d6b92ffaSHans Petter Selasky p_obj_at_key = 742*d6b92ffaSHans Petter Selasky (cl_map_obj_t *) cl_qmap_insert(&p_map->qmap, key, 743*d6b92ffaSHans Petter Selasky &p_map_obj->item); 744*d6b92ffaSHans Petter Selasky 745*d6b92ffaSHans Petter Selasky /* Return the item to the pool if insertion failed. */ 746*d6b92ffaSHans Petter Selasky if (p_obj_at_key != p_map_obj) 747*d6b92ffaSHans Petter Selasky cl_qpool_put(&p_map->pool, &p_map_obj->item.pool_item); 748*d6b92ffaSHans Petter Selasky 749*d6b92ffaSHans Petter Selasky return (cl_qmap_obj(p_obj_at_key)); 750*d6b92ffaSHans Petter Selasky } 751*d6b92ffaSHans Petter Selasky 752*d6b92ffaSHans Petter Selasky void *cl_map_get(IN const cl_map_t * const p_map, IN const uint64_t key) 753*d6b92ffaSHans Petter Selasky { 754*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item; 755*d6b92ffaSHans Petter Selasky 756*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 757*d6b92ffaSHans Petter Selasky 758*d6b92ffaSHans Petter Selasky p_item = cl_qmap_get(&p_map->qmap, key); 759*d6b92ffaSHans Petter Selasky 760*d6b92ffaSHans Petter Selasky if (p_item == cl_qmap_end(&p_map->qmap)) 761*d6b92ffaSHans Petter Selasky return (NULL); 762*d6b92ffaSHans Petter Selasky 763*d6b92ffaSHans Petter Selasky return (cl_qmap_obj(PARENT_STRUCT(p_item, cl_map_obj_t, item))); 764*d6b92ffaSHans Petter Selasky } 765*d6b92ffaSHans Petter Selasky 766*d6b92ffaSHans Petter Selasky void *cl_map_get_next(IN const cl_map_t * const p_map, IN const uint64_t key) 767*d6b92ffaSHans Petter Selasky { 768*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item; 769*d6b92ffaSHans Petter Selasky 770*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 771*d6b92ffaSHans Petter Selasky 772*d6b92ffaSHans Petter Selasky p_item = cl_qmap_get_next(&p_map->qmap, key); 773*d6b92ffaSHans Petter Selasky 774*d6b92ffaSHans Petter Selasky if (p_item == cl_qmap_end(&p_map->qmap)) 775*d6b92ffaSHans Petter Selasky return (NULL); 776*d6b92ffaSHans Petter Selasky 777*d6b92ffaSHans Petter Selasky return (cl_qmap_obj(PARENT_STRUCT(p_item, cl_map_obj_t, item))); 778*d6b92ffaSHans Petter Selasky } 779*d6b92ffaSHans Petter Selasky 780*d6b92ffaSHans Petter Selasky void cl_map_remove_item(IN cl_map_t * const p_map, 781*d6b92ffaSHans Petter Selasky IN const cl_map_iterator_t itor) 782*d6b92ffaSHans Petter Selasky { 783*d6b92ffaSHans Petter Selasky CL_ASSERT(itor->p_map == &p_map->qmap); 784*d6b92ffaSHans Petter Selasky 785*d6b92ffaSHans Petter Selasky if (itor == cl_map_end(p_map)) 786*d6b92ffaSHans Petter Selasky return; 787*d6b92ffaSHans Petter Selasky 788*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(&p_map->qmap, (cl_map_item_t *) itor); 789*d6b92ffaSHans Petter Selasky cl_qpool_put(&p_map->pool, &((cl_map_item_t *) itor)->pool_item); 790*d6b92ffaSHans Petter Selasky } 791*d6b92ffaSHans Petter Selasky 792*d6b92ffaSHans Petter Selasky void *cl_map_remove(IN cl_map_t * const p_map, IN const uint64_t key) 793*d6b92ffaSHans Petter Selasky { 794*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item; 795*d6b92ffaSHans Petter Selasky void *p_obj; 796*d6b92ffaSHans Petter Selasky 797*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 798*d6b92ffaSHans Petter Selasky 799*d6b92ffaSHans Petter Selasky p_item = cl_qmap_remove(&p_map->qmap, key); 800*d6b92ffaSHans Petter Selasky 801*d6b92ffaSHans Petter Selasky if (p_item == cl_qmap_end(&p_map->qmap)) 802*d6b92ffaSHans Petter Selasky return (NULL); 803*d6b92ffaSHans Petter Selasky 804*d6b92ffaSHans Petter Selasky p_obj = cl_qmap_obj((cl_map_obj_t *) p_item); 805*d6b92ffaSHans Petter Selasky cl_qpool_put(&p_map->pool, &p_item->pool_item); 806*d6b92ffaSHans Petter Selasky 807*d6b92ffaSHans Petter Selasky return (p_obj); 808*d6b92ffaSHans Petter Selasky } 809*d6b92ffaSHans Petter Selasky 810*d6b92ffaSHans Petter Selasky void cl_map_remove_all(IN cl_map_t * const p_map) 811*d6b92ffaSHans Petter Selasky { 812*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item; 813*d6b92ffaSHans Petter Selasky 814*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 815*d6b92ffaSHans Petter Selasky 816*d6b92ffaSHans Petter Selasky /* Return all map items to the pool. */ 817*d6b92ffaSHans Petter Selasky while (!cl_is_qmap_empty(&p_map->qmap)) { 818*d6b92ffaSHans Petter Selasky p_item = cl_qmap_head(&p_map->qmap); 819*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(&p_map->qmap, p_item); 820*d6b92ffaSHans Petter Selasky cl_qpool_put(&p_map->pool, &p_item->pool_item); 821*d6b92ffaSHans Petter Selasky 822*d6b92ffaSHans Petter Selasky if (!cl_is_qmap_empty(&p_map->qmap)) { 823*d6b92ffaSHans Petter Selasky p_item = cl_qmap_tail(&p_map->qmap); 824*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(&p_map->qmap, p_item); 825*d6b92ffaSHans Petter Selasky cl_qpool_put(&p_map->pool, &p_item->pool_item); 826*d6b92ffaSHans Petter Selasky } 827*d6b92ffaSHans Petter Selasky } 828*d6b92ffaSHans Petter Selasky } 829*d6b92ffaSHans Petter Selasky 830*d6b92ffaSHans Petter Selasky cl_status_t cl_map_merge(OUT cl_map_t * const p_dest_map, 831*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_src_map) 832*d6b92ffaSHans Petter Selasky { 833*d6b92ffaSHans Petter Selasky cl_status_t status = CL_SUCCESS; 834*d6b92ffaSHans Petter Selasky cl_map_iterator_t itor, next; 835*d6b92ffaSHans Petter Selasky uint64_t key; 836*d6b92ffaSHans Petter Selasky void *p_obj, *p_obj2; 837*d6b92ffaSHans Petter Selasky 838*d6b92ffaSHans Petter Selasky CL_ASSERT(p_dest_map); 839*d6b92ffaSHans Petter Selasky CL_ASSERT(p_src_map); 840*d6b92ffaSHans Petter Selasky 841*d6b92ffaSHans Petter Selasky itor = cl_map_head(p_src_map); 842*d6b92ffaSHans Petter Selasky while (itor != cl_map_end(p_src_map)) { 843*d6b92ffaSHans Petter Selasky next = cl_map_next(itor); 844*d6b92ffaSHans Petter Selasky 845*d6b92ffaSHans Petter Selasky p_obj = cl_map_obj(itor); 846*d6b92ffaSHans Petter Selasky key = cl_map_key(itor); 847*d6b92ffaSHans Petter Selasky 848*d6b92ffaSHans Petter Selasky cl_map_remove_item(p_src_map, itor); 849*d6b92ffaSHans Petter Selasky 850*d6b92ffaSHans Petter Selasky /* Insert the object into the destination map. */ 851*d6b92ffaSHans Petter Selasky p_obj2 = cl_map_insert(p_dest_map, key, p_obj); 852*d6b92ffaSHans Petter Selasky /* Trap for failure. */ 853*d6b92ffaSHans Petter Selasky if (p_obj != p_obj2) { 854*d6b92ffaSHans Petter Selasky if (!p_obj2) 855*d6b92ffaSHans Petter Selasky status = CL_INSUFFICIENT_MEMORY; 856*d6b92ffaSHans Petter Selasky /* Put the object back in the source map. This must succeed. */ 857*d6b92ffaSHans Petter Selasky p_obj2 = cl_map_insert(p_src_map, key, p_obj); 858*d6b92ffaSHans Petter Selasky CL_ASSERT(p_obj == p_obj2); 859*d6b92ffaSHans Petter Selasky /* If the failure was due to insufficient memory, return. */ 860*d6b92ffaSHans Petter Selasky if (status != CL_SUCCESS) 861*d6b92ffaSHans Petter Selasky return (status); 862*d6b92ffaSHans Petter Selasky } 863*d6b92ffaSHans Petter Selasky itor = next; 864*d6b92ffaSHans Petter Selasky } 865*d6b92ffaSHans Petter Selasky 866*d6b92ffaSHans Petter Selasky return (CL_SUCCESS); 867*d6b92ffaSHans Petter Selasky } 868*d6b92ffaSHans Petter Selasky 869*d6b92ffaSHans Petter Selasky static void __cl_map_revert(IN OUT cl_map_t * const p_map1, 870*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_map2, 871*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_new, 872*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_old) 873*d6b92ffaSHans Petter Selasky { 874*d6b92ffaSHans Petter Selasky cl_status_t __attribute__((__unused__)) status; 875*d6b92ffaSHans Petter Selasky 876*d6b92ffaSHans Petter Selasky /* Restore the initial state. */ 877*d6b92ffaSHans Petter Selasky status = cl_map_merge(p_map1, p_old); 878*d6b92ffaSHans Petter Selasky CL_ASSERT(status == CL_SUCCESS); 879*d6b92ffaSHans Petter Selasky status = cl_map_merge(p_map2, p_new); 880*d6b92ffaSHans Petter Selasky CL_ASSERT(status == CL_SUCCESS); 881*d6b92ffaSHans Petter Selasky } 882*d6b92ffaSHans Petter Selasky 883*d6b92ffaSHans Petter Selasky static cl_status_t __cl_map_delta_move(OUT cl_map_t * const p_dest, 884*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_src, 885*d6b92ffaSHans Petter Selasky IN OUT cl_map_iterator_t * const p_itor) 886*d6b92ffaSHans Petter Selasky { 887*d6b92ffaSHans Petter Selasky cl_map_iterator_t next; 888*d6b92ffaSHans Petter Selasky void *p_obj, *p_obj2; 889*d6b92ffaSHans Petter Selasky uint64_t key; 890*d6b92ffaSHans Petter Selasky 891*d6b92ffaSHans Petter Selasky /* Get a valid iterator so we can continue the loop. */ 892*d6b92ffaSHans Petter Selasky next = cl_map_next(*p_itor); 893*d6b92ffaSHans Petter Selasky /* Get the pointer to the object for insertion. */ 894*d6b92ffaSHans Petter Selasky p_obj = cl_map_obj(*p_itor); 895*d6b92ffaSHans Petter Selasky /* Get the key for the object. */ 896*d6b92ffaSHans Petter Selasky key = cl_map_key(*p_itor); 897*d6b92ffaSHans Petter Selasky /* Move the object. */ 898*d6b92ffaSHans Petter Selasky cl_map_remove_item(p_src, *p_itor); 899*d6b92ffaSHans Petter Selasky p_obj2 = cl_map_insert(p_dest, key, p_obj); 900*d6b92ffaSHans Petter Selasky /* Check for failure. We should never get a duplicate. */ 901*d6b92ffaSHans Petter Selasky if (!p_obj2) { 902*d6b92ffaSHans Petter Selasky p_obj2 = cl_map_insert(p_src, key, p_obj); 903*d6b92ffaSHans Petter Selasky CL_ASSERT(p_obj2 == p_obj); 904*d6b92ffaSHans Petter Selasky return (CL_INSUFFICIENT_MEMORY); 905*d6b92ffaSHans Petter Selasky } 906*d6b92ffaSHans Petter Selasky 907*d6b92ffaSHans Petter Selasky /* We should never get a duplicate */ 908*d6b92ffaSHans Petter Selasky CL_ASSERT(p_obj == p_obj2); 909*d6b92ffaSHans Petter Selasky /* Update the iterator so that it is valid. */ 910*d6b92ffaSHans Petter Selasky (*p_itor) = next; 911*d6b92ffaSHans Petter Selasky 912*d6b92ffaSHans Petter Selasky return (CL_SUCCESS); 913*d6b92ffaSHans Petter Selasky } 914*d6b92ffaSHans Petter Selasky 915*d6b92ffaSHans Petter Selasky cl_status_t cl_map_delta(IN OUT cl_map_t * const p_map1, 916*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_map2, 917*d6b92ffaSHans Petter Selasky OUT cl_map_t * const p_new, OUT cl_map_t * const p_old) 918*d6b92ffaSHans Petter Selasky { 919*d6b92ffaSHans Petter Selasky cl_map_iterator_t itor1, itor2; 920*d6b92ffaSHans Petter Selasky uint64_t key1, key2; 921*d6b92ffaSHans Petter Selasky cl_status_t status; 922*d6b92ffaSHans Petter Selasky 923*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map1); 924*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map2); 925*d6b92ffaSHans Petter Selasky CL_ASSERT(p_new); 926*d6b92ffaSHans Petter Selasky CL_ASSERT(p_old); 927*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_map_empty(p_new)); 928*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_map_empty(p_old)); 929*d6b92ffaSHans Petter Selasky 930*d6b92ffaSHans Petter Selasky itor1 = cl_map_head(p_map1); 931*d6b92ffaSHans Petter Selasky itor2 = cl_map_head(p_map2); 932*d6b92ffaSHans Petter Selasky 933*d6b92ffaSHans Petter Selasky /* 934*d6b92ffaSHans Petter Selasky * Note that the check is for the end, since duplicate items will remain 935*d6b92ffaSHans Petter Selasky * in their respective maps. 936*d6b92ffaSHans Petter Selasky */ 937*d6b92ffaSHans Petter Selasky while (itor1 != cl_map_end(p_map1) && itor2 != cl_map_end(p_map2)) { 938*d6b92ffaSHans Petter Selasky key1 = cl_map_key(itor1); 939*d6b92ffaSHans Petter Selasky key2 = cl_map_key(itor2); 940*d6b92ffaSHans Petter Selasky if (key1 < key2) { 941*d6b92ffaSHans Petter Selasky status = __cl_map_delta_move(p_old, p_map1, &itor1); 942*d6b92ffaSHans Petter Selasky /* Check for failure. */ 943*d6b92ffaSHans Petter Selasky if (status != CL_SUCCESS) { 944*d6b92ffaSHans Petter Selasky /* Restore the initial state. */ 945*d6b92ffaSHans Petter Selasky __cl_map_revert(p_map1, p_map2, p_new, p_old); 946*d6b92ffaSHans Petter Selasky /* Return the failure status. */ 947*d6b92ffaSHans Petter Selasky return (status); 948*d6b92ffaSHans Petter Selasky } 949*d6b92ffaSHans Petter Selasky } else if (key1 > key2) { 950*d6b92ffaSHans Petter Selasky status = __cl_map_delta_move(p_new, p_map2, &itor2); 951*d6b92ffaSHans Petter Selasky if (status != CL_SUCCESS) { 952*d6b92ffaSHans Petter Selasky /* Restore the initial state. */ 953*d6b92ffaSHans Petter Selasky __cl_map_revert(p_map1, p_map2, p_new, p_old); 954*d6b92ffaSHans Petter Selasky /* Return the failure status. */ 955*d6b92ffaSHans Petter Selasky return (status); 956*d6b92ffaSHans Petter Selasky } 957*d6b92ffaSHans Petter Selasky } else { 958*d6b92ffaSHans Petter Selasky /* Move both forward since they have the same key. */ 959*d6b92ffaSHans Petter Selasky itor1 = cl_map_next(itor1); 960*d6b92ffaSHans Petter Selasky itor2 = cl_map_next(itor2); 961*d6b92ffaSHans Petter Selasky } 962*d6b92ffaSHans Petter Selasky } 963*d6b92ffaSHans Petter Selasky 964*d6b92ffaSHans Petter Selasky /* Process the remainder if either source map is empty. */ 965*d6b92ffaSHans Petter Selasky while (itor2 != cl_map_end(p_map2)) { 966*d6b92ffaSHans Petter Selasky status = __cl_map_delta_move(p_new, p_map2, &itor2); 967*d6b92ffaSHans Petter Selasky if (status != CL_SUCCESS) { 968*d6b92ffaSHans Petter Selasky /* Restore the initial state. */ 969*d6b92ffaSHans Petter Selasky __cl_map_revert(p_map1, p_map2, p_new, p_old); 970*d6b92ffaSHans Petter Selasky /* Return the failure status. */ 971*d6b92ffaSHans Petter Selasky return (status); 972*d6b92ffaSHans Petter Selasky } 973*d6b92ffaSHans Petter Selasky } 974*d6b92ffaSHans Petter Selasky 975*d6b92ffaSHans Petter Selasky while (itor1 != cl_map_end(p_map1)) { 976*d6b92ffaSHans Petter Selasky status = __cl_map_delta_move(p_old, p_map1, &itor1); 977*d6b92ffaSHans Petter Selasky if (status != CL_SUCCESS) { 978*d6b92ffaSHans Petter Selasky /* Restore the initial state. */ 979*d6b92ffaSHans Petter Selasky __cl_map_revert(p_map1, p_map2, p_new, p_old); 980*d6b92ffaSHans Petter Selasky /* Return the failure status. */ 981*d6b92ffaSHans Petter Selasky return (status); 982*d6b92ffaSHans Petter Selasky } 983*d6b92ffaSHans Petter Selasky } 984*d6b92ffaSHans Petter Selasky 985*d6b92ffaSHans Petter Selasky return (CL_SUCCESS); 986*d6b92ffaSHans Petter Selasky } 987*d6b92ffaSHans Petter Selasky 988*d6b92ffaSHans Petter Selasky /****************************************************************************** 989*d6b92ffaSHans Petter Selasky IMPLEMENTATION OF FLEXI MAP 990*d6b92ffaSHans Petter Selasky ******************************************************************************/ 991*d6b92ffaSHans Petter Selasky 992*d6b92ffaSHans Petter Selasky /* 993*d6b92ffaSHans Petter Selasky * Get the root. 994*d6b92ffaSHans Petter Selasky */ 995*d6b92ffaSHans Petter Selasky static inline cl_fmap_item_t *__cl_fmap_root(IN const cl_fmap_t * const p_map) 996*d6b92ffaSHans Petter Selasky { 997*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 998*d6b92ffaSHans Petter Selasky return (p_map->root.p_left); 999*d6b92ffaSHans Petter Selasky } 1000*d6b92ffaSHans Petter Selasky 1001*d6b92ffaSHans Petter Selasky /* 1002*d6b92ffaSHans Petter Selasky * Returns whether a given item is on the left of its parent. 1003*d6b92ffaSHans Petter Selasky */ 1004*d6b92ffaSHans Petter Selasky static boolean_t __cl_fmap_is_left_child(IN const cl_fmap_item_t * const p_item) 1005*d6b92ffaSHans Petter Selasky { 1006*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 1007*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up); 1008*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up != p_item); 1009*d6b92ffaSHans Petter Selasky 1010*d6b92ffaSHans Petter Selasky return (p_item->p_up->p_left == p_item); 1011*d6b92ffaSHans Petter Selasky } 1012*d6b92ffaSHans Petter Selasky 1013*d6b92ffaSHans Petter Selasky /* 1014*d6b92ffaSHans Petter Selasky * Retrieve the pointer to the parent's pointer to an item. 1015*d6b92ffaSHans Petter Selasky */ 1016*d6b92ffaSHans Petter Selasky static cl_fmap_item_t **__cl_fmap_get_parent_ptr_to_item(IN cl_fmap_item_t * 1017*d6b92ffaSHans Petter Selasky const p_item) 1018*d6b92ffaSHans Petter Selasky { 1019*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 1020*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up); 1021*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up != p_item); 1022*d6b92ffaSHans Petter Selasky 1023*d6b92ffaSHans Petter Selasky if (__cl_fmap_is_left_child(p_item)) 1024*d6b92ffaSHans Petter Selasky return (&p_item->p_up->p_left); 1025*d6b92ffaSHans Petter Selasky 1026*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up->p_right == p_item); 1027*d6b92ffaSHans Petter Selasky return (&p_item->p_up->p_right); 1028*d6b92ffaSHans Petter Selasky } 1029*d6b92ffaSHans Petter Selasky 1030*d6b92ffaSHans Petter Selasky /* 1031*d6b92ffaSHans Petter Selasky * Rotate a node to the left. This rotation affects the least number of links 1032*d6b92ffaSHans Petter Selasky * between nodes and brings the level of C up by one while increasing the depth 1033*d6b92ffaSHans Petter Selasky * of A one. Note that the links to/from W, X, Y, and Z are not affected. 1034*d6b92ffaSHans Petter Selasky * 1035*d6b92ffaSHans Petter Selasky * R R 1036*d6b92ffaSHans Petter Selasky * | | 1037*d6b92ffaSHans Petter Selasky * A C 1038*d6b92ffaSHans Petter Selasky * / \ / \ 1039*d6b92ffaSHans Petter Selasky * W C A Z 1040*d6b92ffaSHans Petter Selasky * / \ / \ 1041*d6b92ffaSHans Petter Selasky * B Z W B 1042*d6b92ffaSHans Petter Selasky * / \ / \ 1043*d6b92ffaSHans Petter Selasky * X Y X Y 1044*d6b92ffaSHans Petter Selasky */ 1045*d6b92ffaSHans Petter Selasky static void __cl_fmap_rot_left(IN cl_fmap_t * const p_map, 1046*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * const p_item) 1047*d6b92ffaSHans Petter Selasky { 1048*d6b92ffaSHans Petter Selasky cl_fmap_item_t **pp_root; 1049*d6b92ffaSHans Petter Selasky 1050*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 1051*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 1052*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_right != &p_map->nil); 1053*d6b92ffaSHans Petter Selasky 1054*d6b92ffaSHans Petter Selasky pp_root = __cl_fmap_get_parent_ptr_to_item(p_item); 1055*d6b92ffaSHans Petter Selasky 1056*d6b92ffaSHans Petter Selasky /* Point R to C instead of A. */ 1057*d6b92ffaSHans Petter Selasky *pp_root = p_item->p_right; 1058*d6b92ffaSHans Petter Selasky /* Set C's parent to R. */ 1059*d6b92ffaSHans Petter Selasky (*pp_root)->p_up = p_item->p_up; 1060*d6b92ffaSHans Petter Selasky 1061*d6b92ffaSHans Petter Selasky /* Set A's right to B */ 1062*d6b92ffaSHans Petter Selasky p_item->p_right = (*pp_root)->p_left; 1063*d6b92ffaSHans Petter Selasky /* 1064*d6b92ffaSHans Petter Selasky * Set B's parent to A. We trap for B being NIL since the 1065*d6b92ffaSHans Petter Selasky * caller may depend on NIL not changing. 1066*d6b92ffaSHans Petter Selasky */ 1067*d6b92ffaSHans Petter Selasky if ((*pp_root)->p_left != &p_map->nil) 1068*d6b92ffaSHans Petter Selasky (*pp_root)->p_left->p_up = p_item; 1069*d6b92ffaSHans Petter Selasky 1070*d6b92ffaSHans Petter Selasky /* Set C's left to A. */ 1071*d6b92ffaSHans Petter Selasky (*pp_root)->p_left = p_item; 1072*d6b92ffaSHans Petter Selasky /* Set A's parent to C. */ 1073*d6b92ffaSHans Petter Selasky p_item->p_up = *pp_root; 1074*d6b92ffaSHans Petter Selasky } 1075*d6b92ffaSHans Petter Selasky 1076*d6b92ffaSHans Petter Selasky /* 1077*d6b92ffaSHans Petter Selasky * Rotate a node to the right. This rotation affects the least number of links 1078*d6b92ffaSHans Petter Selasky * between nodes and brings the level of A up by one while increasing the depth 1079*d6b92ffaSHans Petter Selasky * of C one. Note that the links to/from W, X, Y, and Z are not affected. 1080*d6b92ffaSHans Petter Selasky * 1081*d6b92ffaSHans Petter Selasky * R R 1082*d6b92ffaSHans Petter Selasky * | | 1083*d6b92ffaSHans Petter Selasky * C A 1084*d6b92ffaSHans Petter Selasky * / \ / \ 1085*d6b92ffaSHans Petter Selasky * A Z W C 1086*d6b92ffaSHans Petter Selasky * / \ / \ 1087*d6b92ffaSHans Petter Selasky * W B B Z 1088*d6b92ffaSHans Petter Selasky * / \ / \ 1089*d6b92ffaSHans Petter Selasky * X Y X Y 1090*d6b92ffaSHans Petter Selasky */ 1091*d6b92ffaSHans Petter Selasky static void __cl_fmap_rot_right(IN cl_fmap_t * const p_map, 1092*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * const p_item) 1093*d6b92ffaSHans Petter Selasky { 1094*d6b92ffaSHans Petter Selasky cl_fmap_item_t **pp_root; 1095*d6b92ffaSHans Petter Selasky 1096*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 1097*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 1098*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_left != &p_map->nil); 1099*d6b92ffaSHans Petter Selasky 1100*d6b92ffaSHans Petter Selasky /* Point R to A instead of C. */ 1101*d6b92ffaSHans Petter Selasky pp_root = __cl_fmap_get_parent_ptr_to_item(p_item); 1102*d6b92ffaSHans Petter Selasky (*pp_root) = p_item->p_left; 1103*d6b92ffaSHans Petter Selasky /* Set A's parent to R. */ 1104*d6b92ffaSHans Petter Selasky (*pp_root)->p_up = p_item->p_up; 1105*d6b92ffaSHans Petter Selasky 1106*d6b92ffaSHans Petter Selasky /* Set C's left to B */ 1107*d6b92ffaSHans Petter Selasky p_item->p_left = (*pp_root)->p_right; 1108*d6b92ffaSHans Petter Selasky /* 1109*d6b92ffaSHans Petter Selasky * Set B's parent to C. We trap for B being NIL since the 1110*d6b92ffaSHans Petter Selasky * caller may depend on NIL not changing. 1111*d6b92ffaSHans Petter Selasky */ 1112*d6b92ffaSHans Petter Selasky if ((*pp_root)->p_right != &p_map->nil) 1113*d6b92ffaSHans Petter Selasky (*pp_root)->p_right->p_up = p_item; 1114*d6b92ffaSHans Petter Selasky 1115*d6b92ffaSHans Petter Selasky /* Set A's right to C. */ 1116*d6b92ffaSHans Petter Selasky (*pp_root)->p_right = p_item; 1117*d6b92ffaSHans Petter Selasky /* Set C's parent to A. */ 1118*d6b92ffaSHans Petter Selasky p_item->p_up = *pp_root; 1119*d6b92ffaSHans Petter Selasky } 1120*d6b92ffaSHans Petter Selasky 1121*d6b92ffaSHans Petter Selasky void cl_fmap_init(IN cl_fmap_t * const p_map, IN cl_pfn_fmap_cmp_t pfn_compare) 1122*d6b92ffaSHans Petter Selasky { 1123*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 1124*d6b92ffaSHans Petter Selasky CL_ASSERT(pfn_compare); 1125*d6b92ffaSHans Petter Selasky 1126*d6b92ffaSHans Petter Selasky memset(p_map, 0, sizeof(cl_fmap_t)); 1127*d6b92ffaSHans Petter Selasky 1128*d6b92ffaSHans Petter Selasky /* special setup for the root node */ 1129*d6b92ffaSHans Petter Selasky p_map->root.p_up = &p_map->root; 1130*d6b92ffaSHans Petter Selasky p_map->root.p_left = &p_map->nil; 1131*d6b92ffaSHans Petter Selasky p_map->root.p_right = &p_map->nil; 1132*d6b92ffaSHans Petter Selasky p_map->root.color = CL_MAP_BLACK; 1133*d6b92ffaSHans Petter Selasky 1134*d6b92ffaSHans Petter Selasky /* Setup the node used as terminator for all leaves. */ 1135*d6b92ffaSHans Petter Selasky p_map->nil.p_up = &p_map->nil; 1136*d6b92ffaSHans Petter Selasky p_map->nil.p_left = &p_map->nil; 1137*d6b92ffaSHans Petter Selasky p_map->nil.p_right = &p_map->nil; 1138*d6b92ffaSHans Petter Selasky p_map->nil.color = CL_MAP_BLACK; 1139*d6b92ffaSHans Petter Selasky 1140*d6b92ffaSHans Petter Selasky /* Store the compare function pointer. */ 1141*d6b92ffaSHans Petter Selasky p_map->pfn_compare = pfn_compare; 1142*d6b92ffaSHans Petter Selasky 1143*d6b92ffaSHans Petter Selasky p_map->state = CL_INITIALIZED; 1144*d6b92ffaSHans Petter Selasky 1145*d6b92ffaSHans Petter Selasky cl_fmap_remove_all(p_map); 1146*d6b92ffaSHans Petter Selasky } 1147*d6b92ffaSHans Petter Selasky 1148*d6b92ffaSHans Petter Selasky cl_fmap_item_t *cl_fmap_match(IN const cl_fmap_t * const p_map, 1149*d6b92ffaSHans Petter Selasky IN const void *const p_key, 1150*d6b92ffaSHans Petter Selasky IN cl_pfn_fmap_cmp_t pfn_compare) 1151*d6b92ffaSHans Petter Selasky { 1152*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item; 1153*d6b92ffaSHans Petter Selasky int cmp; 1154*d6b92ffaSHans Petter Selasky 1155*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 1156*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 1157*d6b92ffaSHans Petter Selasky 1158*d6b92ffaSHans Petter Selasky p_item = __cl_fmap_root(p_map); 1159*d6b92ffaSHans Petter Selasky 1160*d6b92ffaSHans Petter Selasky while (p_item != &p_map->nil) { 1161*d6b92ffaSHans Petter Selasky cmp = pfn_compare ? pfn_compare(p_key, p_item->p_key) : 1162*d6b92ffaSHans Petter Selasky p_map->pfn_compare(p_key, p_item->p_key); 1163*d6b92ffaSHans Petter Selasky 1164*d6b92ffaSHans Petter Selasky if (!cmp) 1165*d6b92ffaSHans Petter Selasky break; /* just right */ 1166*d6b92ffaSHans Petter Selasky 1167*d6b92ffaSHans Petter Selasky if (cmp < 0) 1168*d6b92ffaSHans Petter Selasky p_item = p_item->p_left; /* too small */ 1169*d6b92ffaSHans Petter Selasky else 1170*d6b92ffaSHans Petter Selasky p_item = p_item->p_right; /* too big */ 1171*d6b92ffaSHans Petter Selasky } 1172*d6b92ffaSHans Petter Selasky 1173*d6b92ffaSHans Petter Selasky return (p_item); 1174*d6b92ffaSHans Petter Selasky } 1175*d6b92ffaSHans Petter Selasky 1176*d6b92ffaSHans Petter Selasky cl_fmap_item_t *cl_fmap_get(IN const cl_fmap_t * const p_map, 1177*d6b92ffaSHans Petter Selasky IN const void *const p_key) 1178*d6b92ffaSHans Petter Selasky { 1179*d6b92ffaSHans Petter Selasky return cl_fmap_match(p_map, p_key, p_map->pfn_compare); 1180*d6b92ffaSHans Petter Selasky } 1181*d6b92ffaSHans Petter Selasky 1182*d6b92ffaSHans Petter Selasky cl_fmap_item_t *cl_fmap_get_next(IN const cl_fmap_t * const p_map, 1183*d6b92ffaSHans Petter Selasky IN const void *const p_key) 1184*d6b92ffaSHans Petter Selasky { 1185*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item; 1186*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item_found; 1187*d6b92ffaSHans Petter Selasky int cmp; 1188*d6b92ffaSHans Petter Selasky 1189*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 1190*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 1191*d6b92ffaSHans Petter Selasky 1192*d6b92ffaSHans Petter Selasky p_item = __cl_fmap_root(p_map); 1193*d6b92ffaSHans Petter Selasky p_item_found = (cl_fmap_item_t *) & p_map->nil; 1194*d6b92ffaSHans Petter Selasky 1195*d6b92ffaSHans Petter Selasky while (p_item != &p_map->nil) { 1196*d6b92ffaSHans Petter Selasky cmp = p_map->pfn_compare(p_key, p_item->p_key); 1197*d6b92ffaSHans Petter Selasky 1198*d6b92ffaSHans Petter Selasky if (cmp < 0) { 1199*d6b92ffaSHans Petter Selasky p_item_found = p_item; 1200*d6b92ffaSHans Petter Selasky p_item = p_item->p_left; /* too small */ 1201*d6b92ffaSHans Petter Selasky } else { 1202*d6b92ffaSHans Petter Selasky p_item = p_item->p_right; /* too big or match */ 1203*d6b92ffaSHans Petter Selasky } 1204*d6b92ffaSHans Petter Selasky } 1205*d6b92ffaSHans Petter Selasky 1206*d6b92ffaSHans Petter Selasky return (p_item_found); 1207*d6b92ffaSHans Petter Selasky } 1208*d6b92ffaSHans Petter Selasky 1209*d6b92ffaSHans Petter Selasky void cl_fmap_apply_func(IN const cl_fmap_t * const p_map, 1210*d6b92ffaSHans Petter Selasky IN cl_pfn_fmap_apply_t pfn_func, 1211*d6b92ffaSHans Petter Selasky IN const void *const context) 1212*d6b92ffaSHans Petter Selasky { 1213*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_fmap_item; 1214*d6b92ffaSHans Petter Selasky 1215*d6b92ffaSHans Petter Selasky /* Note that context can have any arbitrary value. */ 1216*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 1217*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 1218*d6b92ffaSHans Petter Selasky CL_ASSERT(pfn_func); 1219*d6b92ffaSHans Petter Selasky 1220*d6b92ffaSHans Petter Selasky p_fmap_item = cl_fmap_head(p_map); 1221*d6b92ffaSHans Petter Selasky while (p_fmap_item != cl_fmap_end(p_map)) { 1222*d6b92ffaSHans Petter Selasky pfn_func(p_fmap_item, (void *)context); 1223*d6b92ffaSHans Petter Selasky p_fmap_item = cl_fmap_next(p_fmap_item); 1224*d6b92ffaSHans Petter Selasky } 1225*d6b92ffaSHans Petter Selasky } 1226*d6b92ffaSHans Petter Selasky 1227*d6b92ffaSHans Petter Selasky /* 1228*d6b92ffaSHans Petter Selasky * Balance a tree starting at a given item back to the root. 1229*d6b92ffaSHans Petter Selasky */ 1230*d6b92ffaSHans Petter Selasky static void __cl_fmap_ins_bal(IN cl_fmap_t * const p_map, 1231*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * p_item) 1232*d6b92ffaSHans Petter Selasky { 1233*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_grand_uncle; 1234*d6b92ffaSHans Petter Selasky 1235*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 1236*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 1237*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item != &p_map->root); 1238*d6b92ffaSHans Petter Selasky 1239*d6b92ffaSHans Petter Selasky while (p_item->p_up->color == CL_MAP_RED) { 1240*d6b92ffaSHans Petter Selasky if (__cl_fmap_is_left_child(p_item->p_up)) { 1241*d6b92ffaSHans Petter Selasky p_grand_uncle = p_item->p_up->p_up->p_right; 1242*d6b92ffaSHans Petter Selasky CL_ASSERT(p_grand_uncle); 1243*d6b92ffaSHans Petter Selasky if (p_grand_uncle->color == CL_MAP_RED) { 1244*d6b92ffaSHans Petter Selasky p_grand_uncle->color = CL_MAP_BLACK; 1245*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 1246*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED; 1247*d6b92ffaSHans Petter Selasky p_item = p_item->p_up->p_up; 1248*d6b92ffaSHans Petter Selasky continue; 1249*d6b92ffaSHans Petter Selasky } 1250*d6b92ffaSHans Petter Selasky 1251*d6b92ffaSHans Petter Selasky if (!__cl_fmap_is_left_child(p_item)) { 1252*d6b92ffaSHans Petter Selasky p_item = p_item->p_up; 1253*d6b92ffaSHans Petter Selasky __cl_fmap_rot_left(p_map, p_item); 1254*d6b92ffaSHans Petter Selasky } 1255*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 1256*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED; 1257*d6b92ffaSHans Petter Selasky __cl_fmap_rot_right(p_map, p_item->p_up->p_up); 1258*d6b92ffaSHans Petter Selasky } else { 1259*d6b92ffaSHans Petter Selasky p_grand_uncle = p_item->p_up->p_up->p_left; 1260*d6b92ffaSHans Petter Selasky CL_ASSERT(p_grand_uncle); 1261*d6b92ffaSHans Petter Selasky if (p_grand_uncle->color == CL_MAP_RED) { 1262*d6b92ffaSHans Petter Selasky p_grand_uncle->color = CL_MAP_BLACK; 1263*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 1264*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED; 1265*d6b92ffaSHans Petter Selasky p_item = p_item->p_up->p_up; 1266*d6b92ffaSHans Petter Selasky continue; 1267*d6b92ffaSHans Petter Selasky } 1268*d6b92ffaSHans Petter Selasky 1269*d6b92ffaSHans Petter Selasky if (__cl_fmap_is_left_child(p_item)) { 1270*d6b92ffaSHans Petter Selasky p_item = p_item->p_up; 1271*d6b92ffaSHans Petter Selasky __cl_fmap_rot_right(p_map, p_item); 1272*d6b92ffaSHans Petter Selasky } 1273*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 1274*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED; 1275*d6b92ffaSHans Petter Selasky __cl_fmap_rot_left(p_map, p_item->p_up->p_up); 1276*d6b92ffaSHans Petter Selasky } 1277*d6b92ffaSHans Petter Selasky } 1278*d6b92ffaSHans Petter Selasky } 1279*d6b92ffaSHans Petter Selasky 1280*d6b92ffaSHans Petter Selasky cl_fmap_item_t *cl_fmap_insert(IN cl_fmap_t * const p_map, 1281*d6b92ffaSHans Petter Selasky IN const void *const p_key, 1282*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * const p_item) 1283*d6b92ffaSHans Petter Selasky { 1284*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_insert_at, *p_comp_item; 1285*d6b92ffaSHans Petter Selasky int cmp = 0; 1286*d6b92ffaSHans Petter Selasky 1287*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 1288*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 1289*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 1290*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->root.p_up == &p_map->root); 1291*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->root.color != CL_MAP_RED); 1292*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->nil.color != CL_MAP_RED); 1293*d6b92ffaSHans Petter Selasky 1294*d6b92ffaSHans Petter Selasky p_item->p_left = &p_map->nil; 1295*d6b92ffaSHans Petter Selasky p_item->p_right = &p_map->nil; 1296*d6b92ffaSHans Petter Selasky p_item->p_key = p_key; 1297*d6b92ffaSHans Petter Selasky p_item->color = CL_MAP_RED; 1298*d6b92ffaSHans Petter Selasky 1299*d6b92ffaSHans Petter Selasky /* Find the insertion location. */ 1300*d6b92ffaSHans Petter Selasky p_insert_at = &p_map->root; 1301*d6b92ffaSHans Petter Selasky p_comp_item = __cl_fmap_root(p_map); 1302*d6b92ffaSHans Petter Selasky 1303*d6b92ffaSHans Petter Selasky while (p_comp_item != &p_map->nil) { 1304*d6b92ffaSHans Petter Selasky p_insert_at = p_comp_item; 1305*d6b92ffaSHans Petter Selasky 1306*d6b92ffaSHans Petter Selasky cmp = p_map->pfn_compare(p_key, p_insert_at->p_key); 1307*d6b92ffaSHans Petter Selasky 1308*d6b92ffaSHans Petter Selasky if (!cmp) 1309*d6b92ffaSHans Petter Selasky return (p_insert_at); 1310*d6b92ffaSHans Petter Selasky 1311*d6b92ffaSHans Petter Selasky /* Traverse the tree until the correct insertion point is found. */ 1312*d6b92ffaSHans Petter Selasky if (cmp < 0) 1313*d6b92ffaSHans Petter Selasky p_comp_item = p_insert_at->p_left; 1314*d6b92ffaSHans Petter Selasky else 1315*d6b92ffaSHans Petter Selasky p_comp_item = p_insert_at->p_right; 1316*d6b92ffaSHans Petter Selasky } 1317*d6b92ffaSHans Petter Selasky 1318*d6b92ffaSHans Petter Selasky CL_ASSERT(p_insert_at != &p_map->nil); 1319*d6b92ffaSHans Petter Selasky CL_ASSERT(p_comp_item == &p_map->nil); 1320*d6b92ffaSHans Petter Selasky /* Insert the item. */ 1321*d6b92ffaSHans Petter Selasky if (p_insert_at == &p_map->root) { 1322*d6b92ffaSHans Petter Selasky p_insert_at->p_left = p_item; 1323*d6b92ffaSHans Petter Selasky /* 1324*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of 1325*d6b92ffaSHans Petter Selasky * the existing item. 1326*d6b92ffaSHans Petter Selasky */ 1327*d6b92ffaSHans Petter Selasky __cl_primitive_insert(&p_map->nil.pool_item.list_item, 1328*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item); 1329*d6b92ffaSHans Petter Selasky } else if (cmp < 0) { 1330*d6b92ffaSHans Petter Selasky p_insert_at->p_left = p_item; 1331*d6b92ffaSHans Petter Selasky /* 1332*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of 1333*d6b92ffaSHans Petter Selasky * the existing item. 1334*d6b92ffaSHans Petter Selasky */ 1335*d6b92ffaSHans Petter Selasky __cl_primitive_insert(&p_insert_at->pool_item.list_item, 1336*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item); 1337*d6b92ffaSHans Petter Selasky } else { 1338*d6b92ffaSHans Petter Selasky p_insert_at->p_right = p_item; 1339*d6b92ffaSHans Petter Selasky /* 1340*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of 1341*d6b92ffaSHans Petter Selasky * the existing item. 1342*d6b92ffaSHans Petter Selasky */ 1343*d6b92ffaSHans Petter Selasky __cl_primitive_insert(p_insert_at->pool_item.list_item.p_next, 1344*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item); 1345*d6b92ffaSHans Petter Selasky } 1346*d6b92ffaSHans Petter Selasky /* Increase the count. */ 1347*d6b92ffaSHans Petter Selasky p_map->count++; 1348*d6b92ffaSHans Petter Selasky 1349*d6b92ffaSHans Petter Selasky p_item->p_up = p_insert_at; 1350*d6b92ffaSHans Petter Selasky 1351*d6b92ffaSHans Petter Selasky /* 1352*d6b92ffaSHans Petter Selasky * We have added depth to this section of the tree. 1353*d6b92ffaSHans Petter Selasky * Rebalance as necessary as we retrace our path through the tree 1354*d6b92ffaSHans Petter Selasky * and update colors. 1355*d6b92ffaSHans Petter Selasky */ 1356*d6b92ffaSHans Petter Selasky __cl_fmap_ins_bal(p_map, p_item); 1357*d6b92ffaSHans Petter Selasky 1358*d6b92ffaSHans Petter Selasky __cl_fmap_root(p_map)->color = CL_MAP_BLACK; 1359*d6b92ffaSHans Petter Selasky 1360*d6b92ffaSHans Petter Selasky /* 1361*d6b92ffaSHans Petter Selasky * Note that it is not necessary to re-color the nil node black because all 1362*d6b92ffaSHans Petter Selasky * red color assignments are made via the p_up pointer, and nil is never 1363*d6b92ffaSHans Petter Selasky * set as the value of a p_up pointer. 1364*d6b92ffaSHans Petter Selasky */ 1365*d6b92ffaSHans Petter Selasky 1366*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_ 1367*d6b92ffaSHans Petter Selasky /* Set the pointer to the map in the map item for consistency checking. */ 1368*d6b92ffaSHans Petter Selasky p_item->p_map = p_map; 1369*d6b92ffaSHans Petter Selasky #endif 1370*d6b92ffaSHans Petter Selasky 1371*d6b92ffaSHans Petter Selasky return (p_item); 1372*d6b92ffaSHans Petter Selasky } 1373*d6b92ffaSHans Petter Selasky 1374*d6b92ffaSHans Petter Selasky static void __cl_fmap_del_bal(IN cl_fmap_t * const p_map, 1375*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * p_item) 1376*d6b92ffaSHans Petter Selasky { 1377*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_uncle; 1378*d6b92ffaSHans Petter Selasky 1379*d6b92ffaSHans Petter Selasky while ((p_item->color != CL_MAP_RED) && (p_item->p_up != &p_map->root)) { 1380*d6b92ffaSHans Petter Selasky if (__cl_fmap_is_left_child(p_item)) { 1381*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right; 1382*d6b92ffaSHans Petter Selasky 1383*d6b92ffaSHans Petter Selasky if (p_uncle->color == CL_MAP_RED) { 1384*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_BLACK; 1385*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_RED; 1386*d6b92ffaSHans Petter Selasky __cl_fmap_rot_left(p_map, p_item->p_up); 1387*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right; 1388*d6b92ffaSHans Petter Selasky } 1389*d6b92ffaSHans Petter Selasky 1390*d6b92ffaSHans Petter Selasky if (p_uncle->p_right->color != CL_MAP_RED) { 1391*d6b92ffaSHans Petter Selasky if (p_uncle->p_left->color != CL_MAP_RED) { 1392*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED; 1393*d6b92ffaSHans Petter Selasky p_item = p_item->p_up; 1394*d6b92ffaSHans Petter Selasky continue; 1395*d6b92ffaSHans Petter Selasky } 1396*d6b92ffaSHans Petter Selasky 1397*d6b92ffaSHans Petter Selasky p_uncle->p_left->color = CL_MAP_BLACK; 1398*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED; 1399*d6b92ffaSHans Petter Selasky __cl_fmap_rot_right(p_map, p_uncle); 1400*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right; 1401*d6b92ffaSHans Petter Selasky } 1402*d6b92ffaSHans Petter Selasky p_uncle->color = p_item->p_up->color; 1403*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 1404*d6b92ffaSHans Petter Selasky p_uncle->p_right->color = CL_MAP_BLACK; 1405*d6b92ffaSHans Petter Selasky __cl_fmap_rot_left(p_map, p_item->p_up); 1406*d6b92ffaSHans Petter Selasky break; 1407*d6b92ffaSHans Petter Selasky } else { 1408*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left; 1409*d6b92ffaSHans Petter Selasky 1410*d6b92ffaSHans Petter Selasky if (p_uncle->color == CL_MAP_RED) { 1411*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_BLACK; 1412*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_RED; 1413*d6b92ffaSHans Petter Selasky __cl_fmap_rot_right(p_map, p_item->p_up); 1414*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left; 1415*d6b92ffaSHans Petter Selasky } 1416*d6b92ffaSHans Petter Selasky 1417*d6b92ffaSHans Petter Selasky if (p_uncle->p_left->color != CL_MAP_RED) { 1418*d6b92ffaSHans Petter Selasky if (p_uncle->p_right->color != CL_MAP_RED) { 1419*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED; 1420*d6b92ffaSHans Petter Selasky p_item = p_item->p_up; 1421*d6b92ffaSHans Petter Selasky continue; 1422*d6b92ffaSHans Petter Selasky } 1423*d6b92ffaSHans Petter Selasky 1424*d6b92ffaSHans Petter Selasky p_uncle->p_right->color = CL_MAP_BLACK; 1425*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED; 1426*d6b92ffaSHans Petter Selasky __cl_fmap_rot_left(p_map, p_uncle); 1427*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left; 1428*d6b92ffaSHans Petter Selasky } 1429*d6b92ffaSHans Petter Selasky p_uncle->color = p_item->p_up->color; 1430*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK; 1431*d6b92ffaSHans Petter Selasky p_uncle->p_left->color = CL_MAP_BLACK; 1432*d6b92ffaSHans Petter Selasky __cl_fmap_rot_right(p_map, p_item->p_up); 1433*d6b92ffaSHans Petter Selasky break; 1434*d6b92ffaSHans Petter Selasky } 1435*d6b92ffaSHans Petter Selasky } 1436*d6b92ffaSHans Petter Selasky p_item->color = CL_MAP_BLACK; 1437*d6b92ffaSHans Petter Selasky } 1438*d6b92ffaSHans Petter Selasky 1439*d6b92ffaSHans Petter Selasky void cl_fmap_remove_item(IN cl_fmap_t * const p_map, 1440*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * const p_item) 1441*d6b92ffaSHans Petter Selasky { 1442*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_child, *p_del_item; 1443*d6b92ffaSHans Petter Selasky 1444*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 1445*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 1446*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item); 1447*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_map == p_map); 1448*d6b92ffaSHans Petter Selasky 1449*d6b92ffaSHans Petter Selasky if (p_item == cl_fmap_end(p_map)) 1450*d6b92ffaSHans Petter Selasky return; 1451*d6b92ffaSHans Petter Selasky 1452*d6b92ffaSHans Petter Selasky if ((p_item->p_right == &p_map->nil) || (p_item->p_left == &p_map->nil)) { 1453*d6b92ffaSHans Petter Selasky /* The item being removed has children on at most on side. */ 1454*d6b92ffaSHans Petter Selasky p_del_item = p_item; 1455*d6b92ffaSHans Petter Selasky } else { 1456*d6b92ffaSHans Petter Selasky /* 1457*d6b92ffaSHans Petter Selasky * The item being removed has children on both side. 1458*d6b92ffaSHans Petter Selasky * We select the item that will replace it. After removing 1459*d6b92ffaSHans Petter Selasky * the substitute item and rebalancing, the tree will have the 1460*d6b92ffaSHans Petter Selasky * correct topology. Exchanging the substitute for the item 1461*d6b92ffaSHans Petter Selasky * will finalize the removal. 1462*d6b92ffaSHans Petter Selasky */ 1463*d6b92ffaSHans Petter Selasky p_del_item = cl_fmap_next(p_item); 1464*d6b92ffaSHans Petter Selasky CL_ASSERT(p_del_item != &p_map->nil); 1465*d6b92ffaSHans Petter Selasky } 1466*d6b92ffaSHans Petter Selasky 1467*d6b92ffaSHans Petter Selasky /* Remove the item from the list. */ 1468*d6b92ffaSHans Petter Selasky __cl_primitive_remove(&p_item->pool_item.list_item); 1469*d6b92ffaSHans Petter Selasky /* Decrement the item count. */ 1470*d6b92ffaSHans Petter Selasky p_map->count--; 1471*d6b92ffaSHans Petter Selasky 1472*d6b92ffaSHans Petter Selasky /* Get the pointer to the new root's child, if any. */ 1473*d6b92ffaSHans Petter Selasky if (p_del_item->p_left != &p_map->nil) 1474*d6b92ffaSHans Petter Selasky p_child = p_del_item->p_left; 1475*d6b92ffaSHans Petter Selasky else 1476*d6b92ffaSHans Petter Selasky p_child = p_del_item->p_right; 1477*d6b92ffaSHans Petter Selasky 1478*d6b92ffaSHans Petter Selasky /* 1479*d6b92ffaSHans Petter Selasky * This assignment may modify the parent pointer of the nil node. 1480*d6b92ffaSHans Petter Selasky * This is inconsequential. 1481*d6b92ffaSHans Petter Selasky */ 1482*d6b92ffaSHans Petter Selasky p_child->p_up = p_del_item->p_up; 1483*d6b92ffaSHans Petter Selasky (*__cl_fmap_get_parent_ptr_to_item(p_del_item)) = p_child; 1484*d6b92ffaSHans Petter Selasky 1485*d6b92ffaSHans Petter Selasky if (p_del_item->color != CL_MAP_RED) 1486*d6b92ffaSHans Petter Selasky __cl_fmap_del_bal(p_map, p_child); 1487*d6b92ffaSHans Petter Selasky 1488*d6b92ffaSHans Petter Selasky /* 1489*d6b92ffaSHans Petter Selasky * Note that the splicing done below does not need to occur before 1490*d6b92ffaSHans Petter Selasky * the tree is balanced, since the actual topology changes are made by the 1491*d6b92ffaSHans Petter Selasky * preceding code. The topology is preserved by the color assignment made 1492*d6b92ffaSHans Petter Selasky * below (reader should be reminded that p_del_item == p_item in some cases). 1493*d6b92ffaSHans Petter Selasky */ 1494*d6b92ffaSHans Petter Selasky if (p_del_item != p_item) { 1495*d6b92ffaSHans Petter Selasky /* 1496*d6b92ffaSHans Petter Selasky * Finalize the removal of the specified item by exchanging it with 1497*d6b92ffaSHans Petter Selasky * the substitute which we removed above. 1498*d6b92ffaSHans Petter Selasky */ 1499*d6b92ffaSHans Petter Selasky p_del_item->p_up = p_item->p_up; 1500*d6b92ffaSHans Petter Selasky p_del_item->p_left = p_item->p_left; 1501*d6b92ffaSHans Petter Selasky p_del_item->p_right = p_item->p_right; 1502*d6b92ffaSHans Petter Selasky (*__cl_fmap_get_parent_ptr_to_item(p_item)) = p_del_item; 1503*d6b92ffaSHans Petter Selasky p_item->p_right->p_up = p_del_item; 1504*d6b92ffaSHans Petter Selasky p_item->p_left->p_up = p_del_item; 1505*d6b92ffaSHans Petter Selasky p_del_item->color = p_item->color; 1506*d6b92ffaSHans Petter Selasky } 1507*d6b92ffaSHans Petter Selasky 1508*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->nil.color != CL_MAP_RED); 1509*d6b92ffaSHans Petter Selasky 1510*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_ 1511*d6b92ffaSHans Petter Selasky /* Clear the pointer to the map since the item has been removed. */ 1512*d6b92ffaSHans Petter Selasky p_item->p_map = NULL; 1513*d6b92ffaSHans Petter Selasky #endif 1514*d6b92ffaSHans Petter Selasky } 1515*d6b92ffaSHans Petter Selasky 1516*d6b92ffaSHans Petter Selasky cl_fmap_item_t *cl_fmap_remove(IN cl_fmap_t * const p_map, 1517*d6b92ffaSHans Petter Selasky IN const void *const p_key) 1518*d6b92ffaSHans Petter Selasky { 1519*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item; 1520*d6b92ffaSHans Petter Selasky 1521*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map); 1522*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED); 1523*d6b92ffaSHans Petter Selasky 1524*d6b92ffaSHans Petter Selasky /* Seek the node with the specified key */ 1525*d6b92ffaSHans Petter Selasky p_item = cl_fmap_get(p_map, p_key); 1526*d6b92ffaSHans Petter Selasky 1527*d6b92ffaSHans Petter Selasky cl_fmap_remove_item(p_map, p_item); 1528*d6b92ffaSHans Petter Selasky 1529*d6b92ffaSHans Petter Selasky return (p_item); 1530*d6b92ffaSHans Petter Selasky } 1531*d6b92ffaSHans Petter Selasky 1532*d6b92ffaSHans Petter Selasky void cl_fmap_merge(OUT cl_fmap_t * const p_dest_map, 1533*d6b92ffaSHans Petter Selasky IN OUT cl_fmap_t * const p_src_map) 1534*d6b92ffaSHans Petter Selasky { 1535*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item, *p_item2, *p_next; 1536*d6b92ffaSHans Petter Selasky 1537*d6b92ffaSHans Petter Selasky CL_ASSERT(p_dest_map); 1538*d6b92ffaSHans Petter Selasky CL_ASSERT(p_src_map); 1539*d6b92ffaSHans Petter Selasky 1540*d6b92ffaSHans Petter Selasky p_item = cl_fmap_head(p_src_map); 1541*d6b92ffaSHans Petter Selasky 1542*d6b92ffaSHans Petter Selasky while (p_item != cl_fmap_end(p_src_map)) { 1543*d6b92ffaSHans Petter Selasky p_next = cl_fmap_next(p_item); 1544*d6b92ffaSHans Petter Selasky 1545*d6b92ffaSHans Petter Selasky /* Remove the item from its current map. */ 1546*d6b92ffaSHans Petter Selasky cl_fmap_remove_item(p_src_map, p_item); 1547*d6b92ffaSHans Petter Selasky /* Insert the item into the destination map. */ 1548*d6b92ffaSHans Petter Selasky p_item2 = 1549*d6b92ffaSHans Petter Selasky cl_fmap_insert(p_dest_map, cl_fmap_key(p_item), p_item); 1550*d6b92ffaSHans Petter Selasky /* Check that the item was successfully inserted. */ 1551*d6b92ffaSHans Petter Selasky if (p_item2 != p_item) { 1552*d6b92ffaSHans Petter Selasky /* Put the item in back in the source map. */ 1553*d6b92ffaSHans Petter Selasky p_item2 = 1554*d6b92ffaSHans Petter Selasky cl_fmap_insert(p_src_map, cl_fmap_key(p_item), 1555*d6b92ffaSHans Petter Selasky p_item); 1556*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item2 == p_item); 1557*d6b92ffaSHans Petter Selasky } 1558*d6b92ffaSHans Petter Selasky p_item = p_next; 1559*d6b92ffaSHans Petter Selasky } 1560*d6b92ffaSHans Petter Selasky } 1561*d6b92ffaSHans Petter Selasky 1562*d6b92ffaSHans Petter Selasky static void __cl_fmap_delta_move(IN OUT cl_fmap_t * const p_dest, 1563*d6b92ffaSHans Petter Selasky IN OUT cl_fmap_t * const p_src, 1564*d6b92ffaSHans Petter Selasky IN OUT cl_fmap_item_t ** const pp_item) 1565*d6b92ffaSHans Petter Selasky { 1566*d6b92ffaSHans Petter Selasky cl_fmap_item_t __attribute__((__unused__)) *p_temp; 1567*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_next; 1568*d6b92ffaSHans Petter Selasky 1569*d6b92ffaSHans Petter Selasky /* 1570*d6b92ffaSHans Petter Selasky * Get the next item so that we can ensure that pp_item points to 1571*d6b92ffaSHans Petter Selasky * a valid item upon return from the function. 1572*d6b92ffaSHans Petter Selasky */ 1573*d6b92ffaSHans Petter Selasky p_next = cl_fmap_next(*pp_item); 1574*d6b92ffaSHans Petter Selasky /* Move the old item from its current map the the old map. */ 1575*d6b92ffaSHans Petter Selasky cl_fmap_remove_item(p_src, *pp_item); 1576*d6b92ffaSHans Petter Selasky p_temp = cl_fmap_insert(p_dest, cl_fmap_key(*pp_item), *pp_item); 1577*d6b92ffaSHans Petter Selasky /* We should never have duplicates. */ 1578*d6b92ffaSHans Petter Selasky CL_ASSERT(p_temp == *pp_item); 1579*d6b92ffaSHans Petter Selasky /* Point pp_item to a valid item in the source map. */ 1580*d6b92ffaSHans Petter Selasky (*pp_item) = p_next; 1581*d6b92ffaSHans Petter Selasky } 1582*d6b92ffaSHans Petter Selasky 1583*d6b92ffaSHans Petter Selasky void cl_fmap_delta(IN OUT cl_fmap_t * const p_map1, 1584*d6b92ffaSHans Petter Selasky IN OUT cl_fmap_t * const p_map2, 1585*d6b92ffaSHans Petter Selasky OUT cl_fmap_t * const p_new, OUT cl_fmap_t * const p_old) 1586*d6b92ffaSHans Petter Selasky { 1587*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item1, *p_item2; 1588*d6b92ffaSHans Petter Selasky int cmp; 1589*d6b92ffaSHans Petter Selasky 1590*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map1); 1591*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map2); 1592*d6b92ffaSHans Petter Selasky CL_ASSERT(p_new); 1593*d6b92ffaSHans Petter Selasky CL_ASSERT(p_old); 1594*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_fmap_empty(p_new)); 1595*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_fmap_empty(p_old)); 1596*d6b92ffaSHans Petter Selasky 1597*d6b92ffaSHans Petter Selasky p_item1 = cl_fmap_head(p_map1); 1598*d6b92ffaSHans Petter Selasky p_item2 = cl_fmap_head(p_map2); 1599*d6b92ffaSHans Petter Selasky 1600*d6b92ffaSHans Petter Selasky while (p_item1 != cl_fmap_end(p_map1) && p_item2 != cl_fmap_end(p_map2)) { 1601*d6b92ffaSHans Petter Selasky cmp = p_map1->pfn_compare(cl_fmap_key(p_item1), 1602*d6b92ffaSHans Petter Selasky cl_fmap_key(p_item2)); 1603*d6b92ffaSHans Petter Selasky if (cmp < 0) { 1604*d6b92ffaSHans Petter Selasky /* We found an old item. */ 1605*d6b92ffaSHans Petter Selasky __cl_fmap_delta_move(p_old, p_map1, &p_item1); 1606*d6b92ffaSHans Petter Selasky } else if (cmp > 0) { 1607*d6b92ffaSHans Petter Selasky /* We found a new item. */ 1608*d6b92ffaSHans Petter Selasky __cl_fmap_delta_move(p_new, p_map2, &p_item2); 1609*d6b92ffaSHans Petter Selasky } else { 1610*d6b92ffaSHans Petter Selasky /* Move both forward since they have the same key. */ 1611*d6b92ffaSHans Petter Selasky p_item1 = cl_fmap_next(p_item1); 1612*d6b92ffaSHans Petter Selasky p_item2 = cl_fmap_next(p_item2); 1613*d6b92ffaSHans Petter Selasky } 1614*d6b92ffaSHans Petter Selasky } 1615*d6b92ffaSHans Petter Selasky 1616*d6b92ffaSHans Petter Selasky /* Process the remainder if the end of either source map was reached. */ 1617*d6b92ffaSHans Petter Selasky while (p_item2 != cl_fmap_end(p_map2)) 1618*d6b92ffaSHans Petter Selasky __cl_fmap_delta_move(p_new, p_map2, &p_item2); 1619*d6b92ffaSHans Petter Selasky 1620*d6b92ffaSHans Petter Selasky while (p_item1 != cl_fmap_end(p_map1)) 1621*d6b92ffaSHans Petter Selasky __cl_fmap_delta_move(p_old, p_map1, &p_item1); 1622*d6b92ffaSHans Petter Selasky } 1623