Added bitmask enums and fixed signed to unsigned comparisons

This commit is contained in:
aristocratos 2021-08-11 20:25:11 +02:00
parent d56fe4cdb5
commit f9ed675d47
5 changed files with 64 additions and 65 deletions

View file

@ -273,11 +273,8 @@ namespace Runner {
atomic<bool> waiting (false);
string output;
string overlay;
string clock;
sigset_t mask;
pthread_mutex_t mtx;
const auto zero_sec = std::chrono::seconds(0);
const unordered_flat_map<string, uint_fast8_t> box_bits = {
{"proc", 0b0000'0001},
@ -286,23 +283,32 @@ namespace Runner {
{"cpu", 0b0100'0000},
};
enum bit_pos {
proc_present, proc_running,
mem_present, mem_running,
net_present, net_running,
cpu_present, cpu_running
};
const uint_fast8_t proc_done = 0b0000'0011;
const uint_fast8_t mem_done = 0b0000'1100;
const uint_fast8_t net_done = 0b0011'0000;
const uint_fast8_t cpu_done = 0b1100'0000;
struct runner_conf {
vector<string> boxes;
bool no_update = false;
bool force_redraw = false;
string overlay = "";
string clock = "";
};
struct runner_conf current_conf;
//? ------------------------------- Secondary thread: async launcher and drawing ----------------------------------
void * _runner(void * _) {
(void) _;
void * _runner(void * confptr) {
struct runner_conf *conf;
conf = (struct runner_conf *) confptr;
//? Block all signals in this thread to avoid deadlock from any signal handlers trying to stop this thread
pthread_sigmask(SIG_BLOCK, &mask, NULL);
@ -327,11 +333,10 @@ namespace Runner {
auto timestamp = time_micros();
output.clear();
const auto& conf = current_conf;
//? Setup bitmask for selected boxes instead of parsing strings in the loop
bitset<8> box_mask;
for (const auto& box : conf.boxes) {
for (const auto& box : conf->boxes) {
box_mask |= box_bits.at(box);
}
@ -346,17 +351,17 @@ namespace Runner {
if (stopping) break;
try {
//* PROC
if (box_mask.test(0)) {
if (not box_mask.test(1)) {
proc = async(Proc::collect, conf.no_update);
box_mask.set(1);
if (box_mask.test(proc_present)) {
if (not box_mask.test(proc_running)) {
proc = async(Proc::collect, conf->no_update);
box_mask.set(proc_running);
}
else if (not proc.valid())
throw std::runtime_error("Proc::collect() future not valid.");
else if (proc.wait_for(zero_sec) == future_status::ready) {
else if (proc.wait_for(ZeroSec) == future_status::ready) {
try {
output += Proc::draw(proc.get(), conf.force_redraw, conf.no_update);
output += Proc::draw(proc.get(), conf->force_redraw, conf->no_update);
}
catch (const std::exception& e) {
throw std::runtime_error("Proc:: -> " + (string)e.what());
@ -365,17 +370,17 @@ namespace Runner {
}
}
//* MEM
if (box_mask.test(2)) {
if (not box_mask.test(3)) {
mem = async(Mem::collect, conf.no_update);
box_mask.set(3);
if (box_mask.test(mem_present)) {
if (not box_mask.test(mem_running)) {
mem = async(Mem::collect, conf->no_update);
box_mask.set(mem_running);
}
else if (not mem.valid())
throw std::runtime_error("Mem::collect() future not valid.");
else if (mem.wait_for(zero_sec) == future_status::ready) {
else if (mem.wait_for(ZeroSec) == future_status::ready) {
try {
output += Mem::draw(mem.get(), conf.force_redraw, conf.no_update);
output += Mem::draw(mem.get(), conf->force_redraw, conf->no_update);
}
catch (const std::exception& e) {
throw std::runtime_error("Mem:: -> " + (string)e.what());
@ -384,17 +389,17 @@ namespace Runner {
}
}
//* NET
if (box_mask.test(4)) {
if (not box_mask.test(5)) {
net = async(Net::collect, conf.no_update);
box_mask.set(5);
if (box_mask.test(net_present)) {
if (not box_mask.test(net_running)) {
net = async(Net::collect, conf->no_update);
box_mask.set(net_running);
}
else if (not net.valid())
throw std::runtime_error("Net::collect() future not valid.");
else if (net.wait_for(zero_sec) == future_status::ready) {
else if (net.wait_for(ZeroSec) == future_status::ready) {
try {
output += Net::draw(net.get(), conf.force_redraw, conf.no_update);
output += Net::draw(net.get(), conf->force_redraw, conf->no_update);
}
catch (const std::exception& e) {
throw std::runtime_error("Net:: -> " + (string)e.what());
@ -403,17 +408,17 @@ namespace Runner {
}
}
//* CPU
if (box_mask.test(6)) {
if (not box_mask.test(7)) {
cpu = async(Cpu::collect, conf.no_update);
box_mask.set(7);
if (box_mask.test(cpu_present)) {
if (not box_mask.test(cpu_running)) {
cpu = async(Cpu::collect, conf->no_update);
box_mask.set(cpu_running);
}
else if (not cpu.valid())
throw std::runtime_error("Cpu::collect() future not valid.");
else if (cpu.wait_for(zero_sec) == future_status::ready) {
else if (cpu.wait_for(ZeroSec) == future_status::ready) {
try {
output += Cpu::draw(cpu.get(), conf.force_redraw, conf.no_update);
output += Cpu::draw(cpu.get(), conf->force_redraw, conf->no_update);
}
catch (const std::exception& e) {
throw std::runtime_error("Cpu:: -> " + (string)e.what());
@ -435,8 +440,11 @@ namespace Runner {
pthread_exit(NULL);
}
//? If overlay isn't empty, print output without color or effects and then print overlay on top
cout << Term::sync_start << (overlay.empty() ? output + clock : Theme::c("inactive_fg") + Fx::uncolor(output + clock) + overlay) << Term::sync_end << flush;
//? If overlay isn't empty, print output without color and then print overlay on top
cout << Term::sync_start << (conf->overlay.empty()
? output + conf->clock
: Theme::c("inactive_fg") + Fx::uncolor(output + conf->clock) + conf->overlay)
<< Term::sync_end << flush;
//! DEBUG stats -->
cout << Fx::reset << Mv::to(1, 20) << "Runner took: " << rjust(to_string(time_micros() - timestamp), 5) << " μs. " << flush;
@ -465,20 +473,10 @@ namespace Runner {
Config::unlock();
Config::lock();
if (not Global::overlay.empty())
overlay = Global::overlay;
else if (not overlay.empty())
overlay.clear();
if (not Global::clock.empty())
clock = Global::clock;
else if (not clock.empty())
clock.clear();
current_conf = {(box == "all" ? Config::current_boxes : vector{box}), no_update, force_redraw};
current_conf = { (box == "all" ? Config::current_boxes : vector{box}), no_update, force_redraw, Global::overlay, Global::clock};
pthread_t runner_id;
if (pthread_create(&runner_id, NULL, &_runner, NULL) != 0)
if (pthread_create(&runner_id, NULL, &_runner, (void *) &current_conf) != 0)
throw std::runtime_error("Failed to create _runner thread!");
if (pthread_detach(runner_id) != 0)

View file

@ -30,7 +30,7 @@ tab-size = 4
using std::round, std::views::iota, std::string_literals::operator""s, std::clamp, std::array, std::floor, std::max, std::min,
std::to_string;
std::to_string, std::cmp_equal, std::cmp_less, std::cmp_greater, std::cmp_less_equal;
using namespace Tools;
namespace rng = std::ranges;
@ -629,7 +629,7 @@ namespace Mem {
for (int i = 0; const auto& name : mem.disks_order) {
if (i * 2 > height - 2) break;
disk_meters_used[name] = Draw::Meter{disk_meter, "used"};
if ((int)mem.disks_order.size() * 3 <= height - 1)
if (cmp_less_equal(mem.disks_order.size() * 3, height - 1))
disk_meters_free[name] = Draw::Meter{disk_meter, "free"};
}
}
@ -749,11 +749,11 @@ namespace Mem {
+ disk_meters_used.at(mount)(disk.used_percent) + rjust(human_used, (big_disk ? 9 : 7));
if (++cy > height - 3) break;
if ((int)disks.size() * 3 + (show_io_stat ? disk_ios : 0) <= height - 1) {
if (cmp_less_equal(disks.size() * 3 + (show_io_stat ? disk_ios : 0), height - 1)) {
out += Mv::to(y+1+cy, x+1+cx) + (big_disk ? " Free:" + rjust(to_string(disk.free_percent) + '%', 4) : "F") + ' '
+ disk_meters_free.at(mount)(disk.free_percent) + rjust(human_free, (big_disk ? 9 : 7));
cy++;
if ((int)disks.size() * 4 + (show_io_stat ? disk_ios : 0) <= height - 1) cy++;
if (cmp_less_equal(disks.size() * 4 + (show_io_stat ? disk_ios : 0), height - 1)) cy++;
}
}
@ -872,7 +872,7 @@ namespace Proc {
string draw(const vector<proc_info>& plist, const bool force_redraw, const bool data_same) {
if (Runner::stopping) return "";
auto& proc_tree = Config::getB("proc_tree");
const bool show_detailed = (Config::getB("show_detailed") and Proc::detailed.last_pid == (size_t)Config::getI("detailed_pid"));
const bool show_detailed = (Config::getB("show_detailed") and cmp_equal(Proc::detailed.last_pid, Config::getI("detailed_pid")));
const bool proc_gradient = (Config::getB("proc_gradient") and not Config::getB("lowcolor") and Theme::gradients.contains("proc"));
auto& proc_colors = Config::getB("proc_colors");
auto& tty_mode = Config::getB("tty_mode");
@ -1199,7 +1199,7 @@ namespace Proc {
mem_str += '%';
}
out += (thread_size > 0 ? t_color + rjust(to_string(min(p.threads, 9999ul)), thread_size) + ' ' + end : "" )
+ g_color + ljust(((int)p.user.size() > user_size ? p.user.substr(0, user_size - 1) + '+' : p.user), user_size) + ' '
+ g_color + ljust((cmp_greater(p.user.size(), user_size) ? p.user.substr(0, user_size - 1) + '+' : p.user), user_size) + ' '
+ m_color + rjust(mem_str, 5) + end + ' '
+ (is_selected ? "" : Theme::c("inactive_fg")) + graph_bg * 5
+ (p_graphs.contains(p.pid) ? Mv::l(5) + c_color + p_graphs.at(p.pid)({(p.cpu_p >= 0.1 and p.cpu_p < 5 ? 5ll : (long long)round(p.cpu_p))}, data_same) : "") + end + ' '

View file

@ -225,7 +225,7 @@ namespace Input {
}
else if (key == "right") {
int cur_i = v_index(Proc::sort_vector, Config::getS("proc_sorting"));
if (++cur_i > (int)Proc::sort_vector.size() - 1)
if (std::cmp_greater(++cur_i, Proc::sort_vector.size() - 1))
cur_i = 0;
Config::set("proc_sorting", Proc::sort_vector.at(cur_i));
}

View file

@ -30,8 +30,8 @@ tab-size = 4
#include <btop_config.hpp>
#include <btop_tools.hpp>
using std::string, std::vector, std::ifstream, std::atomic, std::numeric_limits, std::streamsize,
std::round, std::max, std::min, std::clamp, std::string_literals::operator""s;
using std::string, std::vector, std::ifstream, std::atomic, std::numeric_limits, std::streamsize, std::round, std::max, std::min,
std::clamp, std::string_literals::operator""s, std::cmp_equal, std::cmp_less, std::cmp_greater;
namespace fs = std::filesystem;
namespace rng = std::ranges;
using namespace Tools;
@ -325,7 +325,7 @@ namespace Cpu {
done.push_back(sensor);
}
for (const auto& [core, temp] : core_mapping) {
if ((size_t)core + 1 < current_cpu.temp.size() and (size_t)temp < core_sensors.size()) {
if (cmp_less(core + 1, current_cpu.temp.size()) and cmp_less(temp, core_sensors.size())) {
current_cpu.temp.at(core + 1).push_back(found_sensors.at(core_sensors.at(temp)).temp);
if (current_cpu.temp.at(core + 1).size() > 20) current_cpu.temp.at(core + 1).pop_front();
}
@ -407,7 +407,7 @@ namespace Cpu {
}
//? If core mapping from cpuinfo was incomplete try to guess remainder, if missing completely map 0-0 1-1 2-2 etc.
if (core_map.size() < (size_t)Shared::coreCount) {
if (cmp_less(core_map.size(), Shared::coreCount)) {
if (Shared::coreCount % 2 == 0 and (long)core_map.size() == Shared::coreCount / 2) {
for (int i = 0; i < Shared::coreCount / 2; i++)
core_map[Shared::coreCount / 2 + i] = i;
@ -484,7 +484,7 @@ namespace Cpu {
cpu.cpu_percent.at("total").push_back(clamp((long long)round((double)(calc_totals - calc_idles) * 100 / calc_totals), 0ll, 100ll));
//? Reduce size if there are more values than needed for graph
if (cpu.cpu_percent.at("total").size() > (size_t)Term::width * 2) cpu.cpu_percent.at("total").pop_front();
if (cmp_greater(cpu.cpu_percent.at("total").size(), Term::width * 2)) cpu.cpu_percent.at("total").pop_front();
//? Populate cpu.cpu_percent with all fields from stat
for (int ii = 0; const auto& val : times) {
@ -492,7 +492,7 @@ namespace Cpu {
cpu_old.at(time_names.at(ii)) = val;
//? Reduce size if there are more values than needed for graph
if (cpu.cpu_percent.at(time_names.at(ii)).size() > (size_t)Term::width * 2) cpu.cpu_percent.at(time_names.at(ii)).pop_front();
if (cmp_greater(cpu.cpu_percent.at(time_names.at(ii)).size(), Term::width * 2)) cpu.cpu_percent.at(time_names.at(ii)).pop_front();
if (++ii == 10) break;
}
@ -603,7 +603,7 @@ namespace Mem {
//? Remove values beyond whats needed for graph creation
for (auto& [ignored, deq] : mem.percent) {
if (deq.size() > (size_t)Term::width * 2) deq.pop_front();
if (cmp_greater(deq.size(), Term::width * 2)) deq.pop_front();
}
//? Get disks stats
@ -758,7 +758,7 @@ namespace Mem {
else
disk.io_read.push_back(max(0l, (sectors_read - disk.old_io.at(0)) * 512));
disk.old_io.at(0) = sectors_read;
if (disk.io_read.size() > (size_t)Term::width * 2) disk.io_read.pop_front();
if (cmp_greater(disk.io_read.size(), Term::width * 2)) disk.io_read.pop_front();
for (int i = 0; i < 3; i++) { diskread >> std::ws; diskread.ignore(SSmax, ' '); }
diskread >> sectors_write;
@ -767,7 +767,7 @@ namespace Mem {
else
disk.io_write.push_back(max(0l, (sectors_write - disk.old_io.at(1)) * 512));
disk.old_io.at(1) = sectors_write;
if (disk.io_write.size() > (size_t)Term::width * 2) disk.io_write.pop_front();
if (cmp_greater(disk.io_write.size(), Term::width * 2)) disk.io_write.pop_front();
}
diskread.close();
}
@ -906,7 +906,7 @@ namespace Proc {
//? Update cpu percent deque for process cpu graph
if (not Config::getB("proc_per_core")) detailed.entry.cpu_p *= Shared::coreCount;
detailed.cpu_percent.push_back(round(detailed.entry.cpu_p));
if (detailed.cpu_percent.size() > (size_t)Term::width) detailed.cpu_percent.pop_front();
if (cmp_greater(detailed.cpu_percent.size(), Term::width.load())) detailed.cpu_percent.pop_front();
//? Process runtime
detailed.elapsed = sec_to_dhms(uptime - (cache.at(pid).cpu_s / Shared::clkTck));
@ -955,7 +955,7 @@ namespace Proc {
redraw = true;
}
if (detailed.mem_bytes.size() > (size_t)Term::width) detailed.mem_bytes.pop_front();
if (cmp_greater(detailed.mem_bytes.size(), Term::width.load())) detailed.mem_bytes.pop_front();
//? Get bytes read and written from proc/[pid]/io
if (fs::exists(pid_path / "io")) {

View file

@ -56,7 +56,7 @@ namespace Fx {
//* Reset text effects and restore theme foregrund and background color
extern string reset;
//* Regex for matching color, style and curse move escape sequences
//* Regex for matching color, style and cursor move escape sequences
const regex escape_regex("\033\\[\\d+;?\\d?;?\\d*;?\\d*;?\\d*(m|f|s|u|C|D|A|B){1}");
//* Regex for matching only color and style escape sequences
@ -125,6 +125,7 @@ namespace Term {
namespace Tools {
constexpr auto SSmax = std::numeric_limits<std::streamsize>::max();
constexpr auto ZeroSec = std::chrono::seconds(0);
extern atomic<int> active_locks;
//* Return number of UTF8 characters in a string (counts UTF-8 characters with a width > 1 as 2 characters)