reserve a slot within buffer returns a pointer to a 'item size' slot within the buffer this function is thread-safe and lock-free
| 143 | // returns a pointer to a 'item size' slot within the buffer |
| 144 | // this function is thread-safe and lock-free |
| 145 | void *CircularBuffer_Reserve |
| 146 | ( |
| 147 | CircularBuffer cb // buffer to populate |
| 148 | ) { |
| 149 | ASSERT(cb != NULL); |
| 150 | |
| 151 | // atomic update buffer item count |
| 152 | // item is not added if buffer is full |
| 153 | uint64_t item_count = atomic_fetch_add(&cb->item_count, 1); |
| 154 | if(unlikely(item_count >= cb->item_cap)) { |
| 155 | cb->item_count = cb->item_cap; |
| 156 | } |
| 157 | |
| 158 | // determine current and next write position |
| 159 | uint64_t curr = atomic_fetch_add(&cb->write, cb->item_size); |
| 160 | if(unlikely(cb->data + curr >= cb->end_marker)) { |
| 161 | uint64_t old_curr = curr + cb->item_size; |
| 162 | curr -= cb->item_size * cb->item_cap; |
| 163 | // advance write position atomicly |
| 164 | atomic_compare_exchange_weak(&cb->write, &old_curr, curr + cb->item_size); |
| 165 | } |
| 166 | |
| 167 | return cb->data + curr; |
| 168 | } |
| 169 | |
| 170 | // read oldest item from buffer |
| 171 | void *CircularBuffer_Read |
no outgoing calls