⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ck_coredirtree.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
字号:
/* * Copyright (C) 1998, 1999, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Note: This code adapted from my tree package.  Experience suggests * that trying to debug this code in the kernel is lunacy.  Debug the * tree package as an application and then re-convert by changing the * function names.  I have tried to minimize the name changes. */#include <disk/DiskFrame.hxx>#include <kerninc/kernel.hxx>#include <kerninc/MsgLog.hxx>#include <kerninc/Checkpoint.hxx>#define dbg_insert  1u#define dbg_remove  2u#define dbg_flags   ( 0u )#define dbg_find    ( 0u )#define DBCOND(x) (dbg_##x & dbg_flags)#define DEBUG(x) if DBCOND(x)#define TREENODE CoreDirent#define TREEKEY OID#define TREE_NIL CkNIL#define TREE_RED CoreDirent::red#define TREE_BLACK CoreDirent::black#define tree_succ(x) (x)->Successor()/* Returns new root */TREENODE *CoreDirent::B_Insert(TREENODE *root, TREENODE *z){#ifdef VERBOSE  printf("Insert node 0x%08x into 0x%08x\n", z, root);  fflush(stdout);#endif    int whichcase;    z->parent = TREE_NIL;  z->left = TREE_NIL;  z->right = TREE_NIL;    TREENODE *y = TREE_NIL;  TREENODE *x = root;  DEBUG(insert)    assert( Tree_Validate(root, root) );    while (x != TREE_NIL) {    assert (x->left == TREE_NIL || x->left->parent == x);    assert (x->right == TREE_NIL || x->right->parent == x);    y = x;    if ( Tree_Compare(z,x) < 0 ) {      x = x->left;    }    else {      x = x->right;    }  }  z->parent = y;  if (y == TREE_NIL) {    whichcase = 1;    root = z;  }  else {    whichcase = 2;        if ( Tree_Compare(z, y) < 0 )      y->left = z;    else      y->right = z;    assert (y->left == TREE_NIL || y->left->parent == y);    assert (y->right == TREE_NIL || y->right->parent == y);  }  assert(root->parent == TREE_NIL);  DEBUG(insert)    assert ( Tree_Validate(root, root) ) ;  return root;}TREENODE *CoreDirent::RB_Insert(TREENODE * root, TREENODE *x){  root = B_Insert(root, x);  x->color = TREE_RED;  while (x != root && x->parent->color == TREE_RED) {    assert (x->parent->parent);        if (x->parent == x->parent->parent->left) {      TREENODE *y = x->parent->parent->right;      if (y->color == TREE_RED) {	x->parent->color = TREE_BLACK;	y->color = TREE_BLACK;	x->parent->parent->color = TREE_RED;	x = x->parent->parent;      }      else {	if (x == x->parent->right) {	  x = x->parent;	  root = RB_Tree_LeftRotate(root, x);	}	x->parent->color = TREE_BLACK;	assert (x->parent->parent);	x->parent->parent->color = TREE_RED;	root = RB_Tree_RightRotate(root, x->parent->parent);      }    }    else {      TREENODE *y = x->parent->parent->left;      if (y->color == TREE_RED) {	x->parent->color = TREE_BLACK;	y->color = TREE_BLACK;	assert (x->parent->parent != TREE_NIL);	x->parent->parent->color = TREE_RED;	x = x->parent->parent;      }      else {	if (x == x->parent->left) {	  x = x->parent;	  root = RB_Tree_RightRotate(root, x);	}	x->parent->color = TREE_BLACK;	assert (x->parent->parent != TREE_NIL);	x->parent->parent->color = TREE_RED;	root = RB_Tree_LeftRotate(root, x->parent->parent);      }    }  }  root->color = TREE_BLACK;  assert(root->parent == TREE_NIL);  DEBUG(insert)    assert ( Tree_Validate(root, root) );  return root;}TREENODE *CoreDirent::RB_Tree_Remove_Fixup(TREENODE * root, TREENODE *x){  TREENODE *w = TREE_NIL;  if (x->parent == TREE_NIL)	/* deleted last node in tree */    return root;  #ifdef BROKEN  assert (x != TREE_NIL);#endif    while ((x != root) && (x->color == TREE_BLACK)) {    /* MacManis checks x == nilnode && x.parent.left == null OR */    if (x == x->parent->left) {      w = x->parent->right;      if (w->color == TREE_RED) {	w->color = TREE_BLACK;	assert (x->parent != TREE_NIL);	x->parent->color = TREE_RED;	root = RB_Tree_LeftRotate(root, x->parent);	w = x->parent->right;      }      if ((w->left->color == TREE_BLACK) && (w->right->color == TREE_BLACK)) {	assert (w != TREE_NIL);	w->color = TREE_RED;	x = x->parent;		/* move up the tree */      }      else {	if (w->right->color == TREE_BLACK) {	  w->left->color = TREE_BLACK;	  assert (w != TREE_NIL);	  w->color = TREE_RED;	  root = RB_Tree_RightRotate(root, w);	  w = x->parent->right;	}	w->color = x->parent->color;	x->parent->color = TREE_BLACK;	w->right->color = TREE_BLACK;	root = RB_Tree_LeftRotate(root, x->parent);	x = root;      }    }    else {      w = x->parent->left;      if (w->color == TREE_RED) {	w->color = TREE_BLACK;	assert (x->parent != TREE_NIL);	x->parent->color = TREE_RED;	root = RB_Tree_RightRotate(root, x->parent);	w = x->parent->left;      }      if ((w->right->color == TREE_BLACK) && (w->left->color == TREE_BLACK)) {	assert (w != TREE_NIL);	w->color = TREE_RED;	x = x->parent;      }      else {	if (w->left->color == TREE_BLACK) {	  w->right->color = TREE_BLACK;	  assert (w != TREE_NIL);	  w->color = TREE_RED;	  root = RB_Tree_LeftRotate(root, w);	  w = x->parent->left;	}	w->color = x->parent->color;	x->parent->color = TREE_BLACK;	w->left->color = TREE_BLACK;	root = RB_Tree_RightRotate(root, x->parent);	x = root;      }    }  }    x->color = TREE_BLACK;  assert(root->parent == TREE_NIL);  return root;}TREENODE *CoreDirent::RB_Remove(TREENODE * root, TREENODE *z){#ifdef VERBOSE  printf("Remove node 0x%08x from 0x%08x\n", z, root);  fflush(stdout);#endif    TREENODE *y = TREE_NIL;  TREENODE *x = TREE_NIL;    DEBUG(remove)    assert ( Tree_Validate(root, root) );  int whichcase = 0;    TREE_NIL->color = TREE_BLACK;    assert (z != TREE_NIL);    if (z->left == TREE_NIL || z->right == TREE_NIL) {    whichcase |= 0x1;    /* Node to delete has only one child or none; can just splice it     * out.     */    y = z;  }  else {    /* Node to delete has two children.  Find it's suceessor and     * splice successor in in place of deleted node.     */    y = tree_succ(z);  }  assert(y != TREE_NIL);  /* We now know that y has at most one child.  Make x point to that   * child   */  x = (y->left != TREE_NIL) ? y->left : y->right;  x->parent = y->parent;	/* OKAY if X is TREE_NIL per CLR p. 273 */  /* If y was the root, have to update the tree. */  if (y->parent == TREE_NIL) {    whichcase |= 0x10;    root = x;  }  else {    whichcase |= 0x20;    if (y == y->parent->left) {      y->parent->left = x;    }    else {      y->parent->right = x;    }  }#ifndef NDEBUG  DEBUG(remove) {    if ( Tree_FindReference(root, y) ) {      MsgLog::printf("x=0x%08x, y=0x%08x, z=0x%08x root=0x%08x\n", x,		     y, z, root);      MsgLog::fatal("Deleted node 0x%08x still referenced before fixup!\n",		    y);    }  }#endif  /* Until I actually understand the fixup transformation, do this   * just as the book would have us do and then fix the fact that the   * wrong thing was deleted after the fact.   */      if (y != z) {    z->oid = y->oid;    z->lid = y->lid;    z->count = y->count;  }    if ( y->color == TREE_BLACK )    root = RB_Tree_Remove_Fixup(root, x);#ifndef NDEBUG  DEBUG(remove) {    if ( Tree_FindReference(root, (y!=z) ? y : z) )      MsgLog::printf("Deleted znode 0x%08x still referenced by after fixup!\n",		     z);    if ( Tree_Validate(root, root) == false )      MsgLog::fatal("Bad post-remove validation, case 0x%08x\n",		    whichcase);  }#endif  if (y != z) {#ifndef NDEBUG    DEBUG(remove) {      if ( Tree_FindReference(root, y) )	MsgLog::printf("Deleted ynode (post fixup) 0x%08x still referenced by after fixup!\n",		       z);    }#endif    /* The tree is now correct, but for the slight detail that we have     * deleted the wrong node.  It needed to be done that way for     * rb_remove_fixup to work.  At this point, Y is unreferenced, and     * Z (the node we intended to delete) is firmly wired into the     * tree.  Put Y in in Z's place and restore the old value to Z:     */    y->parent = z->parent;    y->left = z->left;    y->right = z->right;    y->oid = z->oid;    y->lid = z->lid;    y->count = z->count;    y->color = z->color;    if (y->parent != TREE_NIL) {      if (y->parent->left == z)	y->parent->left = y;      else	y->parent->right = y;    }    if (y->left != TREE_NIL)      y->left->parent = y;    if (y->right != TREE_NIL)      y->right->parent = y;    if (root == z)      root = y;  }      #ifndef NDEBUG  DEBUG(remove) {    if ( Tree_FindReference(root, z) )      MsgLog::printf("Deleted znode (post fixup) 0x%08x still referenced by after fixup!\n",		     z);        if ( Tree_Validate(root, root) == false ) {      MsgLog::fatal("Bad post-remove validation, case 0x%08x\n",		    whichcase);    }  }#endif    return root;}TREENODE *CoreDirent::RB_Tree_RightRotate(TREENODE *root, TREENODE *y){  TREENODE *x = y->left;  y->left = x->right;  if (x->right != TREE_NIL)    x->right->parent = y;  x->parent = y->parent;  if (x->parent == TREE_NIL)    root = x;  else if (y == y->parent->left)    y->parent->left = x;  else    y->parent->right = x;  x->right = y;  y->parent = x;  assert(root->parent == TREE_NIL);  return root;}TREENODE *CoreDirent::RB_Tree_LeftRotate(TREENODE *root, TREENODE *x){  TREENODE *y = x->right;  x->right = y->left;  if (y->left != TREE_NIL)    y->left->parent = x;  y->parent = x->parent;  if (x->parent == TREE_NIL)    root = y;  else if (x == x->parent->left)    x->parent->left = y;  else    x->parent->right = y;  y->left = x;  x->parent = y;  assert(root->parent == TREE_NIL);  return root;}#if 0/* Preserved for reasons of ancient history until I decide that * unmerged trees are the way to go. */boolCoreDirent::IsLessThan(CklogDirent *n){  if (oid < n->oid)    return true;  if (oid > n->oid)    return false;  /* The current version should always sort lower */  if (generation < n->generation)    return true;  return false;}#endifCoreDirent *CoreDirent::Tree_Find(CoreDirent * root, OID oid){  CoreDirent *n = root;    while (n != CkNIL) {    DEBUG(find)      MsgLog::printf("tree_find: Considering n = 0x%08x\n", n);    if (n->oid == oid) {      DEBUG(find)	MsgLog::printf("tree_find: return w/ n = 0x%08x\n", n);      return n;    }    else if (n->oid > oid)      n = n->left;    else      n = n->right;  }  DEBUG(find)    MsgLog::printf("tree_find: return w/ n = 0x%08x\n", CkNIL);  return CkNIL;}CoreDirent *CoreDirent::Tree_Find_Frame(CoreDirent * root, OID oid){  oid = oid - (oid % EROS_OBJECTS_PER_FRAME);    CoreDirent *n = root;    while (n != CkNIL) {    DEBUG(find)      MsgLog::printf("tree_find: Considering n = 0x%08x\n", n);    OID noid = (n->oid - (n->oid % EROS_OBJECTS_PER_FRAME));     if (noid == oid) {      DEBUG(find)	MsgLog::printf("tree_find: return w/ n = 0x%08x\n", n);      return n;    }    else if (noid > oid)      n = n->left;    else      n = n->right;  }  DEBUG(find)    MsgLog::printf("tree_find: return w/ n = 0x%08x\n", CkNIL);  return CkNIL;}#ifndef NDEBUGboolCoreDirent::Tree_Validate(CoreDirent *root, CoreDirent *node){  if (node == CkNIL)    return true;    if (node == root && node->parent != CkNIL)    return false;    if (node != root && node->parent == CkNIL)    return false;  if (node->left != CkNIL && node->left->parent != node)    return false;  if (node->left != CkNIL && node->left->IsLessThan(node) == false)    return false;    if (node->right != CkNIL && node->right->parent != node)    return false;  if (node->right != CkNIL && node->IsLessThan(node->right) == false)    return false;  if (!Tree_Validate(root, node->left))    return false;    return Tree_Validate(root, node->right);}CoreDirent *CoreDirent::Tree_FindReference(CoreDirent *tree, CoreDirent *node){  if (tree == CkNIL) {    return 0;  }    if (tree == node) {    return tree;  }  assert (tree->left != tree);  assert (tree->right != tree);    CoreDirent *ref;    ref = Tree_FindReference(tree->left, node);  if (ref)    return ref;    ref = Tree_FindReference(tree->right, node);  return ref;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -