NewCircularBuffer allocates a circular buffer of size size and returns a reference to the struct. Only circular buffers of size 2^k are allowed (saves us from having to do expensive modulo operations).
(size uint32)
| 142 | // reference to the struct. Only circular buffers of size 2^k are allowed |
| 143 | // (saves us from having to do expensive modulo operations). |
| 144 | func NewCircularBuffer(size uint32) (*CircularBuffer, error) { |
| 145 | if size&(size-1) != 0 { |
| 146 | return nil, errInvalidCircularBufferSize |
| 147 | } |
| 148 | |
| 149 | n := numCircularBufferPairs |
| 150 | if size/numCircularBufferPairs < 8 { |
| 151 | // If each circular buffer is going to hold less than a very small number |
| 152 | // of items (let's say 8), using multiple circular buffers is very likely |
| 153 | // wasteful. Instead, fallback to one circular buffer holding everything. |
| 154 | n = 1 |
| 155 | } |
| 156 | |
| 157 | cb := &CircularBuffer{ |
| 158 | qp: make([]*queuePair, n), |
| 159 | qpMask: n - 1, |
| 160 | } |
| 161 | |
| 162 | for i := uint32(0); i < n; i++ { |
| 163 | cb.qp[i] = newQueuePair(size / n) |
| 164 | } |
| 165 | |
| 166 | return cb, nil |
| 167 | } |
| 168 | |
| 169 | // Push pushes an element in to the circular buffer. Guaranteed to complete in |
| 170 | // a finite number of steps (also lock-free). Does not guarantee that push |