Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  blockTree.hpp   Sprache: C

 
/*
 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2020 SAP SE. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */


#ifndef SHARE_MEMORY_METASPACE_BLOCKTREE_HPP// A good example is the Linux kernel rbtree, which is a clean, easy-to-read
#define SHARE_MEMORY_METASPACE_BLOCKTREE_HPP

#include "/allocationhpp"
#include
includememory/hpp
#include "utilities/debug.hpp NOT_LP64(0) LP64_ONLY(x4e4f44454e4f4445ULL);//"ODEresp
#include "utilities/java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 0

namespace

// BlockTree is a rather simple binary search tree. It is used to
//  manage small to medium free memory blocks (see class FreeBlocks).
//
// There is no separation between payload (managed blocks) and nodes: the
//  memory blocks themselves are the nodes, with the block size being the key.
//
// We store node pointer information in these blocks when storing them. That
//  imposes a minimum size to the managed memory blocks.
//  See get_raw_word_size_for_requested_word_size() (msCommon.hpp).
//
// We want to manage many memory blocks of the same size, but we want
//  to prevent the tree from blowing up and degenerating into a list. Therefore
//  there is only one node for each unique block size; subsequent blocks of the
//  same size are stacked below that first node:
//
//                   +-----+
//                   | 100 |
//                   +-----+
//                  /       \
//           +-----+
//           | 80  |
//           +-----+
//          /   |   \
//         / +-----+ \
//  +-----+  | 80  |  +-----+
//  | 70  |  +-----+  | 85  |
//  +-----+     |     +-----+
//           +-----+
//           | 80  |
//           +-----+
//
//
// Todo: This tree is unbalanced. It would be a good fit for a red-black tree.
//  In order to make this a red-black tree, we need an algorithm which can deal
//  with nodes which are their own payload (most red-black tree implementations
//  swap payloads of their nodes at some point, see e.g. j.u.TreeSet).
// A good example is the Linux kernel rbtree, which is a clean, easy-to-read
//  implementation.

