The Sparta Modeling Framework
Loading...
Searching...
No Matches
CycleHistogram.hpp
Go to the documentation of this file.
1// <CycleHistogram.h> -*- C++ -*-
2
3
9#pragma once
10
11#include <iostream>
12#include <string>
13#include <vector>
14#include <numeric>
15#include "sparta/utils/MathUtils.hpp"
18#include "sparta/statistics/Counter.hpp"
19#include "sparta/statistics/CycleCounter.hpp"
24
25namespace sparta
26{
41 {
42 public:
43
48
53
58
62 void operator=(const CycleHistogramBase&) = delete;
63
66
70
77 void addValue(uint64_t val)
78 {
80 startCounting_(val);
81 stopCounting_(val, 1);
83
85 }
86
92 double getStandardDeviation() const {
93
94 // Summation of counts in normal bins plus underflow bin and
95 // overflow bin.
96 const double sum = std::accumulate(bin_.begin(), bin_.end(), 0.0)
97 + (*underflow_bin_) + (*overflow_bin_);
98
99 // Total number of bins is number of regular bins
100 // plus one for underflow bin and plus one for
101 // overflow bin.
102 const std::size_t total_num_bins = bin_.size() + 2;
103
104 const double mean = sum / total_num_bins;
105 double accum = 0.0;
106 std::for_each(bin_.begin(), bin_.end(), [&](const sparta::CycleCounter& c) {
107 auto c_get = c.get();
108 accum += pow(c_get - mean, 2);
109 });
110 accum += pow((*underflow_bin_ - mean), 2);
111 accum += pow((*overflow_bin_ - mean), 2);
112 return std::sqrt(accum / (total_num_bins - 1));
113 }
114
120 double getMeanBinCount() const {
121
122 // Summation of counts in normal bins plus underflow bin and
123 // overflow bin.
124 const double sum = std::accumulate(bin_.begin(), bin_.end(), 0.0)
125 + (*underflow_bin_) + (*overflow_bin_);
126
127 // Total number of bins is number of regular bins
128 // plus one for underflow bin and plus one for
129 // overflow bin.
130 const std::size_t total_num_bins = bin_.size() + 2;
131
132 return sum / total_num_bins;
133 }
134
139 return *total_;
140 }
141
145 const std::vector<sparta::CycleCounter>& getRegularBin() const{
146 return bin_;
147 }
148
153 return *underflow_bin_;
154 }
155
160 return *overflow_bin_;
161 }
162
167 return ((static_cast<double>(*underflow_bin_))/(static_cast<double>(*total_)));
168 }
169
174 return ((static_cast<double>(*overflow_bin_))/(static_cast<double>(*total_)));
175 }
176
180 const std::vector<double>& recomputeRegularBinProbabilities() const{
181 bin_prob_vector_.clear();
182 for(const auto& b : bin_){
183 bin_prob_vector_.emplace_back(((static_cast<double>(b))/(static_cast<double>(*total_))));
184 }
185 return bin_prob_vector_;
186 }
187
193 void setValue(uint64_t val)
194 {
195 if (last_value_ != val) {
197 startCounting_(val);
198
199 updateMaxValues_(val);
200 }
201 }
202
205
206 uint64_t getHistogramUpperValue() const { return upper_val_; }
207 uint64_t getHistogramLowerValue() const { return lower_val_; }
208 uint64_t getNumBins() const { return num_bins_; }
209 uint64_t getNumValuesPerBin() const { return num_vals_per_bin_; }
210
211 protected:
212
224 CycleHistogramBase(const uint64_t lower_val,
225 const uint64_t upper_val,
226 const uint64_t num_vals_per_bin,
227 const uint64_t idle_value = 0) :
228 lower_val_(lower_val),
229 upper_val_(upper_val),
230 num_vals_per_bin_(num_vals_per_bin),
231 idle_value_(idle_value)
232 {
233 sparta_assert_context(upper_val > lower_val,
234 "CycleHistogramBase: upper value must be greater than lower value");
235 sparta_assert_context(utils::is_power_of_2(num_vals_per_bin),
236 "CycleHistogramBase: num_vals_per_bin must be power of 2");
237 idx_shift_amount_ = utils::floor_log2(num_vals_per_bin); // for quick divide
238 double actual_num_bins = (upper_val - lower_val)/num_vals_per_bin + 1;
239 num_bins_ = (uint64_t) actual_num_bins;
240 sparta_assert_context(actual_num_bins == num_bins_,
241 "CycleHistogramBase: Actual number of bins (" << actual_num_bins
242 << ") is not an integer");
243 }
244
249 std::string getDisplayStringCumulative_(const std::string &name) const
250 {
251 std::stringstream str;
252 str << std::dec;
253 uint64_t running_sum = *underflow_bin_;
254 str << "\t" << name << "[ UF ] = " << running_sum << std::endl;
255 uint64_t start_val = lower_val_;
256 uint64_t end_val = start_val + num_vals_per_bin_ - 1;
257 for (uint64_t i = 0; i < num_bins_; ++i) {
258 if (end_val > upper_val_) {
259 end_val = upper_val_;
260 }
261 running_sum += (bin_[i]);
262 str << "\t" << name
263 << "[ " << start_val << "-" << end_val << " ] = "
264 << running_sum << '\n';
265 end_val += num_vals_per_bin_;
266 }
267 running_sum += *overflow_bin_;
268 str << "\t" << name << "[ OF ] = " << running_sum << std::endl;
269 return str.str();
270 }
271
279 void startCounting_(uint64_t val, uint64_t delay = 0)
280 {
281 if (val < lower_val_) {
282 (*underflow_bin_).startCounting(delay);
283 }
284 else if (val > upper_val_) {
285 (*overflow_bin_).startCounting(delay);
286 }
287 else {
288 uint64_t idx = (val - lower_val_) >> idx_shift_amount_;
289 (bin_.at(idx)).startCounting(delay);
290 }
291
292 last_value_ = val;
293 }
294
303 void stopCounting_(uint64_t val, uint64_t delay = 0)
304 {
305 if (val < lower_val_) {
306 (*underflow_bin_).stopCounting(delay);
307 }
308 else if (val > upper_val_) {
309 (*overflow_bin_).stopCounting(delay);
310 }
311 else {
312 const uint64_t idx = (val - lower_val_) >> idx_shift_amount_;
313 (bin_.at(idx)).stopCounting(delay);
314 }
315 }
316
321 void updateMaxValues_(uint64_t val)
322 {
323 if (val > max_value_->get()) {
324 max_value_->set(val);
325 }
326 }
327
328 void initializeStats_(StatisticSet* sset,
329 const Clock* clk,
330 const std::string &name,
331 const std::string &description,
336 const std::vector<std::string>& histogram_state_names = {})
337 {
338 // Reserve to use emplacement without tree child reordering
339 bin_.reserve(num_bins_);
340
341 const std::string name_total = name.empty() ? std::string("total") : (name + "_total");
342
343 // Setup the underflow bins
344 const std::string name_uf = name.empty() ? std::string("UF") : (name + "_UF");
346 "underflow bin",
348 clk);
349 underflow_probability_.reset(new StatisticDef(sset,
350 name_uf + "_probability",
351 "Probability of underflow",
352 sset,
353 name_uf + " / " + name_total));
354
355 utils::ValidValue<InstrumentationNode::visibility_t> count_visibility;
356
357 // Setup the normal bins
358 uint64_t start_val = lower_val_;
359 uint64_t end_val = start_val + num_vals_per_bin_ - 1;
360 std::string weighted_total_str = "( " + std::to_string(lower_val_) + " * " + underflow_bin_->getName() + " )";
361 std::string weighted_total_nonzero_str;
362 std::string count0_statistic_str;
363 for (uint64_t i = 0; i < num_bins_; ++i)
364 {
365 if (end_val > upper_val_) {
366 end_val = upper_val_;
367 }
368 std::ostringstream str(name, std::ios_base::ate);
369 if (!name.empty()) {
370 str << "_";
371 }
372 if (SPARTA_EXPECT_TRUE(start_val == end_val)) {
373 if (str.str().empty()) {
374 str << "cycle_";
375 }
376
377 // This vector could be passed to this method from derived EnumCycleHistogram.
378 // If this container is not empty, then we put actual enum constant names in
379 // statistic definition strings, instead of the generic 0, 1, 2, ..., n.
380 if(histogram_state_names.empty()){
381 str << "count" << start_val;
382 }
383 else{
384
385 // Here we are looping over the range of the regular bins of the histogram.
386 // The loop index is stored in variable i.
387 // histogram_state_names[0] will have the the stringified name of the enum constant
388 // with value 0.
389 // histogram_state_names[1] will have the the stringified name of the enum constant
390 // with value 1.
391 // Same goes for when i = 1, 2, 3, ..., n.
392 // So, instead of publishing numbers like 0, 1, 2, we publish names like
393 // UOPSTATE::READY, UOPSTATE::WAIT, UOPSTATE::RETIRE etc.
394 str << "count" << histogram_state_names[i];
395 }
396 } else {
397 str << "bin_" << start_val << "_" << end_val;
398 }
399 if (count0_statistic_str.empty() && start_val == 0) {
400 count0_statistic_str = str.str();
401 }
402
403 InstrumentationNode::visibility_t visibility = stat_vis_detailed;
404 if (i == 0 || i == (num_bins_ - 1)) {
405 if(stat_vis_general == InstrumentationNode::AUTO_VISIBILITY) {
407 } else {
408 visibility = stat_vis_general;
409 }
410 } else { // we are internal counts for different levels of utilization.
411 if (stat_vis_detailed == InstrumentationNode::AUTO_VISIBILITY) {
413 } else {
414 visibility = stat_vis_detailed;
415 }
416 }
417 if (i == num_bins_ - 1) {
418 count_visibility = visibility;
419 }
420
421 bin_.emplace_back(sparta::CycleCounter(sset,
422 str.str(),
423 name.empty() ? std::string("cycle_count") : name, i,
424 description + " histogram bin",
425 sparta::Counter::COUNT_NORMAL,
426 clk, visibility));
427 probabilities_.emplace_back(new StatisticDef(sset,
428 str.str() + "_probability",
429 str.str() + " bin probability",
430 sset,
431 str.str() + "/ " + name_total,
433 visibility));
434
436 weighted_total_str += "+ ( " + std::to_string(start_val) + " * " + str.str() + " )";
437 if (!count0_statistic_str.empty()) {
438 if (i == 1) {
439 weighted_total_nonzero_str = "( " + std::to_string(start_val) + " * " + str.str() + " )";
440 } else if (i > 1) {
441 weighted_total_nonzero_str += "+ ( " + std::to_string(start_val) + " * " + str.str() + " )";
442 }
443 }
444 }
445
446 start_val = end_val + 1;
447 end_val += num_vals_per_bin_;
448 }
449
450 // Setup the overflow bins
451 const std::string name_of = name.empty() ? std::string("OF") : (name + "_OF");
453 "overflow bin",
455 clk);
456 overflow_probability_.reset(new StatisticDef(sset,
457 name_of + "_probability",
458 "Probability of overflow",
459 sset,
460 name_of + " / " + name_total));
461
462 weighted_total_str += " + ( " + std::to_string(upper_val_) + " * " + overflow_bin_->getName() + " )";
463 if (!count0_statistic_str.empty()) {
464 weighted_total_nonzero_str += " + ( " + std::to_string(upper_val_) + " * " + overflow_bin_->getName() + " )";
465 }
466
467 if(stat_vis_avg == InstrumentationNode::AUTO_VISIBILITY) {
469 }
470 // Compute the total of all bins
471 total_.reset(new CycleCounter(sset,
472 name_total,
473 description,
476
477 // Setup to collect the maximum value
478 if(stat_vis_max == InstrumentationNode::AUTO_VISIBILITY) {
480 }
481 max_value_.reset(new Counter(sset,
482 name.empty() ? std::string("max_value") : (name + "_max"),
483 "The maximum value in the histogram",
484 CounterBase::COUNT_LATEST,
485 stat_vis_max));
486
487 // Compute weighted average if single value per bin
489 weighted_average_.reset(new StatisticDef(sset,
490 name.empty() ? std::string("weighted_avg") : (name + "_weighted_avg"),
491 "Weighted average",
492 sset,
493 "( " + weighted_total_str + " ) / " + name_total,
494 sparta::StatisticDef::VS_ABSOLUTE,
495 stat_vis_avg));
496
497 if (!count0_statistic_str.empty()) {
498 const std::string nonzero_weighted_avg_stat_def_name =
499 name.empty() ? std::string("weighted_nonzero_avg") : (name + "_weighted_nonzero_avg");
500
501 const std::string nonzero_weighted_avg_stat_def_equation =
502 "( " + weighted_total_nonzero_str + " ) " +
503 " / " +
504 "( " + name_total + " - " + count0_statistic_str + " )";
505
506 weighted_non_zero_average_.reset(new StatisticDef(sset,
507 nonzero_weighted_avg_stat_def_name,
508 "Weighted nonzero average",
509 sset,
510 nonzero_weighted_avg_stat_def_equation,
512 stat_vis_avg));
513 } else {
514 const std::string nonzero_weighted_avg_stat_def_name =
515 name.empty() ? std::string("weighted_nonzero_avg") : (name + "_weighted_nonzero_avg");
516
517 weighted_non_zero_average_.reset(new StatisticDef(
518 sset,
519 nonzero_weighted_avg_stat_def_name,
520 "Weighted nonzero average",
521 sset,
522 weighted_average_->getExpression(),
524 stat_vis_avg));
525 }
526 }
527
528 if (!bin_.empty()) {
529 std::ostringstream fullness_equation;
530 fullness_equation << bin_.back().getName() + " + " + name_of;
531 const std::string fullness_equation_str = fullness_equation.str();
532
533 const std::string full_name = name.empty() ? std::string("full") : (name + "_full");
534 fullness_.reset(new StatisticDef(sset,
535 full_name,
536 "Fullness",
537 sset,
538 fullness_equation_str,
540 count_visibility.getValue()));
541
542 const std::string full_prob_name = full_name + "_probability";
543 fullness_probability_.reset(new StatisticDef(sset,
544 full_prob_name,
545 "Fullness probability",
546 sset,
547 full_name + " / " + name_total,
549 count_visibility.getValue()));
550 }
551 }
552
553 const uint64_t lower_val_;
554 const uint64_t upper_val_;
555 const uint64_t num_vals_per_bin_;
556 const uint64_t idle_value_;
557
558 std::unique_ptr<sparta::CycleCounter> total_;
561 std::vector<sparta::CycleCounter> bin_;
562 std::unique_ptr<sparta::StatisticDef> underflow_probability_;
563 std::unique_ptr<sparta::StatisticDef> overflow_probability_;
564 std::vector<std::unique_ptr<sparta::StatisticDef>> probabilities_;
565 std::unique_ptr<sparta::StatisticDef> weighted_non_zero_average_;
566 std::unique_ptr<sparta::Counter> max_value_;
567 std::unique_ptr<sparta::StatisticDef> weighted_average_;
568 std::unique_ptr<sparta::StatisticDef> fullness_;
569 std::unique_ptr<sparta::StatisticDef> fullness_probability_;
570
571 uint64_t num_bins_;
573 uint64_t last_value_ = 0;
574 mutable std::vector<double> bin_prob_vector_;
575 }; // class CycleHistogramBase
576
591 {
592 public:
593
598
603
608
612 void operator=(const CycleHistogramStandalone&) = delete;
613
646 const Clock * clk,
647 const std::string &name,
648 const std::string &description,
649 const uint64_t lower_val,
650 const uint64_t upper_val,
651 const uint64_t num_vals_per_bin,
652 const uint64_t idle_value = 0,
657 CycleHistogramBase(lower_val, upper_val, num_vals_per_bin, idle_value),
658 name_(name)
659 {
660 initializeStats_ (sset, clk, name, description, stat_vis_general, stat_vis_detailed, stat_vis_max, stat_vis_avg);
661
662 total_->startCounting();
663 // Start capturing the idle value
666 }
667
672 std::string getDisplayStringCumulative() const
673 {
674 return getDisplayStringCumulative_(name_);
675 }
676
677 private:
678
679 const std::string name_;
680
681 }; // class CycleHistogramStandalone
682
697 {
698 public:
699
704
709
714
718 void operator=(const CycleHistogramTreeNode&) = delete;
719
753 const std::string &histogram_name,
754 const std::string &description,
755 const uint64_t lower_val,
756 const uint64_t upper_val,
757 const uint64_t num_vals_per_bin,
758 const uint64_t idle_value = 0,
763 TreeNode(histogram_name, description),
764 CycleHistogramBase(lower_val, upper_val, num_vals_per_bin, idle_value),
765 stats_(this)
766 {
767 sparta_assert(parent_treenode && parent_treenode->getClock());
768 setExpectedParent_(parent_treenode);
769
770 initializeStats_ (&stats_, parent_treenode->getClock(), std::string(), description,
771 stat_vis_general, stat_vis_detailed, stat_vis_max, stat_vis_avg);
772
773 parent_treenode->addChild(this);
774
775 total_->startCounting();
776 // Start capturing the idle value
779 }
780
785 std::string getDisplayStringCumulative() const
786 {
788 }
789
790 private:
791
792 sparta::StatisticSet stats_;
793
794 }; // class CycleHistogramTreeNode
795
796 using CycleHistogram = CycleHistogramTreeNode;
797
798} // namespace sparta
File that defines the Resource class. Consider using sparta::Unit instead.
#define sparta_assert_context(e, insertions)
Check condition and throw a sparta exception if condition evaluates to false or 0....
Definition Resource.hpp:402
Set of macros for Sparta assertions. Caught by the framework.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
#define SPARTA_EXPECT_TRUE(x)
A macro for hinting to the compiler a particular condition should be considered most likely true.
Contains a statistic definition (some useful information which can be computed)
File that defines the StatisticSet class.
Basic Node framework in sparta device tree composite pattern.
File that defines a ValidValue.
A representation of simulated time.
Definition Clock.hpp:51
@ COUNT_NORMAL
Counter counts the number of times something happens like one would expect. This is a weakly monotoni...
Represents a cycle counter.
CycleHistogramBase class for uint64_t values.
CycleHistogramBase(const CycleHistogramBase &)=delete
Not copy-constructable.
CycleHistogramBase(const uint64_t lower_val, const uint64_t upper_val, const uint64_t num_vals_per_bin, const uint64_t idle_value=0)
CycleHistogramBase constructor.
double getStandardDeviation() const
Calculate Standard Deviation of counts in bins. This API also takes into account the count in underfl...
const uint64_t idle_value_
Value to capture when nothing is captured.
const sparta::CycleCounter & getAggCycles() const
Return aggregate clock cycles of this histogram.
const uint64_t upper_val_
Highest value vaptured in normal bins.
void stopCounting_(uint64_t val, uint64_t delay=0)
Stop counting and increment internal count, taking into account the specified delay.
void updateMaxValues_(uint64_t val)
std::vector< std::unique_ptr< sparta::StatisticDef > > probabilities_
Probabilities of each normal bin.
void addValue(uint64_t val)
Add a value to histogram for one cycle, defaulting back to idle value.
void startCounting_(uint64_t val, uint64_t delay=0)
Start counting, taking into account the specified delay.
void operator=(const CycleHistogramBase &)=delete
Not assignable.
std::string getDisplayStringCumulative_(const std::string &name) const
Render the cumulative values of this histogram for use in standalone model.
std::unique_ptr< sparta::StatisticDef > weighted_average_
The weighted average.
const uint64_t lower_val_
Lowest value captured in normal bins.
std::unique_ptr< sparta::StatisticDef > fullness_probability_
Probability of the histogram being in a full state.
sparta::CycleCounter * underflow_bin_
Bin for all underflow.
uint64_t idx_shift_amount_
Number of bits which cannot distinguish between bins for a given input value.
const uint64_t num_vals_per_bin_
Number of values captured by each bin.
void setValue(uint64_t val)
Set a value to histogram until a new value is set.
std::unique_ptr< sparta::Counter > max_value_
The maximum value in the histogram.
CycleHistogramBase()=delete
Not default constructable.
CycleHistogramBase(CycleHistogramBase &&)=delete
Not move-constructable.
const sparta::CycleCounter & getOverflowBin() const
Return count of overflow bin.
std::unique_ptr< sparta::CycleCounter > total_
Total values.
uint64_t num_bins_
Number of bins.
std::unique_ptr< sparta::StatisticDef > underflow_probability_
Probability of underflow.
const sparta::CycleCounter & getUnderflowBin() const
Return count of underflow bin.
double getUnderflowProbability() const
Return underflow probability.
double getOverflowProbability() const
Return overflow probability.
uint64_t last_value_
Last value updated.
std::vector< sparta::CycleCounter > bin_
Regular bins.
std::unique_ptr< sparta::StatisticDef > overflow_probability_
Probability of overflow.
const std::vector< double > & recomputeRegularBinProbabilities() const
Return vector of probabilities regular bins.
double getMeanBinCount() const
Calculate the mean bin count of all the bins. This API also takes into account the count in underflow...
std::unique_ptr< sparta::StatisticDef > fullness_
Sum of the max bin and the overflow bin.
const std::vector< sparta::CycleCounter > & getRegularBin() const
Return vector of regular bin counts.
sparta::CycleCounter * overflow_bin_
Bin for all overflow.
CycleHistogramStandalone class for uint64_t values.
CycleHistogramStandalone(StatisticSet *sset, const Clock *clk, const std::string &name, const std::string &description, const uint64_t lower_val, const uint64_t upper_val, const uint64_t num_vals_per_bin, const uint64_t idle_value=0, const InstrumentationNode::visibility_t stat_vis_general=InstrumentationNode::AUTO_VISIBILITY, const InstrumentationNode::visibility_t stat_vis_detailed=InstrumentationNode::AUTO_VISIBILITY, const InstrumentationNode::visibility_t stat_vis_max=InstrumentationNode::AUTO_VISIBILITY, const InstrumentationNode::visibility_t stat_vis_avg=InstrumentationNode::AUTO_VISIBILITY)
CycleHistogramStandalone constructor.
CycleHistogramStandalone()=delete
Not default constructable.
CycleHistogramStandalone(CycleHistogramStandalone &&)=delete
Not move-constructable.
CycleHistogramStandalone(const CycleHistogramStandalone &)=delete
Not copy-constructable.
void operator=(const CycleHistogramStandalone &)=delete
Not assignable.
std::string getDisplayStringCumulative() const
Render the cumulative values of this histogram for use in standalone model.
CycleHistogramTreeNode class for uint64_t values.
CycleHistogramTreeNode(const CycleHistogramTreeNode &)=delete
Not copy-constructable.
CycleHistogramTreeNode(TreeNode *parent_treenode, const std::string &histogram_name, const std::string &description, const uint64_t lower_val, const uint64_t upper_val, const uint64_t num_vals_per_bin, const uint64_t idle_value=0, const InstrumentationNode::visibility_t stat_vis_general=InstrumentationNode::AUTO_VISIBILITY, const InstrumentationNode::visibility_t stat_vis_detailed=InstrumentationNode::AUTO_VISIBILITY, const InstrumentationNode::visibility_t stat_vis_max=InstrumentationNode::AUTO_VISIBILITY, const InstrumentationNode::visibility_t stat_vis_avg=InstrumentationNode::AUTO_VISIBILITY)
CycleHistogramTreeNode constructor.
CycleHistogramTreeNode()=delete
Not default constructable.
CycleHistogramTreeNode(CycleHistogramTreeNode &&)=delete
Not move-constructable.
void operator=(const CycleHistogramTreeNode &)=delete
Not assignable.
std::string getDisplayStringCumulative() const
Render the cumulative values of this histogram for use in standalone model.
static constexpr visibility_t CONTAINER_DEFAULT_VISIBILITY
the actual visibility that the sparta containers such as buffer, queue, and array will use when VIS_S...
uint32_t visibility_t
Continuous visibility level. Several key points along continum are indicated within Visibility.
static constexpr visibility_t DEFAULT_VISIBILITY
Default node visibility.
@ VIS_SUPPORT
Supporting data. Used mainly for counters which contain an intermediate value for the sole purpose of...
static constexpr visibility_t AUTO_VISIBILITY
The default sparta resource visibility value that should be used. This is an alias of VIS_MAX at the ...
@ VS_FRACTIONAL
A fractional number. This value should be in the range [0,1]. Some report formatters could show this ...
@ VS_ABSOLUTE
An absolute number having no units (typical default)
Set of StatisticDef and CounterBase-derived objects for visiblility through a sparta Tree.
CounterT & createCounter(_Args &&... __args)
Allocates a Counter which is owned by this StatisticSet and deleted at its destruction.
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
void addChild(TreeNode *child, bool inherit_phase=true)
Adds a TreeNode to this node as a child.
const Clock * getClock() override
Walks up parents (starting with self) until a parent with an associated local clock is found,...
const std::string & getName() const override
Gets the name of this node.
void setExpectedParent_(const TreeNode *parent)
Tracks a node as an expected parent without actually adding this node as a child. This is used almost...
Macros for handling exponential backoff.