13 #include "opentelemetry/nostd/span.h"
14 #include "opentelemetry/sdk/common/atomic_unique_ptr.h"
15 #include "opentelemetry/sdk/common/circular_buffer_range.h"
16 #include "opentelemetry/version.h"
55 template <
class Callback>
56 void Consume(
size_t n, Callback callback) noexcept
58 assert(n <=
static_cast<size_t>(head_ - tail_));
59 auto range = PeekImpl().Take(n);
60 static_assert(noexcept(callback(range)),
"callback not allowed to throw");
86 bool Add(std::unique_ptr<T> &ptr) noexcept
90 uint64_t tail = tail_;
91 uint64_t head = head_;
94 if (head - tail >= capacity_ - 1)
99 uint64_t head_index = head % capacity_;
100 if (data_[head_index].SwapIfNull(ptr))
102 auto new_head = head + 1;
103 auto expected_head = head;
104 if (head_.compare_exchange_weak(expected_head, new_head, std::memory_order_release,
105 std::memory_order_relaxed))
116 data_[head_index].Swap(ptr);
121 bool Add(std::unique_ptr<T> &&ptr) noexcept
124 bool result =
Add(std::ref(ptr));
139 size_t max_size() const noexcept {
return capacity_ - 1; }
144 bool empty() const noexcept {
return head_ == tail_; }
154 uint64_t tail = tail_;
155 uint64_t head = head_;
156 assert(tail <= head);
171 std::unique_ptr<AtomicUniquePtr<T>[]> data_;
173 std::atomic<uint64_t> head_{0};
174 std::atomic<uint64_t> tail_{0};
176 CircularBufferRange<AtomicUniquePtr<T>> PeekImpl() noexcept
178 uint64_t tail_index = tail_ % capacity_;
179 uint64_t head_index = head_ % capacity_;
180 if (head_index == tail_index)
184 AtomicUniquePtr<T> *
data = data_.get();
185 if (tail_index < head_index)
188 data + tail_index,
static_cast<std::size_t
>(head_index - tail_index)}};
191 static_cast<std::size_t
>(capacity_ - tail_index)},