MADARA  3.4.1
CircularBuffer.inl
Go to the documentation of this file.
1 
2 #ifndef _MADARA_KNOWLEDGE_CONTAINERS_CIRCULARBUFFER_INL_
3 #define _MADARA_KNOWLEDGE_CONTAINERS_CIRCULARBUFFER_INL_
4 
5 #include <sstream>
6 #include <math.h>
7 
8 #include "CircularBuffer.h"
13 
14 namespace madara
15 {
16 namespace knowledge
17 {
18 namespace containers
19 {
21  : context_(0), settings_(settings)
22 {
23 }
24 
25 inline void CircularBuffer::check_name(const char* func) const
26 {
27  if (name_ == "")
28  {
30  std::string("CircularBuffer::") + func + ": name is empty.");
31  }
32 }
33 
34 inline void CircularBuffer::check_context(const char* func) const
35 {
36  check_name(func);
37  if (!context_)
38  {
40  std::string("CircularBuffer::") + func + ": context is not set.");
41  }
42 }
43 
44 inline void CircularBuffer::check_all(const char* func) const
45 {
46  std::string reason = "";
47  if (context_ == 0)
48  {
49  reason = "context has not been set";
50  }
51 
52  if (name_ == "")
53  {
54  if (reason.size() > 0)
55  {
56  reason += " and ";
57  }
58  reason = "name has not been set";
59  }
60 
61  if (buffer_.size() == 0)
62  {
63  if (reason.size() > 0)
64  {
65  reason += " and ";
66  }
67  reason = "size == 0";
68  }
69 
70  if (reason != "")
71  {
72  std::stringstream message;
73  message << "CircularBuffer::" << func << ": ";
74  message << "Invalid access because " << reason << "\n";
75  throw exceptions::IndexException(message.str());
76  }
77 }
78 
81  : context_(&(knowledge.get_context())), name_(name), settings_(settings)
82 {
83  check_name(__func__);
84 
85  ContextGuard context_guard(knowledge);
86  set_name(name, knowledge);
87 }
88 
91  : context_(knowledge.get_context()), name_(name), settings_(settings)
92 {
93  check_name(__func__);
94 
95  ContextGuard context_guard(*knowledge.get_context());
96  set_name(name, knowledge);
97 }
98 
100  KnowledgeBase& knowledge, int size, const KnowledgeUpdateSettings& settings)
101  : context_(&(knowledge.get_context())), name_(name), settings_(settings)
102 {
103  check_name(__func__);
104 
105  ContextGuard context_guard(knowledge);
106  set_name(name, knowledge);
107  if (size >= 0)
108  {
110  }
111 }
112 
114  Variables& knowledge, int size, const KnowledgeUpdateSettings& settings)
115  : context_(knowledge.get_context()), name_(name), settings_(settings)
116 {
117  check_name(__func__);
118 
119  ContextGuard context_guard(*knowledge.get_context());
120  set_name(name, knowledge);
121  if (size >= 0)
122  {
124  }
125 }
126 
127 inline bool CircularBuffer::operator==(const CircularBuffer& value) const
128 {
129  return name_ == value.get_name();
130 }
131 
132 inline bool CircularBuffer::operator!=(const CircularBuffer& value) const
133 {
134  return name_ != value.get_name();
135 }
136 
137 inline void CircularBuffer::clear(void)
138 {
139  check_all(__func__);
140 
141  ContextGuard context_guard(*context_);
142 
143  index_ = -1;
144  buffer_.resize(0);
145 }
146 
149 {
150  KnowledgeRecord::Integer result = base + value;
151  if (buffer_.size() > 0 && base + value >= 0)
152  {
153  return (result) % (KnowledgeRecord::Integer)buffer_.size();
154  }
155  else if (buffer_.size() > 0)
156  {
157  return (KnowledgeRecord::Integer)buffer_.size() + result;
158  }
159  else
160  {
161  std::stringstream message;
162  message << "CircularBuffer::increment: ";
163  message << "Result of " << base << "+" << value << " is " << result;
164  message << " which is impossible to access with size " << size() << ".\n";
165  throw exceptions::IndexException(message.str());
166  }
167 }
168 
170 {
171  check_all(__func__);
172 
173  ContextGuard context_guard(*context_);
174 
176 
177  context_->set(buffer_.vector_[(size_t)index], record, settings_);
178 
180 
181  ++index_;
182 }
183 
184 inline void CircularBuffer::add(const std::vector<KnowledgeRecord>& records)
185 {
186  check_all(__func__);
187 
188  ContextGuard context_guard(*context_);
189 
191 
192  for (auto record : records)
193  {
194  index = increment(index, 1);
195 
196  context_->set(buffer_.vector_[(size_t)index], record, settings_);
197  }
198 
200 
201  index_ += (KnowledgeRecord::Integer)records.size();
202 }
203 
205 {
206  check_all(__func__);
207 
208  ContextGuard context_guard(*context_);
209 
211  index = increment(index, 0);
212 
213  if (count() > 0)
214  return context_->get(buffer_.vector_[(size_t)index], settings_);
215  else
216  return KnowledgeRecord();
217 }
218 
220  KnowledgeRecord::Integer position) const
221 {
222  check_context(__func__);
223  ContextGuard context_guard(*context_);
224 
226 
227  if ((position <= 0 && -position < inserted) ||
228  (position > 0 && inserted == (KnowledgeRecord::Integer)size() &&
229  position < inserted))
230  {
231  size_t index =
232  (size_t)increment(*index_, (KnowledgeRecord::Integer)position);
233 
234  return context_->get(buffer_.vector_[index], settings_);
235  }
236  else
237  {
238  std::stringstream message;
239  message << "CircularBuffer::inspect: ";
240  message << "Invalid access for " << position << " element when count is ";
241  message << inserted << "\n";
242  throw exceptions::IndexException(message.str());
243  }
244 }
245 
246 inline std::vector<KnowledgeRecord> CircularBuffer::inspect(
247  KnowledgeRecord::Integer position, size_t count) const
248 {
249  check_context(__func__);
250 
251  ContextGuard context_guard(*context_);
252 
254 
255  if ((position <= 0 && -position < inserted) ||
256  (position > 0 && inserted == (KnowledgeRecord::Integer)size() &&
257  position < inserted))
258  {
261 
262  std::vector<KnowledgeRecord> result;
263 
264  for (size_t i = 0; i < count; ++i, index = increment(index, 1))
265  {
266  result.push_back(buffer_[(size_t)index]);
267  }
268 
269  return result;
270  }
271  else
272  {
273  std::stringstream message;
274  message << "CircularBuffer::inspect: ";
275  message << "Invalid access for " << position << " element when count is ";
276  message << inserted << "\n";
277  throw exceptions::IndexException(message.str());
278  }
279 }
280 
282 {
283  return name_;
284 }
285 
286 inline size_t CircularBuffer::size(void) const
287 {
288  return buffer_.size();
289 }
290 
291 inline size_t CircularBuffer::count(void) const
292 {
293  check_context(__func__);
294 
295  ContextGuard context_guard(*context_);
296 
297  return std::min((size_t)(*index_ + 1), buffer_.size());
298 }
299 
300 inline void CircularBuffer::resize(int size)
301 {
302  check_context(__func__);
303 
304  ContextGuard context_guard(*context_);
305 
306  buffer_.resize(size, false);
307 
309 }
310 
312  const KnowledgeUpdateSettings& settings)
313 {
314  KnowledgeUpdateSettings old_settings = settings_;
315 
316  settings_ = settings;
317 
318  return old_settings;
319 }
320 
322  uint32_t quality, const KnowledgeReferenceSettings& settings)
323 {
324  check_context(__func__);
325 
326  ContextGuard context_guard(*context_);
327  context_->set_quality(name_, quality, true, settings);
328 }
329 
331  const std::string& name, KnowledgeBase& knowledge)
332 {
333  if (name != "")
334  {
335  ContextGuard context_guard(knowledge);
336  name_ = name;
337  context_ = &(knowledge.get_context());
338  index_.set_name(name + ".index", knowledge);
339  buffer_.set_name(name, knowledge);
341  if (buffer_.size() == 0 && index_ != -1)
342  {
343  index_ = -1;
344  }
345  }
346  else
347  {
349  "CircularBuffer::set_name: empty name provided.");
350  }
351 }
352 
354  const std::string& name, Variables& knowledge)
355 {
356  if (name != "")
357  {
358  ContextGuard context_guard(*knowledge.get_context());
359  name_ = name;
360  context_ = knowledge.get_context();
361  index_.set_name(name + ".index", knowledge);
362  buffer_.set_name(name, knowledge);
364  if (buffer_.size() == 0 && index_ != -1)
365  {
366  index_ = -1;
367  }
368  }
369  else
370  {
372  "CircularBuffer::set_name: empty name provided.");
373  }
374 }
375 
377 {
378  check_context(__func__);
379  index_ = index;
380 }
381 
382 inline std::vector<KnowledgeRecord> CircularBuffer::get_latest(
383  size_t count) const
384 {
385  check_all(__func__);
386 
387  ContextGuard context_guard(*context_);
388 
389  count = std::min(count, this->count());
390 
391  std::vector<KnowledgeRecord> result;
392 
394 
395  for (size_t i = 0; i < count; ++i, cur = increment(cur, -1))
396  {
397  result.push_back(buffer_[(size_t)cur]);
398  }
399 
400  return result;
401 }
402 
403 inline std::vector<KnowledgeRecord> CircularBuffer::get_earliest(
404  size_t count) const
405 {
406  check_all(__func__);
407 
408  ContextGuard context_guard(*context_);
409  std::vector<KnowledgeRecord> result;
410 
411  count = std::min(count, this->count());
412 
413  // start is either 0 or index_ + 1
415  this->count() < buffer_.size() ? 0 : increment(*index_, 1);
416 
417  for (size_t i = 0; i < count; ++i, cur = increment(cur, 1))
418  {
419  result.push_back(buffer_[(size_t)cur]);
420  }
421 
422  return result;
423 }
424 
425 } // end containers namespace
426 } // end knowledge namespace
427 } // end madara namespace
428 
429 #endif // _MADARA_KNOWLEDGE_CONTAINERS_CIRCULARBUFFER_INL_
const ThreadSafeContext * context_
madara::knowledge::KnowledgeRecord KnowledgeRecord
An exception for attempting to access an invalid context1.
An exception for out-of-bounds accessing in arrays/vectors.
An exception for setting an invalid name in MADARA.
Definition: NameException.h:16
A thread-safe guard for a context or knowledge base.
Definition: ContextGuard.h:24
This class provides a distributed knowledge base to users.
Definition: KnowledgeBase.h:45
This class encapsulates an entry in a KnowledgeBase.
Settings for applying knowledge updates.
Settings for applying knowledge updates.
madara::knowledge::KnowledgeRecord get(const std::string &key, const KnowledgeReferenceSettings &settings=KnowledgeReferenceSettings()) const
Atomically returns the current value of a variable.
void mark_modified(const VariableReference &variable, const KnowledgeUpdateSettings &settings=KnowledgeUpdateSettings())
Marks the variable reference as updated for the purposes of sending or checkpointing knowledge (for g...
int set(const std::string &key, T &&value, const KnowledgeUpdateSettings &settings=KnowledgeUpdateSettings())
Atomically sets the value of a variable to the specific record.
uint32_t set_quality(const std::string &key, uint32_t quality, bool force_update, const KnowledgeReferenceSettings &settings)
Atomically sets quality of this process for a variable.
Provides an interface for external functions into the MADARA KaRL variable settings.
Definition: Variables.h:53
This container stores a thread-safe circular buffer with O(1) access times.
void set_name(const std::string &name, KnowledgeBase &knowledge)
Sets the variable name that this refers to.
std::vector< KnowledgeRecord > get_earliest(size_t count) const
Gets the oldest added records up to a specified count.
KnowledgeRecord::Integer increment(KnowledgeRecord::Integer base, KnowledgeRecord::Integer value) const
Increments the base by the value, using size as a boundary.
ThreadSafeContext * context_
guard for access and changes
size_t size(void) const
Returns the maximum size of the CircularBuffer.
std::string name_
Prefix of variable.
Vector buffer_
Underlying array of records.
void check_context(const char *func) const
VariableReference size_ref_
Reference to the size field of the vector space.
KnowledgeUpdateSettings settings_
Settings for modifications.
bool operator!=(const CircularBuffer &value) const
Checks for inequality.
void clear(void)
Clears the CircularBuffer.
std::vector< KnowledgeRecord > get_latest(size_t count) const
Gets the most recently added records up to a specified count.
void set_index(KnowledgeRecord::Integer index)
Sets the index into the circular buffer to an arbitrary position.
void set_quality(uint32_t quality, const KnowledgeReferenceSettings &settings=KnowledgeReferenceSettings(false))
Sets the quality of writing to the counter variables.
void resize(int size=-1)
Resizes the CircularBuffer.
CircularBuffer(const KnowledgeUpdateSettings &settings=KnowledgeUpdateSettings())
Default constructor.
Integer index_
Index for latest item in circular buffer.
std::string get_name(void) const
Returns the name of the variable.
KnowledgeUpdateSettings set_settings(const KnowledgeUpdateSettings &settings)
Sets the update settings for the variable.
void add(const knowledge::KnowledgeRecord &record)
Adds a record to the end of the CircularBuffer.
knowledge::KnowledgeRecord get(void) const
Gets the most recently added record.
bool operator==(const CircularBuffer &value) const
Checks for equality.
knowledge::KnowledgeRecord inspect(KnowledgeRecord::Integer position) const
Retrieves a record at a position relative to last added.
size_t count(void) const
Returns the number of records in the CircularBuffer.
void set_name(const std::string &var_name, KnowledgeBase &knowledge)
Sets the variable name that this refers to.
Definition: Integer.inl:54
VariableReference get_size_ref(void)
Returns a reference to the size field of the current name.
Definition: Vector.cpp:131
std::vector< VariableReference > vector_
Values of the array.
Definition: Vector.h:616
void set_name(const std::string &var_name, KnowledgeBase &knowledge, int size=-1)
Sets the variable name that this refers to.
Definition: Vector.inl:29
void resize(int size=-1, bool delete_vars=true)
Resizes the vector.
Definition: Vector.cpp:200
size_t size(void) const
Returns the size of the local vector.
Definition: Vector.inl:23
Provides container classes for fast knowledge base access and mutation.
Definition: Barrier.h:27
constexpr string_t string
Provides functions and classes for the distributed knowledge base.
Copyright(c) 2020 Galois.