mirror of
https://github.com/aristocratos/btop.git
synced 2024-05-21 04:43:36 +12:00
Added bitmask enums and fixed signed to unsigned comparisons
This commit is contained in:
parent
d56fe4cdb5
commit
f9ed675d47
90
src/btop.cpp
90
src/btop.cpp
|
@ -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 *) ¤t_conf) != 0)
|
||||
throw std::runtime_error("Failed to create _runner thread!");
|
||||
|
||||
if (pthread_detach(runner_id) != 0)
|
||||
|
|
|
@ -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 + ' '
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue