github.com/avenga/couper@v1.12.2/handler/ratelimit/ring_buffer.go (about)

     1  package ratelimit
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  )
     7  
     8  type ringBuffer struct {
     9  	buf []time.Time
    10  	len uint
    11  	mu  sync.RWMutex
    12  	r   uint
    13  	w   uint
    14  }
    15  
    16  // newRingBuffer creates a new ringBuffer
    17  // instance. ringBuffer is thread safe.
    18  func newRingBuffer(len uint) *ringBuffer {
    19  	return &ringBuffer{
    20  		buf: make([]time.Time, len),
    21  		len: len,
    22  		r:   0,
    23  		w:   len - 1,
    24  	}
    25  }
    26  
    27  // put rotates the ring buffer and puts t at
    28  // the "last" position. r must not be empty.
    29  func (r *ringBuffer) put(t time.Time) {
    30  	if r == nil {
    31  		panic("r must not be empty")
    32  	}
    33  
    34  	r.mu.Lock()
    35  
    36  	r.r++
    37  	r.r %= r.len
    38  
    39  	r.w++
    40  	r.w %= r.len
    41  
    42  	r.buf[r.w] = t
    43  
    44  	r.mu.Unlock()
    45  }
    46  
    47  // get returns the value of the "first" element
    48  // in the ring buffer. r must not be empty.
    49  func (r *ringBuffer) get() time.Time {
    50  	if r == nil {
    51  		panic("r must not be empty")
    52  	}
    53  
    54  	r.mu.Lock()
    55  	defer r.mu.Unlock()
    56  
    57  	return r.buf[r.r]
    58  }