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 }