github.com/m3db/m3@v1.5.0/src/aggregator/aggregation/quantile/cm/list.go (about) 1 // Copyright (c) 2016 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package cm 22 23 const _maxSamplesToReuse = 2048 24 25 var ( 26 emptySampleList sampleList 27 ) 28 29 // sampleList is a list of samples. 30 type sampleList struct { 31 head *Sample 32 tail *Sample 33 samples []Sample 34 free []int32 35 } 36 37 // Empty returns true if the list is empty. 38 func (l *sampleList) Empty() bool { return len(l.samples) == 0 } 39 40 // Len returns the number of samples in the list. 41 func (l *sampleList) Len() int { return len(l.samples) - len(l.free) } 42 43 // Front returns the first sample in the list. 44 func (l *sampleList) Front() *Sample { return l.head } 45 46 // Back returns the last sample in the list. 47 func (l *sampleList) Back() *Sample { return l.tail } 48 49 // Reset resets the list. 50 func (l *sampleList) Reset() { 51 for i := range l.samples { 52 l.samples[i].next, l.samples[i].prev = nil, nil 53 } 54 55 l.samples = l.samples[:0] 56 l.free = l.free[:0] 57 if cap(l.samples) > _maxSamplesToReuse || cap(l.free) > _maxSamplesToReuse { 58 l.samples = nil 59 l.free = nil 60 } 61 l.head, l.tail = nil, nil 62 } 63 64 // PushBack pushes a sample to the end of the list. 65 func (l *sampleList) PushBack(sample *Sample) { 66 sample.prev = l.tail 67 sample.next = nil 68 if l.head == nil { 69 l.head = sample 70 } else { 71 l.tail.next = sample 72 } 73 74 l.tail = sample 75 } 76 77 // InsertBefore inserts a sample before the mark. 78 func (l *sampleList) InsertBefore(sample *Sample, mark *Sample) { 79 var prev *Sample 80 81 if mark.prev == nil { 82 l.head = sample 83 } else { 84 prev = mark.prev 85 prev.next = sample 86 } 87 88 mark.prev = sample 89 sample.next = mark 90 sample.prev = prev 91 } 92 93 // Remove removes a sample from the list. 94 func (l *sampleList) Remove(sample *Sample) { 95 prev := sample.prev 96 next := sample.next 97 l.release(sample) 98 if prev == nil { 99 l.head = next 100 } else { 101 prev.next = next 102 } 103 if next == nil { 104 l.tail = prev 105 } else { 106 next.prev = prev 107 } 108 } 109 110 func (l *sampleList) Acquire() *Sample { 111 idx := 0 112 113 if len(l.free) > 0 { 114 idx = int(l.free[len(l.free)-1]) 115 l.free = l.free[:len(l.free)-1] 116 return &l.samples[idx] 117 } 118 119 if len(l.samples) < cap(l.samples) { 120 l.samples = l.samples[:len(l.samples)+1] 121 } else { 122 l.samples = append(l.samples, Sample{}) 123 } 124 125 idx = len(l.samples) - 1 126 s := &l.samples[idx] 127 s.idx = int32(idx) 128 return s 129 } 130 131 func (l *sampleList) release(sample *Sample) { 132 idx := sample.idx 133 sample.next, sample.prev = nil, nil 134 l.free = append(l.free, idx) 135 }