baseline_circular_buffer.h 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include <cstdint>
  5. #include <memory>
  6. #include <mutex>
  7. #include <vector>
  8. #include "opentelemetry/version.h"
  9. OPENTELEMETRY_BEGIN_NAMESPACE
  10. namespace testing
  11. {
  12. /**
  13. * A locking circular buffer.
  14. *
  15. * Used as a baseline in benchmarking.
  16. */
  17. template <class T>
  18. class BaselineCircularBuffer
  19. {
  20. public:
  21. explicit BaselineCircularBuffer(size_t max_size) : data_{max_size} {}
  22. /**
  23. * Add an element to the circular buffer.
  24. * @param element the element to add
  25. * @return true if the element was added successfully
  26. */
  27. bool Add(std::unique_ptr<T> &element) noexcept { return this->Add(std::move(element)); }
  28. bool Add(std::unique_ptr<T> &&element) noexcept
  29. {
  30. std::lock_guard<std::mutex> lock_guard{mutex_};
  31. if (tail_ + data_.size() == head_)
  32. {
  33. return false;
  34. }
  35. data_[head_ % data_.size()] = std::move(element);
  36. head_ += 1;
  37. return true;
  38. }
  39. /**
  40. * Consume elements in the circular buffer.
  41. * @param f the callback to call for each element
  42. */
  43. template <class F>
  44. void Consume(F f) noexcept
  45. {
  46. std::lock_guard<std::mutex> lock_guard{mutex_};
  47. if (head_ == tail_)
  48. {
  49. return;
  50. }
  51. auto tail_index = tail_ % data_.size();
  52. auto head_index = head_ % data_.size();
  53. if (tail_index < head_index)
  54. {
  55. for (auto i = tail_index; i < head_index; ++i)
  56. {
  57. f(std::move(data_[i]));
  58. }
  59. }
  60. else
  61. {
  62. for (auto i = tail_index; i < data_.size(); ++i)
  63. {
  64. f(std::move(data_[i]));
  65. }
  66. for (auto i = 0ull; i < head_index; ++i)
  67. {
  68. f(std::move(data_[i]));
  69. }
  70. }
  71. tail_ = head_;
  72. }
  73. private:
  74. std::mutex mutex_;
  75. uint64_t head_{0};
  76. uint64_t tail_{0};
  77. std::vector<std::unique_ptr<T>> data_;
  78. };
  79. } // namespace testing
  80. OPENTELEMETRY_END_NAMESPACE