summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--btop.cpp14
-rw-r--r--src/btop_config.h64
-rw-r--r--src/btop_draw.h2
-rw-r--r--src/btop_input.h2
-rw-r--r--src/btop_linux.h2
-rw-r--r--src/btop_theme.h4
-rw-r--r--src/btop_tools.h66
8 files changed, 116 insertions, 44 deletions
diff --git a/README.md b/README.md
index 9649812..50e8026 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,9 @@ Look to the creators of the terminal emulator you use to fix these issues if the
None
-But will need G++ 11 if compiling from source.
+### Compiling from source
+
+Needs at least G++ 10, preferably 11 (or higher) to make use of some C++20 functionality.
## Screenshots
@@ -132,7 +134,7 @@ Options menu.
#### Manual compilation and installation
-Requires GCC/G++ 11!
+Requires GCC/G++ 10 or higher!
>Clone and compile
diff --git a/btop.cpp b/btop.cpp
index b7c428f..20c62c5 100644
--- a/btop.cpp
+++ b/btop.cpp
@@ -179,6 +179,7 @@ int main(int argc, char **argv){
std::atexit(_exit_handler);
+ //? Linux init
#if defined(LINUX)
Global::coreCount = sysconf(_SC_NPROCESSORS_ONLN);
if (Global::coreCount < 1) Global::coreCount = 1;
@@ -225,17 +226,17 @@ int main(int argc, char **argv){
if (Global::debug) { Logger::loglevel = 4; Logger::debug("Starting in debug mode");}
if (!string(getenv("LANG")).ends_with("UTF-8") && !string(getenv("LANG")).ends_with("utf-8")) {
- string err_msg = "No UTF-8 locale was detected! Symbols might not look as intended.";
+ string err_msg = "No UTF-8 locale was detected! Symbols might not look as intended.\n"s
+ + "Make sure your $LANG evironment variable is set and with a UTF-8 locale."s;
Logger::warning(err_msg);
cout << "WARNING: " << err_msg << endl;
}
//? Initialize terminal and set options
if (!Term::init()) {
- string err_msg = "No tty detected!";
- Logger::error(err_msg + " Quitting.");
+ string err_msg = "No tty detected!\nbtop++ needs an interactive shell to run.";
+ Logger::error(err_msg);
cout << "ERROR: " << err_msg << endl;
- cout << "btop++ needs an interactive shell to run." << endl;
clean_quit(1);
}
@@ -246,7 +247,7 @@ int main(int argc, char **argv){
//? Read config file if present
Config::load();
- // Config::setB("truecolor", false);
+ // Config::set("truecolor", false);
auto thts = time_ms();
@@ -311,6 +312,7 @@ int main(int argc, char **argv){
exit(0);
}
+
if (false) {
Draw::Meter kmeter;
kmeter(Term::width - 2, "cpu", false);
@@ -336,7 +338,7 @@ int main(int argc, char **argv){
exit(0);
}
- if (true) {
+ if (false) {
vector<long long> mydata;
for (long long i = 0; i <= 100; i++) mydata.push_back(i);
diff --git a/src/btop_config.h b/src/btop_config.h
index 86f50a4..e1463b0 100644
--- a/src/btop_config.h
+++ b/src/btop_config.h
@@ -17,7 +17,7 @@ tab-size = 4
*/
#ifndef _btop_config_included_
-#define _btop_config_included_ 1
+#define _btop_config_included_
#include <string>
#include <vector>
@@ -38,6 +38,8 @@ namespace Config {
fs::path conf_dir;
fs::path conf_file;
+ atomic<bool> locked (false);
+ atomic<bool> writelock (false);
bool changed = false;
unordered_flat_map<string, string> strings = {
@@ -57,6 +59,8 @@ namespace Config {
{"net_iface", ""},
{"log_level", "WARNING"}
};
+ unordered_flat_map<string, string> stringsTmp;
+
unordered_flat_map<string, bool> bools = {
{"theme_background", true},
{"truecolor", true},
@@ -89,11 +93,20 @@ namespace Config {
{"show_battery", true},
{"show_init", false}
};
+ unordered_flat_map<string, bool> boolsTmp;
+
unordered_flat_map<string, int> ints = {
{"update_ms", 2000},
{"proc_update_mult", 2},
{"tree_depth", 3}
};
+ unordered_flat_map<string, int> intsTmp;
+
+ bool _locked(){
+ atomic_wait(writelock);
+ if (!changed) changed = true;
+ return locked.load();
+ }
}
//* Return config value <name> as a bool
@@ -113,26 +126,59 @@ namespace Config {
//* Set config value <name> to bool <value>
void set(string name, bool value){
- bools.at(name) = value;
- changed = true;
+ if (_locked()) boolsTmp[name] = value;
+ else bools.at(name) = value;
}
//* Set config value <name> to int <value>
void set(string name, int value){
+ if (_locked()) intsTmp[name] = value;
ints.at(name) = value;
- changed = true;
}
//* Set config value <name> to string <value>
void set(string name, string value){
- strings.at(name) = value;
- changed = true;
+ if (_locked()) stringsTmp[name] = value;
+ else strings.at(name) = value;
}
- //* Flip config bool value
+ //* Flip config bool <name>
void flip(string name){
- bools.at(name) = !bools.at(name);
- changed = true;
+ if (_locked()) {
+ if (boolsTmp.contains(name)) boolsTmp.at(name) = !boolsTmp.at(name);
+ else boolsTmp[name] = !bools.at(name);
+ }
+ else bools.at(name) = !bools.at(name);
+ }
+
+ //* Wait if locked then lock config and cache changes until unlock
+ void lock(){
+ atomic_wait_set(locked, true);
+ }
+
+ //* Unlock config and write any cached values to config
+ void unlock(){
+ atomic_wait_set(writelock, true);
+ if (stringsTmp.size() > 0) {
+ for (auto& item : stringsTmp){
+ strings.at(item.first) = item.second;
+ }
+ stringsTmp.clear(); stringsTmp.compact();
+ }
+ if (intsTmp.size() > 0) {
+ for (auto& item : intsTmp){
+ ints.at(item.first) = item.second;
+ }
+ intsTmp.clear(); intsTmp.compact();
+ }
+ if (boolsTmp.size() > 0) {
+ for (auto& item : boolsTmp){
+ bools.at(item.first) = item.second;
+ }
+ boolsTmp.clear(); boolsTmp.compact();
+ }
+ writelock.store(false);
+ locked.store(false);
}
void load(){
diff --git a/src/btop_draw.h b/src/btop_draw.h
index 6736eab..029779b 100644
--- a/src/btop_draw.h
+++ b/src/btop_draw.h
@@ -31,7 +31,7 @@ tab-size = 4
#include <btop_tools.h>
#ifndef _btop_draw_included_
-#define _btop_draw_included_ 1
+#define _btop_draw_included_
using std::string, std::vector, robin_hood::unordered_flat_map, std::round, std::views::iota,
std::string_literals::operator""s, std::clamp, std::array, std::floor;
diff --git a/src/btop_input.h b/src/btop_input.h
index 9ce1f5a..79e2fa9 100644
--- a/src/btop_input.h
+++ b/src/btop_input.h
@@ -17,7 +17,7 @@ tab-size = 4
*/
#ifndef _btop_input_included_
-#define _btop_input_included_ 1
+#define _btop_input_included_
#include <string>
#include <robin_hood.h>
diff --git a/src/btop_linux.h b/src/btop_linux.h
index 6c533e4..d1ce554 100644
--- a/src/btop_linux.h
+++ b/src/btop_linux.h
@@ -17,7 +17,7 @@ tab-size = 4
*/
#ifndef _btop_linux_included_
-#define _btop_linux_included_ 1
+#define _btop_linux_included_
#include <string>
#include <vector>
diff --git a/src/btop_theme.h b/src/btop_theme.h
index 98c7885..900087a 100644
--- a/src/btop_theme.h
+++ b/src/btop_theme.h
@@ -17,7 +17,7 @@ tab-size = 4
*/
#ifndef _btop_theme_included_
-#define _btop_theme_included_ 1
+#define _btop_theme_included_
#include <string>
#include <cmath>
@@ -240,7 +240,7 @@ namespace Theme {
int rng = (rgb_arr[1][0] >= 0) ? 50 : 100;
for (int rgb : iota(0, 3)){
int arr1 = 0, offset = 0;
- int arr2 = (rng == 50) ? 1 : 2;
+ int arr2 = (rng == 50) ? 1 : 2;
for (int i : iota(0, 101)) {
dec_arr[i][rgb] = rgb_arr[arr1][rgb] + (i - offset) * (rgb_arr[arr2][rgb] - rgb_arr[arr1][rgb]) / rng;
diff --git a/src/btop_tools.h b/src/btop_tools.h
index 8bc8639..ad6abe9 100644
--- a/src/btop_tools.h
+++ b/src/btop_tools.h
@@ -17,7 +17,7 @@ tab-size = 4
*/
#ifndef _btop_tools_included_
-#define _btop_tools_included_ 1
+#define _btop_tools_included_
#include <string>
#include <cmath>
@@ -226,12 +226,27 @@ namespace Term {
namespace Tools {
//* Return number of UTF8 characters in a string with option to disregard escape sequences
- size_t ulen(string s, bool escape=false){
- if (escape) s = std::regex_replace(s, Fx::escape_regex, "");
- return std::count_if(s.begin(), s.end(),
+ size_t ulen(string str, bool escape=false){
+ if (escape) str = std::regex_replace(str, Fx::escape_regex, "");
+ return std::count_if(str.begin(), str.end(),
[](char c) { return (static_cast<unsigned char>(c) & 0xC0) != 0x80; } );
}
+ //* Resize a string consisting of UTF8 characters (only reduces size)
+ string uresize(string str, const size_t len){
+ if (str.size() < 1) return str;
+ if (len < 1) return "";
+ for (size_t x = 0, i = 0; i < str.size(); i++) {
+ if ((static_cast<unsigned char>(str.at(i)) & 0xC0) != 0x80) x++;
+ if (x == len) {
+ str.resize(i + 1);
+ str.shrink_to_fit();
+ break;
+ }
+ }
+ return str;
+ }
+
//* Return current time since epoch in seconds
uint64_t time_s(){
return std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
@@ -301,10 +316,7 @@ namespace Tools {
//* Left justify string <str> if <x> is greater than <str> length, limit return size to <x> by default
string ljust(string str, const size_t x, bool utf=false, bool escape=false, bool lim=true){
if (utf || escape) {
- if (!escape && lim && ulen(str) > x) {
- auto i = str.size();
- while (ulen(str) > x) str.resize(--i);
- }
+ if (!escape && lim && ulen(str) > x) str = uresize(str, x);
return str + string(max((int)(x - ulen(str, escape)), 0), ' ');
}
else {
@@ -316,10 +328,7 @@ namespace Tools {
//* Right justify string <str> if <x> is greater than <str> length, limit return size to <x> by default
string rjust(string str, const size_t x, bool utf=false, bool escape=false, bool lim=true){
if (utf || escape) {
- if (!escape && lim && ulen(str) > x) {
- auto i = str.size();
- while (ulen(str) > x) str.resize(--i);
- }
+ if (!escape && lim && ulen(str) > x) str = uresize(str, x);
return string(max((int)(x - ulen(str, escape)), 0), ' ') + str;
}
else {
@@ -328,13 +337,6 @@ namespace Tools {
}
}
- //* Trim trailing characters if utf8 string length is greatear than <x>
- string uresize(string str, const size_t x){
- if (str.empty()) return str;
- while (ulen(str) > x) str.pop_back();
- return str;
- }
-
//* Replace whitespaces " " with escape code for move right
string trans(string str){
size_t pos;
@@ -425,10 +427,30 @@ namespace Tools {
return ss.str();
}
+
+ #if __GNUC__ > 10
+ //* Redirects to atomic wait
+ void atomic_wait(atomic<bool>& atom, bool val=true){
+ atom.wait(val);
+ }
+ #else
+ //* Crude implementation of atomic wait for GCC < 11
+ void atomic_wait(atomic<bool>& atom, bool val=true){
+ while (atom.load() == val) sleep_ms(1);
+ }
+ #endif
+
+ //* Waits for <atom> to not be <val> and then sets it to <val> again
+ void atomic_wait_set(atomic<bool>& atom, bool val){
+ atomic_wait(atom, val);
+ atom.store(val);
+ }
+
}
//* Simple logging implementation
namespace Logger {
+ using namespace Tools;
namespace {
std::atomic<bool> busy (false);
bool first = true;
@@ -447,7 +469,7 @@ namespace Logger {
void log_write(uint level, string& msg){
if (loglevel < level || logfile.empty()) return;
- busy.wait(true); busy.store(true);
+ atomic_wait_set(busy, true);
std::error_code ec;
if (fs::file_size(logfile, ec) > 1024 << 10 && !ec) {
auto old_log = logfile;
@@ -457,8 +479,8 @@ namespace Logger {
}
if (!ec) {
std::ofstream lwrite(logfile, std::ios::app);
- if (first) { first = false; lwrite << "\n" << Tools::strf_time(tdf) << "===> btop++ v." << Global::Version << "\n";}
- lwrite << Tools::strf_time(tdf) << log_levels[level] << ": " << msg << "\n";
+ if (first) { first = false; lwrite << "\n" << strf_time(tdf) << "===> btop++ v." << Global::Version << "\n";}
+ lwrite << strf_time(tdf) << log_levels[level] << ": " << msg << "\n";
lwrite.close();
}
else logfile.clear();