github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/database/internal/treap/common.go (about)

     1  // Copyright (c) 2015-2016 The btcsuite developers
     2  // Copyright (c) 2016 The Dash developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package treap
     7  
     8  import (
     9  	"math/rand"
    10  	"time"
    11  )
    12  
    13  const (
    14  	// staticDepth is the size of the static array to use for keeping track
    15  	// of the parent stack during treap iteration.  Since a treap has a very
    16  	// high probability that the tree height is logarithmic, it is
    17  	// exceedingly unlikely that the parent stack will ever exceed this size
    18  	// even for extremely large numbers of items.
    19  	staticDepth = 128
    20  
    21  	// nodeFieldsSize is the size the fields of each node takes excluding
    22  	// the contents of the key and value.  It assumes 64-bit pointers so
    23  	// technically it is smaller on 32-bit platforms, but overestimating the
    24  	// size in that case is acceptable since it avoids the need to import
    25  	// unsafe.  It consists of 24-bytes for each key and value + 8 bytes for
    26  	// each of the priority, left, and right fields (24*2 + 8*3).
    27  	nodeFieldsSize = 72
    28  )
    29  
    30  var (
    31  	// emptySlice is used for keys that have no value associated with them
    32  	// so callers can distinguish between a key that does not exist and one
    33  	// that has no value associated with it.
    34  	emptySlice = make([]byte, 0)
    35  )
    36  
    37  // treapNode represents a node in the treap.
    38  type treapNode struct {
    39  	key      []byte
    40  	value    []byte
    41  	priority int
    42  	left     *treapNode
    43  	right    *treapNode
    44  }
    45  
    46  // nodeSize returns the number of bytes the specified node occupies including
    47  // the struct fields and the contents of the key and value.
    48  func nodeSize(node *treapNode) uint64 {
    49  	return nodeFieldsSize + uint64(len(node.key)+len(node.value))
    50  }
    51  
    52  // newTreapNode returns a new node from the given key, value, and priority.  The
    53  // node is not initially linked to any others.
    54  func newTreapNode(key, value []byte, priority int) *treapNode {
    55  	return &treapNode{key: key, value: value, priority: priority}
    56  }
    57  
    58  // parentStack represents a stack of parent treap nodes that are used during
    59  // iteration.  It consists of a static array for holding the parents and a
    60  // dynamic overflow slice.  It is extremely unlikely the overflow will ever be
    61  // hit during normal operation, however, since a treap's height is
    62  // probabilistic, the overflow case needs to be handled properly.  This approach
    63  // is used because it is much more efficient for the majority case than
    64  // dynamically allocating heap space every time the treap is iterated.
    65  type parentStack struct {
    66  	index    int
    67  	items    [staticDepth]*treapNode
    68  	overflow []*treapNode
    69  }
    70  
    71  // Len returns the current number of items in the stack.
    72  func (s *parentStack) Len() int {
    73  	return s.index
    74  }
    75  
    76  // At returns the item n number of items from the top of the stack, where 0 is
    77  // the topmost item, without removing it.  It returns nil if n exceeds the
    78  // number of items on the stack.
    79  func (s *parentStack) At(n int) *treapNode {
    80  	index := s.index - n - 1
    81  	if index < 0 {
    82  		return nil
    83  	}
    84  
    85  	if index < staticDepth {
    86  		return s.items[index]
    87  	}
    88  
    89  	return s.overflow[index-staticDepth]
    90  }
    91  
    92  // Pop removes the top item from the stack.  It returns nil if the stack is
    93  // empty.
    94  func (s *parentStack) Pop() *treapNode {
    95  	if s.index == 0 {
    96  		return nil
    97  	}
    98  
    99  	s.index--
   100  	if s.index < staticDepth {
   101  		node := s.items[s.index]
   102  		s.items[s.index] = nil
   103  		return node
   104  	}
   105  
   106  	node := s.overflow[s.index-staticDepth]
   107  	s.overflow[s.index-staticDepth] = nil
   108  	return node
   109  }
   110  
   111  // Push pushes the passed item onto the top of the stack.
   112  func (s *parentStack) Push(node *treapNode) {
   113  	if s.index < staticDepth {
   114  		s.items[s.index] = node
   115  		s.index++
   116  		return
   117  	}
   118  
   119  	// This approach is used over append because reslicing the slice to pop
   120  	// the item causes the compiler to make unneeded allocations.  Also,
   121  	// since the max number of items is related to the tree depth which
   122  	// requires expontentially more items to increase, only increase the cap
   123  	// one item at a time.  This is more intelligent than the generic append
   124  	// expansion algorithm which often doubles the cap.
   125  	index := s.index - staticDepth
   126  	if index+1 > cap(s.overflow) {
   127  		overflow := make([]*treapNode, index+1)
   128  		copy(overflow, s.overflow)
   129  		s.overflow = overflow
   130  	}
   131  	s.overflow[index] = node
   132  	s.index++
   133  }
   134  
   135  func init() {
   136  	rand.Seed(time.Now().UnixNano())
   137  }