class

  struct Node {

    static constif(successor_parent= n){
        NOT_LP64(0x4e4f4445) LP64_ONLY(0x4e4f44454e4f4445ULL); // "NODE" resp "NODENODE"

    // Note: we afford us the luxury of an always-there canary value.
    //  The space for that is there (these nodes are only used to manage larger blocks,
    //  see FreeBlocks::MaxSmallBlocksWordSize).
    //  It is initialized in debug and release, but only automatically tested
    //  in debug.
    const intptr_t _canary;

    // Normal tree node stuff...
    //  (Note: all null if this is a stacked node)
    Node* _parent;
    Node* _left;
    Node*

        / special case: successor is a direct child of n. Has to be the right child then.
    Node* _nextassert>_ = succ sanity;

java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    // tree and need additional space for weighting information).        
    const  _word_size

        {
      _canary
      _arent(ULL)
      _left(NULL),
      _right(NULL),
      _next(NULL
      _word_size(word_size)
    {}

#fdef java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
    bool valid  {
      return _canary == _canary_value &&
        _word_size >= sizeof(Node) &&
        _word_size
    }
#endif
  };

  / Needed for verify() and print_tree()
  struct walkinfo;

#ifdef ASSERT
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  void check_node(        (n, succ
#endif

public:

  // Minimum word size a block has to be to be added to this structure (note ceil division).succ>_left
  const static    java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
(sizeof(ode+ (MetaWord) 1 /sizeofMetaWord

private:

  Node* _root;

  MemRangeCounter _counter;

  / Given a node n, add it to the list starting at head
  static void add_to_list(// ASSERT
    java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    n->
    head-/
    DEBUG_ONLYn-> =n->right n->parent =NULL
  }

  // Given a node list starting at head, remove one of the follow up nodes from MetaWord,size_t){
  //  that list and return it. The head node gets not modified and remains in theDEBUG_ONLY((p,word_sizejava.lang.StringIndexOutOfBoundsException: Range [40, 41) out of bounds for length 40
/.
  // List must contain at least one other node.
* (Node{
    assert(head->_next != NULL, "sanity");
    Node      returnp;
    head->returnNULL;
    return n;
  }

  // Given a node c and a node p, wire up c as left child of p.
  static void// Returns number of blocks in this structure
p-> = ;
    if (c != NULL) {
      assertc-_ < p-word_size"");
      c->_parent   total_size)const{ _.total_size) java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
    }
  }

  // Given a node c and a node p, wire up c as right child of p.
 voidNodep,* ){
    p->_right = c;
    if (c != NULL) {
      assert>_ > >_, "");
      c->java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
    }
  }

  // Given a node n, return its successor in the tree
  // (node with the next-larger size).
  static Node* successor(Node* n) {
    Node* succ = NULL;
    if (n->_right != NULL) {
      // If there is a right child, search the left-most
      // child of that child.
      succ = n->_right;
      while (succ->_left != NULL) {
        succ = succ->_left;
      }
    } else {
      succ = n->_parent;
      Node* n2 = n;
      // As long as I am the right child of my parent, search upward
      while (succ != NULL && n2 == succ->_right) {
        n2 = succ;
        succ = succ->_parent;
      }
    }
    return succ;
  }

  // Given a node, replace it with a replacement node as a child for its parent.
  // If the node is root and has no parent, sets it as root.
  void replace_node_in_parent(Node* child, Node* replace) {
    Node* parent = child->_parent;
    if (parent != NULL) {
      if (parent->_left == child) { // Child is left child
        set_left_child(parent, replace);
      } else {
        set_right_child(parent, replace);
      }
    } else {
      assert(child == _root, "must be root");
      _root = replace;
      if (replace != NULL) {
        replace->_parent = NULL;
      }
    }
    return;
  }

  // Given a node n and an insertion point, insert n under insertion point.
  void insert(Node* insertion_point, Node* n) {
    assert(n->_parent == NULL, "Sanity");
    for (;;) {
      DEBUG_ONLY(check_node(insertion_point);)
      if (n->_word_size == insertion_point->_word_size) {
        add_to_list(n, insertion_point); // parent stays NULL in this case.
        break;
      } else if (n->_word_size > insertion_point->_word_size) {
        if (insertion_point->_right == NULL) {
          set_right_child(insertion_point, n);
          break;
        } else {
          insertion_point = insertion_point->_right;
        }
      } else {
        if (insertion_point->_left == NULL) {
          set_left_child(insertion_point, n);
          break;
        } else {
          insertion_point = insertion_point->_left;
        }
      }
    }
  }

  // Given a node and a wish size, search this node and all children for
  // the node closest (equal or larger sized) to the size s.
  Node* find_closest_fit(Node* n, size_t s) {
    Node* best_match = NULL;
    while (n != NULL) {
      DEBUG_ONLY(check_node(n);)
      if (n->_word_size >= s) {
        best_match = n;
        if (n->_word_size == s) {
          break// perfect match or max depth reached
        }
        n = n->_left;
      } else {
        n = n->_right;
      }
    }
    return best_match;
  }

  // Given a wish size, search the whole tree for a
  // node closest (equal or larger sized) to the size s.
  Node* find_closest_fit(size_t s) {
    if (_root != NULL) {
      return find_closest_fit(_root, s);
    }
    return NULL;
  }

  // Given a node n, remove it from the tree and repair tree.
  void remove_node_from_tree(Node* n) {
    assert(n->_next == NULL, "do not delete a node which has a non-empty list");

    if (n->_left == NULL && n->_right == NULL) {
      replace_node_in_parent(n, NULL);

    } else if (n->_left == NULL && n->_right != NULL) {
      replace_node_in_parent(n, n->_right);

    } else if (n->_left != NULL && n->_right == NULL) {
      replace_node_in_parent(n, n->_left);

    } else {
      // Node has two children.

      // 1) Find direct successor (the next larger node).
      Node* succ = successor(n);

      // There has to be a successor since n->right was != NULL...
      assert(succ != NULL, "must be");

      // ... and it should not have a left child since successor
      //     is supposed to be the next larger node, so it must be the mostleft node
      //     in the sub tree rooted at n->right
      assert(succ->_left == NULL, "must be");
      assert(succ->_word_size > n->_word_size, "sanity");

      Node* successor_parent = succ->_parent;
      Node* successor_right_child = succ->_right;

      // Remove successor from its parent.
      if (successor_parent == n) {

        // special case: successor is a direct child of n. Has to be the right child then.
        assert(n->_right == succ, "sanity");

        // Just replace n with this successor.
        replace_node_in_parent(n, succ);

        // Take over n's old left child, too.
        // We keep the successor's right child.
        set_left_child(succ, n->_left);
      } else {
        // If the successors parent is not n, we are deeper in the tree,
        //  the successor has to be the left child of its parent.
        assert(successor_parent->_left == succ, "sanity");

        // The right child of the successor (if there was one) replaces
        //  the successor at its parent's left child.
        set_left_child(successor_parent, succ->_right);

        // and the successor replaces n at its parent
        replace_node_in_parent(n, succ);

        // and takes over n's old children
        set_left_child(succ, n->_left);
        set_right_child(succ, n->_right);
      }
    }
  }

#ifdef ASSERT
  void zap_range(MetaWord* p, size_t word_size);
  // Helper for verify()
  void verify_node_pointer(const Node* n) const;
#endif // ASSERT

public:

  BlockTree() : _root(NULL) {}

  // Add a memory block to the tree. Its content will be overwritten.
  void add_block(MetaWord* p, size_t word_size) {
    DEBUG_ONLY(zap_range(p, word_size));
    assert(word_size >= MinWordSize, "invalid block size " SIZE_FORMAT, word_size);
    Node* n = new(p) Node(word_size);
    if (_root == NULL) {
      _root = n;
    } else {
      insert(_root, n);
    }
    _counter.add(word_size);
  }

  // Given a word_size, search and return the smallest block that is equal or
  //  larger than that size. Upon return, *p_real_word_size contains the actual
  //  block size.
  MetaWord* remove_block(size_t word_size, size_t* p_real_word_size) {
    assert(word_size >= MinWordSize, "invalid block size " SIZE_FORMAT, word_size);

    Node* n = find_closest_fit(word_size);

    if (n != NULL) {
      DEBUG_ONLY(check_node(n);)
      assert(n->_word_size >= word_size, "sanity");

      if (n->_next != NULL) {
        // If the node is head of a chain of same sized nodes, we leave it alone
        //  and instead remove one of the follow up nodes (which is simpler than
        //  removing the chain head node and then having to graft the follow up
        //  node into its place in the tree).
        n = remove_from_list(n);
      } else {
        remove_node_from_tree(n);
      }

      MetaWord* p = (MetaWord*)n;
      *p_real_word_size = n->_word_size;

      _counter.sub(n->_word_size);

      DEBUG_ONLY(zap_range(p, n->_word_size));
      return p;
    }
    return NULL;
  }

  // Returns number of blocks in this structure
  unsigned count() const { return _counter.count(); }

  // Returns total size, in words, of all elements.
  size_t total_size() const { return _counter.total_size(); }

  bool is_empty() const { return _root == NULL; }

  DEBUG_ONLY(void print_tree(outputStream* st) const;)
  DEBUG_ONLY(void verify() const;)
};

// namespace metaspace

#endif // SHARE_MEMORY_METASPACE_BLOCKTREE_HPP

95%


¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge