From f9ed675d478de7a8d143d3a811f49672bfbe68a6 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 11 Aug 2021 20:25:11 +0200 Subject: [PATCH] Added bitmask enums and fixed signed to unsigned comparisons --- src/btop.cpp | 90 +++++++++++++++++++++++----------------------- src/btop_draw.cpp | 12 +++---- src/btop_input.cpp | 2 +- src/btop_linux.cpp | 22 ++++++------ src/btop_tools.hpp | 3 +- 5 files changed, 64 insertions(+), 65 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 33e8949..7f5ca6e 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -273,11 +273,8 @@ namespace Runner { atomic 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 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 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 *) ¤t_conf) != 0) throw std::runtime_error("Failed to create _runner thread!"); if (pthread_detach(runner_id) != 0) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index e09f802..8f6c71e 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -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& 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 + ' ' diff --git a/src/btop_input.cpp b/src/btop_input.cpp index ad90994..d7616a6 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -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)); } diff --git a/src/btop_linux.cpp b/src/btop_linux.cpp index c926a98..916b20d 100644 --- a/src/btop_linux.cpp +++ b/src/btop_linux.cpp @@ -30,8 +30,8 @@ tab-size = 4 #include #include -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")) { diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index a1902bc..e9d7f50 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -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::max(); + constexpr auto ZeroSec = std::chrono::seconds(0); extern atomic active_locks; //* Return number of UTF8 characters in a string (counts UTF-8 characters with a width > 1 as 2 characters)