hyperledger/iroha
Iroha - A simple, decentralized ledger http://iroha.tech
ring_buffer.hpp
Go to the documentation of this file.
1 
6 #ifndef IROHA_COMMON_RING_BUFFER_HPP
7 #define IROHA_COMMON_RING_BUFFER_HPP
8 
9 namespace iroha {
10  namespace containers {
17  template <typename T, size_t Count>
18  class RingBuffer final {
19  public:
20  using Type = T;
21  using Handle = size_t;
22 
23  private:
24  static_assert(Count > 0, "Unexpected count value. It must be above 0.");
25 
26  enum { kTypeSize = sizeof(Type) };
27 
31  enum { kActualLimit = Count };
32 
39  enum { kVirtualLimit = 2 * kActualLimit };
40 
41  struct Node {
42  uint8_t data[kTypeSize];
43  } data_[Count];
44 
45  Handle begin_;
46  Handle end_;
47 
48  inline bool handleInBound(Handle h) const {
52  auto sz_handle = ((h - end_) % kVirtualLimit);
53  auto sz_begin = ((begin_ - end_) % kVirtualLimit);
54  return (sz_handle < sz_begin);
55  }
56 
57  inline size_t incrementAndNormalize(size_t val) const {
58  return (++val % kVirtualLimit);
59  }
60 
61  inline size_t handleToPosition(Handle h) const {
62  return (h % kActualLimit);
63  }
64 
65  inline size_t internalSize() const {
66  assert(((begin_ - end_) % kVirtualLimit) <= kActualLimit);
67  return ((begin_ - end_) % kVirtualLimit);
68  }
69 
70  inline bool internalEmpty() const {
71  return (begin_ == end_);
72  }
73 
74  inline Type &internalGetItem(Node &node) {
75  return *reinterpret_cast<Type *>(node.data);
76  }
77 
78  inline Type const &internalGetItem(Node const &node) const {
79  return *reinterpret_cast<Type const *>(node.data);
80  }
81 
82  inline void destruct(Node &node) {
83  assert(!internalEmpty());
84 
85  auto &item = internalGetItem(node);
86  item.~Type();
87  }
88 
89  template <typename FuncOnRemove>
90  inline void destructLast(FuncOnRemove &&on_remove) {
91  auto &node = internalToNode(end_);
92  on_remove(end_, internalGetItem(node));
93 
94  destruct(node);
95  end_ = incrementAndNormalize(end_);
96  }
97 
98  template <typename... Args>
99  inline void construct(Node &node, Args &&... args) {
100  assert(internalSize() < kActualLimit);
101  new (node.data) Type(std::forward<Args>(args)...);
102  }
103 
104  template <typename FuncOnAdd, typename... Args>
105  inline void constructFirst(FuncOnAdd &&on_add, Args &&... args) {
106  auto &node = internalToNode(begin_);
107  auto const constructed_h = begin_;
108 
109  construct(node, std::forward<Args>(args)...);
110  begin_ = incrementAndNormalize(begin_);
111 
112  on_add(constructed_h, internalGetItem(node));
113  }
114 
115  inline Node &internalToNode(Handle h) {
116  assert(h < kVirtualLimit);
117  return data_[handleToPosition(h)];
118  }
119 
120  inline Node const &internalToNode(Handle h) const {
121  assert(h < kVirtualLimit);
122  return data_[handleToPosition(h)];
123  }
124 
125  public:
126  RingBuffer() : begin_(0ull), end_(0ull) {}
127 
129  while (!internalEmpty()) pop([](Handle, Type const &) {});
130  }
131 
132  template <typename FuncOnAdd, typename FuncOnRemove, typename... Args>
133  void push(FuncOnAdd &&on_add, FuncOnRemove &&on_remove, Args &&... args) {
134  assert(internalSize() <= kActualLimit);
135  if (internalSize() == kActualLimit) {
136  destructLast(std::move(on_remove));
137  }
138  constructFirst(std::move(on_add), std::forward<Args>(args)...);
139  }
140 
141  template <typename FuncOnRemove>
142  void pop(FuncOnRemove &&on_remove) {
143  if (!internalEmpty()) {
144  destructLast(std::move(on_remove));
145  }
146  }
147 
149  assert(handleInBound(h));
150  return internalGetItem(internalToNode(h));
151  }
152 
153  Type const &getItem(Handle h) const {
154  assert(handleInBound(h));
155  return internalGetItem(internalToNode(h));
156  }
157 
158  bool empty() const {
159  return internalEmpty();
160  }
161 
162  size_t size() const {
163  return internalSize();
164  }
165  };
166  } // namespace containers
167 } // namespace iroha
168 
169 #endif // IROHA_COMMON_RING_BUFFER_HPP
~RingBuffer()
Definition: ring_buffer.hpp:128
Type const & getItem(Handle h) const
Definition: ring_buffer.hpp:153
KeyAndValue Type
Definition: ring_buffer.hpp:20
Type & getItem(Handle h)
Definition: ring_buffer.hpp:148
RingBuffer()
Definition: ring_buffer.hpp:126
bool empty() const
Definition: ring_buffer.hpp:158
Definition: block_query.hpp:15
void push(FuncOnAdd &&on_add, FuncOnRemove &&on_remove, Args &&... args)
Definition: ring_buffer.hpp:133
void pop(FuncOnRemove &&on_remove)
Definition: ring_buffer.hpp:142
size_t size() const
Definition: ring_buffer.hpp:162
Definition: ring_buffer.hpp:18
size_t Handle
Definition: ring_buffer.hpp:21