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  }