Skip to content

Instantly share code, notes, and snippets.

@pgoodman
Created September 15, 2018 17:21
Show Gist options
  • Select an option

  • Save pgoodman/d69b402e220b50e4dbde812ffb644a22 to your computer and use it in GitHub Desktop.

Select an option

Save pgoodman/d69b402e220b50e4dbde812ffb644a22 to your computer and use it in GitHub Desktop.
/*
* Copyright (c) 2018 Trail of Bits, Inc.
*/
#include "mcsema/Util/ProgressBar.h"
#include <algorithm>
#include <cinttypes>
#include <cmath>
#include <cstdio>
namespace mcsema {
namespace {
static const auto kProgressBars = \
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||";
static const double kNumProgressBars = 40;
static int NumDigits(uint64_t val) {
if (!val) {
return 1;
} else {
int num_digits = 0;
while (val) {
val /= 10;
num_digits++;
}
return num_digits;
}
}
} // namespace
ProgressBar::ProgressBar(const char *label_, uint64_t max_num_steps_,
std::chrono::seconds report_freq_)
: label(label_),
max_num_steps(max_num_steps_),
report_frequency(report_freq_),
current_step(0),
progress_reporter([=] (void) {
do {
Report();
std::this_thread::sleep_for(report_frequency);
} while (current_step.load(std::memory_order_acquire) < max_num_steps);
}) {
Report();
}
ProgressBar::~ProgressBar(void) {
current_step.store(max_num_steps, std::memory_order_seq_cst);
if (progress_reporter.joinable()) {
progress_reporter.join();
}
Report();
fprintf(stderr, "\n");
fflush(stderr);
}
void ProgressBar::Advance(void) {
current_step.fetch_add(1, std::memory_order_seq_cst);
}
void ProgressBar::Report(void) {
const auto curr = current_step.load(std::memory_order_acquire);
const auto steps_done = static_cast<double>(curr);
const auto steps_total = static_cast<double>(max_num_steps);
const auto percentage = std::min<double>(1.0, steps_done / steps_total);
const auto lpad = percentage * kNumProgressBars;
const auto rpad = kNumProgressBars - lpad;
const auto num_digits = NumDigits(max_num_steps);
fprintf(stderr, "\r%s (%*" PRIu64 " / %" PRIu64 ") %3d%% [%.*s%*s] ",
label, num_digits, curr, max_num_steps, static_cast<int>(percentage * 100.0),
static_cast<int>(lpad), kProgressBars, static_cast<int>(rpad), "");
fflush(stderr);
}
} // namespace mcsema
/*
* Copyright (c) 2018 Trail of Bits, Inc.
*/
#pragma once
#include <atomic>
#include <chrono>
#include <cstdint>
#include <thread>
namespace mcsema {
class ProgressBar {
public:
ProgressBar(const char *label_, uint64_t max_num_steps_,
std::chrono::seconds report_freq_);
~ProgressBar(void);
void Advance(void);
private:
ProgressBar(void) = delete;
void Report(void);
const char * const label;
const uint64_t max_num_steps;
const std::chrono::seconds report_frequency;
std::atomic<uint64_t> current_step;
std::thread progress_reporter;
};
} // namespace mcsema
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment